📄 uart.c
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the EM86XX boot loader *//* * uart.c * * UART Input/Output * * modified from jasper boot loader by Ho Lee 12/10/2002 */#include "config.h"#include "uart.h"#include "io.h"#include "em86xxapi.h"#include "util.h"#include "vsprintf.h"#ifdef CONFIG_ENABLE_FIP#include "ide.h"#include "fip.h"#endif// global variablesstatic unsigned int g_uartbase = (DEFAULT_UART_PORT == 0) ? UART0_BASE : UART1_BASE;static int g_baudrate = DEFAULT_UART_BAUDRATE;// function prototypesvoid uart_init(void);void uart_init_port(int port, int baudrate, int fifo);static int uart_getclkdiv(int baudrate);void uart_putc(int ch);void uart_puts(const char *t);void uart_putns(const char *t, int maxlen);int uart_printf(const char *fmt, ...);void uart_printbyte(unsigned int data);void uart_printshort(unsigned int data);void uart_printlong(unsigned int data);int uart_peekc(void);int uart_getc(void);char *uart_gets_raw(char *str, int maxlen);char *uart_gets(char *str, int maxlen, int flag);char *uart_getcmd(char *str);//// UART initialization//void uart_init(void){ uart_init_port(0, DEFAULT_UART_BAUDRATE, 1); uart_init_port(1, DEFAULT_UART_BAUDRATE, 1);}void uart_init_port(int port, int baudrate, int fifo){ unsigned int base = (port == 0) ? UART0_BASE : UART1_BASE; int lcr, clkdiv = uart_getclkdiv(baudrate); unsigned int dummy; g_baudrate = baudrate; dummy = __raw_readl(base + UART_MSR); /* Clear Modem interrupt */ lcr = (DEFAULT_UART_DATABITS - 5); if (DEFAULT_UART_STOPBITS == 2) lcr |= UART_LCR_STOP; lcr |= DEFAULT_UART_PARITY; __raw_writel(0x00, base + UART_IER); // IRQ ENABL: all disabled if (fifo) __raw_writel(0x1f, base + UART_FCR); // FIFO CTRL: depth=16, clear rec & transm. FIFO, Tx.Trig = 4bytes else __raw_writel(0x00, base + UART_FCR); // FIFO CTRL: diable FIFO __raw_writel(lcr, base + UART_LCR); // LINE CTRL: #ifdef CONFIG_USE_SYSCLK __raw_writel(0x00, base + UART_CLKSEL); // CLK SEL : SELECT INTERNAL CLOCK#else __raw_writel(0x01, base + UART_CLKSEL); // CLK SEL : SELECT EXTERNAL CLOCK#endif __raw_writel(clkdiv, base + UART_CLKDIV); // CLK DIV : DEVIDED according to PLL Speed}void uart_reset(void){ uart_init_port(0, g_baudrate, 1); uart_init_port(1, g_baudrate, 1);}int uart_getclkdiv(int baudrate){ int clkdiv; unsigned long speed;#ifdef CONFIG_USE_SYSCLK speed = em86xx_getclock() >> 1;#else speed = EM86XX_EXT_CLOCK;#endif // clkdiv = speed / (baudrate * 16) // no divide instruction for (clkdiv = 0; (long) speed > 0; speed -= (baudrate << 4)) ++clkdiv; return clkdiv;}//// UART output//void uart_putc(int ch){ while ((__raw_readl(g_uartbase + UART_LSR) & 0x20) == 0) ; __raw_writel(ch, g_uartbase + UART_TBR); while ((__raw_readl(g_uartbase + UART_LSR) & 0x20) == 0) ;}void uart_puts(const char *t){ while (*t) { if (*t == '\n') uart_putc('\r'); uart_putc(*t++); }}void uart_putns(const char *t, int maxlen){ while (maxlen-- && *t) { if (*t == '\n') uart_putc('\r'); uart_putc(*t++); }}int uart_printf(const char *fmt, ...){ char buf[256]; va_list args; int i; va_start(args, fmt); i = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ va_end(args); uart_puts(buf); return i;}static char g_hextab[] = "0123456789ABCDEF";void uart_printbyte(unsigned int data){ char str[2]; str[0] = g_hextab[(data >> 4) & 0xF]; str[1] = g_hextab[(data) & 0xF]; uart_putns(str, 2);}void uart_printshort(unsigned int data){ char str[4]; str[0] = g_hextab[(data >> 12) & 0xF]; str[1] = g_hextab[(data >> 8) & 0xF]; str[2] = g_hextab[(data >> 4) & 0xF]; str[3] = g_hextab[(data) & 0xF]; uart_putns(str, 4);}void uart_printlong(unsigned int data){ char str[8]; str[0] = g_hextab[(data >> 28) & 0xF]; str[1] = g_hextab[(data >> 24) & 0xF]; str[2] = g_hextab[(data >> 20) & 0xF]; str[3] = g_hextab[(data >> 16) & 0xF]; str[4] = g_hextab[(data >> 12) & 0xF]; str[5] = g_hextab[(data >> 8) & 0xF]; str[6] = g_hextab[(data >> 4) & 0xF]; str[7] = g_hextab[(data) & 0xF]; uart_putns(str,8);}void uart_printint(int data){ char str[32], *cp = str + sizeof str - 1; *cp = 0; do { *--cp = (data % 10) + '0'; data /= 10; } while (data != 0); uart_puts(cp);}//// UART input//static int s_ungetc = 0;int uart_peekc(void){ if (__raw_readl(g_uartbase + UART_LSR) & 0x01) return __raw_readl(g_uartbase + UART_RBR); else return -1;}int uart_getc(void){#if defined(CONFIG_ENABLE_FIP) && defined(CONFIG_ENABLE_IDE) extern int downloading; unsigned long key = 0;#endif if (s_ungetc > 0) { int ch = s_ungetc; s_ungetc = 0; return ch; } while ((__raw_readl(g_uartbase + UART_LSR) & 0x01) == 0) {#if defined(CONFIG_ENABLE_FIP) && defined(CONFIG_ENABLE_IDE) if (downloading == 0) { key = fip_readkey(); /* See if any buttons is pressed */ if (key == FIP_KEY_W1) /* Ejecting the CD *///by lai 20080619 ide_cdrom_eject(0, key); }#endif ; } return __raw_readl(g_uartbase + UART_RBR);}void uart_ungetc(int ch){ s_ungetc = ch;}char *uart_gets_raw(char *str, int maxlen){ int pos = 0; int ch; if (maxlen < 0) maxlen = 256; for (;;) { ch = uart_getc(); if (pos < maxlen - 2) str[pos++] = ch; if (ch == '\r' || ch == '\n') break; } str[pos] = 0; return str;}char *uart_gets(char *str, int maxlen, int flag){ int pos = 0; int ch; if (maxlen < 0) maxlen = 256; if (flag & GETSTR_APPEND) { while (str[pos] != 0) { if (flag & GETSTR_APPENDDISP) uart_putc(str[pos]); ++pos; } } for (;;) { ch = uart_getc(); // escape sequence (0x1b, ...) if (ch == 0x1b) { if (flag & GETSTR_ESCAPE) { str[pos] = 0; return NULL; } } if (ch == 0x7f) // DEL ch = '\b'; else if (ch == '\n') ch = '\r'; if (ch != '\b') uart_putc(ch); if (ch == '\r') { uart_putc('\n'); break; } else if (ch == '\b') { if (pos > 0) { --pos; uart_putc(ch); uart_putc(' '); uart_putc(ch); } } else { if (pos < maxlen - 2) str[pos++] = ch; } } str[pos] = 0; return str;}#define GETCMD_MAXBUF 32#define GETCMD_MAXLEN 512char *uart_getcmd(char *str){ static char s_cmdbuf[GETCMD_MAXBUF][GETCMD_MAXLEN]; static int s_cmdnum = 0; int i, ch, len, cmdpos = s_cmdnum; int flag = GETSTR_ESCAPE | GETSTR_APPEND; str[0] = 0; while (uart_gets(str, GETCMD_MAXLEN, flag) == NULL) { // get the escape sequence ch = uart_getc(); if (ch != 0x5b) continue; ch = uart_getc(); if (ch == 0x33) { ch = uart_getc(); if (ch == 0x7e) // DEL uart_ungetc('\b'); continue; } else if (ch == 0x41) { // up if (cmdpos == 0) continue; --cmdpos; } else if (ch == 0x42) { // down if (cmdpos == s_cmdnum) continue; ++cmdpos; } else continue; // clear line for (len = strlen(str); len > 0; --len) { uart_putc('\b'); uart_putc(' '); uart_putc('\b'); } // redisplay line if (cmdpos == s_cmdnum) str[0] = 0; else { strcpy(str, s_cmdbuf[cmdpos]); uart_puts(str); } } if (str[0] != 0) { // process '!' history if (str[0] == '!') { for (i = s_cmdnum - 1; i >= 0; --i) if (strncmp(s_cmdbuf[i], str + 1, strlen(str) - 1) == 0) { strcpy(str, s_cmdbuf[i]); break; } } // append new command if (s_cmdnum > 0 && strcmp(s_cmdbuf[s_cmdnum - 1], str) == 0) ; else if (s_cmdnum == GETCMD_MAXBUF) { for (i = 0; i < GETCMD_MAXBUF - 1; ++i) strcpy(s_cmdbuf[i], s_cmdbuf[i + 1]); } else ++s_cmdnum; strcpy(s_cmdbuf[s_cmdnum - 1], str); } return str;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -