aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/at91/image/dfboot/src/com.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/at91/image/dfboot/src/com.c')
-rw-r--r--target/linux/at91/image/dfboot/src/com.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/target/linux/at91/image/dfboot/src/com.c b/target/linux/at91/image/dfboot/src/com.c
new file mode 100644
index 000000000..aacfb5555
--- /dev/null
+++ b/target/linux/at91/image/dfboot/src/com.c
@@ -0,0 +1,368 @@
+/*----------------------------------------------------------------------------
+ * 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;
+}