以前在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,程序能夠正常跳轉運行。。。。