add new dfboot loader - a complete revison of romboot code.
[openwrt.git] / target / linux / at91-2.6 / image / dfboot / src / com.c
1 /*----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support - ROUSSET -
3 *----------------------------------------------------------------------------
4 * The software is delivered "AS IS" without warranty or condition of any
5 * kind, either express, implied or statutory. This includes without
6 * limitation any warranty or condition with respect to merchantability or
7 * fitness for any particular purpose, or against the infringements of
8 * intellectual property rights of others.
9 *----------------------------------------------------------------------------
10 * File Name : com.c
11 * Object :
12 * Creation : HIi 03/27/2003
13 *
14 *----------------------------------------------------------------------------
15 */
16 #include "AT91RM9200.h"
17 #include "lib_AT91RM9200.h"
18 #include "config.h"
19 #include "com.h"
20 #include "stdio.h"
21
22 static char erase_seq[] = "\b \b"; /* erase sequence */
23
24 unsigned int usa[2] = {(unsigned int)AT91C_BASE_DBGU, (unsigned int)AT91C_ALTERNATE_USART};
25 unsigned int us;
26 int port_detected;
27
28 void at91_init_uarts(void)
29 {
30 int i;
31
32 port_detected = 0;
33 AT91F_DBGU_CfgPIO();
34 AT91F_US0_CfgPIO();
35 AT91F_US0_CfgPMC();
36
37 for(i=0; i<2; i++) {
38 us = usa[i];
39 AT91F_US_ResetRx((AT91PS_USART)us);
40 AT91F_US_ResetTx((AT91PS_USART)us);
41
42 // Configure DBGU
43 AT91F_US_Configure(
44 (AT91PS_USART)us, // DBGU base address
45 AT91C_MASTER_CLOCK, // 60 MHz
46 AT91C_US_ASYNC_MODE, // mode Register to be programmed
47 115200, // baudrate to be programmed
48 0 // timeguard to be programmed
49 );
50
51 // Enable Transmitter
52 AT91F_US_EnableTx((AT91PS_USART)us);
53 // Enable Receiver
54 AT91F_US_EnableRx((AT91PS_USART)us);
55 }
56 us = usa[0];
57 }
58
59 int at91_serial_putc(int ch)
60 {
61 if (ch == '\n')
62 at91_serial_putc('\r');
63 while (!AT91F_US_TxReady((AT91PS_USART)us));
64 AT91F_US_PutChar((AT91PS_USART)us, (char)ch);
65 return ch;
66 }
67
68 /* This getc is modified to be able work on more than one port. On certain
69 * boards (i.e. Figment Designs VersaLink), the debug port is not available
70 * once the unit is in it's enclosure, so, if one needs to get into dfboot
71 * for any reason it is impossible. With this getc, it scans between the debug
72 * port and another port and once it receives a character, it sets that port
73 * as the debug port. */
74 int at91_serial_getc()
75 {
76 while(1) {
77 if (!port_detected) {
78 if (us == usa[0]) {
79 us = usa[1];
80 }
81 else {
82 us = usa[0];
83 }
84 }
85 if(AT91F_US_RxReady((AT91PS_USART)us)) {
86 port_detected = 1;
87 return((int)AT91F_US_GetChar((AT91PS_USART)us));
88 }
89 }
90 }
91
92 /*-----------------------------------------------------------------------------
93 * Function Name : AT91F_ReadLine()
94 * Object :
95 * Input Parameters :
96 * Return value :
97 *-----------------------------------------------------------------------------
98 */
99 int AT91F_ReadLine (const char *const prompt, char *console_buffer)
100 {
101 char *p = console_buffer;
102 int n = 0; /* buffer index */
103 int plen = strlen (prompt); /* prompt length */
104 int col; /* output column cnt */
105 char c;
106
107 /* print prompt */
108 if (prompt)
109 printf(prompt);
110 col = plen;
111
112 for (;;) {
113 c = getc();
114
115 switch (c) {
116 case '\r': /* Enter */
117 case '\n':
118 *p = '\0';
119 puts ("\n");
120 return (p - console_buffer);
121
122 case 0x03: /* ^C - break */
123 console_buffer[0] = '\0'; /* discard input */
124 return (-1);
125
126 case 0x08: /* ^H - backspace */
127 case 0x7F: /* DEL - backspace */
128 if (n) {
129 --p;
130 printf(erase_seq);
131 col--;
132 n--;
133 }
134 continue;
135
136 default:
137 /*
138 * Must be a normal character then
139 */
140 if (n < (AT91C_CB_SIZE -2))
141 {
142 ++col; /* echo input */
143 putc(c);
144 *p++ = c;
145 ++n;
146 }
147 else
148 { /* Buffer full */
149 putc('\a');
150 }
151 }
152 }
153 }
154
155
156 /*-----------------------------------------------------------------------------
157 * Function Name : AT91F_WaitKeyPressed()
158 * Object :
159 * Input Parameters :
160 * Return value :
161 *-----------------------------------------------------------------------------
162 */
163 void AT91F_WaitKeyPressed(void)
164 {
165 int c;
166 puts("KEY");
167 c = getc();
168 putc('\n');
169 }
170
171 int puts(const char *str)
172 {
173 while(*str != 0) {
174 at91_serial_putc(*str);
175 str++;
176 }
177 return 1;
178 }
179
180 int putc(int c)
181 {
182 return at91_serial_putc(c);
183 }
184
185 int putchar(c)
186 {
187 return putc(c);
188 }
189
190 int getc()
191 {
192 return at91_serial_getc();
193 }
194
195 int strlen(const char *str)
196 {
197 int len = 0;
198
199 if(str == (char *)0)
200 return 0;
201
202 while(*str++ != 0)
203 len++;
204
205 return len;
206 }
207
208 #define ZEROPAD 1 /* pad with zero */
209 #define SIGN 2 /* unsigned/signed long */
210 #define LEFT 4 /* left justified */
211 #define LARGE 8 /* use 'ABCDEF' instead of 'abcdef' */
212
213 #define do_div(n,base) ({ \
214 int __res; \
215 __res = ((unsigned) n) % (unsigned) base; \
216 n = ((unsigned) n) / (unsigned) base; \
217 __res; \
218 })
219
220 static int number(int num, int base, int size,
221 int precision, int type)
222 {
223 char c, sign, tmp[66];
224 const char *digits="0123456789ABCDEF";
225 int i;
226
227 if (type & LEFT)
228 type &= ~ZEROPAD;
229 if (base < 2 || base > 16)
230 return 0;
231 c = (type & ZEROPAD) ? '0' : ' ';
232 sign = 0;
233
234 if(type & SIGN && num < 0)
235 {
236 sign = '-';
237 num = -num;
238 size--;
239 }
240
241 i = 0;
242 if(num == 0)
243 tmp[i++] = digits[0];
244 else while(num != 0)
245 tmp[i++] = digits[do_div(num, base)];
246
247 if(i > precision)
248 precision = i;
249 size -= precision;
250
251 if(!(type&(ZEROPAD+LEFT)))
252 while(size-->0)
253 putc(' ');
254
255 if(sign)
256 putc(sign);
257
258 if (!(type & LEFT))
259 while (size-- > 0)
260 putc(c);
261
262 while (i < precision--)
263 putc('0');
264
265 while (i-- > 0)
266 putc(tmp[i]);
267
268 while (size-- > 0)
269 putc(' ');;
270
271 return 1;
272 }
273
274 int hvfprintf(const char *fmt, va_list va)
275 {
276 char *s;
277
278 do {
279 if(*fmt == '%') {
280 bool done = false;
281
282 int type = 0;
283 int precision = 0;
284
285 do {
286 fmt++;
287 switch(*fmt) {
288 case '0' :
289 if(!precision)
290 type |= ZEROPAD;
291 case '1' :
292 case '2' :
293 case '3' :
294 case '4' :
295 case '5' :
296 case '6' :
297 case '7' :
298 case '8' :
299 case '9' :
300 precision = precision * 10 + (*fmt - '0');
301 break;
302 case '.' :
303 break;
304 case 's' :
305 s = va_arg(va, char *);
306 if(!s)
307 puts("<NULL>");
308 else
309 puts(s);
310 done = true;
311 break;
312 case 'c' :
313 putc(va_arg(va, int));
314 done = true;
315 break;
316 case 'd' :
317 number(va_arg(va, int), 10, 0, precision, type);
318 done = true;
319 break;
320 case 'x' :
321 case 'X' :
322 number(va_arg(va, int), 16, 0, precision, type);
323 done = true;
324 break;
325 case '%' :
326 putc(*fmt);
327 done = true;
328 default:
329 putc('%');
330 putc(*fmt);
331 done = true;
332 break;
333 }
334 } while(!done);
335 } else if(*fmt == '\\') {
336 fmt++;
337 if(*fmt == 'r') {
338 putc('\r');
339 } else if(*fmt == 'n') {
340 putc('\n');
341 }
342 } else {
343 putc(*fmt);
344 }
345 fmt++;
346 } while(*fmt != 0);
347
348 return 0;
349 }
350
351 int printf(const char *fmt, ...)
352 {
353 va_list ap;
354 int i;
355
356 va_start(ap, fmt);
357 i = hvfprintf(fmt, ap);
358 va_end(ap);
359
360 return i;
361 }
This page took 0.07841 seconds and 5 git commands to generate.