以前在iar下开发都是在官方例程或网络中下载的例程,开发时IAR直接跳入main中执行c代码,最近想建立个新的stm32工程来写一些汇编文件了解下CM3汇编指令,因而痛苦摸索了不少天。网络
起初建立了IAR新工程,使用的stm32f103x,加入了官方提供的iar工程文件:startup.s,本来想将keil下的startup文件直接copy过来,然而现实是keil和iar使用的一些汇编伪指令差异很大,一个百行的startup.s就有一万个错误,直接爆炸。不过官方分别提供了keil iar gcc对应的工程及启动文件,能够按需求使用。函数
startup.s文件中最重要的天然是__vector_table,一个异常向量表,表中记录了全部异常的入口地址3d
除第一个外,其它都是入口地址。CM3将第一个视为芯片复位后MSP的值,这里我一直有个猜想但尚未实验,CM3的MSP不须要手动配置,而是复位后默认去flash的0x80000000地址去取 (个人stm32f103 flash首地址从0x80000000开始,彷佛也会被映射位0x0,两个地址均可用,但相对的都是flash的0地址。也就是说工程生成的bin文件前四个字节就是MSP的复位值),这样的话是否是CM3的bootloader不必定非要使用汇编来写,直接跑c也是能够的?若是说汇编可以使用16位指令来节省空间,那么c在编译时不会生成16位指令吗?blog
加入启动文件还要根据芯片选择官方提供的.ICF文件,ICF文件主要用来告诉编译器芯片的RAM ROM地址范围以及程序中的不一样段在存储器中的存放位置。内存
IAR中有一些段的内部关键字如CSTACK,HEAP等开发
使用的ICF中将向量表放在flash的首地址编译器
place at address mem:0x80000000 { readonly section .intvec };源码
startup.s中__vector_table天然是被放在.intvec段:flash
SECTION .intvec:CODE:NOROOT(2)it
在IAR生成的map文件中能够清晰的看到
至于A1 P1 字样,IAR解释为A是绝对位置,P则是相对位置
这两个文件添加完成后执行编译发现报错:__iar_program_start没有定义,
在IAR option中看到了他的身影:
IAR执行链接时默认去找__iar_program_start入口,最开始第一个钩我没有勾上,致使没法链接入IAR提供的.S文件,__iar_program_start天然不会被找到。这个入口也能够选择被从新定义彻底由开发者重命名重写。
IAR安装目录下提供了不少种类芯片的.S文件,其中一些是启动文件和初始化文件,CM3的__iar_program_start被放在cstartup_M.s中。
起初我尝试了重写__iar_program_start入口,这个模块中主要去初始化全局段以及对一些未赋值的全局变量段清零就能够了,后来发现IAR .map文件中有
Region$$Table$$Base 0x00000000 -- Gb - Linker created -
Region$$Table$$Limit 0x00000000 -- Gb - Linker created -
字样,查阅了一些资料有说这两个符号标志了一块内存,里面存放了多个段的信息。实际上到最后我也没摸索出该怎么使用它们,主要是全局变量所在的段如何与ICF文件对应起来成了问题。若是pass这一过程那么C代码中则不容许有全局变量,汇编中不能使用DCB之类的开辟内存,有的话IAR则会报出__iar_data_init3错误,一直搞不懂全局变量为何和__iar_data_init3会有关。
这个__iar_data_init3模块在官方提供的__iar_program_start里面被调用过,因为没有找到__iar_data_init3源码,只看到了__iar_data_init函数,因此一直猜想__iar_data_init3就是__iar_data_init。
至于__iar_data_init代码是c写的:
里面确实和RegionTable有关联,至于怎么实现的,将全局变量从ROM搬到RAM 我在源码中实在看不出来。
最后绕不过全局段初始化这个槛,仍是勾上使用IAR提供的.s选项,使用iar的__iar_program_start,程序能够正常跳转运行。。。。