我在STM32f405芯片上开发蓝牙接收功能,发现从发送端过来的数据,居然会被随机修改。非常诡异的是,我的实验发现,缓存数组经常是某个位置如i的数据不对,而i-1和i+1的位置和其他位置都是正确的。为排查该问题,
我首先怀疑蓝牙数据传送出错。后来问AI得知蓝牙传输物理层面因为有空口确实有可能有出错,但是模块本身有纠错和重传机制,对于应用层不用考虑这个问题。另外,我通过调试信息发现在DMA接收中断的时刻,绑定的接收circular buffer中的数据是完全正确的。我用的方法是发送方从0开始,不断加1发送数据,接收端同样从0开始接收,预期下一个接收到的字节是上一个+1。数据完全对的上,这就排除了蓝牙模块的问题。
但是从DMA绑定的circular buffer拷贝到程序另开的缓存buffer,仅仅是memcpy,完后再查这个缓存buffer,发现数据就有随机不正确的。我也通过头尾指针比较排除了由于数据来得太快,缓存来不及处理的overflow问题。memcpy也很稳定,不可能出现拷贝出错。
那这个问题很奇怪,我从AI中获得了提示,有可能是stack太小了,出现了stack overflow。
芯片的stack size在 startup_stm32f405xx.s中定义,
;* <<< Use Configuration Wizard in Context Menu >>>
;
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x0400
stack size只有1024 byte,但我的代码里有这么一段:
void Bt_Task(void)
{
u8 batch_bufBT_STREAM_FIFO_LEN;
其中,BT_STREAM_FIFO_LEN 是1024。因为batch_buf是这个函数的local变量,它会分配在stack里,stack本身只有1K Byte,这样立马就stack overflow了,内容会拓展到其他内存空间,出现unexpected error就很正常了。
解决方案:
- 把stack空间改大。因为改芯片的SRAM有128K Bytes,把stack空间增加到4K Bytes问题不大。
Stack_Size EQU 0x1000
- 不创建大容量local数组,把数组移到全局变量,全局变量不占用stack空间。
这么改以后,内存中的数据就完全正常了。