2322|1

1366

帖子

6

TA的资源

版主

楼主
 

[玩转先楫串口uart外设系列之一]利用硬件FIFO实现非阻塞方式发送 [复制链接]

 

一、背景

    在先楫HPM6000系列中,DMA控制器分别有HDMA和XDMA,每个控制器有8个通道,一共有16个DMA通道。但是hpm6000系列中的串口有些16个,有些8个等等。如果相对应的每个串口的接收和发送都使用了DMA,那么也不一定够用,而且有些重要的外设也需要DMA。在这种情况下,硬件的串口FIFO就有了实际意义了。

    先楫hpm6000系列的串口,发送和接收都有16字节的硬件FIFO。

 

    对于接收使用硬件FIFO,还可以使用接收FIFO timeout标志来接收不定长数据,这个先楫官方公众号对此方案进行了阐述(传送门:再谈 HPM6700/6400/6300 产品系列串口接收不定长数据的方式),对应的例子也在hpm_sdk 1.2版本当中,对应相对路径为 ../hpm_sdk/samples/drivers/uart/uart_rx_timeout

    因此,本文只阐述发送端的利用硬件FIFO实现无阻塞发送机制。

 

二、适用性

    相比单字节发送进入中断来说,可以减少16倍的中断次数,比如发送5112字节,不使用FIFO的情况下,发送需要进入512次中断,如果使用FIFO,那么只需要进入32次中断。

    所以对于这种方式来说,有一部分应用场景可以适用。

    1、使用的串口数量多,但是DMA通道不够用的情况。

    2  、发送数据量不大的情况。

    3、内部数据交互有ringbuffer,依次出列发送的情况。

    4、需要非阻塞发送的情况。

    5、实在不想用DMA但是想非阻塞发送的情况。

 

三、实现流程

    对于这个流程,hpm_sdk同样也提供了对应例子,对应相对路径为 ../hpm_sdk/samples/drivers/uart/uart_irq。本文就以此例子作为本文阐述发送的sample。

    该例子主要是演示串口中断收发功能,也就是串口的收发都在中断中完成,串口的收发可以通过使能FIFO_MODE来决定是否使用硬件FIFO进行收发。

    例子中的CMakelists.txt中,宏定义了CONFIG_UART_FIFO_MODE,默认使能了硬件FIFO模式。这样我们可以根据使能和禁能硬件FIFO来测试发送的中断次数。

 

(一)配置流程

1、串口引脚和时钟初始化

    需要注意的是,在自己的项目当中,需要先初始化好引脚,再开启工作时钟。否则可能会出现串口收发上电乱码的问题。这是因为这时候串口已经开始工作,而后初始化引脚后检测到串口电平的变化导致认为是数据产生。

    在hpm_sdk中,每个官方开发板的board.c中对于串口的初始化都是基于上述配置。比如hpm6750evk2的board的串口初始化。内部函数也做了注释说明,为了其可靠性,建议开发者按照官方操作流程进行初始化。

 

2、串口配置初始化

    对于配置初始化,比如设置波特率,parity,传输长度等等,在hpm_sdk中,已经封装为uart_config_t结构体进行描述,在其结构体成员中赋值对应成员,然后调用uart_init这个API接口,即可完成串口配置初始化。

 

    在uart_config_t成员赋值中,驱动提供了一个缺省接口赋值,建议开发者可以进行调用,以便串口可以在缺省安全的参数启动。

 

 

(二)硬件FIFO开启

    在hpm_sdk的uart_irq这个sample中,根据上述阐述,可以通过fifo_enable进行对硬件FIFO的开启和使能,对串口的数据寄存器,手册中,定义了两个寄存器,一个是接收一个是发送。

分别是RBR和THR寄存器。开发者可以根据FIFO模式进行对应的赋值操作。

 

    在hpm_sdk中,对于这两个寄存器,注释也做了说明。

    当为FIFO模式的时候,这两个寄存器相当接收和发送硬件FIFO,而当非FIFO模式,也就是BUFFER模式的时候,这两个寄存器仅仅是个字节缓存,也就是单个读写。

 

(三)填充FIFO,使能中断

    经过上述初始化之后,需要开启相关中断,对于中断使能位,手册和SDK同样提供了对应了寄存器操作API。比如hpm6700系列。

 

    在这里使能了发送FIFO为空时候产生中断,也就是上述的ETHEI位域,以便告知这时候发送的硬件FIFO是为空的,可以填充数据到FIFO。

    当为非FIFO模式的时候,THRE标志产生的中断标志依旧可以作为发送单字节完成标志。

 

    在发送利用硬件FIFO流程:

1、在填充硬件FIFO之前,需要关闭掉对应的中断,然后根据发送的长度和FIFO长度(16字节)比较得出最小长度。以便保证FIFO空间不溢出,塞满整个硬件FIFO,之后开启FIFO为空中断

2、进入中断之后,重复1的操作,进而在中断里面继续塞入硬件FIFO

3、在中断自己操作2,直到整个发送数据完成。

这个流程,SDK中的例子也封装好了演示接口

 

    那么当接收收到指定的长度数据后,开始在中断调用以上接口,以此在中断循环上述流程。详细的代码参考可以在hpm_sdk对应的sample中看到。

 

四、验证

    在官方的sample中,可以做个测试,以此来验证FIFO模式和非FIFO模式发送所需要的中断次数。收发数据固定为128字节。

    定义一个中断次数变量,每当进入一次FIFO为空中断标志,累加1。发送完成打印中断次数。

可以从打印log看到,除了第一次配置发送不需要在中断,按16个字节FIFO,128字节需要填充8次FIFO,相比单字节发送中断次数需要128次中断,利用硬件FIFO发送只需要7次,缩短16倍以上的次数。

 

五、实战(ringbuffer+硬件FIFO实现异步非阻塞发送)

    在实际项目当中,对于发送来说,有一部分利用ringbuffer 软件FIFO异步发送来实现无阻塞发送方案。

    把需要发送的数据入列到软件ringbuffer,在一个线程或者状态机,轮询ringbuffer是否有待出列的数据,如果有就进行发送。实际发送的实现可以DMA发送,或者阻塞发送一定数据量。

    在这里可以使用上述的阐述,流程如下:

    1、在有待发送的软件FIFO出列时候,先判断下硬件FIFO是否为空,若为空,则关闭发送为空的中断,然后读取ringbuffer数据,塞入到硬件FIFO当中

    2、当ringbuffer仍有数据,那开启发送为空的中断,若没有,那就是这一帧发送完成,不需要再开中断。

    3 、进入中断后,循环1。

    如此以来可以实现异步无阻塞发送,并且最大化减少中断次数。

 

    串口中断判断是否为发送FIFO为空标志,若是,则硬件FIFO可以继续塞入数据,再次调用以上接口

 

效果如下:

 

六、总结

1、先楫对于串口这个外设,提供了16字节的发送和接收硬件FIFO,开发者可以根据自己需求对其进行利用。

2、对于DMA不适用的场景,比如上述的背景描述,可以利用16字节的硬件FIFO,相比非FIFO能减少16倍以上的中断次数来最大化实现发送性能,实现非阻塞式发送。

最新回复

在发送时,有一部分用ringbuffer 软件FIFO异步发送来实现无阻塞发送的方法,实际项目中经常使用的,谢谢分享   详情 回复 发表于 2023-7-25 07:23
点赞 关注
个人签名

1084534438 欢迎交流  [加油,一切皆有可能]

 
 

回复
举报

6822

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

在发送时,有一部分用ringbuffer 软件FIFO异步发送来实现无阻塞发送的方法,实际项目中经常使用的,谢谢分享

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表