RT-Thread / rt-thread

RT-Thread is an open source IoT Real-Time Operating System (RTOS).
https://www.rt-thread.io
Apache License 2.0
10.47k stars 5.01k forks source link

stm32串口掉数据 #8428

Open cc-caixf opened 10 months ago

cc-caixf commented 10 months ago

场景:

现象

分析

还发现的问题

chnykn commented 10 months ago

你提到的“数据包中掉1个字节”,是不是在遇到 \r\n 两个字符的时候,\n没有了?

如果是这种情况的话,原因在于: ./rt-thread/components/net/at/src/at_client.c 的at_recv_readline和client_parser函数中 如果传输的是二进制文件或数据,其中内容当中凑巧有\r\n的字符,at_recv_readline函数会解释为换行 随后client_parser函数当中,会把把\n替换为\0, 导致内容变化。

cc-caixf commented 10 months ago

你提到的“数据包中掉1个字节”,是不是在遇到 \r\n 两个字符的时候,\n没有了?

如果是这种情况的话,原因在于: ./rt-thread/components/net/at/src/at_client.c 的at_recv_readline和client_parser函数中 如果传输的是二进制文件或数据,其中内容当中凑巧有\r\n的字符,at_recv_readline函数会解释为换行 随后client_parser函数当中,会把把\n替换为\0, 导致内容变化。

我是串口接收数据流, 没用到at, 跟你描述的不是同一个现象/问题.

thewon86 commented 9 months ago

https://club.rt-thread.org/ask/article/bfd92159ba11aef6.html 这里的开关中断换成只开关当前串口外设的中断就不会影响到其它串口了。

cc-caixf commented 9 months ago

这个串口DMA接收实现(stm32)就是个大坑!!!!!

现在的逻辑是: DMA一直接收, 根本不管buffer有没有溢出, 这将导致: 如果buffer溢出(buffer里面的值可能已经修改了几伦, 然而len值已经不能反应buffer内的真实数据量), 上层(应用层)根本感知不到buffer已经溢出(buffer中的数据已经覆盖再覆盖了, len已经背离真实情况), 上层怎么处理都恢复不了正常状态, 除非关闭再打开串口(清除底层buffer的len, 让len恢复正常).

正常的逻辑不应该是: DMA根据buffer的余量接收, 如果buffer满了, 就不应该接收, 等上层处理完了(buffer有余量了), 在接收数据啊.

thewon86 commented 9 months ago

这个串口DMA接收实现(stm32)就是个大坑!!!!!

现在的逻辑是: DMA一直接收, 根本不管buffer有没有溢出, 这将导致: 如果buffer溢出(buffer里面的值可能已经修改了几伦, 然而len值已经不能反应buffer内的真实数据量), 上层(应用层)根本感知不到buffer已经溢出(buffer中的数据已经覆盖再覆盖了, len已经背离真实情况), 上层怎么处理都恢复不了正常状态, 除非关闭再打开串口(清除底层buffer的len, 让len恢复正常).

正常的逻辑不应该是: DMA根据buffer的余量接收, 如果buffer满了, 就不应该接收, 等上层处理完了(buffer有余量了), 在接收数据啊.

还可以保证新的数据全部就收,丢弃最旧的数据,反正应用层已经处理不过来了,总需要丢掉一些数据。

放弃 v2 吧,论坛上还有个人多read了数据的,提问了不止三次了,没人敢解答,v2 的问题没人帮你解决得了的

cc-caixf commented 9 months ago

这个串口DMA接收实现(stm32)就是个大坑!!!!! 现在的逻辑是: DMA一直接收, 根本不管buffer有没有溢出, 这将导致: 如果buffer溢出(buffer里面的值可能已经修改了几伦, 然而len值已经不能反应buffer内的真实数据量), 上层(应用层)根本感知不到buffer已经溢出(buffer中的数据已经覆盖再覆盖了, len已经背离真实情况), 上层怎么处理都恢复不了正常状态, 除非关闭再打开串口(清除底层buffer的len, 让len恢复正常). 正常的逻辑不应该是: DMA根据buffer的余量接收, 如果buffer满了, 就不应该接收, 等上层处理完了(buffer有余量了), 在接收数据啊.

还可以保证新的数据全部就收,丢弃最旧的数据,反正应用层已经处理不过来了,总需要丢掉一些数据。

放弃 v2 吧,论坛上还有个人多read了数据的,提问了不止三次了,没人敢解答,v2 的问题没人帮你解决得了的

看了博流的串口DMA RX实现, 感觉这种实现方式很合理, 先DMA到指定底层buffer中, 再在半满/全满/idle中断, 将底层buffer中的数据读到ringbuffer中, 应用层再从ringbuffer中读数据. 这样ringbuffer满不满(应用层处理不处理的过来)跟DMA无关

thewon86 commented 9 months ago

这个串口DMA接收实现(stm32)就是个大坑!!!!! 现在的逻辑是: DMA一直接收, 根本不管buffer有没有溢出, 这将导致: 如果buffer溢出(buffer里面的值可能已经修改了几伦, 然而len值已经不能反应buffer内的真实数据量), 上层(应用层)根本感知不到buffer已经溢出(buffer中的数据已经覆盖再覆盖了, len已经背离真实情况), 上层怎么处理都恢复不了正常状态, 除非关闭再打开串口(清除底层buffer的len, 让len恢复正常). 正常的逻辑不应该是: DMA根据buffer的余量接收, 如果buffer满了, 就不应该接收, 等上层处理完了(buffer有余量了), 在接收数据啊.

还可以保证新的数据全部就收,丢弃最旧的数据,反正应用层已经处理不过来了,总需要丢掉一些数据。 放弃 v2 吧,论坛上还有个人多read了数据的,提问了不止三次了,没人敢解答,v2 的问题没人帮你解决得了的

看了博流的串口DMA RX实现, 感觉这种实现方式很合理, 先DMA到指定底层buffer中, 再在半满/全满/idle中断, 将底层buffer中的数据读到ringbuffer中, 应用层再从ringbuffer中读数据. 这样ringbuffer满不满(应用层处理不处理的过来)跟DMA无关

serialX 就是这样做的,见前链接