m3dev

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

main.c (4901B)


      1 /* main.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 <fw/types.h>
     19 #include <fw/lib.h>
     20 #include <fw/io.h>
     21 #include <fw/string.h>
     22 
     23 #include <arch/hardware.h>
     24 
     25 extern u8 board_name[];
     26 
     27 #define RAM_BASE	0x10000000
     28 #define RAM_SIZE	(7 * 1024)
     29 
     30 #define ROM_BASE	0x00001000
     31 #define ROM_SIZE	(28 * 1024)
     32 
     33 void (*romcall)(u32 *in, u32 *out) = (void*) 0x1fff1ff1;
     34 
     35 /* { PREPARE, startpage, endpage } */
     36 #define OP_PREPARE	50
     37 /* { WRITE, dstaddr, srcaddr, bytes, sysclk_khz } */
     38 #define OP_WRITE	51
     39 /* { ERASE, startpage, endpage, sysclk_khz } */
     40 #define OP_ERASE	52
     41 
     42 struct device_info {
     43 	u8 part[16];
     44 	u8 board[16];
     45 	u32 version;
     46 	u32 ram_base;
     47 	u32 ram_size;
     48 	u32 rom_base;
     49 	u32 rom_size;
     50 	u32 unused0;
     51 	u32 unused1;
     52 	u32 unused2;
     53 };
     54 
     55 struct device_info DEVICE = {
     56 	.part = "LPC1343",
     57 	.version = 0x0001000,
     58 	.ram_base = RAM_BASE,
     59 	.ram_size = RAM_SIZE,
     60 	.rom_base = ROM_BASE,
     61 	.rom_size = ROM_SIZE,
     62 };
     63 
     64 void iap_erase_page(unsigned addr) {
     65 	u32 in[4];
     66 	u32 out[5];
     67 	in[0] = OP_PREPARE;
     68 	in[1] = (addr >> 12) & 0xF;
     69 	in[2] = (addr >> 12) & 0xF;
     70 	romcall(in, out);
     71 	in[0] = OP_ERASE;
     72 	in[1] = (addr >> 12) & 0xF;
     73 	in[2] = (addr >> 12) & 0xF;
     74 	in[3] = 48000;
     75 	romcall(in, out);
     76 }
     77 
     78 void iap_write_page(unsigned addr, void *src) {
     79 	u32 in[5];
     80 	u32 out[5];
     81 	in[0] = OP_PREPARE;
     82 	in[1] = (addr >> 12) & 0xF;
     83 	in[2] = (addr >> 12) & 0xF;
     84 	romcall(in, out);
     85 	in[0] = OP_WRITE;
     86 	in[1] = addr;
     87 	in[2] = (u32) src;
     88 	in[3] = 0x1000;
     89 	in[4] = 48000;
     90 	romcall(in, out);
     91 }
     92 
     93 static u32 buf[64];
     94 
     95 void start_image(u32 pc, u32 sp);
     96 
     97 void _boot_image(void *img) {
     98 	start_image(((u32*)img)[1], ((u32*)img)[0]);
     99 }
    100 
    101 void boot_image(void *img) {
    102 	board_debug_led(0);
    103 	usb_stop();
    104 
    105 	/* TODO: shut down various peripherals */
    106 	_boot_image(img);
    107 }
    108 
    109 void handle(u32 magic, u32 cmd, u32 arg) {
    110 	u32 reply[2];
    111 	u32 addr, xfer;
    112 	void *ram = (void*) RAM_BASE;
    113 
    114 	if (magic != 0xDB00A5A5)
    115 		return;
    116 
    117 	reply[0] = magic;
    118 	reply[1] = -1;
    119 
    120 	switch (cmd) {
    121 	case 'E':
    122 		iap_erase_page(0x1000);
    123 		reply[1] = 0;
    124 		break;
    125 	case 'W':
    126 		if (arg > ROM_SIZE)
    127 			break;
    128 		reply[1] = 0;
    129 		usb_xmit(reply, 8);
    130 		addr = ROM_BASE;
    131 		while (arg > 0) {
    132 			xfer = (arg > 4096) ? 4096 : arg;
    133 			usb_recv(ram, xfer);
    134 			iap_erase_page(addr);
    135 			iap_write_page(addr, ram);
    136 			addr += 4096;
    137 			arg -= xfer;
    138 		}
    139 		break;
    140 	case 'X':
    141 		if (arg > RAM_SIZE)
    142 			break;
    143 		reply[1] = 0;
    144 		usb_xmit(reply, 8);
    145 		usb_recv(ram, arg);
    146 		usb_xmit(reply, 8);
    147 
    148 		/* let last txn clear */
    149 		usb_recv_timeout(buf, 64, 10);
    150 
    151 		boot_image(ram);
    152 		break;
    153 	case 'Q':
    154 		reply[1] = 0;
    155 		usb_xmit(reply, 8);
    156 		usb_xmit(&DEVICE, sizeof(DEVICE));
    157 		return;
    158 	case 'A':
    159 		/* reboot-into-app -- signal to bootloader via GPREGn */
    160 		writel(0x12345678, GPREG0);
    161 		writel(0xA5A50001, GPREG1);
    162 	case 'R':
    163 		/* reboot "normally" */
    164 		reply[1] = 0;
    165 		usb_xmit(reply, 8);
    166 		usb_recv_timeout(buf, 64, 10);
    167 		reboot();
    168 	default:
    169 		break;
    170 	}
    171 	usb_xmit(reply, 8);
    172 }
    173 
    174 int main() {
    175 	int n, x, timeout;
    176 	u32 tmp;
    177 	u32 gpr0,gpr1;
    178 
    179 	/* sample GPREG and clear */
    180 	gpr0 = readl(GPREG0);
    181 	gpr1 = readl(GPREG1);
    182 	writel(0xBBBBBBBB, GPREG0);
    183 	writel(0xBBBBBBBB, GPREG1);
    184 
    185 	/* request to boot directly into the "app" image */
    186 	if ((gpr0 == 0x12345678) && (gpr1 == 0xA5A50001))
    187 		_boot_image((void*) 0x1000);
    188 
    189 	board_init();
    190 
    191 	usb_init(0x18d1, 0xdb00, "m3dev", "m3boot");
    192 
    193 	/* check for an app image and set a 3s timeout if it exists */
    194 	tmp = *((u32*) 0x1000);
    195 	if ((tmp != 0) && (tmp != 0xFFFFFFFF))
    196 		timeout = 30;
    197 	else
    198 		timeout = 0;
    199 
    200 	/* request to stay in the bootloader forever? */
    201 	if ((gpr0 == 0x12345678) && (gpr1 == 0xA5A50000))
    202 		timeout = 0;
    203 
    204 	strcpy((char*) DEVICE.board, (char*) board_name);
    205 
    206 	if (timeout) {
    207 		/* wait up to 1s to enumerate */
    208 		writel(readl(SYS_CLK_CTRL) | SYS_CLK_CT32B0, SYS_CLK_CTRL);
    209 		writel(48, TM32B0PR);
    210 		writel(TM32TCR_ENABLE, TM32B0TCR);
    211 		while (!usb_online() && (readl(TM32B0TC) < 2000000)) ;
    212 		writel(readl(SYS_CLK_CTRL) & (~SYS_CLK_CT32B0), SYS_CLK_CTRL);
    213 		if (!usb_online())
    214 			goto start_app;
    215 	}
    216 
    217 	x = 0;
    218 	for (;;) {
    219 		board_debug_led(x & 1);
    220 		x++;
    221 		n = usb_recv_timeout(buf, 64, 100);
    222 
    223 		if ((n == -ETIMEOUT) && timeout) {
    224 			timeout--;
    225 			if (timeout == 0)
    226 				break;
    227 		}
    228 
    229 		if (n == 12) {
    230 			timeout = 0;
    231 			handle(buf[0], buf[1], buf[2]);
    232 		}
    233 	}
    234 
    235 start_app:
    236 	/* warm reset into the app */
    237 	writel(0x12345678, GPREG0);
    238 	writel(0xA5A50001, GPREG1);
    239 	reboot();
    240 
    241 	return 0;
    242 }
    243