mdebug

cortex m series debugger
git clone http://frotz.net/git/mdebug.git
Log | Files | Refs | README | LICENSE

lpcboot.c (6193B)


      1 /* lpcboot.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 <unistd.h>
     21 #include <string.h>
     22 #include <fcntl.h>
     23 #include <stdint.h>
     24 
     25 #include "usb.h"
     26 
     27 int usage(void) {
     28 	fprintf(stderr,
     29 		"lpcboot usage\n-------------\n"
     30 		" lpcboot query         display information about target\n"
     31 		" lpcboot boot <app>    download app to ram and execute\n"
     32 		" lpcboot flash <app>   write app image to flash\n"
     33 		" lpcboot erase         erase app image\n"
     34 		" lpcboot reboot        reboot the bootloader\n"
     35 		" lpcboot app           reboot into the app in flash\n");
     36 	return -1;
     37 }
     38 
     39 struct device_info {
     40 	char part[16];
     41 	char board[16];
     42 	uint32_t version;
     43 	uint32_t ram_base;
     44 	uint32_t ram_size;
     45 	uint32_t rom_base;
     46 	uint32_t rom_size;
     47 	uint32_t ununsed0;
     48 	uint32_t ununsed1;
     49 	uint32_t ununsed2;
     50 };
     51 
     52 #define DFU_DETACH      0
     53 #define DFU_DNLOAD      1
     54 #define DFU_UPLOAD      2
     55 #define DFU_GETSTATUS   3
     56 #define DFU_CLRSTATUS   4
     57 #define DFU_GETSTATE    5
     58 #define DFU_ABORT       6
     59 
     60 #define STATE_APP_IDLE                  0x00
     61 #define STATE_APP_DETACH                0x01
     62 #define STATE_DFU_IDLE                  0x02
     63 #define STATE_DFU_DOWNLOAD_SYNC         0x03
     64 #define STATE_DFU_DOWNLOAD_BUSY         0x04
     65 #define STATE_DFU_DOWNLOAD_IDLE         0x05
     66 #define STATE_DFU_MANIFEST_SYNC         0x06
     67 #define STATE_DFU_MANIFEST              0x07
     68 #define STATE_DFU_MANIFEST_WAIT_RESET   0x08
     69 #define STATE_DFU_UPLOAD_IDLE           0x09
     70 #define STATE_DFU_ERROR                 0x0a
     71 
     72 // 0xA1 getstatus: status[1] pollms[3] state[1] stridx[1]
     73 int dfu_status(usb_handle *usb, unsigned *state) {
     74 	uint8_t io[6];
     75 	if (usb_ctrl(usb, io, 0xA1, DFU_GETSTATUS, 0, 0, 6) != 6) {
     76 		fprintf(stderr, "dfu status: io error\n");
     77 		return -1;
     78 	}
     79 	if (io[0]) {
     80 		fprintf(stderr, "dfu status: 0x%02x\n", io[0]);
     81 		return io[0];
     82 	}
     83 	*state = io[4];
     84 	return 0;
     85 }
     86 
     87 static uint8_t lpcheader[16] = {
     88 	0xda, 0xff, 0x40, 0x00, 0xff, 0xff, 0xff, 0xff,
     89 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     90 };
     91 
     92 int dfu_download(void *_data, unsigned sz) {
     93 	int once = 1;
     94 	uint8_t *data = _data;
     95 	usb_handle *usb;
     96 	unsigned state;
     97 	unsigned xfer;
     98 	uint16_t count = 0;
     99 	for (;;) {
    100 		usb = usb_open(0x1fc9, 0x000c, 0);
    101 		if (usb == 0) {
    102 			if (once) {
    103 				fprintf(stderr,"waiting for DFU device...\n");
    104 				once = 0;
    105 			}
    106 		} else {
    107 			break;
    108 		}
    109 	}
    110 	if (dfu_status(usb, &state)) return -1;
    111 	if (state != STATE_DFU_IDLE) {
    112 		fprintf(stderr, "dfu state not idle (0x%02x)?\n", state);
    113 		return -1;
    114 	}
    115 
    116 	// prepend isp header
    117 	data -= 16;
    118 	sz += 16;
    119 	memcpy(data, lpcheader, 16);
    120 
    121 	// send binary
    122 	while (sz > 0) {
    123 		fprintf(stderr,".");
    124 		xfer = (sz > 2048) ? 2048 : sz;
    125 		if (usb_ctrl(usb, data, 0x21, DFU_DNLOAD, count, 0, xfer) != xfer) {
    126 			fprintf(stderr,"\ndfu dnload: io error\n");
    127 			return -1;
    128 		}
    129 		count++;
    130 		data += xfer;
    131 		sz -= xfer;
    132 		if (dfu_status(usb, &state)) return -1;
    133 		if (state != STATE_DFU_DOWNLOAD_IDLE) {
    134 			fprintf(stderr,"\ndfu dnload state 0x%02x?!\n", state);
    135 			return -1;
    136 		}
    137 	}
    138 	if (usb_ctrl(usb, NULL, 0x21, DFU_DNLOAD, 0, 0, 0) != 0) {
    139 		fprintf(stderr,"\ndfu dnload2: io error\n");
    140 		return -1;
    141 	}
    142 	fprintf(stderr,"\ndone\n");
    143 	if (dfu_status(usb, &state)) return -1;
    144 	if (state == STATE_DFU_MANIFEST_WAIT_RESET) return 0;
    145 	fprintf(stderr,"dfu dnload2: state 0x%02x?!\n", state);
    146 	return -1;
    147 }
    148 
    149 int main(int argc, char **argv) {
    150 	usb_handle *usb;
    151 	char buf[1024*1024+256];
    152 	int fd, once = 1, sz = 0, dl = 0, dfu = 0;
    153 	uint32_t cmd[3];
    154 	uint32_t rep[2];
    155 	struct device_info di;
    156 
    157 	if (argc < 2) 
    158 		return usage();
    159 
    160 	cmd[0] = 0xDB00A5A5;
    161 	if (!strcmp(argv[1],"flash")) {
    162 		dl = 1;
    163 		cmd[1] = 'W';
    164 	} else if (!strcmp(argv[1],"flash:boot")) {
    165 		dl = 1;
    166 		cmd[1] = 'w';
    167 	} else if (!strcmp(argv[1],"boot")) {
    168 		dl = 1;
    169 		cmd[1] = 'X';
    170 	} else if (!strcmp(argv[1],"erase")) {
    171 		cmd[1] = 'E';
    172 	} else if (!strcmp(argv[1],"query")) {
    173 		cmd[1] = 'Q';
    174 	} else if (!strcmp(argv[1],"reboot")) {
    175 		cmd[1] = 'R';
    176 	} else if (!strcmp(argv[1],"app")) {
    177 		cmd[1] = 'A';
    178 	} else if (!strcmp(argv[1],"dfu")) {
    179 		dl = 1;
    180 		dfu = 1;
    181 	} else {
    182 		return usage();
    183 	}
    184 
    185 	if (dl) {
    186 		if (argc < 3)
    187 			return usage();
    188 		fd = open(argv[2], O_RDONLY);
    189 		sz = read(fd, buf + 256, sizeof(buf) - 256);
    190 		close(fd);
    191 		if ((fd < 0) || (sz < 1)) {
    192 			fprintf(stderr,"error: cannot read '%s'\n", argv[2]);
    193 			return -1;
    194 		}
    195 	}
    196 	cmd[2] = sz;
    197 
    198 	if (dfu) {
    199 		return dfu_download(buf + 256, sz);
    200 	}
    201 	for (;;) {
    202 		usb = usb_open(0x1209, 0x5039, 0);
    203 		if (usb == 0) {
    204 			usb = usb_open(0x18d1, 0xdb00, 0);
    205 		}
    206 		if (usb == 0) {
    207 			if (once) {
    208 				fprintf(stderr,"waiting for device...\n");
    209 				once = 0;
    210 			}
    211 		} else {
    212 			break;
    213 		}
    214 	}
    215 
    216 	if (usb_write(usb, cmd, 12) != 12) {
    217 		fprintf(stderr,"io error\n");
    218 		return -1;
    219 	}
    220 	for (;;) {
    221 		if (usb_read(usb, rep, 8) != 8) {
    222 			fprintf(stderr,"io error\n");
    223 			return -1;
    224 		}
    225 		if (rep[0] != 0xDB00A5A5) {
    226 			fprintf(stderr,"protocol error\n");
    227 			return -1;
    228 		}
    229 		if (rep[1] != 0) {
    230 			fprintf(stderr,"%s failure\n", argv[1]);
    231 			return -1;
    232 		}
    233 		if (!strcmp(argv[1],"query")) {
    234 			if (usb_read(usb, &di, sizeof(di)) != sizeof(di)) {
    235 				fprintf(stderr,"io error\n");
    236 				return -1;
    237 			}
    238 			fprintf(stderr,"Part:  %s\n", di.part);
    239 			fprintf(stderr,"Board: %s\n", di.board);
    240 			fprintf(stderr,"RAM:   @%08x (%dKB)\n",
    241 				di.ram_base, di.ram_size / 1024);
    242 			fprintf(stderr,"Flash: @%08x (%dKB)\n",
    243 				di.rom_base, di.rom_size / 1024);
    244 			return 0;
    245 		}
    246 		if (!dl)
    247 			break;
    248 		fprintf(stderr,"sending %d bytes...\n", sz);
    249 		if (usb_write(usb, buf + 256, sz) != sz) {
    250 			fprintf(stderr,"download failure %d\n", sz);
    251 			return -1;
    252 		}
    253 		dl = 0;
    254 	}
    255 	fprintf(stderr,"OKAY\n");
    256 	return 0;
    257 }