toolchain 的使用已經不在困擾我, 困難的是 cpu arm 架構與硬體平台, 這可要看不少資料。通過開發環境的試鍊後, 我打算點亮 led 燈來做為第一個 c 語言的練習程式。
不過沒想到這支作業系統之前的程式就難倒我, 是有關 io 的部份, 不像 前一個程式, 這個程式會用到平台相關的程式碼, 點亮 led, 得先要查詢接腳資料, 而查詢接腳資料是很磨人的, 我從 這裡的範例程式修改而來。這是 st 公司提供的 library, 可以省下不少看 datasheet 的功夫, 也可幫助程式 port 到其他 st 平台, 是很重要的參考資料。
一樣化繁為簡, 將程式庫的部份抽取出來, 簡化成一個小的作業系統之前的程式。
程式結果就是先閃綠燈, 閃紅燈在一起熄滅, 如此循環下去。
其他和 io 相關的 .h 檔案就不列出。我要解說的部份只和開機程式有關, IO 部份請自己搞定, 這不是文章的重點。和 x86 不同, cortex-m3 可以 完全使用 c 語言來寫開機程式, 而不像 x86 需要 inline 組合語言。一開機, 位址 0~3 存放的值會被填到 sp, 完成 stack 設定, 在 c 語言中完成最重要的設定。
再來是 bss section:
這段 code 便是在初使化 .bss, .data, 就這樣完成 c startup code, 完全不需要組合語言介入, 厲害的設計。
也許你想知道 .bss, .data 為什麼要初始化, 這不是很容易寫在 blog 上, 用個例子簡單說明:
int a=6;
void func()
{
static int i;
}
a 位於 .data, i 位於 .bss, 在程式執行時, a 要是 6, 而 i 要是 0, 這不是憑空得來的, 初始化 .bss, .data 就是在完成這樣的工作, 我知道, 這只能解除你一半的疑惑, 你一定想知道更多吧!
那 x86 的 bss section 也可以這樣寫嗎?由於有名的 segment address, 你得先確定你指的位址 0x100 真的是絕對位址 0x100 嗎?這是很容易搞亂的。
而透過 link script, section(".isr_vector") 會被放到 0 開頭的位址, 達到 0~3 是 stack value, 4 ~ 7 是 reset handle 的目的, 進而透過 ResetISR call main 去執行 main()。
按照之前的慣例, 下一個應該是 c++ 的版本, 不過 ...
source code:
https://github.com/descent/stm32f4_prog
ref:
gpio gpio push-pull or open drain:
http://www.coactionos.com/embedded-design/98-gpio-output-pin-modes.html
http://chunyenchu0818.pixnet.net/blog/post/40596842-gpio%E8%A8%AD%E5%AE%9Aod-or-pp
介紹一些 arm 指令:
http://jnotes.googlecode.com/svn-history/r105/trunk/Notes/NotesOnCM3/stm32WithGCC.html
books: coretex-m3 之 stm32 嵌入式系統設計
不過沒想到這支作業系統之前的程式就難倒我, 是有關 io 的部份, 不像 前一個程式, 這個程式會用到平台相關的程式碼, 點亮 led, 得先要查詢接腳資料, 而查詢接腳資料是很磨人的, 我從 這裡的範例程式修改而來。這是 st 公司提供的 library, 可以省下不少看 datasheet 的功夫, 也可幫助程式 port 到其他 st 平台, 是很重要的參考資料。
一樣化繁為簡, 將程式庫的部份抽取出來, 簡化成一個小的作業系統之前的程式。
2 #include "stm32f4xx_gpio.h" 3 #include "stm32f4xx.h"stm32f4xx_gpio.h, stm32f4xx.h, 從範例程式裡頭挖出來小改一下。大部份是 gpio, rcc 的 macro。stm32.h 是 coretex-m3 之 stm32 嵌入式系統設計的範例。由於沒有 SDRAM 控制器, 省下這部份的程式碼, lucky!!
程式結果就是先閃綠燈, 閃紅燈在一起熄滅, 如此循環下去。
其他和 io 相關的 .h 檔案就不列出。我要解說的部份只和開機程式有關, IO 部份請自己搞定, 這不是文章的重點。和 x86 不同, cortex-m3 可以 完全使用 c 語言來寫開機程式, 而不像 x86 需要 inline 組合語言。一開機, 位址 0~3 存放的值會被填到 sp, 完成 stack 設定, 在 c 語言中完成最重要的設定。
再來是 bss section:
14 void ResetISR(void) 15 { 16 unsigned long *pulSrc, *pulDest; 17 18 pulSrc = &_etext; 19 for (pulDest = &_data; pulDest < &_edata;) 20 *pulDest++ = *pulSrc++; 21 for (pulDest = &_bss; pulDest < &_ebss;) 22 *pulDest++ = 0; 23 24 main(); 25 }
這段 code 便是在初使化 .bss, .data, 就這樣完成 c startup code, 完全不需要組合語言介入, 厲害的設計。
也許你想知道 .bss, .data 為什麼要初始化, 這不是很容易寫在 blog 上, 用個例子簡單說明:
int a=6;
void func()
{
static int i;
}
a 位於 .data, i 位於 .bss, 在程式執行時, a 要是 6, 而 i 要是 0, 這不是憑空得來的, 初始化 .bss, .data 就是在完成這樣的工作, 我知道, 這只能解除你一半的疑惑, 你一定想知道更多吧!
那 x86 的 bss section 也可以這樣寫嗎?由於有名的 segment address, 你得先確定你指的位址 0x100 真的是絕對位址 0x100 嗎?這是很容易搞亂的。
而透過 link script, section(".isr_vector") 會被放到 0 開頭的位址, 達到 0~3 是 stack value, 4 ~ 7 是 reset handle 的目的, 進而透過 ResetISR call main 去執行 main()。
按照之前的慣例, 下一個應該是 c++ 的版本, 不過 ...
source code:
https://github.com/descent/stm32f4_prog
ref:
gpio gpio push-pull or open drain:
http://www.coactionos.com/embedded-design/98-gpio-output-pin-modes.html
http://chunyenchu0818.pixnet.net/blog/post/40596842-gpio%E8%A8%AD%E5%AE%9Aod-or-pp
介紹一些 arm 指令:
http://jnotes.googlecode.com/svn-history/r105/trunk/Notes/NotesOnCM3/stm32WithGCC.html
books: coretex-m3 之 stm32 嵌入式系統設計