1.4. UART

包含多个串口,支持奇偶校验,dma收发,1个起始位,8个数据位,1个停止位。其中串口1支持硬件流控。串口外设的数量及校验情况请参阅对应Soc规格书。 时钟源:std24m,std48m,lsb。一般为std48m。 详细的示例代码请参考SDK “uart_demo.c或uart_test.c”

备注

串口收发的dma buffer 必须使用全局buffer,或者使用dma_malloc申请,不能使用临时变量,或者malloc申请。

1.4.1. 串口基本接口

1.4.1.1. uart_init

初始化串口,支持指定串口号,或者自动分配串口。指定串口号方式节省代码空间。

原型:

int uart_init(uart_dev uart_num, const struct uart_config *config)
参数:

uart_num

串口号0~n,-1表示自动分配空闲的串口

config

串口配置信息

返回值

<0:串口初始化失败,>=0:为串口号

示例:

struct uart_config config = {
    .baud_rate = 2000000,
    .tx_pin = IO_PORTB_15,
    .rx_pin = IO_PORTB_14,
    .parity = UART_PARITY_DISABLE,
    .tx_wait_mutex = 0,//1:发送接口不支持中断调用,启用互斥功能,0:支持中断,不互斥
};

int uart_num = uart_init(-1, &config);
if (uart_num < 0) {
    printf("uart init error");
}else{
    printf("uart%d init succ", uart_num);
}

1.4.1.2. uart_dma_init

串口dma初始化,串口接收必须配置dma参数,使用前先调用uart_init

原型:

int uart_dma_init(uart_dev uart_num, const struct uart_dma_config *dma_config);
参数:

uart_num

串口号

dma_config

串口配置信息

返回值

0:成功,<0:失败

示例:

const int uart_rx_dma_buffer_size = 768;
void *uart_rx_ptr = dma_malloc(uart_rx_dma_buffer_size);

struct uart_dma_config dma = {
    .rx_timeout_thresh = 100,   //接收数据不够frame_size,串口通信空闲100us后触发中断
    .frame_size = 32,   //接收32字节就触发RX中断,不足32byte触发RX_TIMEOUT中断
    .event_mask = UART_EVENT_RX_TIMEOUT | UART_EVENT_RX_FIFO_OVF | UART_EVENT_TX_DONE,
    .irq_callback = uart_irq_func,//在中断里面调用
    .irq_priority = 3,//中断优先级
    .rx_cbuffer = uart_rx_ptr,   //使用支持dma的内存
    .rx_cbuffer_size = uart_rx_dma_buffer_size,
};
//frame_size 一般是一个通讯帧的大小,rx_buffer_size一般为frame_size的两倍,内部是一个循环buffer
//使用前先调用uart_init
int r = uart_dma_init(uart_num, &dma);
if (r < 0) {
    log_error("dma init error %d", uart_num);
} else {
    log_info("dma init ok %d", uart_num);
}

1.4.1.3. uart_deinit

关闭串口,释放TX、RX io为高阻状态,关闭crossbar映射。

原型:

s32 uart_deinit(uart_dev uart_num)
参数:

uart_num

串口号

返回值

0:成功,<0:失败

1.4.1.4. uart_set_baudrate

设置串口波特率

原型:

s32 uart_set_baudrate(uart_dev uart_num, u32 baud_rate);
参数:

uart_num

串口号

baud_rate

波特率

返回值

实际波特率,>0:成功,<0:失败

1.4.1.5. uart_set_rx_timeout_thresh

设置超时时间ot,接收通信结束后ot时长后触发ot中断。

原型:

s32 uart_set_rx_timeout_thresh(uart_dev uart_num, u32 timeout_thresh);
参数:

uart_num

串口号

timeout_thresh

ot时间,单位us

返回值

0:成功,<0:失败

1.4.1.6. uart_send_bytes

启动串口发送dma,不等待dma发送结束,直接退出,由成员tx_wait_mutex决定能否在中断函数调用,数据指针要求在发送完成之前保持有效

原型:

s32 uart_send_bytes(uart_dev uart_num, const void *buffer, u32 size);
参数:

uart_num

串口号

buffer

需要发送的数据指针,需要使用dma_malloc申请,或者全局变量

size

需要发送的数据长度

返回值

等于发送的长度tx_size:ok,<0:error

1.4.1.7. uart_wait_tx_idle

等待串口发送完成,不允许在中断函数使用

原型:

s32 uart_wait_tx_idle(uart_dev uart_num, u32 timeout_ms);
参数:

uart_num

串口号

timeout_ms

超时时间,0就一直等,直到发送完成

返回值

0:成功,其他值:失败

1.4.1.8. uart_send_blocking

阻塞式发送数据,由成员tx_wait_mutex决定能否在中断函数调用

原型:

s32 uart_send_blocking(uart_dev uart_num, const void *buffer, u32 size, u32 timeout_ms);
参数:

uart_num

串口号

buffer

需要发送的数据指针,需要使用dma_malloc申请,或者全局变量

size

需要发送的数据长度

timeout_ms

超时时间,0就一直等,直到发送完成

返回值

等于发送的长度tx_size:ok,<0:error

1.4.1.9. uart_get_recv_len

获取dma接收长度,支持中断调用

原型:

//return,返回dma接收的长度 <0:error;
s32 uart_get_recv_len(uart_dev uart_num);
参数:

uart_num

串口号

返回值

接收的长度<0:error; 0=< <len:ok

1.4.1.10. uart_recv_bytes

获取接收数据,支持中断调用

原型:

s32 uart_recv_bytes(uart_dev uart_num void *buffer, u32 len);
参数:

uart_num

串口号

buffer

读取数据存放的buffer

len

需要读取数据长度

返回值

接收的长度<0:error; 0=< <len:ok

1.4.1.11. uart_recv_blocking

阻塞式读取串口接收的数据,不允许在中断函数,或者关闭中断的情况下使用

原型:

s32 uart_recv_blocking(uart_dev uart_num, void *buffer, u32 len, int timeout_ms);
参数:

uart_num

串口号

buffer

读取数据存放的buffer

len

需要读取数据长度

timeout_ms

超时时间,0就一直等,直到读取完成

返回值

接收的长度<0:error; 0=< <len:ok

1.4.1.12. uart_dma_rx_reset

dma rx fifo over接收溢出或接收错乱时重置dma及buf。

原型:

enum uart_state uart_dma_rx_reset(uart_dev uart_num);
参数:

uart_num

串口号

返回值

见枚举:uart_state

1.4.1.13. uart_set_idle_query_wait

配置串口延时进低功耗时间(默认延时30ms)。

原型:

void uart_set_idle_query_wait(u32 ms);
参数:

ms

延时时间ms

返回值

1.4.2. 串口硬件流接口

1.4.2.1. uart_flow_ctrl_init

流控配置,cts:检测到cts停止发送;rts:设置好阈值后当接收达到阈值会触发rts,当缓存少于阈值会释放rts,设置的阈值余量要足够。硬件流初始化后会后台运行。 查看芯片soc稳定确定是否支持硬件流控,一般uart1支持硬件流。

原型:

s32 uart_flow_ctrl_init(uart_dev uart_num, const struct uart_flow_ctrl *flow_ctrl);
参数:

uart_num

串口号

flow_ctrl

流控相关参数

返回值

0:成功,<0:失败

1.4.2.2. uart_flow_ctrl_deinit

关闭流控。当调uart_deinit关闭串口时会调用该函数关闭硬件流。

原型:

s32 uart_flow_ctrl_deinit(uart_dev uart_num);
参数:

uart_num

串口号

返回值

0:成功,<0:失败

1.4.3. 串口资源占用打印

1.4.3.1. uart_dump

打印所有串口初始化情况,功能启用情况。

原型:

//打印uart配置信息
void uart_dump();
参数:

返回值

1.4.4. 示例

示例:

详细的示例代码请参考SDK “uart_demo.c或uart_tset.c”

void uart_irq_func(uart_dev uart_num, enum uart_event enent)
{
    if (event & UART_EVENT_TX_DONE){
        uart_send_bytes(uart_num, tx_buffer, 32);
    }

    if (event & UART_EVENT_RX_TIMEOUT) {
        // int rx_len = uart_recv_bytes(uart_num,rx_buffer,32);
        printf("uart[%d] rx timerout data", uart_num);
    }

    if(event & UART_EVENT_RX_FIFO_OVF){
       printf(" rx_buffer too small");
    }
}


struct uart_config config = {
    .baud_rate = 2000000,
    .tx_pin = IO_PORTB_15,
    .rx_pin = IO_PORTB_14,
    .parity = UART_PARITY_DISABLE,
    .tx_wait_mutex = 0,//1:不支持中断调用,互斥,0:支持中断,不互斥
};

//使用自动分配串口号模式(-1):消耗内存大;指定串口号消耗内存小
int uart_num = uart_init(-1, &config);
if (uart_num < 0) {
    printf("uart init error");
}else{
    printf("uart%d init succ", uart_num);
}


const int uart_rx_dma_buffer_size = 768;
void *uart_rx_ptr = dma_malloc(uart_rx_dma_buffer_size);

struct uart_dma_config dma = {
    .rx_timeout_thresh = 100,   //接收数据不够frame_size,串口通信空闲100us后触发中断
    .event_mask = UART_EVENT_RX_FIFO_OVF | UART_EVENT_TX_DONE | UART_EVENT_RX_TIMEOUT,
    .irq_callback = uart_irq_func,//在中断里面调用
    .irq_priority = 3,
    .rx_cbuffer = uart_rx_ptr,   //使用支持dma的内存
    .rx_cbuffer_size = uart_rx_dma_buffer_size,
    .frame_size = uart_rx_dma_buffer_size,
};
//frame_size 一般是一个通讯帧的大小,rx_buffer_size一般为frame_size的两倍,内部是一个循环buffer
//串口dma初始化,串口收必须配置dma参数,使用前先调用uart_init
int r = uart_dma_init(uart_num, &dma);
if (r < 0) {
    log_error("dma init error %d", uart_num);
} else {
    log_info("dma init ok %d", uart_num);
}