rt-thread icon indicating copy to clipboard operation
rt-thread copied to clipboard

[bsp/stm32] 简化drv_usart中的DMA接收逻辑

Open BreederBai opened this issue 3 years ago • 19 comments

拉取/合并请求描述:(PR description)

[ 原有的DMA接收逻辑不是很清晰,我按照V2的代码进行了简化。已经在stm32427和405上进行了测试,功能正常。 ]

以下的内容不应该在提交PR时的message修改,修改下述message,PR会被直接关闭。请在提交PR后,浏览器查看PR并对以下检查项逐项check,没问题后逐条在页面上打钩。 The following content must not be changed in the submitted PR message. Otherwise, the PR will be closed immediately. After submitted PR, please use a web browser to visit PR, and check items one by one, and ticked them if no problem.

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • [ ] 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • [ ] 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • [ ] 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • [ ] 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • [ ] 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • [ ] 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • [ ] 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • [ ] 本拉取/合并请求代码是高质量的 Code in this PR is of high quality
  • [ ] 本拉取/合并使用formatting等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification

BreederBai avatar Aug 31 '22 09:08 BreederBai

有没有做过擦写片内 Flash 同时 DMA 接收数据的测试?

我记得 STM32 在擦写片内 Flash 时,CPU 是没法响应中断的,此时 DMA 依然可以持续的接收数据。等擦写 Flash 完成后,中断 ISR 才会执行,此时可能串口空闲中断晚于串口 DMA 缓存区满中断。所以为了考虑这个情况,专门增加了一些额外逻辑。可以留意下当时的这个 PR https://github.com/RT-Thread/rt-thread/pull/739

armink avatar Aug 31 '22 09:08 armink

有没有做过擦写片内 Flash 同时 DMA 接收数据的测试?

我记得 STM32 在擦写片内 Flash 时,CPU 是没法响应中断的,此时 DMA 依然可以持续的接收数据。等擦写 Flash 完成后,中断 ISR 才会执行,此时可能串口空闲中断晚于串口 DMA 缓存区满中断。所以为了考虑这个情况,专门增加了一些额外逻辑。可以留意下当时的这个 PR #739

刚测试了下,在DMA 接收数据时,擦内部flash,没有发现有什么异常

BreederBai avatar Aug 31 '22 09:08 BreederBai

有没有做过擦写片内 Flash 同时 DMA 接收数据的测试? 我记得 STM32 在擦写片内 Flash 时,CPU 是没法响应中断的,此时 DMA 依然可以持续的接收数据。等擦写 Flash 完成后,中断 ISR 才会执行,此时可能串口空闲中断晚于串口 DMA 缓存区满中断。所以为了考虑这个情况,专门增加了一些额外逻辑。可以留意下当时的这个 PR #739

刚测试了下,在DMA 接收数据时,擦内部flash,没有发现有什么异常

测试时,在内部 Flash 擦写过程中,是有确认触发 DMA 缓冲区满中断的吗?

armink avatar Sep 02 '22 05:09 armink

有没有做过擦写片内 Flash 同时 DMA 接收数据的测试? 我记得 STM32 在擦写片内 Flash 时,CPU 是没法响应中断的,此时 DMA 依然可以持续的接收数据。等擦写 Flash 完成后,中断 ISR 才会执行,此时可能串口空闲中断晚于串口 DMA 缓存区满中断。所以为了考虑这个情况,专门增加了一些额外逻辑。可以留意下当时的这个 PR #739

刚测试了下,在DMA 接收数据时,擦内部flash,没有发现有什么异常

测试时,在内部 Flash 擦写过程中,是有确认触发 DMA 缓冲区满中断的吗?

这个不确定,我不是在调试下测试的

BreederBai avatar Sep 02 '22 08:09 BreederBai

测试了下,擦flash的时候还会响应中断,下面是我打断点的地方。但我不清楚打断点的地方对不对。 HAL_FLASHEx_Erase函数中 image

drv_usart.c里dma_recv_isr函数中 image

BreederBai avatar Sep 04 '22 05:09 BreederBai

擦写 Flash 的过程中,是不会执行代码的,也包括 ISR ,擦写完成才会触发 ISR。可以选择 F4 芯片,它有个 128KB 扇区,擦除时间较长,利于测试。

armink avatar Sep 05 '22 01:09 armink

擦写 Flash 的过程中,是不会执行代码的,也包括 ISR ,擦写完成才会触发 ISR。可以选择 F4 芯片,它有个 128KB 扇区,擦除时间较长,利于测试。

哦哦,原来是这样,如果原理上是不会执行的,那我测试的应该有些问题。我还有个疑问,我目前的修改只是对之前代码的整理,如果没有考虑擦flash的情况,那之前的代码也没有考虑。我之所以改这个地方,是因为最近一次关于计算DMA接收长度的更改,导致我的代码接收数据出了问题,那个改法应该是有BUG。

BreederBai avatar Sep 05 '22 03:09 BreederBai

擦写 Flash 的过程中,是不会执行代码的,也包括 ISR ,擦写完成才会触发 ISR。可以选择 F4 芯片,它有个 128KB 扇区,擦除时间较长,利于测试。

我的设想是在擦除flash前后打两个断点,在DMA中断函数里打一个断点,然后去看是不是擦flash的时候,只有走完擦flash的第二个断点后,才会进中断。按我发的图中那样,在擦flash第二个断点前,就进DMA中断了。 请问,按照我这个思路去测试,该把断点打到哪个地方呢

BreederBai avatar Sep 05 '22 03:09 BreederBai

@armink 您提到的因为考虑到擦flash的情况,增加的额外逻辑,我使用的这个代码里似乎是有的。

BreederBai avatar Sep 05 '22 03:09 BreederBai

建议这块最好增加一个测试用例,单片机接收测试时候,增加数据有效性校验检查,保证即便有 Flash 擦写条件下也不影响正常接收数据的有效性就好了

armink avatar Sep 06 '22 01:09 armink

没看出来哪儿简化了。看看 serialX 里的处理,那个才叫简化 dma_cnt = RT_SERIAL_DMA_BUFSZ - __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); 三种中断,同一个公式搞定。

thewon86 avatar Sep 06 '22 02:09 thewon86

建议这块最好增加一个测试用例,单片机接收测试时候,增加数据有效性校验检查,保证即便有 Flash 擦写条件下也不影响正常接收数据的有效性就好了

能具体下如何测试吗?我不太清楚该怎么测试。

BreederBai avatar Sep 06 '22 02:09 BreederBai

没看出来哪儿简化了。看看 serialX 里的处理,那个才叫简化 dma_cnt = RT_SERIAL_DMA_BUFSZ - __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); 三种中断,同一个公式搞定。

如果能用一个公式最好了,没注意serialX中的处理,目前只是按照serialv2中的方法,做了统一。改这个地方也是因为之前的逻辑,接收有些问题。serialX框架中,USB虚拟串口可以使用吗?我目前测试serialv2框架的USB虚拟串口接收不了数据

BreederBai avatar Sep 06 '22 02:09 BreederBai

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

thewon86 avatar Sep 06 '22 05:09 thewon86

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

对,是cdc_vcom.c,这个用到了rt_hw_serial_isr,而且和serial有些耦合,所以导致串口架构会影响USB虚拟串口,这个地方做的是有些问题,,,不知道serialX,有没有对cdc_vcom.c做适配

BreederBai avatar Sep 06 '22 12:09 BreederBai

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

对,是cdc_vcom.c,这个用到了rt_hw_serial_isr,而且和serial有些耦合,所以导致串口架构会影响USB虚拟串口,这个地方做的是有些问题,,,不知道serialX,有没有对cdc_vcom.c做适配

上面说了,vcom 和 串口没半毛钱关系,没兴趣去做适配。 自己重写 vcom 驱动吧,把 serial 相关的东西全删掉。

thewon86 avatar Sep 07 '22 00:09 thewon86

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

对,是cdc_vcom.c,这个用到了rt_hw_serial_isr,而且和serial有些耦合,所以导致串口架构会影响USB虚拟串口,这个地方做的是有些问题,,,不知道serialX,有没有对cdc_vcom.c做适配

上面说了,vcom 和 串口没半毛钱关系,没兴趣去做适配。 自己重写 vcom 驱动吧,把 serial 相关的东西全删掉。

如果是这样,那感觉有些问题,新功能的引用,不应该破坏原有的功能

BreederBai avatar Sep 07 '22 02:09 BreederBai

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

对,是cdc_vcom.c,这个用到了rt_hw_serial_isr,而且和serial有些耦合,所以导致串口架构会影响USB虚拟串口,这个地方做的是有些问题,,,不知道serialX,有没有对cdc_vcom.c做适配

cdc_vcom里的串口代码是将和pc通信的通道注册为了一个串口设备。这样应用层直接打开这个vcom串口就可以和PC通信了。

Guozhanxin avatar Sep 07 '22 02:09 Guozhanxin

你说的 “USB虚拟串口” 是 cdc_vcom.c 文件实现的功能吗? 看看这个文件源码就知道了,这个东西跟串口驱动没一点儿关系,借用了 rt_hw_serial_isr 这个函数和 struct rt_uart_ops 这个结构体,很奇葩的想法。

对,是cdc_vcom.c,这个用到了rt_hw_serial_isr,而且和serial有些耦合,所以导致串口架构会影响USB虚拟串口,这个地方做的是有些问题,,,不知道serialX,有没有对cdc_vcom.c做适配

cdc_vcom里的串口代码是将和pc通信的通道注册为了一个串口设备。这样应用层直接打开这个vcom串口就可以和PC通信了。

serial V2中的虚拟串口似乎有问题,目前有其他人提这个问题吗?有计划多久解决这个问题吗

BreederBai avatar Sep 13 '22 03:09 BreederBai