From 3dd37ea0658ef033aa1bc20963e03e14b9b6e512 Mon Sep 17 00:00:00 2001 From: Hamish Guthrie Date: Mon, 4 Jun 2007 17:41:40 +0000 Subject: add new dfboot loader - a complete revison of romboot code. git-svn-id: svn://svn.openwrt.org/openwrt/trunk@7492 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/at91-2.6/image/dfboot/src/com.c | 361 +++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 target/linux/at91-2.6/image/dfboot/src/com.c (limited to 'target/linux/at91-2.6/image/dfboot/src/com.c') diff --git a/target/linux/at91-2.6/image/dfboot/src/com.c b/target/linux/at91-2.6/image/dfboot/src/com.c new file mode 100644 index 0000000000..38a2898f7e --- /dev/null +++ b/target/linux/at91-2.6/image/dfboot/src/com.c @@ -0,0 +1,361 @@ +/*---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support - ROUSSET - + *---------------------------------------------------------------------------- + * The software is delivered "AS IS" without warranty or condition of any + * kind, either express, implied or statutory. This includes without + * limitation any warranty or condition with respect to merchantability or + * fitness for any particular purpose, or against the infringements of + * intellectual property rights of others. + *---------------------------------------------------------------------------- + * File Name : com.c + * Object : + * Creation : HIi 03/27/2003 + * + *---------------------------------------------------------------------------- + */ +#include "AT91RM9200.h" +#include "lib_AT91RM9200.h" +#include "config.h" +#include "com.h" +#include "stdio.h" + +static char erase_seq[] = "\b \b"; /* erase sequence */ + +unsigned int usa[2] = {(unsigned int)AT91C_BASE_DBGU, (unsigned int)AT91C_ALTERNATE_USART}; +unsigned int us; +int port_detected; + +void at91_init_uarts(void) +{ + int i; + + port_detected = 0; + AT91F_DBGU_CfgPIO(); + AT91F_US0_CfgPIO(); + AT91F_US0_CfgPMC(); + + for(i=0; i<2; i++) { + us = usa[i]; + AT91F_US_ResetRx((AT91PS_USART)us); + AT91F_US_ResetTx((AT91PS_USART)us); + + // Configure DBGU + AT91F_US_Configure( + (AT91PS_USART)us, // DBGU base address + AT91C_MASTER_CLOCK, // 60 MHz + AT91C_US_ASYNC_MODE, // mode Register to be programmed + 115200, // baudrate to be programmed + 0 // timeguard to be programmed + ); + + // Enable Transmitter + AT91F_US_EnableTx((AT91PS_USART)us); + // Enable Receiver + AT91F_US_EnableRx((AT91PS_USART)us); + } + us = usa[0]; +} + +int at91_serial_putc(int ch) +{ + if (ch == '\n') + at91_serial_putc('\r'); + while (!AT91F_US_TxReady((AT91PS_USART)us)); + AT91F_US_PutChar((AT91PS_USART)us, (char)ch); + return ch; +} + +/* This getc is modified to be able work on more than one port. On certain + * boards (i.e. Figment Designs VersaLink), the debug port is not available + * once the unit is in it's enclosure, so, if one needs to get into dfboot + * for any reason it is impossible. With this getc, it scans between the debug + * port and another port and once it receives a character, it sets that port + * as the debug port. */ +int at91_serial_getc() +{ + while(1) { + if (!port_detected) { + if (us == usa[0]) { + us = usa[1]; + } + else { + us = usa[0]; + } + } + if(AT91F_US_RxReady((AT91PS_USART)us)) { + port_detected = 1; + return((int)AT91F_US_GetChar((AT91PS_USART)us)); + } + } +} + +/*----------------------------------------------------------------------------- + * Function Name : AT91F_ReadLine() + * Object : + * Input Parameters : + * Return value : + *----------------------------------------------------------------------------- + */ +int AT91F_ReadLine (const char *const prompt, char *console_buffer) +{ + char *p = console_buffer; + int n = 0; /* buffer index */ + int plen = strlen (prompt); /* prompt length */ + int col; /* output column cnt */ + char c; + + /* print prompt */ + if (prompt) + printf(prompt); + col = plen; + + for (;;) { + c = getc(); + + switch (c) { + case '\r': /* Enter */ + case '\n': + *p = '\0'; + puts ("\n"); + return (p - console_buffer); + + case 0x03: /* ^C - break */ + console_buffer[0] = '\0'; /* discard input */ + return (-1); + + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + if (n) { + --p; + printf(erase_seq); + col--; + n--; + } + continue; + + default: + /* + * Must be a normal character then + */ + if (n < (AT91C_CB_SIZE -2)) + { + ++col; /* echo input */ + putc(c); + *p++ = c; + ++n; + } + else + { /* Buffer full */ + putc('\a'); + } + } + } +} + + +/*----------------------------------------------------------------------------- + * Function Name : AT91F_WaitKeyPressed() + * Object : + * Input Parameters : + * Return value : + *----------------------------------------------------------------------------- + */ +void AT91F_WaitKeyPressed(void) +{ + int c; + puts("KEY"); + c = getc(); + putc('\n'); +} + +int puts(const char *str) +{ + while(*str != 0) { + at91_serial_putc(*str); + str++; + } + return 1; +} + +int putc(int c) +{ + return at91_serial_putc(c); +} + +int putchar(c) +{ + return putc(c); +} + +int getc() +{ + return at91_serial_getc(); +} + +int strlen(const char *str) +{ + int len = 0; + + if(str == (char *)0) + return 0; + + while(*str++ != 0) + len++; + + return len; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define LEFT 4 /* left justified */ +#define LARGE 8 /* use 'ABCDEF' instead of 'abcdef' */ + +#define do_div(n,base) ({ \ + int __res; \ + __res = ((unsigned) n) % (unsigned) base; \ + n = ((unsigned) n) / (unsigned) base; \ + __res; \ +}) + +static int number(int num, int base, int size, + int precision, int type) +{ + char c, sign, tmp[66]; + const char *digits="0123456789ABCDEF"; + int i; + + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 16) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + + if(type & SIGN && num < 0) + { + sign = '-'; + num = -num; + size--; + } + + i = 0; + if(num == 0) + tmp[i++] = digits[0]; + else while(num != 0) + tmp[i++] = digits[do_div(num, base)]; + + if(i > precision) + precision = i; + size -= precision; + + if(!(type&(ZEROPAD+LEFT))) + while(size-->0) + putc(' '); + + if(sign) + putc(sign); + + if (!(type & LEFT)) + while (size-- > 0) + putc(c); + + while (i < precision--) + putc('0'); + + while (i-- > 0) + putc(tmp[i]); + + while (size-- > 0) + putc(' ');; + + return 1; +} + +int hvfprintf(const char *fmt, va_list va) +{ + char *s; + + do { + if(*fmt == '%') { + bool done = false; + + int type = 0; + int precision = 0; + + do { + fmt++; + switch(*fmt) { + case '0' : + if(!precision) + type |= ZEROPAD; + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + precision = precision * 10 + (*fmt - '0'); + break; + case '.' : + break; + case 's' : + s = va_arg(va, char *); + if(!s) + puts(""); + else + puts(s); + done = true; + break; + case 'c' : + putc(va_arg(va, int)); + done = true; + break; + case 'd' : + number(va_arg(va, int), 10, 0, precision, type); + done = true; + break; + case 'x' : + case 'X' : + number(va_arg(va, int), 16, 0, precision, type); + done = true; + break; + case '%' : + putc(*fmt); + done = true; + default: + putc('%'); + putc(*fmt); + done = true; + break; + } + } while(!done); + } else if(*fmt == '\\') { + fmt++; + if(*fmt == 'r') { + putc('\r'); + } else if(*fmt == 'n') { + putc('\n'); + } + } else { + putc(*fmt); + } + fmt++; + } while(*fmt != 0); + + return 0; +} + +int printf(const char *fmt, ...) +{ + va_list ap; + int i; + + va_start(ap, fmt); + i = hvfprintf(fmt, ap); + va_end(ap); + + return i; +} -- cgit v1.2.3