Update uart.c

This commit is contained in:
Bernard Xiong 2015-10-30 17:19:53 +08:00
parent bb5f57f91c
commit 59653699b2
1 changed files with 228 additions and 227 deletions

View File

@ -17,308 +17,309 @@
#include <rtthread.h> #include <rtthread.h>
#include "LPC17xx.h" #include "LPC17xx.h"
#define IER_RBR 0x01 #define IER_RBR 0x01
#define IER_THRE 0x02 #define IER_THRE 0x02
#define IER_RLS 0x04 #define IER_RLS 0x04
#define IIR_PEND 0x01 #define IIR_PEND 0x01
#define IIR_RLS 0x03 #define IIR_RLS 0x03
#define IIR_RDA 0x02 #define IIR_RDA 0x02
#define IIR_CTI 0x06 #define IIR_CTI 0x06
#define IIR_THRE 0x01 #define IIR_THRE 0x01
#define LSR_RDR 0x01 #define LSR_RDR 0x01
#define LSR_OE 0x02 #define LSR_OE 0x02
#define LSR_PE 0x04 #define LSR_PE 0x04
#define LSR_FE 0x08 #define LSR_FE 0x08
#define LSR_BI 0x10 #define LSR_BI 0x10
#define LSR_THRE 0x20 #define LSR_THRE 0x20
#define LSR_TEMT 0x40 #define LSR_TEMT 0x40
#define LSR_RXFE 0x80 #define LSR_RXFE 0x80
/** /**
* @addtogroup LPC11xx * @addtogroup LPC176x
*/ */
/*@{*/ /*@{*/
#if defined(RT_USING_UART0) && defined(RT_USING_DEVICE) #if defined(RT_USING_UART0) && defined(RT_USING_DEVICE)
#define UART_BAUDRATE 115200 #define UART_BAUDRATE 115200
#define LPC_UART LPC_UART0 #define LPC_UART LPC_UART0
#define UART_IRQn UART0_IRQn #define UART_IRQn UART0_IRQn
struct rt_uart_lpc struct rt_uart_lpc
{ {
struct rt_device parent; struct rt_device parent;
/* buffer for reception */ /* buffer for reception */
rt_uint8_t read_index, save_index; rt_uint8_t read_index, save_index;
rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE];
}uart_device; } uart_device;
void UART0_IRQHandler(void) void UART0_IRQHandler(void)
{ {
rt_ubase_t level, iir; rt_ubase_t level, iir;
struct rt_uart_lpc* uart = &uart_device; struct rt_uart_lpc *uart = &uart_device;
/* read IIR and clear it */ /* read IIR and clear it */
iir = LPC_UART->IIR; iir = LPC_UART->IIR;
iir >>= 1; /* skip pending bit in IIR */ iir >>= 1; /* skip pending bit in IIR */
iir &= 0x07; /* check bit 1~3, interrupt identification */ iir &= 0x07; /* check bit 1~3, interrupt identification */
if (iir == IIR_RDA) /* Receive Data Available */ if (iir == IIR_RDA) /* Receive Data Available */
{ {
/* Receive Data Available */ /* Receive Data Available */
uart->rx_buffer[uart->save_index] = LPC_UART->RBR; uart->rx_buffer[uart->save_index] = LPC_UART->RBR;
level = rt_hw_interrupt_disable(); level = rt_hw_interrupt_disable();
uart->save_index ++; uart->save_index ++;
if (uart->save_index >= RT_UART_RX_BUFFER_SIZE) if (uart->save_index >= RT_UART_RX_BUFFER_SIZE)
uart->save_index = 0; uart->save_index = 0;
rt_hw_interrupt_enable(level); rt_hw_interrupt_enable(level);
/* invoke callback */ /* invoke callback */
if(uart->parent.rx_indicate != RT_NULL) if (uart->parent.rx_indicate != RT_NULL)
{ {
rt_size_t length; rt_size_t length;
if (uart->read_index > uart->save_index) if (uart->read_index > uart->save_index)
length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index; length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index;
else else
length = uart->save_index - uart->read_index; length = uart->save_index - uart->read_index;
uart->parent.rx_indicate(&uart->parent, length); uart->parent.rx_indicate(&uart->parent, length);
} }
}else if(iir == IIR_RLS) }
{ else if (iir == IIR_RLS)
iir = LPC_Uart->LSR; //oe pe fe oe read for clear interrupt {
} iir = LPC_UART->LSR; //oe pe fe oe read for clear interrupt
}
return; return;
} }
static rt_err_t rt_uart_init (rt_device_t dev) static rt_err_t rt_uart_init(rt_device_t dev)
{ {
rt_uint32_t Fdiv; rt_uint32_t Fdiv;
rt_uint32_t pclkdiv, pclk; rt_uint32_t pclkdiv, pclk;
/* Init UART Hardware */ /* Init UART Hardware */
if (LPC_UART == LPC_UART0) if (LPC_UART == LPC_UART0)
{ {
LPC_PINCON->PINSEL0 &= ~0x000000F0; LPC_PINCON->PINSEL0 &= ~0x000000F0;
LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 is P0.3 and TxD0 is P0.2 */ LPC_PINCON->PINSEL0 |= 0x00000050; /* RxD0 is P0.3 and TxD0 is P0.2 */
/* By default, the PCLKSELx value is zero, thus, the PCLK for /* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */ all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 6~7 is for UART0 */ /* Bit 6~7 is for UART0 */
pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03; pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
switch ( pclkdiv ) switch (pclkdiv)
{ {
case 0x00: case 0x00:
default: default:
pclk = SystemCoreClock/4; pclk = SystemCoreClock / 4;
break; break;
case 0x01: case 0x01:
pclk = SystemCoreClock; pclk = SystemCoreClock;
break; break;
case 0x02: case 0x02:
pclk = SystemCoreClock/2; pclk = SystemCoreClock / 2;
break; break;
case 0x03: case 0x03:
pclk = SystemCoreClock/8; pclk = SystemCoreClock / 8;
break; break;
} }
LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
Fdiv = ( pclk / 16 ) / UART_BAUDRATE; /*baud rate */
LPC_UART0->DLM = Fdiv / 256;
LPC_UART0->DLL = Fdiv % 256;
LPC_UART0->LCR = 0x03; /* DLAB = 0 */
LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
}
else if ((LPC_UART1_TypeDef*)LPC_UART == LPC_UART1)
{
LPC_PINCON->PINSEL4 &= ~0x0000000F;
LPC_PINCON->PINSEL4 |= 0x0000000A; /* Enable RxD1 P2.1, TxD1 P2.0 */
/* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 8,9 are for UART1 */
pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
switch ( pclkdiv )
{
case 0x00:
default:
pclk = SystemCoreClock/4;
break;
case 0x01:
pclk = SystemCoreClock;
break;
case 0x02:
pclk = SystemCoreClock/2;
break;
case 0x03:
pclk = SystemCoreClock/8;
break;
}
LPC_UART1->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
Fdiv = ( pclk / 16 ) / UART_BAUDRATE ; /*baud rate */
LPC_UART1->DLM = Fdiv / 256;
LPC_UART1->DLL = Fdiv % 256;
LPC_UART1->LCR = 0x03; /* DLAB = 0 */
LPC_UART1->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
}
/* Ensure a clean start, no data in either TX or RX FIFO. */ LPC_UART0->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) ); Fdiv = (pclk / 16) / UART_BAUDRATE; /*baud rate */
while ( LPC_UART->LSR & LSR_RDR ) LPC_UART0->DLM = Fdiv / 256;
{ LPC_UART0->DLL = Fdiv % 256;
Fdiv = LPC_UART->RBR; /* Dump data from RX FIFO */ LPC_UART0->LCR = 0x03; /* DLAB = 0 */
} LPC_UART0->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */ }
else if ((LPC_UART1_TypeDef *)LPC_UART == LPC_UART1)
{
LPC_PINCON->PINSEL4 &= ~0x0000000F;
LPC_PINCON->PINSEL4 |= 0x0000000A; /* Enable RxD1 P2.1, TxD1 P2.0 */
return RT_EOK; /* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
/* Bit 8,9 are for UART1 */
pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
switch (pclkdiv)
{
case 0x00:
default:
pclk = SystemCoreClock / 4;
break;
case 0x01:
pclk = SystemCoreClock;
break;
case 0x02:
pclk = SystemCoreClock / 2;
break;
case 0x03:
pclk = SystemCoreClock / 8;
break;
}
LPC_UART1->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */
Fdiv = (pclk / 16) / UART_BAUDRATE ; /*baud rate */
LPC_UART1->DLM = Fdiv / 256;
LPC_UART1->DLL = Fdiv % 256;
LPC_UART1->LCR = 0x03; /* DLAB = 0 */
LPC_UART1->FCR = 0x07; /* Enable and reset TX and RX FIFO. */
}
/* Ensure a clean start, no data in either TX or RX FIFO. */
while ((LPC_UART->LSR & (LSR_THRE | LSR_TEMT)) != (LSR_THRE | LSR_TEMT));
while (LPC_UART->LSR & LSR_RDR)
{
Fdiv = LPC_UART->RBR; /* Dump data from RX FIFO */
}
LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */
return RT_EOK;
} }
static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag) static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag)
{ {
RT_ASSERT(dev != RT_NULL); RT_ASSERT(dev != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX) if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{ {
/* Enable the UART Interrupt */ /* Enable the UART Interrupt */
NVIC_EnableIRQ(UART_IRQn); NVIC_EnableIRQ(UART_IRQn);
} }
return RT_EOK; return RT_EOK;
} }
static rt_err_t rt_uart_close(rt_device_t dev) static rt_err_t rt_uart_close(rt_device_t dev)
{ {
RT_ASSERT(dev != RT_NULL); RT_ASSERT(dev != RT_NULL);
if (dev->flag & RT_DEVICE_FLAG_INT_RX) if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{ {
/* Disable the UART Interrupt */ /* Disable the UART Interrupt */
NVIC_DisableIRQ(UART_IRQn); NVIC_DisableIRQ(UART_IRQn);
} }
return RT_EOK; return RT_EOK;
} }
static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{ {
rt_uint8_t* ptr; rt_uint8_t *ptr;
struct rt_uart_lpc *uart = (struct rt_uart_lpc*)dev; struct rt_uart_lpc *uart = (struct rt_uart_lpc *)dev;
RT_ASSERT(uart != RT_NULL); RT_ASSERT(uart != RT_NULL);
/* point to buffer */ /* point to buffer */
ptr = (rt_uint8_t*) buffer; ptr = (rt_uint8_t *) buffer;
if (dev->flag & RT_DEVICE_FLAG_INT_RX) if (dev->flag & RT_DEVICE_FLAG_INT_RX)
{ {
while (size) while (size)
{ {
/* interrupt receive */ /* interrupt receive */
rt_base_t level; rt_base_t level;
/* disable interrupt */ /* disable interrupt */
level = rt_hw_interrupt_disable(); level = rt_hw_interrupt_disable();
if (uart->read_index != uart->save_index) if (uart->read_index != uart->save_index)
{ {
*ptr = uart->rx_buffer[uart->read_index]; *ptr = uart->rx_buffer[uart->read_index];
uart->read_index ++; uart->read_index ++;
if (uart->read_index >= RT_UART_RX_BUFFER_SIZE) if (uart->read_index >= RT_UART_RX_BUFFER_SIZE)
uart->read_index = 0; uart->read_index = 0;
} }
else else
{ {
/* no data in rx buffer */ /* no data in rx buffer */
/* enable interrupt */ /* enable interrupt */
rt_hw_interrupt_enable(level); rt_hw_interrupt_enable(level);
break; break;
} }
/* enable interrupt */ /* enable interrupt */
rt_hw_interrupt_enable(level); rt_hw_interrupt_enable(level);
ptr ++; ptr ++;
size --; size --;
} }
return (rt_uint32_t)ptr - (rt_uint32_t)buffer; return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
} }
return 0; return 0;
} }
static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{ {
char *ptr; char *ptr;
ptr = (char*)buffer; ptr = (char *)buffer;
if (dev->flag & RT_DEVICE_FLAG_STREAM) if (dev->flag & RT_DEVICE_FLAG_STREAM)
{ {
/* stream mode */ /* stream mode */
while (size) while (size)
{ {
if (*ptr == '\n') if (*ptr == '\n')
{ {
/* THRE status, contain valid data */ /* THRE status, contain valid data */
while ( !(LPC_UART->LSR & LSR_THRE) ); while (!(LPC_UART->LSR & LSR_THRE));
/* write data */ /* write data */
LPC_UART->THR = '\r'; LPC_UART->THR = '\r';
} }
/* THRE status, contain valid data */ /* THRE status, contain valid data */
while ( !(LPC_UART->LSR & LSR_THRE) ); while (!(LPC_UART->LSR & LSR_THRE));
/* write data */ /* write data */
LPC_UART->THR = *ptr; LPC_UART->THR = *ptr;
ptr ++;
size --;
}
}
else
{
while ( size != 0 )
{
/* THRE status, contain valid data */
while ( !(LPC_UART->LSR & LSR_THRE) );
/* write data */
LPC_UART->THR = *ptr;
ptr++;
size--;
}
}
return (rt_size_t) ptr - (rt_size_t) buffer; ptr ++;
size --;
}
}
else
{
while (size != 0)
{
/* THRE status, contain valid data */
while (!(LPC_UART->LSR & LSR_THRE));
/* write data */
LPC_UART->THR = *ptr;
ptr++;
size--;
}
}
return (rt_size_t) ptr - (rt_size_t) buffer;
} }
void rt_hw_uart_init(void) void rt_hw_uart_init(void)
{ {
struct rt_uart_lpc* uart; struct rt_uart_lpc *uart;
/* get uart device */ /* get uart device */
uart = &uart_device; uart = &uart_device;
/* device initialization */ /* device initialization */
uart->parent.type = RT_Device_Class_Char; uart->parent.type = RT_Device_Class_Char;
rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer)); rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer));
uart->read_index = uart->save_index = 0; uart->read_index = uart->save_index = 0;
/* device interface */ /* device interface */
uart->parent.init = rt_uart_init; uart->parent.init = rt_uart_init;
uart->parent.open = rt_uart_open; uart->parent.open = rt_uart_open;
uart->parent.close = rt_uart_close; uart->parent.close = rt_uart_close;
uart->parent.read = rt_uart_read; uart->parent.read = rt_uart_read;
uart->parent.write = rt_uart_write; uart->parent.write = rt_uart_write;
uart->parent.control = RT_NULL; uart->parent.control = RT_NULL;
uart->parent.user_data = RT_NULL; uart->parent.user_data = RT_NULL;
rt_device_register(&uart->parent, rt_device_register(&uart->parent,
"uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX); "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STREAM | RT_DEVICE_FLAG_INT_RX);
} }
#endif /* end of UART */ #endif /* end of UART */