程序执行

程序编译生成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
2
3
4
5
6
7
8
volatile char mybuf[20*1024];
volatile int index = 0;
void *malloc(int size)
{
char *ret = &mybuf[index];
index += size;
return ret;
}

单片机程序运行栈不够的时候,程序会跑飞

函数