这些问题都是我在做大创项目的时候遇到的问题,这次先把内存问题说了,下次说怎么用代码实现通信协议的,这是我第一次写博客,请各位多多指正。
再说之前先感谢学校老师和公司带我的师傅的帮助,没有他们的帮忙很那开展调试。
我用的是STM32F103C8T6,FLASH是128K,RAM是20K,只要是涉及算法和通信的就有点不够用
#1.发现内存不足
当我把代码修改好编译成功下载到STM32中,发现有时候可以流畅运行,有时候非常卡顿甚至开机上电卡死,我刚开始以为是代码哪里不对,哪里阻塞了;于是开始用keil5的调试模式,接上ST-LINK,一条代码一条代码调试,后来发现有时候就跑到硬件错误中断里去了;
再加上算法里要用到两个500的数组,于是我怀疑是内存的问题。
uint32_t aun_ir_buffer[500]; //IR LED sensor
int32_t n_ir_buffer_length; //data length
uint32_t aun_red_buffer[500]; //Red LED sensor data
int32_t n_sp02; //SPO2 value
int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
int32_t n_heart_rate; //heart rate value
int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
uint8_t uch_dummy;
于是我打开编译好自动产生的listings文件夹下的.map文件,找到Image component sizes
发现Total RW Size (RW Data + ZI Data)
,已经超过20k到达31k多,也就是上电后FLASH要往RAM写的数据。怪不得我一上电就死机。
#2.解决方法
#2.1 查看变量
你在代码里申请的所有变量,包括局部和全局变量,都能在.map里看到,变量在Image Symbol Table
下找,局部变量Local Symbols
全局变量Global Symbols
我发现我的两个500数组全在局部变量里,可能写入栈的时候爆了,于是我把这两个放到全局变量,为了防止相同问题,我们需要把相对应栈的大小调大一些。
STM32一般是先把变量写入栈的,如果变量太大或者栈太小有可能会导致卡顿或者死机。
#2.2 修改栈大小
在STM32的启动汇编文件里有相关设置
Stack_Size EQU 0x00001FFF
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; Heap Configuration
; Heap Size (in Bytes)
;
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
THUMB
;Stack_Size是栈大小的设置
;Heap_Size一般用于malloc函数,如果代码里没有malloc函数,建议清零
#2.3 修改栈大小出现编译错误解决方案
当然具体的Stack_Size
的大小需要自己去调试,只要编译不报错就行,我这里调的是0x00001FFF,大一点编译就会报错,就像这样。
最后当一切都调试好,编译成功后,再打开.map文件,翻到最后,查看Total RW Size (RW Data + ZI Data)
只要小于20k就行,但是因为我的代码里有很多延时检测标志位的代码,所以还是感觉很卡顿。
如果你不确定程序是不是在运行,你可以加一个心跳灯,让他跑一遍程序就闪一下。
LED1( ON );
Delay(0x4000);
LED1( OFF );
Delay(0x4000);
延时代码
void Delay(__IO u32 nCount)
{
for(; nCount != 0; nCount--);
}