背景
上月底,先楫发布了新的hpm_sdk版本,相比上次的版本,串口外设多了一个uart_hardware_rx_idle的sample,不过这个硬件的空闲中断,目前也只能适用于hpm6200系列。对于hpm67_64_63这三个系列的MCU并不支持硬件的空闲中断机制。
概述
开始这篇文章之前,有必要对以上的串口相关sample进行简单的描述。
①、uart_dma 这个demo是串口均使用DMA掌管进行收发,判断收发完成只需要一次DMA传输完成中断,但只能定长收发,适用于固定长度的收发场景。此demo适用先楫所有MCU系列。
②、uart_hardware_rx_idle 这个demo是使用硬件空闲机制+DMA接收进行接收不定长。适合接收不定长数据的场景,但此demo只适用先楫HPM6200系列MCU
③、uart_irq 这个demo是串口均适用中断来进行收发,可适用任何应用场景;中断进行接收带来的一个问题就是每接收一个字节就会进入一次中断,在数据量稍大的场景比较耗费中断次数。此demo适用先楫所有MCU系列。
4、uart_software_rx_idle 这个demo需要定时器的两个通道,并且互联到一个IO,这个IO需要接到串口的RX引脚;一个通道作为捕获RX引脚下降沿以此判断开始接收,另一个通道作为同步输入SYNC(触发会重置计数器)以此来判断接收完成。利用定时器来实现空闲机制实现接收不定长数据。适用在资源利用不紧张的场景,因为每个串口都需要定时器的两个通道作为辅助外设。此demo适用先楫所有MCU系列。
对于某些应用场合,比如接收不定长数据,有硬件空闲中断的支持,可以再配合DMA,可以以最小的中断损耗(只需要一次中断)以及最少的外设辅助(不需要定时器查询)实现接收不定长数据。
实现方案
看起来好像hpm67_64_63对于接收不定长很无能为力的样子,而且需要的资源也不少。但是可以通过查阅hpm67_64_63的UM用户手册,再配合下sdk的串口驱动。倒是可以不需要定时器作为辅助实现类似空闲机制来接收不定长数据,这也是本篇文章探讨的方式。
1、虽然先楫hpm67_64_63没有空闲中断机制,但是为了减少单个字节收发带来的中断损耗,hpm的串口支持16字节的RXFIFO和TXFIFO。
2、先楫目前所有系列的串口的FIFO都支持阈值触发中断,也就是FIFO存储到多少个字节认为一次有效数据进而触发中断。这样可以大大减少触发中断次数。那么有了FIFO阈值中断,就可以在进入中断后,一次性把FIFO的所有数据取出来。
虽然在UM手册中并无详细描述阈值范围,但是可以在SDK中找到相关痕迹。由枚举可知:
接收触发阈值为0 (uart_rx_fifo_trg_not_empty):代表RX FIFO不为空就一次触发中断,也就是接收到1字节就会触发中断
接收触发阈值为1 (uart_rx_fifo_trg_gt_one_quarter):代表RX FIFO接收到FIFO的四分之一就触发一次中断,也就是16字节的四分之一,即是接收到4字节就会触发一次中断。
接收触发阈值为2 (uart_rx_fifo_trg_gt_half):代表RX FIFO接收到FIFO的一半就触发一次中断,也就是16字节的一半,即是接收到8字节就会触发一次中断。
接收触发阈值为3 (uart_rx_fifo_trg_gt_three_quarters):代表RX FIFO接收到FIFO的四分之三就触发一次中断,也就是16字节的四分之三,即是接收到12字节以上就会触发一次中断。
3、有了FIFO阈值设置,先楫的串口还提供了个FIFO timeout的中断。
这个中断的产生需要以下的并立条件:
① 需要使能FIFO
② RXFIFO里面需要存在至少一个字符
③ RXFIFO在四个字符的时间再也没有收到新的字符
4、结合以上两个特点,当接收阈值中断产生,把接收的数据从FIFO提取出来;当FIFO timeout中断触发时,再最后把接收的数据从FIFO提取出来。这样能够实现一帧不定长数据的接收。用户可以根据以下特点以及自己的需求应用决定是否采取此方案。
① 相比单个字节接收,接收中断次数能减少10倍以上,比如接收1000个字节,单个字节接收需要进入1000次中断,而适用rx fifo阈值+fifo超时机制,只需要进入88次,相比减少12倍中断次数。
② 接收阈值中断和超时中断是一起使能触发的。
② 使用这种方式的话,接收无法配合DMA,但是发送可以使用DMA。
③ 超时条件是四个字符时间。也就是在四个字符时间没收到新数据,则判断超时。
验证
1、结合上述说明,开发一个sample进行验证。接收使用RX FIFO + FIFO timeout方式,发送则使用DMA。使用100到1000字节随机几组进行验证接收的中断次数。
对于RX FIFO + fifo timeout方式,代码只需要配置以下:
中断进行提取FIFO的数据:
2、实验现象:
由下面现象可看到,在数据量大的情况下,减少中断次数相对于单字节接收,1000个字节,相比单个字节中断需要1000次中断,而这个方式则需要88次中断。这样看来是相当客观的,还可以做到不用定时器辅助判断接收一帧不定长数据。
本帖最后由 RCSN 于 2023-4-11 17:56 编辑