m3dev

cortex m3 debug tools -- superceded by mdebug
git clone http://frotz.net/git/m3dev.git
Log | Files | Refs | README | LICENSE

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 }