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 }