设计说明
信息配置
SDK 中 UART 的配置信息包括
-
SoC 配置: Kconfig.chip
-
开发板配置:Kconfig.board
-
Pimux 配置:pinmux.c
-
设备配置:Kconfig.dev
SoC 的 UART 模块的基础信息配置在 bsp/artinchip/sys/soc name/Kconfig.chip 中设置
-
驱动版本信息
-
UART 数目信息
config AIC_UART_DRV bool default n config AIC_UART_DRV_V10 bool default y if AIC_UART_DRV config AIC_UART_DRV_VER string default "10" if AIC_UART_DRV_V10 config AIC_UART_DEV_NUM int default 8 if AIC_UART_DRV
在 target/soc name/board name/Kconfig.board 中完成某一开发板中 UART 的相关信息设置, 一般会配置需要的 UART 端口
config AIC_USING_UART0 bool "Using uart0" default n select AIC_UART_DRV config AIC_USING_UART1 bool "Using uart1" default n select AIC_UART_DRV
在 target/soc name/board name/pinmux.c 中配置 UART 端口的 pinmux
struct aic_pinmux aic_pinmux_config[] = { ... #ifdef AIC_USING_UART0 /* uart0 */ {5, PIN_PULL_DIS, 3, "PA.0"}, {5, PIN_PULL_DIS, 3, "PA.1"}, #endif
在 bsp/artinchip/drv/uart/Kconfig.dev 中设置设备的工作参数
-
clock
-
baudrate
-
data bites
-
stop bits
-
parity
-
function
config AIC_DEV_UART0_BAUDRATE int "uart0 baudrate" default 115200 config AIC_DEV_UART0_DATABITS int "uart0 data bits" range 0 15 default 8 config AIC_DEV_UART0_STOPBITS int "uart0 stop bits" range 0 3 default 1
源码说明
UART 的功能通过三层包装实现:
-
HAL 层: bsp/artinchip/hal/uart/aic_hal_uart.c
-
驱动层: bsp/artinchip/drv/uart/aic_drv_uart.c
-
应用层: kernel/rt-thread/components/drivers/serial/serial.c
HAL 层
HAL 层主要完成对寄存的操作,对基础功能块的封装
typedef struct { union { __IM uint32_t RBR; /* Offset: 0x000 (R/ ) Receive buffer register */ __OM uint32_t THR; /* Offset: 0x000 ( /W) Transmission hold register */ __IOM uint32_t DLL; /* Offset: 0x000 (R/W) Clock frequency division low section register */ }; union { __IOM uint32_t DLH; /* Offset: 0x004 (R/W) Clock frequency division high section register */ __IOM uint32_t IER; /* Offset: 0x004 (R/W) Interrupt enable register */ }; union { __IM uint32_t IIR; /* Offset: 0x008 (R/ ) Interrupt indicia register */ __IOM uint32_t FCR; /* Offset: 0x008 (W) FIFO control register */ }; __IOM uint32_t LCR; /* Offset: 0x00C (R/W) Transmission control register */ __IOM uint32_t MCR; /* Offset: 0x010 (R/W) Modem Control register */ __IM uint32_t LSR; /* Offset: 0x014 (R/ ) Transmission state register */ __IM uint32_t MSR; /* Offset: 0x018 (R/ ) Modem state register */ uint32_t RESERVED1[24]; /**/ __IM uint32_t USR; /* Offset: 0x07c (R/ ) UART state register */ uint32_t RESERVED2[1]; __IM uint32_t RFL; /* Offset: 0x084 (R/ ) UART rx fifo level register */ __IOM uint32_t HSK; /* Offset: 0x088 (R/W) UART dma hsk register */ uint32_t RESERVED3[6]; __IOM uint32_t HALT; /* Offset: 0x0A4 */ } aic_usart_reg_t;
typedef struct { __IOM uint32_t RS485DE; /* Offset: 0x0B8 (R/W ) RS485 DE Time register*/ uint32_t RESERVED0; __IOM uint32_t RS485CTL; /* Offset: 0x0C0 (R/W ) RS485 Control and Status register*/ __IOM uint32_t RS485AM; /* Offset: 0x0C4 (R/W ) RS485 Address Match register*/ __IOM uint32_t RS485BIC; /* Offset: 0x0C8 (R/W ) RS485 Bus Idle Check register*/ } aic_usart_exreg_t;
接口设计
函数原型 | static int hal_usart_initialize(int32_t idx, usart_event_cb_t cb_event, void *handler) |
---|---|
功能说明 | 初始化 UART 端口 |
参数定义 |
index - UART 端口号
cb_event - event call back
handler - 生成的工作句柄
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int hal_usart_uninitialize(void *handler) |
---|---|
功能说明 | 关闭 UART 端口 |
参数定义 |
handler - UART 句柄
cb_event - event call back
handler - 生产的工作句柄
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int hal_usart_config(usart_handle_t handle, ……) |
---|---|
功能说明 | 配置 UART 的工作参数 |
参数定义 |
handle - UART 句柄
baud - 波特率
mode - 工作模式,同步还是异步
parity - 极性
stopbits - 停止位
bits - 数据位
func - 功能,RS232,RF485 等
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int32_t al_usart_send(usart_handle_t handle, const void *data, uint32_t num) |
---|---|
功能说明 | 发送数据 |
参数定义 |
handle - UART 句柄
data - 待发送数据
num - 数据长度
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int32_t hal_usart_receive(usart_handle_t handle, void *data, uint32_t num) |
---|---|
功能说明 | 接收数据 |
参数定义 |
handle - UART 句柄
data - 接收数据 buffer
num - 要接收的数据长度
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int32_t hal_usart_receive_query(usart_handle_t handle, void *data, uint32_t num) |
---|---|
功能说明 | 查询要接收的数据的长度 |
参数定义 |
handle - UART 句柄
data - 接收数据 buffer
num - buffer 的大小
|
返回值 | 长度 |
注意事项 | - |
函数原型 | usart_status_t hal_usart_get_status(usart_handle_t handle) |
---|---|
功能说明 | 获取 UART 的状态 |
参数定义 | handle - UART 句柄 |
返回值 | 状态值 |
注意事项 | - |
函数原型 | int32_t hal_usart_flush(usart_handle_t handle, usart_flush_type_e type) |
---|---|
功能说明 | flush 发送或接收的数据 |
参数定义 |
handle - UART 句柄
type - 发送或者接收
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int32_t hal_usart_config_flowctrl(usart_handle_t handle, usart_flowctrl_type_e flowctrl_type) |
---|---|
功能说明 | 配置 UART 的流控 |
参数定义 |
handle - UART 句柄
flowctrl_type - 流控类型
|
返回值 | 0,成功; < 0,失败 |
注意事项 | - |
函数原型 | int32_t hal_uart_set_fifo(usart_handle_t handle) |
---|---|
功能说明 | 设置 UART-DMA 模式下 rx_fifo 和 tx_fifo 的触发阈值 |
参数定义 |
handle - UART 句柄
|
返回值 | 0,成功 |
注意事项 | - |
函数原型 | int32_t hal_usart_set_hsk(usart_handle_t handle) |
---|---|
功能说明 | 配置 UART-DMA 握手模式 |
参数定义 |
handle - UART 句柄
|
返回值 | 0,成功 |
注意事项 | - |
函数原型 | int32_t hal_usart_get_rx_fifo_num(usart_handle_t handle) |
---|---|
功能说明 | 读取 rx_fifo 里面的数据量 |
参数定义 |
handle - UART 句柄
|
返回值 | fifo_num,数据的多少 |
注意事项 | - |
函数原型 | int32_t hal_uart_rx_dma_config(usart_handle_t handle, uint8_t *buf, uint32_t size) |
---|---|
功能说明 | 配置 UART-DMA 接收的参数 |
参数定义 |
handle - UART 句柄
buf - DMA 搬运的目标地址
size - 搬运数据的大小
|
返回值 | 0,成功 |
注意事项 | - |
函数原型 | int32_t hal_uart_send_by_dma(usart_handle_t handle, uint8_t *buf, uint32_t size) |
---|---|
功能说明 | 配置 UART-DMA 发送的参数 |
参数定义 |
handle - UART 句柄
buf - DMA 搬运的源端地址
size - 搬运数据的大小
|
返回值 | 0,成功 |
注意事项 | - |
函数原型 | int32_t hal_usart_halt_tx_enable(usart_handle_t handle, uint8_t halt_tx_enable) |
---|---|
功能说明 | 控制设备发送数据的开关 |
参数定义 |
handle - UART 句柄
halt_tx_enable - 禁止发送使能标志
|
返回值 | 0,成功 |
注意事项 | - |
驱动层
驱动层通过调用 HAL 层的接口,完成对 UART 设备的驱动实现, 代码在 bsp/artinchip/drv/uart/aic_drv_uart.c
struct drv_uart_dev_para { uint32_t index :4; uint32_t data_bits :4; uint32_t stop_bits :2; uint32_t parity :2; uint32_t flag; uint32_t baud_rate; uint32_t clk_freq; uint32_t function; char * name; char * uart_rts_name; char * uart_cts_name; }; const struct drv_uart_dev_para uart_dev_paras[] = { #ifdef AIC_USING_UART0 {0, AIC_DEV_UART0_DATABITS, AIC_DEV_UART0_STOPBITS, AIC_DEV_UART0_PARITY, AIC_UART0_FLAG, AIC_DEV_UART0_BAUDRATE, AIC_CLK_UART0_FREQ, AIC_DEV_UART0_MODE, "uart0", AIC_UART0_RTS_NAME, AIC_UART0_CTS_NAME}, #endif #ifdef AIC_USING_UART1 {1, AIC_DEV_UART1_DATABITS, AIC_DEV_UART1_STOPBITS, AIC_DEV_UART1_PARITY, AIC_UART1_FLAG, AIC_DEV_UART1_BAUDRATE, AIC_CLK_UART1_FREQ, AIC_DEV_UART1_MODE, "uart1", AIC_UART1_RTS_NAME, AIC_UART1_CTS_NAME}, #endif #ifdef AIC_USING_UART2 {2, AIC_DEV_UART2_DATABITS, AIC_DEV_UART2_STOPBITS, AIC_DEV_UART2_PARITY, AIC_UART2_FLAG, AIC_DEV_UART2_BAUDRATE, AIC_CLK_UART2_FREQ, AIC_DEV_UART2_MODE, "uart2", AIC_UART2_RTS_NAME, AIC_UART2_CTS_NAME}, #endif #ifdef AIC_USING_UART3 {3, AIC_DEV_UART3_DATABITS, AIC_DEV_UART3_STOPBITS, AIC_DEV_UART3_PARITY, AIC_UART3_FLAG, AIC_DEV_UART3_BAUDRATE, AIC_CLK_UART3_FREQ, AIC_DEV_UART3_MODE, "uart3", AIC_UART3_RTS_NAME, AIC_UART3_CTS_NAME}, #endif #ifdef AIC_USING_UART4 {4, AIC_DEV_UART4_DATABITS, AIC_DEV_UART4_STOPBITS, AIC_DEV_UART4_PARITY, AIC_UART4_FLAG, AIC_DEV_UART4_BAUDRATE, AIC_CLK_UART4_FREQ, AIC_DEV_UART4_MODE, "uart4", AIC_UART4_RTS_NAME, AIC_UART4_CTS_NAME}, #endif #ifdef AIC_USING_UART5 {5, AIC_DEV_UART5_DATABITS, AIC_DEV_UART5_STOPBITS, AIC_DEV_UART5_PARITY, AIC_UART5_FLAG, AIC_DEV_UART5_BAUDRATE, AIC_CLK_UART5_FREQ, AIC_DEV_UART5_MODE, "uart5", AIC_UART5_RTS_NAME, AIC_UART5_CTS_NAME}, #endif #ifdef AIC_USING_UART6 {6, AIC_DEV_UART6_DATABITS, AIC_DEV_UART6_STOPBITS, AIC_DEV_UART6_PARITY, AIC_UART6_FLAG, AIC_DEV_UART6_BAUDRATE, AIC_CLK_UART6_FREQ, AIC_DEV_UART6_MODE, "uart6", AIC_UART6_RTS_NAME, AIC_UART6_CTS_NAME}, #endif #ifdef AIC_USING_UART7 {7, AIC_DEV_UART7_DATABITS, AIC_DEV_UART7_STOPBITS, AIC_DEV_UART7_PARITY, AIC_UART7_FLAG, AIC_DEV_UART7_BAUDRATE, AIC_CLK_UART7_FREQ, AIC_DEV_UART7_MODE, "uart7", AIC_UART7_RTS_NAME, AIC_UART7_CTS_NAME}, #endif };
INIT_BOARD_EXPORT(drv_usart_init); int drv_usart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; int u = 0; int i = 0; for (i=0; i<sizeof(uart_dev_paras)/sizeof(struct drv_uart_dev_para); i++) { u = uart_dev_paras[i].index; g_serial[u].ops = & drv_uart_ops; g_serial[u].config = config; g_serial[u].config.bufsz = 2048; g_serial[u].config.baud_rate = uart_dev_paras[i].baud_rate; g_serial[u].config.data_bits = uart_dev_paras[i].data_bits; g_serial[u].config.stop_bits = uart_dev_paras[i].stop_bits - 1; g_serial[u].config.parity = uart_dev_paras[i].parity; g_serial[u].config.function = uart_dev_paras[i].function; g_serial[u].config.flag = uart_dev_paras[i].flag; g_serial[u].config.uart_index = uart_dev_paras[i].index; hal_clk_set_freq(CLK_UART0 + u, uart_dev_paras[i].clk_freq); hal_clk_enable(CLK_UART0 + u); hal_reset_assert(RESET_UART0 + u); aic_udelay(10000); hal_reset_deassert(RESET_UART0 + u); #ifdef FINSH_POLL_MODE uart_handle[u] = hal_usart_initialize(u, NULL, NULL); #else uart_handle[u] = hal_usart_initialize(u, NULL, drv_usart_irqhandler); #endif rt_hw_serial_register(&g_serial[u], uart_dev_paras[i].name, #ifdef FINSH_POLL_MODE RT_DEVICE_FLAG_RDWR, #else uart_dev_paras[i].flag, #endif uart_handle[u]); if (uart_dev_paras[i].flag == AIC_UART_DMA_FLAG) { hal_uart_set_fifo((aic_usart_priv_t *)g_serial[u].parent.user_data); hal_uart_attach_callback((aic_usart_priv_t *)g_serial[u].parent.user_data, drv_uart_callback, NULL); hal_usart_set_ier((aic_usart_priv_t *)g_serial[u].parent.user_data, 1); } drv_usart_function_init(i, u); } return 0; }
const struct rt_uart_ops drv_uart_ops = { drv_uart_configure, drv_uart_control, drv_uart_putc, drv_uart_getc, #if defined (RT_SERIAL_USING_DMA) drv_uart_dma_transmit, #endif };
应用层
UART 在应用层被封装成了一个标准的设备,通过读写进行数据的发送和接收
设备实现代码:kernel/rt-thread/components/drivers/serial/serial.c 使用示例代码:bsp/examples/test-uart/test_uart.c
函数原型 | rt_device_t rt_device_find(const char *name); |
---|---|
功能说明 | 找到相应的设备 |
参数定义 | name - 设备名 |
返回值 | 设备变量或者 NULL |
注意事项 | - |
函数原型 | rt_err_t rt_device_open (rt_device_t dev, rt_uint16_t oflag); |
---|---|
功能说明 | 打开设备 |
参数定义 |
dev - UART device
oflag - 打开参数
|
返回值 | 0,成功; 其他,失败 |
注意事项 | - |
函数原型 | rt_err_t rt_device_close(rt_device_t dev); |
---|---|
功能说明 | 关闭设备 |
参数定义 | dev - 设备名 |
返回值 | 0,成功; 其他,失败 |
注意事项 | - |
函数原型 | rt_size_t rt_device_read (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); |
---|---|
功能说明 | 接收信息 |
参数定义 |
dev - UART device
pos - 起始位置
buffer - 数据存储区
size - 大小
|
返回值 | 接收数据的大小 |
注意事项 | - |
函数原型 | rt_size_t rt_device_write (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); |
---|---|
功能说明 | 发送信息 |
参数定义 |
dev - UART device
pos - 起始位置
buffer - 数据存储区
size - 大小
|
返回值 | 发送数据的大小 |
注意事项 | - |
使用示例
static rt_device_t serial = rt_device_find("uart1"); rt_device_open(serial, RT_DEVICE_FLAG_RDONLY); rt_device_write(serial, 0, str_send, (sizeof(str_send) - 1)); rt_device_read(serial, 0, str_send, 1);