C语言的本质
程序执行
程序编译生成axf/hex/bin文件烧写到单片机flash中,cpu上电后依次读取flash中的指令并执行这些指令
在调用函数时,LR寄存器保存执行函数前下一条指令的地址,执行完函数后跳回到LR寄存器中保存的地址。
在调用函数前,先进行保存现场,将当前寄存器中的数值压入栈中
PC保存函数的地址,CPU每次都是执行PC寄存器中的指令
局部变量
局部变量初始化先分配在栈中,在初始化时先使用压栈指令给局部变量分配空间,再使用mov指令和str指令对该空间进行赋值
在进入函数时分配局部变量和程序开始执行时分配局部变量相同,在退出函数时依次将当前栈内的数据弹栈赋值给寄存器,将进入栈时压入的LR寄存器的数值赋值给PC寄存器,栈指针恢复到进入函数之前的位置。
全局变量的初始化和空间分配
在调用main函数之前需要先调用一个copy函数将flash中的全局变量全部复制到ram中
链接器会根据已经指定的内存地址来进行空间分配
在对全局变量进行赋值操作时,首先去flash中读取全局变量在内存中的地址,根据该地址来得到全局变量的数值
没有进行初始化或者初始化为0的全局变量/静态局部变量存储到bss段
多线程访问全局变量会产生非线程安全现象,在线程A对变量进行修改时,切换到线程B,切换前进行保护现场的操作,将还未经修改寄存器数值保存到堆栈,线程B修改寄存器数值后切换到A线程时需要恢复A线程的现场,将堆栈中未经修改的寄存器数值又赋值回了寄存器中,相当于线程B进行了无效操作。
为防止以上现象发生可以在访问全局变量时关中断,防止中断函数打断访问过程。
RAM、ROM和FLASH
ROM中存放用户程序和需要永久保存的数据。
RAM中存储用户程序中用到的变量,包括全局变量,局部变量,堆栈段。
FLASH中存储用户程序和需要永久保存的数据。
以f103为例,ram仅有64k,flash有512k,代码段存放在flash中
栈和堆
栈向下增长
堆就是一块可以使用malloc和free函数管理的空闲空间
堆的简易实现为一个占位空间大的数组
1 | volatile char mybuf[20*1024]; |
单片机程序运行栈不够的时候,程序会跑飞