串口方式:用串口接收中断方式接收,不是DMA. 遇到的问题:串口数据有帧丢失。 原因描述:在串口接收中断中接收到字节时变量size++。在main循环中解析一帧数据时size--,导致的size值不对,从而导致解析错误,导致数据帧丢失的情况。实际的原因是对size的操作不是原子操作的,具体更改见文档。有相关程序和具体的分析。 ### STM32串口变量的原子操作问题详解 #### 一、问题背景及描述 在进行STM32单片机的串口通信开发过程中,可能会遇到串口数据帧丢失的问题。这种现象通常表现为:尽管串口接收到了完整的数据包(如512个字节或1024个字节),但解析时却发现接收缓冲区的实际大小(mid_uart_rx.buf_size)小于预期值,从而导致解析过程出现错误,进而使得整个数据帧丢失。 #### 二、问题的具体表现 当使用中断方式处理串口接收任务而非DMA时,由于对缓冲区大小变量(size)的操作不是原子性的,即在同一时间可能发生多个任务对该变量进行读取和修改,这可能导致以下情况: 1. **中断中的++操作**:在串口接收中断发生时,每接收到一个字节,都会执行size++来增加接收数据的计数。 2. **main循环中的--操作**:在主循环中,每当解析出一个字节的数据后,执行size--来减少计数。 3. **非原子性导致的问题**:如果在main循环中执行size--时被中断打断,并且此时中断执行了size++操作,那么中断返回后,main循环继续执行size--操作时,就有可能将中断中size++的结果覆盖掉。这意味着即使中断已经增加了计数,但后续的size--操作仍然基于原来的值进行,最终导致计数不准确,从而引发数据帧丢失。 #### 三、问题原因分析 1. **非原子性操作**:STM32的CM0+内核不支持原子操作,这意味着对变量的操作(例如读取、修改、写回)不是在一个不可分割的时间段内完成的。因此,在多任务环境下,这些操作可能被其他任务打断,导致数据不一致。 2. **位带区限制**:即使是在支持原子操作的CM3内核中,原子操作也只能针对单个比特位,而不能对整个字节进行原子操作。这意味着在STM32中,对字节级别的变量进行原子操作是非常有限的。 #### 四、问题解决方案 1. **4.1 原子操作尝试**:尽管理论上可行,但由于STM32 CM0+内核不支持原子操作,且即使是CM3内核的原子操作也仅限于比特级别,因此这种方法并不可行。 2. **4.2 减少--操作**:一种较为保守的方案是,在所有数据都被成功解析之后,一次性地减少已解析的数据量。这种方法虽然降低了出现问题的概率,但仍存在一定的风险。 3. **4.3 开关串口中断的方法**:通过在对size进行操作前后禁用和启用串口中断,可以避免中断引起的竞争条件。然而,频繁地开启和关闭中断可能会引入额外的风险,如中断响应延迟等问题。 4. **4.4 在串口中断中减少解析的数据量**:最理想的做法是在串口中断内部处理所有的数据接收和计数更新,包括对已解析数据量的减少。这样可以在一个单一的上下文中完成所有操作,从而避免了因并发操作而导致的数据不一致性。 #### 五、总结与建议 对于STM32串口变量的原子操作问题,最可行的方案是在串口中断内部完成所有的数据接收和计数更新操作。这种方式不仅能够确保数据的一致性,还能最大限度地降低因并发操作引起的潜在风险。此外,虽然STM32 CM0+内核不支持原子操作,但在实际开发中可以通过一些技巧来规避这一限制,比如采用适当的编程策略来减少竞争条件的发生,从而提高系统的稳定性和可靠性。
- 粉丝: 8
- 资源: 16
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- asm-西电微机原理实验
- Arduino-arduino
- C语言-leetcode题解之70-climbing-stairs.c
- C语言-leetcode题解之68-text-justification.c
- C语言-leetcode题解之66-plus-one.c
- C语言-leetcode题解之64-minimum-path-sum.c
- C语言-leetcode题解之63-unique-paths-ii.c
- C语言-leetcode题解之62-unique-paths.c
- C语言-leetcode题解之61-rotate-list.c
- C语言-leetcode题解之59-spiral-matrix-ii.c