volatile:防止编译器进行“过度优化”,保证每次访问变量时都真的去读/写它的内存地址,而不是使用寄存器里的“缓存”值。
编译器的工作是让你的代码跑得更快。其中一个重要优化是:把变量从慢速的内存加载到快速的CPU寄存器中,然后在寄存器里进行多次操作,最后再写回内存。这在单线程、无外部干扰的程序里是完全正确且高效的。但是,在嵌入式系统里,一个变量的值可能被“外部力量”改变,而编译器并不知道。如果编译器还傻傻地用着寄存器里的“旧值”,程序就会行为错乱。
BSP工程管理
链接脚本imx6ul.lds文件要加上start.o的路径如下图第五行。
Makefile文件
第1~7行定义了一些变量,除了第2行以外其它的都是跟编译器有关的,如果使用其它编译器的话只需要修改第1行即可。第2行的变量TARGET目标名字,不同的例程名字不一 样。
第9行的变量INCDIRS包含整个工程的.h头文件目录,文件中的所有头文件目录都要添 加到变量INCDIRS中。比如本例程中包含.h头文件的目录有imx6ul、bsp/clk、bsp/delay和bsp/led, 所以就需要在变量INCDIRS中添加这些目录,即:
仔细观察的话会发现第9~11行后面都会有一个符号“\”,这个相当于“换行符”,表示本行和下一行属于同一行,一般一行写不下的时候就用符号“\”来换行。在后面的裸机例程中会根据实际情况来在变量INCDIRS中添加头文件目录。
第17行是变量SRCDIRS,和变量INCDIRS一样,只是SRCDIRS包含的是整个工程的所 有.c 和.S 文件目录。比如本例程包含有.c和.S的目录有bsp/clk、bsp/delay、bsp/led 和 project, 即:
第26行的变量INCLUDE使用到了函数patsubst,通过函数patsubst给变量INCDIRS添加 一个“-I”,即:
加“-I”的目的是因为Makefile语法要求指明头文件目录的时候需要加上“-I”。
第28 行变量SFILES 保存工程中所有的.s汇编文件(包含绝对路径),变量SRCDIRS已经 存放了工程中所有的.c和.S文件,所以我们只需要从里面挑出所有的.S汇编文件即可,这里借助了函数foreach和函数wildcard,最终SFILES如下:
第29行变量CFILES和变量SFILES一样,只是CFILES保存工程中所有的.c文件(包含绝 对路径),最终CFILES如下:
第31和32行的变量SFILENDIR和CFILENDIR包含所有的.S汇编文件和.c文件,相比变量SFILES 和CFILES,SFILENDIR 和 CFILNDIR 只是文件名,不包含文件的绝对路径。使用 函数notdir 将SFILES和CFILES中的路径去掉即可,SFILENDIR和CFILENDIR如下:
第34和35行的变量SOBJS和COBJS是.S和.c文件编译以后对应的.o文件目录,默认所 有的文件编译出来的.o文件和源文件在同一个目录中,这里我们将所有的.o文件都放到obj文件夹下,SOBJS和COBJS内容如下:
第36行变量OBJS是变量SOBJS和COBJS的集合,如下:
编译完成以后所有的.o文件就全部存放到了obj目录下。
第38行的VPATH是指定搜索目录的,这里指定的搜素目录就是变量SRCDIRS所保存的 目录,这样当编译的时候所需的.S和.c文件就会在SRCDIRS中指定的目录中查找。
自动变量
加上清除BSS段,代码不运行原因