openwrt-owl/target/linux/at91/image/dfboot/src/com.c

369 lines
7.3 KiB
C

/*----------------------------------------------------------------------------
* 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 */
#define MAX_UARTS 1
//unsigned int usa[2] = {(unsigned int)AT91C_BASE_DBGU, (unsigned int)AT91C_ALTERNATE_USART};
unsigned int usa[1] = {(unsigned int)AT91C_BASE_DBGU};
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<MAX_UARTS; 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 0
if (!port_detected) {
if (us == usa[0]) {
us = usa[1];
}
else {
us = usa[0];
}
}
#endif
if(AT91F_US_RxReady((AT91PS_USART)us)) {
#if 0
port_detected = 1;
#endif
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("<NULL>");
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;
}