https://docs.zephyrproject.org/latest/hardware/peripherals/uart.html#uart-interrupt-api
本文基本上就是翻译官方文档,写个笔记
zephyr提供串口的三种方式
1、Polling API(轮询方式)
2、Interrupt-driven API(中断方式)
3、Asynchronous API using Direct Memory Access (DMA)(异步DMA)
配置项
CONFIG_SERIAL //打开串口驱动,有许多配置项需要依赖这一项 CONFIG_UART_INTERRUPT_DRIVEN //使能串口中断 CONFIG_UART_ASYNC_API //使能异步串口中断(DMA) CONFIG_UART_WIDE_DATA //使能16字节的api(驱动支持的情况下),比如uart_poll_in_u16、uart_fifo_fill_u16等 CONFIG_UART_USE_RUNTIME_CONFIGURE //启用UART控制器的运行时配置,允许应用程序在运行时调用uart_configure()来配置UART控制器,并调用uart_config_get()来检索配置 //如果禁用此功能,则UART控制器依赖UART驱动程序的初始化功能来正确配置控制器(dts配置) CONFIG_UART_LINE_CTRL //使能流控制 CONFIG_UART_DRV_CMD //允许使用api向驱动程序发送一些命令
硬件流控制可以参考这位的博客
常用api
此处列举文档中的functions,方便查询,具体参数和返回值详见文档
api | 简述 |
---|---|
int uart_err_check(const struct device *dev) | 检查串口是否错误 |
int uart_configure(const struct device *dev, const struct uart_config *cfg) | 配置串口 |
int uart_config_get(const struct device *dev, struct uart_config *cfg) | 获取当前串口配置 |
int uart_line_ctrl_set(const struct device *dev, uint32_t ctrl, uint32_t val) | 设置串口的流控制(宏控制) |
int uart_line_ctrl_get(const struct device *dev, uint32_t ctrl, uint32_t *val) | 获取串口的流控制等数据 |
int uart_drv_cmd(const struct device *dev, uint32_t cmd, uint32_t p) | 发送额外的命令给驱动(宏控制) |
struct uart_config { uint32_t baudrate; /* 波特率 */ uint8_t parity; /* 奇偶校验 */ uint8_t stop_bits; /* 停止位 */ uint8_t data_bits; /* 数据位 */ uint8_t flow_ctrl; /* 流控制 */ };
其他函数中所需的结构体详见代码,路径如下:
zephyr/include/zephyr/drivers/uart.h
轮询方式(Polling)
api | 简述 |
---|---|
int uart_poll_in(const struct device *dev, unsigned char *p_char) | 串口接收一个字节的数据 |
int uart_poll_in_u16(const struct device *dev, uint16_t *p_u16) | 接收两个字节的数据(宏配置) |
void uart_poll_out(const struct device *dev, unsigned char out_char) | 串口输出一个字节的数据 |
void uart_poll_out_u16(const struct device *dev, uint16_t out_u16) | 串口输出两个字节数据 |
说明:串口输出直接使用printf puts或printk更便捷
测试demo
/*dts中需要将uart1这个label起个别名*/ aliases { single-line-uart1 = &usart1; };
#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/drivers/uart.h> #define UART_NODE1 DT_ALIAS(single_line_uart1) const struct device *const sl_uart1 = DEVICE_DT_GET(UART_NODE1); int main(void) { unsigned char recv; if (!device_is_ready(sl_uart1)) { printk("uart devices not ready "); return 0; } while (true) { int ret = uart_poll_in(sl_uart1, &recv); if (ret < 0) { printk("Receiving failed. Error: %d ", ret); } else { printk("Received %c ", recv); } k_sleep(K_MSEC(1000)); } return 0; }
*** Booting Zephyr OS build zephyr-v3.5.0 *** Receiving failed. Error: -1 Receiving failed. Error: -1 Receiving failed. Error: -1 Received 2
中断方式
函数指针 | 功能 |
---|---|
typedef void (*uart_irq_callback_user_data_t)(const struct device *dev, void *user_data | static inline int uart_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb)的第二个参数,函数指针 |
typedef void (*uart_irq_config_func_t)(const struct device *dev) | 配置串口的函数指针 |
函数 | 简述 |
---|---|
static inline int uart_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) | 发送8位data到FIFO |
static inline int uart_fifo_fill_u16(const struct device *dev, const uint16_t *tx_data, int size) | 发送16位data到FIFO |
static inline int uart_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) | 从FIFO接收8位 |
static inline int uart_fifo_read_u16(const struct device *dev, uint16_t *rx_data, const int size) | 从FIFO接收16位 |
上述的api,使用的时候,需要先判断 uart_irq_tx_ready() uart_irq_rx_ready(),如果返回1,则必须在中断处理函数中调用
api | brief |
---|---|
void uart_irq_tx_enable(const struct device *dev) | enable TX |
void uart_irq_tx_disable(const struct device *dev) | disable TX |
static inline int uart_irq_tx_ready(const struct device *dev) | 检查发送缓冲区是否有数据 |
void uart_irq_rx_enable(const struct device *dev) | enable RX |
void uart_irq_rx_disable(const struct device *dev) | disable RX |
static inline int uart_irq_tx_complete(const struct device *dev) | 检查tx是否传输完成 |
static inline int uart_irq_rx_ready(const struct device *dev) | 检查接收缓冲区是否有数据 |
void uart_irq_err_enable(const struct device *dev) | enable error interrupt |
void uart_irq_err_disable(const struct device *dev) | Disable error interrupt |
int uart_irq_is_pending(const struct device *dev) | 检查是否有等待的中断 |
int uart_irq_update(const struct device *dev) | 开始中断 |
static inline int uart_irq_callback_user_data_set(const struct device *dev, uart_irq_callback_user_data_t cb, void *user_data) | 设置中断请求函数指针,指定用户uart_irq_callback_user_data_t |
static inline int uart_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb) | 设置中断请求函数指针 |
注:1、中断处理函数中,在调用uart_irq_tx_ready之前,必须调用 uart_irq_update()函数
2、中断处理函数中,在调用uart_irq_tx_complete之前,必须调用 uart_irq_update()函数
3、文档中ISR指Interrupt Service Routine,中断服务程序
4、文档中IRQ指Interrupt Request, 中断请求
5、uart_irq_update函数是中断开始时调用的第一个函数
测试demo和dma的方式后续有空再补