rt-thread/bsp/nuvoton_nuc472/drivers/usart.c

359 lines
8.6 KiB
C
Raw Normal View History

2017-12-17 12:08:31 +08:00
/*
* File : usart.c
* This file is part of RT-Thread RTOS
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2017-12-12 Bluebear233 first implementation
*/
#include <rtconfig.h>
#include <rtdevice.h>
#include <usart.h>
#include <NUC472_442.h>
/* Private Define ---------------------------------------------------------------*/
#define USEING_UART0 //Tx:PG2 Rx:PG1
/* Private Typedef --------------------------------------------------------------*/
struct usart
{
rt_serial_t dev;
UART_T *usart_base;
};
typedef struct usart* usart_t;
/* Private functions ------------------------------------------------------------*/
static rt_err_t usart_gpio_configure(struct rt_serial_device *serial);
static rt_err_t usart_configure(struct rt_serial_device *serial, struct serial_configure *cfg);
static rt_err_t usart_control(struct rt_serial_device *serial, int cmd, void *arg);
static int usart_send(struct rt_serial_device *serial, char c);
static int usart_receive(struct rt_serial_device *serial);
static void rt_hw_uart_register(usart_t uart, UART_T *uart_base,
char *name);
static void uart_isr(usart_t serial);
//static rt_err_t stm32_uart_tx_dma_configure(rt_stm32_uart_t *serial, rt_bool_t bool);
//static rt_err_t stm32_uart_tx_dma_nvic(rt_stm32_uart_t *serial, rt_bool_t bool);
/* Private Variables ------------------------------------------------------------*/
static const struct rt_uart_ops stm32_uart_ops =
{ usart_configure, usart_control, usart_send, usart_receive,
RT_NULL };
static const struct serial_configure stm32_uart_default_config =
RT_SERIAL_CONFIG_DEFAULT;
#ifdef USEING_UART0
struct usart uart0;
#endif
/* Interrupt Handle Funtion ----------------------------------------------------*/
#ifdef USEING_UART0
/* 串口0 中断入口 */
void UART0_IRQHandler(void)
{
uart_isr(&uart0);
}
#endif
/**
*
*/
static void uart_isr(usart_t serial)
{
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
// 获取中断事件
uint32_t u32IntSts= uart_base->INTSTS;
// 接收中断
if(u32IntSts & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk))
{
rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND);
}
}
/**
*
*/
static rt_err_t usart_gpio_configure(struct rt_serial_device *serial)
{
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
switch((uint32_t)uart_base)
{
case UART0_BASE:
SYS->GPG_MFPL = SYS_GPG_MFPL_PG1MFP_UART0_RXD | SYS_GPG_MFPL_PG2MFP_UART0_TXD;
break;
default:
rt_kprintf("unknow uart module\n");
RT_ASSERT(0);
}
return RT_EOK;
}
/**
*
*/
static rt_err_t usart_configure(struct rt_serial_device *serial,
struct serial_configure *cfg)
{
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
uint32_t uart_module = 0;
uint32_t uart_word_len = 0;
uint32_t uart_stop_bit = 0;
uint32_t uart_parity = 0;
uint32_t uart_irq_channel = 0;
switch((uint32_t)uart_base)
{
case UART0_BASE:
uart_module = UART0_MODULE;
uart_irq_channel = UART0_IRQn;
break;
default:
rt_kprintf("unknow uart module\n");
RT_ASSERT(0);
}
/* Enable IP clock */
CLK_EnableModuleClock(uart_module);
/* Select IP clock source */
CLK_SetModuleClock(uart_module, CLK_CLKSEL1_UARTSEL_HXT, CLK_CLKDIV0_UART(1));
/* check baudrate */
RT_ASSERT(cfg->baud_rate != 0);
/* check word len */
switch(cfg->data_bits)
{
case DATA_BITS_5:
uart_word_len = UART_WORD_LEN_5;
break;
case DATA_BITS_6:
uart_word_len = UART_WORD_LEN_6;
break;
case DATA_BITS_7:
uart_word_len = UART_WORD_LEN_7;
break;
case DATA_BITS_8:
uart_word_len = UART_WORD_LEN_8;
break;
default:
rt_kprintf("unsupose data len");
RT_ASSERT(0);
}
/* check stop bit */
switch(cfg->stop_bits)
{
case STOP_BITS_1:
uart_stop_bit = UART_STOP_BIT_1;
break;
case STOP_BITS_2:
uart_stop_bit = UART_STOP_BIT_2;
break;
default:
rt_kprintf("unsupose stop bit");
RT_ASSERT(0);
}
/* check stop bit */
switch(cfg->parity)
{
case PARITY_NONE:
uart_parity = UART_PARITY_NONE;
break;
case PARITY_ODD:
uart_parity = UART_PARITY_ODD;
break;
case PARITY_EVEN:
uart_parity = UART_PARITY_EVEN;
break;
default:
rt_kprintf("unsupose parity");
RT_ASSERT(0);
}
/* Open uart */
{
uint8_t u8UartClkSrcSel;
uint32_t u32ClkTbl[4] = {__HXT, 0, __HIRC, __HIRC};
uint32_t u32Clk;
uint32_t u32Baud_Div;
u32ClkTbl[1] = CLK_GetPLLClockFreq();
u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos;
uart_base->FUNCSEL = UART_FUNCSEL_UART;
uart_base->LINE = uart_word_len | uart_stop_bit | uart_parity;
uart_base->FIFO = 6 << UART_FIFO_RFITL_Pos;
uart_base->TOUT = (1 << UART_TOUT_DLY_Pos) | (40 << UART_TOUT_TOIC_Pos);
u32Clk = (u32ClkTbl[u8UartClkSrcSel]) / (((CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos) + 1);
u32Baud_Div = UART_BAUD_MODE2_DIVIDER(u32Clk, cfg->baud_rate);
if (u32Baud_Div > 0xFFFF)
uart_base->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, cfg->baud_rate));
else
uart_base->BAUD = (UART_BAUD_MODE2 | u32Baud_Div);
}
/* config nvic */
NVIC_EnableIRQ(uart_irq_channel);
/* config gpio */
usart_gpio_configure(serial);
return RT_EOK;
}
/**
*
*/
static rt_err_t usart_control(struct rt_serial_device *serial,
int cmd, void *arg)
{
rt_err_t result = RT_EOK;
rt_uint32_t flag;
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
switch ((uint32_t) arg)
{
case RT_DEVICE_FLAG_INT_RX:
flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk;
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
UART_DISABLE_INT(uart_base, flag);
break;
case RT_DEVICE_CTRL_SET_INT:
UART_ENABLE_INT(uart_base, flag);
break;
default:
RT_ASSERT(0);
}
break;
// TODO 完善DMA接口
// case RT_DEVICE_FLAG_DMA_TX:
// USART_DMACmd(dev->usart_base, USART_DMAReq_Tx, ENABLE);
// stm32_uart_tx_dma_configure(dev, RT_TRUE);
// stm32_uart_tx_dma_nvic(dev, RT_TRUE);
// break;
default:
RT_ASSERT(0)
;
}
return result;
return RT_EOK;
}
/**
*
*/
static int usart_send(struct rt_serial_device *serial, char c)
{
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
// 等待FIFO 发送
while(uart_base->FIFOSTS & UART_FIFOSTS_TXFULL_Msk);
// 发送字符
uart_base->DAT = c;
return 1;
}
/**
*
*/
static int usart_receive(struct rt_serial_device *serial)
{
// 获取串口基地址
UART_T *uart_base = ((usart_t)serial)->usart_base;
// 如果FIFO 为空返回
if(uart_base->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk)
{
return -1;
}
return UART_READ(uart_base);
}
/**
* @brief
* @param uart : UART设备结构体
* @param uart_base : STM32 UART外设基地址
* @param name : STM32 UART设备名
* @param tx_dma_channel : STM32 UART TX的DMA通道基地址()
*/
static void rt_hw_uart_register(usart_t usart, UART_T * uart_base, char *name)
{
rt_uint32_t flag;
RT_ASSERT(usart != RT_NULL);
RT_ASSERT(uart_base != RT_NULL);
// 没有定义对应的硬件I2C
if (!(uart_base == UART0 || uart_base == UART1 || uart_base == UART2
|| uart_base == UART3 || uart_base == UART4 || uart_base == UART5))
{
RT_ASSERT(0);
}
usart->usart_base = uart_base;
usart->dev.ops = &stm32_uart_ops;
usart->dev.config = stm32_uart_default_config;
flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX;
rt_hw_serial_register(&usart->dev, name,
flag, RT_NULL);
}
/**
*
*/
void rt_hw_usart_init(void)
{
#ifdef USEING_UART0
rt_hw_uart_register(&uart0, UART0, "uart0");
#endif
}