]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/gps4020/v2_0/support/download/gps4020_download.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / gps4020 / v2_0 / support / download / gps4020_download.c
1 //-------------------------------------------------------------------
2 //
3 // gps4020_download.c
4 //
5 //-------------------------------------------------------------------
6 //
7 // Copyright (C) 2003, MLB Associates.
8 //
9 // Routine to download code into main [external] SRAM and then
10 // execute it.
11 //
12 //-------------------------------------------------------------------
13
14 //#define DEBUG_DOWNLOAD
15
16 extern void tty_init(void);
17 extern unsigned char tty_getc(int chan);
18 extern void tty_putc(int chan, char c);
19 extern void tty_puts(int chan, char *c);
20 extern void tty_puthex(int chan, unsigned long val, int width);
21
22 typedef int bool;
23 #define false 0
24 #define true  1
25
26 // Validate a hex character
27 __inline__ static bool
28 _is_hex(char c)
29 {
30     return (((c >= '0') && (c <= '9')) ||
31             ((c >= 'A') && (c <= 'F')) ||            
32             ((c >= 'a') && (c <= 'f')));
33 }
34
35 // Convert a single hex nibble
36 __inline__ static int
37 _from_hex(char c) 
38 {
39     int ret = 0;
40
41     if ((c >= '0') && (c <= '9')) {
42         ret = (c - '0');
43     } else if ((c >= 'a') && (c <= 'f')) {
44         ret = (c - 'a' + 0x0a);
45     } else if ((c >= 'A') && (c <= 'F')) {
46         ret = (c - 'A' + 0x0A);
47     }
48     return ret;
49 }
50
51
52 //
53 // Process the next hex value from a string
54 //
55 unsigned long
56 _hex(char **_cp)
57 {
58     unsigned long val;
59     unsigned char *cp = *_cp;
60
61     val = 0;
62     while (_is_hex(*cp)) {
63         val = (val << 4) | _from_hex(*cp++);
64     }
65     *_cp = cp;
66     return val;
67 }
68
69 //
70 // Simple GDB protocol handler
71 // Only three commands are handled:
72 //   $M<loc>,<len>:<data...>#<cksum>
73 //     $M20000000,10:0e0000ea18f09fe518f09fe518f09fe5#59
74 //   $P<reg>=<val>#<cksum>
75 //   $c#<cksum>
76 // <cksum> is a simple accumulation of all of the ASCII
77 // characters following the "$"
78
79 static char
80 _getc(void)
81 {
82     char c;
83     c = tty_getc(0);
84 #ifdef DEBUG_DOWNLOAD
85     tty_putc(1, c);
86 #endif
87     return c;
88 }
89
90 void 
91 GDB_protocol(void)
92 {
93     char c;
94     unsigned char cksum, _cksum;
95     unsigned char line[64];
96     char *cp;
97     bool eol, ok;
98     unsigned char *loc;
99     unsigned long len;
100     unsigned char val;
101     void (*entry_address)(void);
102
103     while (true) {
104         // Wait for a '$'
105         do {
106             c = _getc();
107             // HACK - '>>' indicates to jump to FLASH/ROM
108             if (c == '>') {
109                 c = _getc();
110                 if (c == '>') {
111                     entry_address = (void *)0x60000000;
112                     (*entry_address)();
113                 }
114             }
115         } while (c != '$');
116         cksum = 0;
117         eol = false;
118         cp = line;
119         while (!eol) {
120             c = _getc();
121             if (c != '#') {
122                 cksum += c;
123                 *cp++ = c;
124                 *cp = '\0';
125             } else {
126                 c = _getc();
127                 _cksum = _from_hex(c) << 4;
128                 c = _getc();
129                 _cksum |= _from_hex(c);
130                 ok = (cksum == _cksum);
131                 tty_putc(0, ok ? '+' : '-');
132                 eol = true;
133             }
134         }
135 #ifdef DEBUG_DOWNLOAD
136         tty_puts(1, ok ? " = OK\n" : " = BAD\n");
137 #endif
138         if (ok) {
139             // Empty "OK" message
140             tty_puts(0, "#00");
141             // Process command
142             cp = line;
143             switch (*cp++) {
144             case 'M':
145                 loc = (unsigned char *)_hex(&cp);
146                 if (*cp++ != ',') continue;
147                 len = _hex(&cp);
148                 if (*cp++ != ':') continue;
149                 while (len-- > 0) {
150                     val = _from_hex(*cp++) << 4;
151                     val |= _from_hex(*cp++);
152                     *loc++ = val;
153                 }
154                 break;
155             case 'P':
156                 // Ignore register #
157                 cp += 2;
158                 if (*cp++ != '=') continue;
159                 entry_address = (void *)_hex(&cp);
160                 break;
161             case 'c':
162                 (*entry_address)();
163                 break;
164             default:
165                 tty_puts(0, "** unknown command: $");
166                 tty_puts(0, line);
167             }
168         }
169     }
170 }
171
172 int
173 main(void)
174 {
175     tty_init();
176     // Change 0x6XXXXXXX to use external ROM
177     *(volatile short *)0x4010100C |= (1<<9);
178     tty_puts(0, "Ready to download >>");
179 #ifdef DEBUG_DOWNLOAD
180     tty_puts(1, "... GDB data:\n");
181 #endif
182     GDB_protocol();
183     return 0;  // Never happens!
184 }