芯片CSI驱动开发
概述
CSI驱动有规范的实现流程,以UART为例进行说明,驱动包含以下几个部分: 1、初始化/去初始化 2、配置 3、同步输入输出 4、异步输入输出
统一的设备和中断管理
如下图,描述设备初始化和中断处理流程。
UART驱动编写
初始化
获取基地址和中断号
通过target_get接口获取设备基地址和中断号,保存到csi_uart_t控制块中。
target_get接口的获取方式详见“芯片设备信息描述”章节
csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx)
{
//...
ret = target_get(DEV_DW_UART_TAG, idx, &uart->dev);
//...
}
初始化设备硬件
初始化UART FIFO等。
csi_error_t csi_uart_init(csi_uart_t *uart, uint32_t idx)
{
//...
dw_uart_fifo_init(uart_base);
//...
}
配置
UART 需要实现配置 baudrate、format、flowctrl。
csi_error_t csi_uart_baud(csi_uart_t *uart, uint32_t baud);
csi_error_t csi_uart_format(csi_uart_t *uart, csi_uart_data_bits_t data_bits,
csi_uart_parity_t parity, csi_uart_stop_bits_t stop_bits);
csi_error_t csi_uart_flowctrl(csi_uart_t *uart, csi_uart_flowctrl_t flowctrl);
同步输入输出
同步输入输出通过轮询的方式实现,实现send/receive接口。
uint32_t csi_uart_send(csi_uart_t *uart, const void *data, uint32_t size, uint32_t timeout);
uint32_t csi_uart_receive(csi_uart_t *uart, void *data, uint32_t size, uint32_t timeout);
异步输出输出
异步接口包含中断方式和DMA方式,send/receive接口统一。
默认状态下csi_uart_send_async是通过中断方式,用户调用了LINK DMA接口则变成DMA方式 实现send_async/receive_async接口。
csi_error_t csi_uart_send_async(csi_uart_t *uart, const void *data, uint32_t size);
csi_error_t csi_uart_receive_async(csi_uart_t *uart, void *data, uint32_t size);
注册回调函数
CSI 接口的使用者不需要实现中断处理函数,只需要通过回调函数来接收中断事件。 驱动需要实现csi_uart_attach_callback接口供用户注册。
csi_error_t csi_uart_attach_callback(csi_uart_t *uart, void *callback, void *arg);
void csi_uart_detach_callback(csi_uart_t *uart);
中断
中断处理函数
UART中断处理函数,把数据接收到csi_uart_t rx_data中;把csi_uart_t tx_data的数据发送出去。
中断处理函数通过csi_irq_attach注册到g_irq_table中。g_irq_table中通过中断号存放csi_dev_t结构体变量。
void dw_uart_irq_handler(void *arg);
DMA
默认的,csi_uart_send_async使用中断方式发送;只有调用了csi_uart_link_dma后,才会启用DMA方式发送。
csi_error_t csi_uart_link_dma(csi_uart_t *uart, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma);
芯片设备信息描述
设备信息统一描述在devices.c文件中。设备初始化接口csi_xxx_init会通过target_get接口获取设备的基地址,中断号和设备号信息。示例如下,也可参考dummy芯片中的devices.c
const csi_perip_info_t g_soc_info[] = {
{DW_UART0_BASE, DW_UART0_IRQn, 0, DEV_DW_UART_TAG},
{DW_UART1_BASE, DW_UART1_IRQn, 1, DEV_DW_UART_TAG},
{DW_TIMER0_BASE, DW_TIMER0_IRQn, 0, DEV_DW_TIMER_TAG},
{DW_TIMER1_BASE, DW_TIMER1_IRQn, 1, DEV_DW_TIMER_TAG},
{DW_TIMER2_BASE, DW_TIMER2_IRQn, 2, DEV_DW_TIMER_TAG},
{DW_TIMER3_BASE, DW_TIMER3_IRQn, 3, DEV_DW_TIMER_TAG},
{0, 0, 0, 0}
};
typedef struct {
unsigned long reg_base; //设备基地址
uint8_t irq_num; //中断号
uint8_t idx; //设备号,若UART0,则idx=0
uint16_t dev_tag; //设备TAG,该设备类型的唯一标志符,如DEV_DW_UART_TAG
} csi_perip_info_t;