来源于小伙伴提问。
对于如此高的网络数据吞吐量,依赖单纯的中断或主循环显然不够有效。
需要通过合理的机制进行优化,分离网络接收和数据处理的工作。
STM32 MCU 提供了 DMA 功能,它可以让网口芯片直接将接收到的数据写入内存,而无需 CPU 介入。
利用 DMA 传输数据后,可以通过中断通知主程序处理。
DMA 操作:DMA 将网络数据直接从外设(以太网控制器)传送到内存中。这样可以在后台异步处理数据的接收,减轻 CPU 的负担。
中断通知:通过中断机制,数据接收完成后触发处理,通知主程序进行处理。
这样可以大大提高数据接收速率,并避免在中断中直接进行数据处理所带来的延迟和 overflow 问题。
对于网络数据的处理,环形缓冲区是一个经典方案,可以有效解决数据丢失和延迟问题。
中断只负责把数据存入缓冲区,而数据的处理则放到主循环或独立的任务中。
中断将接收到的数据直接写入环形缓冲区。
主循环(或者通过任务调度)从缓冲区读取数据进行处理。
由于环形缓冲区是循环的,可以有效避免缓冲区溢出。
但需要注意的是,环形缓冲区的管理需要考虑并发访问问题,可以通过 信号量 或 互斥锁 来确保数据一致性。
LWIP 默认的中断处理会处理很多协议栈的细节,可能导致处理速度变慢。
你可以通过以下方法优化 LWIP:
减少协议栈的调度频率:例如,降低内存分配和释放的频率,或者调整 LWIP 的定时器频率(通过 SYS_ARCH 配置来减少定时器中断的频率)。
优化内存池和缓冲区大小:根据接收流量,调整 LWIP 的内存池、TCP 和 UDP 的缓冲区大小。
调整缓冲区的大小和数量:合理配置 LWIP 的输入输出缓冲区,确保足够的缓冲空间来缓存接收到的数据,避免数据丢失。
LWIP 本身也支持通过定时器和任务系统来分离网络数据的接收与协议栈的处理。
将数据接收和协议栈处理分离,避免中断中处理过多任务。
接收数据的异步处理:通过 DMA 和环形缓冲区将数据接收放到主循环或者独立的任务中,协议栈只负责处理传输层的数据。
TCP/UDP 协议的解包和处理:这些可以在主循环中执行,避免长时间占用中断。
根据实际情况选择适合的网络协议,如果网络中没有可靠性要求,可以选择 UDP 协议,避免 TCP 的连接管理开销。
对于大流量数据,可以考虑将数据拆分为小包或者压缩数据,减少网络负担和协议栈处理时间。