串口收发处理框架(基于sdk-ameba-v4.0c_180328)
一.包括如下处理函数:
(1)static void uart_irq(uint32_t id, SerialIrq event)
该函数主要处理串口有数据产生中断时调用,主要实现:
获取收到的字符,并存储到 u->recv_buf 接收buffer 中;当u->recv_buf满时,u->prxwrite 会重新从头部开始写入,并置标志位u->rxoverlap 为 1,表示buffer处于满状态。
如果u->prxwrite 大于 u->prxread 的时候,证明已经覆盖旧的未读数据,这时需要 u->prxread = u->prxwrite;。更新超时tick , u->last_update(主要为了记录超出定义的接收时间,视为接收完毕)。
(2)static void uart_send_stream_done(uint32_t id)
该函数,串口数据发送完毕时调用,主要实现:
清除发送buffer;释放发送相关的block信号量(u->tx_sema ,u->dma_tx_sema)。
(3)static int uart_send_stream(uart_socket_t *u, char* pbuf, int len)
该函数发送串口数据流时调用,主要实现:
获取发送信号量u->dma_tx_sema (主要保护正在发送的数据,使之完全发送后再释放信号量u->dma_tx_sema );
发送串口数据流serial_send_stream_dma();
(4)static s32 uart_wait_rx_complete(uart_socket_t *u)
该函数接收完毕等待超时,主要实现:
当前tick_current与自从接收到数据的u->last_update tick数做比较,达到超出自定义时间值后退出。
(5)static void uart_action_handler(void* param)
该函数处理串口数据收发逻辑,主要实现:
当获取到u->action_sema信号量的时候,表示有串口数据需要处理,
u->rx_start当此变量置1,表示有串口数据需要接收,并置FD_ISSET为真以及ublock select 函数,在应用线程循环里处理接收数据。
u->tx_start当此变量置1,表示有串口数据需要发送,调用uart_send_stream 函数进行发送。
(6)uart_socket_t* uart_open(uart_set_str *puartpara)
该函数打开串口数据通道,主要实现:
串口初始化:
/*initial uart */
serial_init(&u->sobj, uart_tx,uart_rx);
serial_baud(&u->sobj,puartpara->BaudRate);
serial_format(&u->sobj, puartpara->number, (SerialParity)puartpara->parity, puartpara->StopBits);
串口中断回调注册初始化:
/*uart irq handle*/
serial_irq_handler(&u->sobj, uart_irq, (int)u);
serial_irq_set(&u->sobj, RxIrq, 1);
serial_irq_set(&u->sobj, TxIrq, 1);
串口发送完毕回调注册:
serial_send_comp_handler(&u->sobj, (void*)uart_send_stream_done, (uint32_t)u);
分配串口socket 句柄,主要是为FD_ISSET ,select函数服务:
/*alloc a socket*/
u->fd = lwip_allocsocketsd();
初始化串口处理相关信号量:
/*init uart related semaphore*/
rtw_init_sema(&u->action_sema, 0);//串口收发信号量
rtw_init_sema(&u->tx_sema, 1);//串口发送信号量
rtw_init_sema(&u->dma_tx_sema, 1);//DMA数据发送信号量
(7) int uart_close(uart_socket_t *u)
释放uart_socket:
/* Close uart socket */
if(lwip_close(u->fd) == -1)
{
uart_printf("%s(): close uart failed!", __func__);
}
/* Delete uart_action task */
u->fd = -1;
释放信号量:
rtw_up_sema(&u->action_sema);
rtw_msleep_os(20);
/* Free uart related semaphore */
rtw_free_sema(&u->action_sema);
rtw_free_sema(&u->tx_sema);
rtw_free_sema(&u->dma_tx_sema);
释放串口结构体相关的内存资源:
/* Free serial */
serial_free(&u->sobj);
rtw_mfree((u8 *)u, sizeof(uart_socket_t));
(8)int uart_read(uart_socket_t *u, void *read_buf, size_t size)
根据写(u->prxread)和读(u->prxread)的index,以及溢出的标志位u->rxoverlap 判断 u->recv_buf 当前需要读取的数据,读取的大小由 size 决定。
把需要的数据都出来后,清空socket select事件,并把读( u->prxread )的index 重新更新。
lwip_setsockrcvevent(u->fd, 0);
if((pread_local + read_bytes) >= UART_RECV_BUFFER_LEN){ //update pread
u->prxread = (pread_local + read_bytes) - UART_RECV_BUFFER_LEN;
u->rxoverlap = 0; //clean overlap flags
} else
u->prxread = pread_local + read_bytes;
(9)int uart_write(uart_socket_t *u, void *pbuf, size_t size)
获取信号锁rtw_down_sema(&u->tx_sema) ,并释放收发处理线程信号锁rtw_up_sema(&u->action_sema); 让uart_action_handler 处理串口写操作。
二. 程序逻辑流程图