udebug.c (4610B)
1 // Copyright 2018, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <ctype.h> 5 #include <errno.h> 6 #include <stdint.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <termios.h> 11 #include <unistd.h> 12 13 #include <sys/fcntl.h> 14 15 #include "crc8.h" 16 17 int openserial(const char *device, unsigned speed) { 18 struct termios tio; 19 int fd; 20 21 /* open the serial port non-blocking to avoid waiting for cd */ 22 if ((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) { 23 return -1; 24 } 25 26 memset(&tio, 0, sizeof(tio)); 27 tio.c_iflag |= IGNBRK | IGNPAR; // ignore break, ignore parity/frame err 28 tio.c_cflag |= CS8 | CREAD | CLOCAL; // 8bit, enable rx, no modem lines 29 tio.c_cc[VMIN] = 1; // min chars to read 30 tio.c_cc[VTIME] = 0; // blocking read 31 cfmakeraw(&tio); 32 cfsetispeed(&tio, speed); 33 cfsetospeed(&tio, speed); 34 35 if (tcsetattr(fd, TCSAFLUSH, &tio)) { 36 fprintf(stderr, "error: cannot set serial port attributes: %d %s\n", errno, strerror(errno)); 37 close(fd); 38 return -1; 39 } 40 41 return fd; 42 } 43 44 void cmd(int fd, unsigned cmd, unsigned data) { 45 uint8_t msg[7]; 46 msg[0] = 0xCD; 47 msg[1] = cmd; 48 msg[2] = data; 49 msg[3] = data >> 8; 50 msg[4] = data >> 16; 51 msg[5] = data >> 24; 52 msg[6] = crc8(0xFF, msg, 6); 53 write(fd, msg, 7); 54 } 55 56 void cmd_wr_u8(int fd, uint32_t addr, uint8_t* p, size_t len) { 57 if (len > 4096) { 58 return; 59 } 60 uint8_t data[4097*7]; 61 uint8_t* msg = data; 62 63 msg[0] = 0xCD; 64 msg[1] = 0x01; 65 msg[2] = addr; 66 msg[3] = addr >> 8; 67 msg[4] = addr >> 16; 68 msg[5] = addr >> 24; 69 msg[6] = crc8(0xFF, msg, 6); 70 msg += 7; 71 72 while (len-- > 0) { 73 msg[0] = 0xCD; 74 msg[1] = 0x00; 75 msg[2] = *p++; 76 msg[3] = 0x00; 77 msg[4] = 0x00; 78 msg[5] = 0x00; 79 msg[6] = crc8(0xFF, msg, 6); 80 msg += 7; 81 } 82 write(fd, data, msg - data); 83 } 84 85 void cmd_wr_u16(int fd, uint32_t addr, uint16_t* p, size_t len) { 86 if (len > 4096) { 87 return; 88 } 89 uint8_t data[4097*7]; 90 uint8_t* msg = data; 91 92 msg[0] = 0xCD; 93 msg[1] = 0x01; 94 msg[2] = addr; 95 msg[3] = addr >> 8; 96 msg[4] = addr >> 16; 97 msg[5] = addr >> 24; 98 msg[6] = crc8(0xFF, msg, 6); 99 msg += 7; 100 101 while (len-- > 0) { 102 msg[0] = 0xCD; 103 msg[1] = 0x00; 104 msg[2] = *p; 105 msg[3] = *p >> 8; 106 msg[4] = 0x00; 107 msg[5] = 0x00; 108 msg[6] = crc8(0xFF, msg, 6); 109 msg += 7; 110 p++; 111 } 112 write(fd, data, msg - data); 113 } 114 115 int usage(void) { 116 fprintf(stderr, 117 "usage: udebug <port> <command>*\n" 118 "\n" 119 "command: -load <addr> <hexfile> - write hex file\n" 120 " -write <addr> <value>... - write wolds\n" 121 " -reset - processor RST=1\n" 122 " -run - processor RST=0\n" 123 " -error - cause link error\n" 124 " -clear - clear link error\n" 125 ); 126 return -1; 127 } 128 129 int main(int argc, char **argv) { 130 uint16_t addr; 131 uint16_t data[4096]; 132 size_t n; 133 134 if (argc < 2) { 135 return usage(); 136 } 137 138 int sfd = openserial(argv[1], B1000000); 139 if (sfd < 0) { 140 fprintf(stderr, "error: cannot open serial port '%s'\n", argv[1]); 141 return -1; 142 } 143 144 argc -= 2; 145 argv += 2; 146 while (argc > 0) { 147 if (!strcmp(argv[0], "-load")) { 148 if (argc < 3) { 149 return usage(); 150 } 151 char buf[1024]; 152 addr = strtoul(argv[1], 0, 16); 153 FILE *fp = fopen(argv[2], "r"); 154 if (fp == NULL) { 155 fprintf(stderr, "error: cannot open '%s'\n", argv[3]); 156 return -1; 157 } 158 n = 0; 159 while (fgets(buf, 1024, fp)) { 160 if (!isalnum(buf[0])) continue; 161 if (n == 4096) return -1; 162 data[n++] = strtoul(buf, 0, 16); 163 } 164 fclose(fp); 165 cmd_wr_u16(sfd, addr, data, n); 166 argc -= 3; 167 argv += 3; 168 } else if (!strcmp(argv[0], "-write")) { 169 if (argc < 3) { 170 return usage(); 171 } 172 addr = strtoul(argv[1], 0, 16); 173 argc -= 2; 174 argv += 2; 175 n = 0; 176 while (argc > 0) { 177 if (argv[0][0] == '-') { 178 break; 179 } 180 if (argv[0][0] == '/') { 181 char *s = argv[0] + 1; 182 while (*s != 0) { 183 if (n == 4096) return -1; 184 data[n++] = *s++; 185 } 186 } else { 187 if (n == 4096) return -1; 188 data[n++] = strtoul(argv[0], 0, 16); 189 } 190 argc--; 191 argv++; 192 } 193 cmd_wr_u16(sfd, addr, data, n); 194 } else if (!strcmp(argv[0], "-reset")) { 195 data[0] = 1; 196 cmd_wr_u16(sfd, 0xF000, data, 1); 197 argc--; 198 argv++; 199 } else if (!strcmp(argv[0], "-run")) { 200 data[0] = 0; 201 cmd_wr_u16(sfd, 0xF000, data, 1); 202 argc--; 203 argv++; 204 } else if (!strcmp(argv[0], "-error")) { 205 cmd(sfd, 0xFF, 0); 206 argc--; 207 argv++; 208 } else if (!strcmp(argv[0], "-clear")) { 209 cmd(sfd, 0x02, 0); 210 argc--; 211 argv++; 212 } else { 213 usage(); 214 } 215 } 216 217 close(sfd); 218 return 0; 219 }