m3dev

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

main.c (5899B)


      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 
     22 #include <arch/hardware.h>
     23 
     24 #include <protocol/rswdp.h>
     25 #include "swdp.h"
     26 
     27 #define TRACE 0
     28 
     29 #define GPIO_LED	5
     30 #define GPIO_RESET_N	3
     31 
     32 extern unsigned swdp_trace;
     33 
     34 void clocks_to_72mhz() {
     35 	/* external oscillator enable */
     36 	writel(readl(RCC_CR) | 0x00010001, RCC_CR);
     37 	while ((readl(RCC_CR) & 0x00020000) == 0) ;
     38 
     39 	/* flash prefetch enable */
     40 	writel(0x12, 0x40022000);
     41 
     42 	/* configure PLL for 72MHz */
     43 	writel(readl(RCC_CFGR) | 0x001D0400, RCC_CFGR);
     44 	writel(readl(RCC_CR) | 0x01000000, RCC_CR);
     45 	while ((readl(RCC_CR) & 0x03000000) == 0) ;
     46 
     47 	/* set SYSCLK to PLL */
     48 	writel(readl(RCC_CFGR) | 2, RCC_CFGR);
     49 	while ((readl(RCC_CFGR) & 8) == 0) ;
     50 }
     51 
     52 extern u8 __bss_start__;
     53 extern u8 __bss_end__;
     54 void bss_init() {
     55 	u32 *bss, *end;
     56 	bss = (void*) &__bss_start__;
     57 	end = (void*) &__bss_end__;
     58 	while (bss < end)
     59 		*bss++ = 0;
     60 }
     61 
     62 #define DEBUG_MAX 52
     63 static struct {
     64 	u32 txn;
     65 	u32 cmd;
     66 	u8 data[DEBUG_MAX];
     67 } pmsg = {
     68 	.txn = RSWD_TXN_ASYNC,
     69 	.cmd = RSWD_MSG(CMD_DEBUG_PRINT, 0, DEBUG_MAX/4),
     70 };
     71 static unsigned poff = 0;
     72 
     73 void flushu(void) {
     74 	while (poff < DEBUG_MAX)
     75 		pmsg.data[poff++] = 0;
     76 	usb_xmit(&pmsg, sizeof(pmsg));
     77 	poff = 0;
     78 }
     79 
     80 void _putu(unsigned c) {
     81 	pmsg.data[poff++] = c;
     82 	if (poff == DEBUG_MAX)
     83 		flushu();
     84 }
     85 
     86 void printu(const char *fmt, ...) {
     87 	va_list ap;
     88 	va_start(ap, fmt);
     89 	vprintx(_putu, fmt, ap);
     90 	va_end(ap);
     91 	if (poff)
     92 		flushu();
     93 }
     94 
     95 static u8 optable[16] = {
     96 	[OP_RD | OP_DP | OP_X0] = RD_IDCODE,
     97 	[OP_RD | OP_DP | OP_X4] = RD_DPCTRL,
     98 	[OP_RD | OP_DP | OP_X8] = RD_RESEND,
     99 	[OP_RD | OP_DP | OP_XC] = RD_BUFFER,
    100 	[OP_WR | OP_DP | OP_X0] = WR_ABORT,
    101 	[OP_WR | OP_DP | OP_X4] = WR_DPCTRL,
    102 	[OP_WR | OP_DP | OP_X8] = WR_SELECT,
    103 	[OP_WR | OP_DP | OP_XC] = WR_BUFFER,
    104 	[OP_RD | OP_AP | OP_X0] = RD_AP0,
    105 	[OP_RD | OP_AP | OP_X4] = RD_AP1,
    106 	[OP_RD | OP_AP | OP_X8] = RD_AP2,
    107 	[OP_RD | OP_AP | OP_XC] = RD_AP3,
    108 	[OP_WR | OP_AP | OP_X0] = WR_AP0,
    109 	[OP_WR | OP_AP | OP_X4] = WR_AP1,
    110 	[OP_WR | OP_AP | OP_X8] = WR_AP2,
    111 	[OP_WR | OP_AP | OP_XC] = WR_AP3,
    112 };
    113 
    114 /* TODO bounds checking -- we trust the host far too much */
    115 void process_txn(u32 txnid, u32 *rx, int rxc, u32 *tx) {
    116 	unsigned msg, op, n;
    117 	unsigned txc = 1;
    118 	unsigned count = 0;
    119 	unsigned status = 0;
    120 	void (*func)(void) = 0;
    121 
    122 	tx[0] = txnid;
    123 
    124 	while (rxc-- > 0) {
    125 		count++;
    126 		msg = *rx++;
    127 		op = RSWD_MSG_OP(msg);
    128 		n = RSWD_MSG_ARG(msg);
    129 #if TRACE
    130 		printx("> %b %b %h <\n", RSWD_MSG_CMD(msg), op, n);
    131 #endif
    132 		switch (RSWD_MSG_CMD(msg)) {
    133 		case CMD_NULL:
    134 			continue;
    135 		case CMD_SWD_WRITE:
    136 			while (n-- > 0) {
    137 				rxc--;
    138 				if (swdp_write(optable[op], *rx++)) {
    139 					status = 3;
    140 					goto done;
    141 				}
    142 			}
    143 			continue;
    144 		case CMD_SWD_READ:
    145 			tx[txc++] = RSWD_MSG(CMD_SWD_DATA, 0, n); 
    146 			while (n-- > 0) {
    147 				if (swdp_read(optable[op], tx + txc)) {
    148 					txc++;
    149 					while (n-- > 0)
    150 						tx[txc++] = 0xfefefefe;
    151 					status = 3;
    152 					goto done;
    153 				}
    154 				txc++;
    155 			}
    156 			continue;
    157 		case CMD_SWD_DISCARD:
    158 			while (n-- > 0) {
    159 				u32 tmp;
    160 				if (swdp_read(optable[op], &tmp)) {
    161 					status = 3;
    162 					goto done;
    163 				}
    164 			}
    165 			continue;
    166 		case CMD_ATTACH:
    167 			swdp_reset();
    168 			continue;
    169 		case CMD_RESET:
    170 			if (n == 0) {
    171 				/* deassert RESET */
    172 				gpio_config(GPIO_RESET_N,
    173 					GPIO_INPUT | GPIO_FLOATING);
    174 			} else {
    175 				/* assert RESET */
    176 				gpio_clr(GPIO_RESET_N);
    177 				gpio_config(GPIO_RESET_N,
    178 					GPIO_OUTPUT_10MHZ | GPIO_ALT_PUSH_PULL);
    179 			}
    180 			continue;
    181 		case CMD_DOWNLOAD: {
    182 			u32 *addr = (void*) *rx++;
    183 			rxc--;
    184 			while (n) {
    185 				*addr++ = *rx++;
    186 				rxc--;
    187 			}
    188 			continue;
    189 		}
    190 		case CMD_EXECUTE:
    191 			func = (void*) *rx++;
    192 			rxc--;
    193 			continue;
    194 		case CMD_TRACE:
    195 			swdp_trace = op;
    196 			continue;
    197 		default:
    198 			printx("unknown command %b\n", RSWD_MSG_CMD(msg));
    199 			status = 1;
    200 			goto done;
    201 		}
    202 	}
    203 
    204 done:
    205 	tx[txc++] = RSWD_MSG(CMD_STATUS, status, count);
    206 	if ((txc & 0x3f) == 0)
    207 		tx[txc++] = RSWD_MSG(CMD_NULL, 0, 0);
    208 
    209 #if TRACE
    210 	printx("[ send %x words ]\n", txc);
    211 	for (n = 0; n < txc; n+=4) {
    212 		printx("%x %x %x %x\n",
    213 			tx[n], tx[n+1], tx[n+2], tx[n+3]);
    214 	}
    215 #endif
    216 	usb_xmit(tx, txc * 4);
    217 
    218 	if (func) {
    219 		func();
    220 		for (;;) ;
    221 	}	
    222 }
    223 
    224 static u32 rxbuffer[1024];
    225 static u32 txbuffer[1024];
    226 
    227 int main() {
    228 	int rxc;
    229 
    230 	writel(readl(RCC_APB2ENR) |
    231 		RCC_APB2_GPIOA | RCC_APB2_USART1,
    232 		RCC_APB2ENR);
    233 
    234 	gpio_config(9, GPIO_OUTPUT_10MHZ | GPIO_ALT_PUSH_PULL);
    235 	gpio_config(GPIO_LED, GPIO_OUTPUT_10MHZ | GPIO_OUT_PUSH_PULL);
    236 
    237 	clocks_to_72mhz();
    238 	bss_init();
    239 	serial_init(72000000, 115200);
    240 	printx("[ rswdp agent v0.9 ]\n");
    241 	printx("[ built " __DATE__ " " __TIME__ " ]\n");
    242 
    243 #if 0
    244 	irq_set_base(0x20001000);
    245 	irq_enable(i_usb_lp);
    246 	irq_enable(i_usb_hp);
    247 #endif
    248 
    249 	usb_init(0x18d1, 0xdb03, 0, 0);
    250 
    251 	for (;;) {
    252 		gpio_clr(GPIO_LED);
    253 		rxc = usb_recv(rxbuffer, sizeof(rxbuffer));
    254 		gpio_set(GPIO_LED);
    255 
    256 #if TRACE
    257 		int n;
    258 		printx("[ recv %x words ]\n", rxc/4);
    259 		for (n = 0; n < (rxc/4); n+=4) {
    260 			printx("%x %x %x %x\n",
    261 				rxbuffer[n], rxbuffer[n+1], rxbuffer[n+2], rxbuffer[n+3]);
    262 		}
    263 #endif
    264 
    265 		if ((rxc < 4) || (rxc & 3)) {
    266 			printx("error, runt frame, or strange frame... %x\n", rxc);
    267 			continue;
    268 		}
    269 
    270 		rxc = rxc / 4;
    271 
    272 		if ((rxbuffer[0] & 0xFFFF0000) != 0xAA770000) {
    273 			printx("invalid frame %x\n", rxbuffer[0]);
    274 			continue;
    275 		}
    276 
    277 		process_txn(rxbuffer[0], rxbuffer + 1, rxc - 1, txbuffer);
    278 	}
    279 }