stm32boot.c (7477B)
1 /* stm32boot.c 2 * 3 * Copyright 2011 Brian Swetland <swetland@frotz.net> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 #include <unistd.h> 22 #include <errno.h> 23 24 #include <termios.h> 25 #include <signal.h> 26 #include <poll.h> 27 #include <unistd.h> 28 29 #include <sys/time.h> 30 #include <sys/ioctl.h> 31 #include <sys/fcntl.h> 32 #include <sys/types.h> 33 34 #if 0 35 int WRITE(int fd, void *ptr, int len) { 36 int r; 37 fprintf(stderr,"["); 38 for (r = 0; r < len; r++) 39 fprintf(stderr," %02x", ((unsigned char *) ptr)[r]); 40 fprintf(stderr," ]\n"); 41 return write(fd, ptr, len); 42 } 43 44 int READ(int fd, void *ptr, int len) { 45 int n, r; 46 r = read(fd, ptr, len); 47 if (r <= 0) { 48 fprintf(stderr,"<XX>\n"); 49 return r; 50 } 51 fprintf(stderr,"<"); 52 for (n = 0; n < len; n++) 53 fprintf(stderr," %02x", ((unsigned char *) ptr)[n]); 54 fprintf(stderr," >\n"); 55 return r; 56 } 57 58 #define read READ 59 #define write WRITE 60 #endif 61 62 int openserial(const char *device, int speed) 63 { 64 struct termios tio; 65 int fd; 66 fd = open(device, O_RDWR | O_NOCTTY);// | O_NDELAY); 67 68 if (fd < 0) 69 return -1; 70 71 if (tcgetattr(fd, &tio)) 72 memset(&tio, 0, sizeof(tio)); 73 74 tio.c_cflag = B57600 | CS8 | CLOCAL | CREAD | PARENB; 75 tio.c_ispeed = B57600; 76 tio.c_ospeed = B57600; 77 tio.c_iflag = IGNPAR; 78 tio.c_oflag = 0; 79 tio.c_lflag = 0; /* turn of CANON, ECHO*, etc */ 80 tio.c_cc[VTIME] = 1; 81 tio.c_cc[VMIN] = 0; 82 tcsetattr(fd, TCSANOW, &tio); 83 tcflush(fd, TCIFLUSH); 84 85 #ifdef __APPLE__ 86 tio.c_cflag = CS8 | CLOCAL | CREAD | PARENB; 87 #else 88 tio.c_cflag = speed | CS8 | CLOCAL | CREAD | PARENB; 89 #endif 90 tio.c_ispeed = speed; 91 tio.c_ospeed = speed; 92 93 tcsetattr(fd, TCSANOW, &tio); 94 tcflush(fd, TCIFLUSH); 95 return fd; 96 } 97 98 #define ACK 0x79 99 #define NAK 0x1F 100 101 int readAck(int fd) { /* 3s timeout */ 102 int n; 103 unsigned char x; 104 for (n = 0; n < 30; n++) { 105 if (read(fd, &x, 1) == 1) { 106 if (x == ACK) 107 return 0; 108 fprintf(stderr,"?? %02x\n",x); 109 return -1; 110 } 111 } 112 fprintf(stderr,"*TIMEOUT*\n"); 113 return -1; 114 } 115 116 int sendCommand(int fd, unsigned cmd) { 117 unsigned char data[2]; 118 data[0] = cmd; 119 data[1] = cmd ^ 0xFF; 120 if (write(fd, data, 2) != 2) 121 return -1; 122 if (readAck(fd)) 123 return -1; 124 return 0; 125 } 126 127 int sendAddress(int fd, unsigned addr) { 128 unsigned char data[5]; 129 data[0] = addr >> 24; 130 data[1] = addr >> 16; 131 data[2] = addr >> 8; 132 data[3] = addr; 133 data[4] = data[0] ^ data[1] ^ data[2] ^ data[3]; 134 if (write(fd, data, 5) != 5) 135 return -1; 136 if (readAck(fd)) 137 return -1; 138 return 0; 139 } 140 141 int sendLength(int fd, unsigned len) { 142 unsigned char data[2]; 143 if ((len < 1) || (len > 256)) 144 return -1; 145 len--; 146 data[0] = len; 147 data[1] = len ^ 0xFF; 148 if (write(fd, data, 2) != 2) 149 return -1; 150 if (readAck(fd)) 151 return -1; 152 return 0; 153 } 154 155 int sendData(int fd, void *ptr, unsigned len) 156 { 157 unsigned char x; 158 unsigned char check; 159 unsigned char *data = ptr; 160 unsigned n; 161 162 if ((len < 1) || (len > 256)) 163 return -1; 164 check = x = (len - 1); 165 for (n = 0; n < len; n++) { 166 check ^= data[n]; 167 } 168 if (write(fd, &x, 1) != 1) 169 return -1; 170 if (write(fd, data, len) != len) 171 return -1; 172 if (write(fd, &check, 1) != 1) 173 return -1; 174 if (readAck(fd)) 175 return -1; 176 return 0; 177 } 178 179 int readData(int fd, void *ptr, int len) 180 { 181 unsigned char *data = ptr; 182 int r; 183 while (len > 0) { 184 r = read(fd, data, len); 185 if (r <= 0) { 186 fprintf(stderr,"*UNDERFLOW*\n"); 187 return -1; 188 } 189 len -= r; 190 data += r; 191 } 192 return 0; 193 } 194 195 int readMemory(int fd, unsigned addr, void *ptr, int len) 196 { 197 unsigned char *data = ptr; 198 while (len > 0) { 199 int xfer = (len > 256) ? 256 : len; 200 fprintf(stderr,"read %04x at %08x -> %p\n", xfer, addr, data); 201 if (sendCommand(fd, 0x11)) 202 return -1; 203 if (sendAddress(fd, addr)) 204 return -1; 205 if (sendLength(fd, xfer)) 206 return -1; 207 if (readData(fd, data, xfer)) 208 return -1; 209 data += xfer; 210 len -= xfer; 211 addr += xfer; 212 } 213 return 0; 214 } 215 216 int writeMemory(int fd, unsigned addr, void *ptr, int len) 217 { 218 unsigned char *data = ptr; 219 while (len > 0) { 220 int xfer = (len > 256) ? 256 : len; 221 if (sendCommand(fd, 0x31)) 222 return -1; 223 if (sendAddress(fd, addr)) 224 return -1; 225 if (sendData(fd, data, xfer)) 226 return -1; 227 data += xfer; 228 len -= xfer; 229 addr += xfer; 230 } 231 return 0; 232 } 233 234 int eraseFlash(int fd) 235 { 236 unsigned data[2] = { 0xFF, 0x00 }; 237 if (sendCommand(fd, 0x43)) 238 return -1; 239 if (write(fd, data, 2) != 2) 240 return -1; 241 if (readAck(fd)) 242 return -1; 243 return 0; 244 } 245 246 int jumpToAddress(int fd, unsigned addr) 247 { 248 if (sendCommand(fd, 0x21)) 249 return -1; 250 if (sendAddress(fd, addr)) 251 return -1; 252 return 0; 253 } 254 255 int usage(void) 256 { 257 fprintf(stderr, 258 "usage: stm32boot [ erase | flash <file> | exec <file> ]\n"); 259 return -1; 260 } 261 int main(int argc, char *argv[]) 262 { 263 int speed = B115200; 264 const char *device = "/dev/ttyUSB0"; 265 unsigned char x; 266 int fd, n; 267 unsigned char buf[32768]; 268 269 unsigned do_erase = 0; 270 unsigned do_write = 0; 271 unsigned do_exec = 0; 272 unsigned addr = 0; 273 274 if (argc < 2) 275 return usage(); 276 277 if (!strcmp(argv[1],"erase")) { 278 do_erase = 1; 279 } else if (!strcmp(argv[1],"flash")) { 280 do_erase = 1; 281 do_write = 1; 282 addr = 0x08000000; 283 } else if (!strcmp(argv[1],"exec")) { 284 do_write = 1; 285 do_exec = 1; 286 addr = 0x20001000; 287 } else { 288 return usage(); 289 } 290 291 if (do_write && argc != 3) 292 return usage(); 293 294 fd = openserial(device, speed); 295 if (fd < 0) { 296 fprintf(stderr, "stderr open '%s'\n", device); 297 return -1; 298 } 299 300 n = TIOCM_DTR; 301 ioctl(fd, TIOCMBIS, &n); 302 usleep(2500); 303 ioctl(fd, TIOCMBIC, &n); 304 usleep(2500); 305 306 /* If the board just powered up, we need to send an ACK 307 * to auto-baud and will get an ACK back. If the board 308 * is already up, two ACKs will get a NAK (invalid cmd). 309 * Either way, we're talking! 310 */ 311 for (n = 0; n < 5; n++) { 312 unsigned char SYNC = 0x7F; 313 if (write(fd, &SYNC, 1)) { /* do nothing */ } 314 if (read(fd, &x, 1) != 1) 315 continue; 316 if ((x == 0x79) || (x == 0x1f)) 317 break; 318 } 319 if (n == 5) { 320 fprintf(stderr,"sync failure\n"); 321 return -1; 322 } 323 324 #if 0 325 readMemory(fd, 0x1FFFF000, buf, 4096); 326 for (n = 0; n < 1024; n++) 327 fprintf(stderr,"%02x ", buf[n]); 328 return 0; 329 #endif 330 if (do_write) { 331 int fd2 = open(argv[2], O_RDONLY); 332 n = read(fd2, buf, sizeof(buf)); 333 close(fd2); 334 if ((fd2 < 0) || (n <= 0)) { 335 fprintf(stderr,"cannot read '%s'\n", argv[2]); 336 return -1; 337 } 338 n += (n % 4); 339 340 341 if (do_erase) { 342 fprintf(stderr,"erasing flash...\n"); 343 if (eraseFlash(fd)) { 344 fprintf(stderr,"erase failed\n"); 345 return -1; 346 } 347 } 348 349 fprintf(stderr,"sending %d bytes...\n", n); 350 if (writeMemory(fd, addr, buf, n)) { 351 fprintf(stderr,"write failed\n"); 352 return -1; 353 } 354 fprintf(stderr,"done\n"); 355 356 if (do_exec) { 357 jumpToAddress(fd, addr); 358 } else { 359 return 0; 360 } 361 } else if (do_erase) { 362 if (eraseFlash(fd)) { 363 fprintf(stderr,"erase failed\n"); 364 return -1; 365 } 366 fprintf(stderr,"flash erased\n"); 367 return 0; 368 } 369 370 for (;;) { 371 if (read(fd, &x, 1) == 1) { 372 if (x == 27) break; 373 if ((x < 0x20) || (x > 0x7f)) 374 if ((x != 10) && (x != 13)) 375 x = '.'; 376 fprintf(stderr,"%c", x); 377 } 378 } 379 380 return 0; 381 }