diff --git a/bsp/lpc2478/board.c b/bsp/lpc2478/board.c index c68b8c1300..26059b5072 100644 --- a/bsp/lpc2478/board.c +++ b/bsp/lpc2478/board.c @@ -58,44 +58,6 @@ void rt_hw_board_init() T0TCR = 0x01; //enable timer0 counter } -#ifdef RT_USING_FINSH -extern void finsh_notify(void); -void rt_serial_isr(int vector) -{ - rt_uint32_t iir; - - if (U0LSR & 0x01) - { - rt_uint8_t ch; - - while (U0LSR & 0x01) - { - ch = U0RBR; - rt_serial_savechar(ch); - } - - /* notify finsh shell thread */ - finsh_notify(); - } - - /* clear interrupt source */ - iir = U0IIR; - - /* acknowledge Interrupt */ - VICVectAddr = 0; -} - -void rt_hw_finsh_init() -{ - /* init UART rx interrupt */ - U0IER = 0x01; - - /* install UART isr */ - rt_hw_interrupt_install(UART0_INT, rt_serial_isr, RT_NULL); - rt_hw_interrupt_umask(UART0_INT); -} -#endif - /****************************************************************************** ** Function name: TargetInit ** diff --git a/bsp/lpc2478/board.h b/bsp/lpc2478/board.h index 8aa9ee1aa8..2f9bf8b7e9 100644 --- a/bsp/lpc2478/board.h +++ b/bsp/lpc2478/board.h @@ -98,6 +98,9 @@ void rt_hw_finsh_init(void); #define VECT_ADDR_INDEX 0x100 #define VECT_CNTL_INDEX 0x200 + +#define CCLK 60000000 /* Fosc = 12MHz, M = 5 */ +#define PCLK 15000000 /* CCLK/4, use default */ /****************************************************************************** ** Function name: TargetInit diff --git a/bsp/lpc2478/rtconfig.h b/bsp/lpc2478/rtconfig.h index 700d6a4ec1..249945b009 100644 --- a/bsp/lpc2478/rtconfig.h +++ b/bsp/lpc2478/rtconfig.h @@ -9,7 +9,7 @@ #define RT_ALIGN_SIZE 4 /* PRIORITY_MAX*/ -#define RT_THREAD_PRIORITY_MAX 32 +#define RT_THREAD_PRIORITY_MAX 256 /* Tick per Second*/ #define RT_TICK_PER_SECOND 100 @@ -55,7 +55,9 @@ /* SECTION: Device System */ /* Using Device System*/ -/* #define RT_USING_DEVICE */ +#define RT_USING_DEVICE +#define RT_USING_UART1 +#define RT_UART_RX_BUFFER_SIZE 64 /* SECTION: Console options */ /* the buffer size of console*/ @@ -68,10 +70,6 @@ #define FINSH_USING_SYMTAB #define FINSH_USING_DESCRIPTION -/* SECTION: emulator options */ -/* Using QEMU or SkyEye*/ -/* #define RT_USING_EMULATOR */ - /* SECTION: a mini libc */ /* Using mini libc library*/ /* #define RT_USING_MINILIBC */ diff --git a/libcpu/arm/lpc24xx/serial.c b/libcpu/arm/lpc24xx/serial.c index d3960a5e00..4bfa7614e9 100644 --- a/libcpu/arm/lpc24xx/serial.c +++ b/libcpu/arm/lpc24xx/serial.c @@ -1,149 +1,387 @@ -/* - * File : serial.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006, RT-Thread Development Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://openlab.rt-thread.com/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2006-08-23 Bernard first version - */ - -#include +/* + * File : serial.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://openlab.rt-thread.com/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2006-08-23 Bernard first version + */ + +#include #include + #include "lpc214x.h" #include "board.h" -void rt_serial_init(void); +/* serial hardware register */ +#define REG8(d) (*((volatile unsigned char *)(d))) +#define REG32(d) (*((volatile unsigned long *)(d))) -#define PCLK 18000000 -#define BAUD_RATE 115200 +#define UART_RBR(base) REG8(base + 0x00) +#define UART_THR(base) REG8(base + 0x00) +#define UART_IER(base) REG32(base + 0x04) +#define UART_IIR(base) REG32(base + 0x08) +#define UART_FCR(base) REG8(base + 0x08) +#define UART_LCR(base) REG8(base + 0x0C) +#define UART_MCR(base) REG8(base + 0x10) +#define UART_LSR(base) REG8(base + 0x14) +#define UART_MSR(base) REG8(base + 0x18) +#define UART_SCR(base) REG8(base + 0x1C) +#define UART_DLL(base) REG8(base + 0x00) +#define UART_DLM(base) REG8(base + 0x04) +#define UART_ACR(base) REG32(base + 0x20) +#define UART_FDR(base) REG32(base + 0x28) +#define UART_TER(base) REG8(base + 0x30) + +/* LPC serial device */ +struct rt_lpcserial +{ + /* inherit from device */ + struct rt_device parent; + + rt_uint32_t hw_base; + rt_uint32_t irqno; + rt_uint32_t baudrate; + + /* reception field */ + rt_uint16_t save_index, read_index; + rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; +}; + +#ifdef RT_USING_UART1 +struct rt_lpcserial serial1; +#endif +#ifdef RT_USING_UART2 +struct rt_lpcserial serial2; +#endif + +void rt_hw_serial_init(void); + #define U0PINS 0x00000005 -/** - * @addtogroup LPC2100 - */ +void rt_hw_uart_isr(struct rt_lpcserial* lpc_serial) +{ + UNUSED rt_uint32_t iir; + + RT_ASSERT(lpc_serial != RT_NULL) + + if (UART_LSR(lpc_serial->hw_base) & 0x01) + { + rt_base_t level; + + while (UART_LSR(lpc_serial->hw_base) & 0x01) + { + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + /* read character */ + lpc_serial->rx_buffer[lpc_serial->save_index] = + UART_RBR(lpc_serial->hw_base); + lpc_serial->save_index ++; + if (lpc_serial->save_index >= RT_UART_RX_BUFFER_SIZE) + lpc_serial->save_index = 0; + + /* if the next position is read index, discard this 'read char' */ + if (lpc_serial->save_index == lpc_serial->read_index) + { + lpc_serial->read_index ++; + if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE) + lpc_serial->read_index = 0; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + } + + /* invoke callback */ + if(lpc_serial->parent.rx_indicate != RT_NULL) + { + lpc_serial->parent.rx_indicate(&lpc_serial->parent, 1); + } + } + + /* clear interrupt source */ + iir = UART_IIR(lpc_serial->hw_base); + + /* acknowledge Interrupt */ + VICVectAddr = 0; +} + +#ifdef RT_USING_UART1 +void rt_hw_uart_isr_1(int irqno) +{ + /* get lpc serial device */ + rt_hw_uart_isr(&serial1); +} +#endif + +#ifdef RT_USING_UART2 +void rt_hw_uart_isr_2(int irqno) +{ + /* get lpc serial device */ + rt_hw_uart_isr(&serial2); +} +#endif + +/** + * @addtogroup LPC214x + */ /*@{*/ - -/** - * This function is used to display a string on console, normally, it's - * invoked by rt_kprintf - * - * @param str the displayed string - */ -void rt_console_puts(const char* str) + +static rt_err_t rt_serial_init (rt_device_t dev) { - while (*str) - { - rt_serial_putc (*str++); - } + return RT_EOK; } - -#define UART_RX_BUFFER_SIZE 64 -static rt_uint8_t uart_rx_buffer[UART_RX_BUFFER_SIZE]; -static rt_uint32_t uart_read_index, uart_save_index; - -/** - * This function initializes serial - */ -void rt_serial_init() + +static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag) { - unsigned long Fdiv; - - PINSEL0 = 0x00000050; /* RxD0 and TxD0 */ - - rt_memset(uart_rx_buffer, 0, sizeof(uart_rx_buffer)); - uart_read_index = uart_save_index = 0; - - U0LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ - /*PCLK select is 00,so /4*/ - Fdiv = ( PCLK / 16 ) / BAUD_RATE ; /*baud rate */ - U0DLM = Fdiv / 256; - U0DLL = Fdiv % 256; - U0FCR = 0x00; /* Enable and reset TX and RX FIFO. */ - U0LCR = 0x03; /* DLAB = 0 */ -} - -/* save a char to serial buffer */ -void rt_serial_savechar(char ch) -{ - rt_base_t level; + struct rt_lpcserial* lpc_serial; + lpc_serial = (struct rt_lpcserial*) dev; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - uart_rx_buffer[uart_save_index] = ch; - uart_save_index ++; - if (uart_save_index >= UART_RX_BUFFER_SIZE) - uart_save_index = 0; - - /* if the next position is read index, discard this 'read char' */ - if (uart_save_index == uart_read_index) + RT_ASSERT(lpc_serial != RT_NULL); + if (dev->flag & RT_DEVICE_FLAG_INT_RX) { - uart_read_index ++; - if (uart_read_index >= UART_RX_BUFFER_SIZE) - uart_read_index = 0; + /* init UART rx interrupt */ + UART_IER(lpc_serial->hw_base) = 0x01; + + /* install ISR */ + if (lpc_serial->irqno == UART0_INT) + { +#ifdef RT_USING_UART1 + rt_hw_interrupt_install(lpc_serial->irqno, rt_hw_uart_isr_1, RT_NULL); +#endif + } + else + { +#ifdef RT_USING_UART2 + rt_hw_interrupt_install(lpc_serial->irqno, rt_hw_uart_isr_2, RT_NULL); +#endif + } + + rt_hw_interrupt_umask(lpc_serial->irqno); } - /* enable interrupt */ - rt_hw_interrupt_enable(level); + return RT_EOK; } -/** - * This function read a character from serial without interrupt enable mode - * - * @return the read char - */ -char rt_serial_getc() +static rt_err_t rt_serial_close(rt_device_t dev) { - char ch; - rt_base_t level; + struct rt_lpcserial* lpc_serial; + lpc_serial = (struct rt_lpcserial*) dev; - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - - if (uart_read_index != uart_save_index) - { - ch = uart_rx_buffer[uart_read_index]; + RT_ASSERT(lpc_serial != RT_NULL); - uart_read_index ++; - if (uart_read_index >= UART_RX_BUFFER_SIZE) - uart_read_index = 0; + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* disable UART rx interrupt */ + UART_IER(lpc_serial->hw_base) = 0x00; + } + + return RT_EOK; +} + +static rt_err_t rt_serial_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + return RT_EOK; +} + +static rt_size_t rt_serial_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) +{ + rt_uint8_t* ptr; + struct rt_lpcserial *lpc_serial = (struct rt_lpcserial*)dev; + RT_ASSERT(lpc_serial != RT_NULL); + + /* point to buffer */ + ptr = (rt_uint8_t*) buffer; + + if (dev->flag & RT_DEVICE_FLAG_INT_RX) + { + while (size) + { + /* interrupt receive */ + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + if (lpc_serial->read_index != lpc_serial->save_index) + { + *ptr = lpc_serial->rx_buffer[lpc_serial->read_index]; + + lpc_serial->read_index ++; + if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE) + lpc_serial->read_index = 0; + } + else + { + /* no data in rx buffer */ + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + break; + } + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + ptr ++; size --; + } + + return (rt_uint32_t)ptr - (rt_uint32_t)buffer; + } + else if (dev->flag & RT_DEVICE_FLAG_DMA_RX) + { + /* not support right now */ + RT_ASSERT(0); + } + + /* polling mode */ + while (size && (UART_LSR(lpc_serial->hw_base) & 0x01)) + { + /* Read Character */ + *ptr = UART_RBR(lpc_serial->hw_base); - /* enable interrupt */ - rt_hw_interrupt_enable(level); - - return ch; + ptr ++; + size --; } - /* enable interrupt */ - rt_hw_interrupt_enable(level); - - return 0; + return (rt_size_t)ptr - (rt_size_t)buffer; } -/** - * This function will write a character to serial without interrupt enable mode - * - * @param c the char to write - */ -void rt_serial_putc(const char c) +static rt_size_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { - /* - to be polite with serial console add a line feed - to the carriage return character - */ - if (c=='\n') + struct rt_lpcserial* lpc_serial; + char *ptr; + + lpc_serial = (struct rt_lpcserial*) dev; + if (dev->flag & RT_DEVICE_FLAG_INT_TX) { - while (!(U0LSR & 0x20)); - U0THR = '\r'; + /* not support */ + RT_ASSERT(0); + } + else if (dev->flag & RT_DEVICE_FLAG_DMA_TX) + { + /* not support */ + RT_ASSERT(0); } - while (!(U0LSR & 0x20)); - U0THR = c; + /* polling write */ + ptr = (char *)buffer; + + if (dev->flag & RT_DEVICE_FLAG_STREAM) + { + /* stream mode */ + while (size) + { + if (*ptr == '\n') + { + while (!(UART_LSR(lpc_serial->hw_base) & 0x20)); + UART_THR(lpc_serial->hw_base) = '\r'; + } + + while (!(UART_LSR(lpc_serial->hw_base) & 0x20)); + UART_THR(lpc_serial->hw_base) = *ptr; + + ptr ++; + size --; + } + } + else + { + while (size) + { + while (!(UART_LSR(lpc_serial->hw_base) & 0x20)); + UART_THR(lpc_serial->hw_base) = *ptr; + + ptr ++; + size --; + } + } + + return (rt_size_t) ptr - (rt_size_t) buffer; } -/*@}*/ +void rt_hw_serial_init(void) +{ + struct rt_lpcserial* lpc_serial; + +#ifdef RT_USING_UART1 + lpc_serial = &serial1; + + lpc_serial->parent.type = RT_Device_Class_Char; + + lpc_serial->hw_base = 0xE000C000; + lpc_serial->baudrate = 115200; + lpc_serial->irqno = UART0_INT; + + rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer)); + lpc_serial->read_index = lpc_serial->save_index = 0; + + /* Enable UART0 RxD and TxD pins */ + PINSEL0 |= 0x05; + + /* 8 bits, no Parity, 1 Stop bit */ + UART_LCR(lpc_serial->hw_base) = 0x83; + + /* Setup Baudrate */ + UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF; + UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF; + + /* DLAB = 0 */ + UART_LCR(lpc_serial->hw_base) = 0x03; + + lpc_serial->parent.init = rt_serial_init; + lpc_serial->parent.open = rt_serial_open; + lpc_serial->parent.close = rt_serial_close; + lpc_serial->parent.read = rt_serial_read; + lpc_serial->parent.write = rt_serial_write; + lpc_serial->parent.control = rt_serial_control; + lpc_serial->parent.private = RT_NULL; + + rt_device_register(&lpc_serial->parent, + "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX); +#endif + +#ifdef RT_USING_UART2 + lpc_serial = &serial2; + + lpc_serial->parent.type = RT_Device_Class_Char; + + lpc_serial->hw_base = 0xE0010000; + lpc_serial->baudrate = 115200; + lpc_serial->irqno = UART1_INT; + + rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer)); + lpc_serial->read_index = lpc_serial->save_index = 0; + + /* Enable UART1 RxD and TxD pins */ + PINSEL0 |= 0x05 << 16; + + /* 8 bits, no Parity, 1 Stop bit */ + UART_LCR(lpc_serial->hw_base) = 0x83; + + /* Setup Baudrate */ + UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF; + UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF; + + /* DLAB = 0 */ + UART_LCR(lpc_serial->hw_base) = 0x03; + + lpc_serial->parent.init = rt_serial_init; + lpc_serial->parent.open = rt_serial_open; + lpc_serial->parent.close = rt_serial_close; + lpc_serial->parent.read = rt_serial_read; + lpc_serial->parent.write = rt_serial_write; + lpc_serial->parent.control = rt_serial_control; + lpc_serial->parent.private = RT_NULL; + + rt_device_register(&lpc_serial->parent, + "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX); +#endif +} + +/*@}*/