作業系統之前的程式 for rpi2 (0)-點亮led by c

作者: descent (「雄辯是銀,沉默是金」)   2015-08-05 23:05:39
這是我第三個平台的 bare-metal 程式, 第一個是 x86 在 legacy bios/uefi, 有
bios/uefi 擋路, 不算真的是 bare-metal。第二個是 stm32f4 - discovery, 有 jtag,
而且真的是從上電開始寫程式, 真的是 bare-metal 程式, 過癮, 可惜沒有 mmu, 不能練
習 mmu。rpi2 是 cortex a7, 又是一個新平台, 我已經有了不少經驗, 該怎麼開始呢?
沒有 bcm2836 datasheet 實在很麻煩, 沒有 boot code source 也是一樣麻煩。好在有
不少人也對 bare-metal 有興趣, 本篇文章大量參考: Step01 – Bare Metal
Programming in C Pt1 ( http://goo.gl/k1T6AZ ) (後文以 Pt1 稱呼), 能遇上同好真
是開心, 我不用一人辛苦了。
不過沒有 jtag, 要除錯時就得靠「冥想」了, 而且也無法驗證程式跑的流程是不是和我
想的一樣, 依照以前的經驗, 通常是不一樣 (我只是個普通程式員, 別難為我了)。
rpi2 開機流程:
Pt1 ( http://goo.gl/k1T6AZ ) 裡頭就寫到了, 不過還是大概提一下, 和一般的 arm 開
發板從 arm core boot 並從 address 0 讀入第一個 arm 指令不同, rpi2 是從 gpu 開
機, 也就是說某個地方放著執行 gpu 的程式碼, 它會去找 sd card 上的 bootcode.bin
然後載入並執行 bootcode.bin, bootcode.bin 再去找 sd card 上的 start.elf, 這兩
個檔案都是 gpu 執行檔, 不是 arm machine code, 再來終於到 kernel.img,
kernel7.img, 那個 7 就是給 rpi2 (arm cortex-A7) 用的, kernel.img 則是原來 rpi
(ARM1176JZF) 用的, start.elf 會自動去判斷載入正確的 kernel*.img。
descent@NB-debian:boot$ file start.elf
start.elf: ELF 32-bit LSB executable, Broadcom VideoCore III, version 1
(SYSV), statically linked, stripped
和這篇的 boot 方式比較一下, 也許會覺得 rpi1/2 很與眾不同。
嵌入式系統 Boot Loader 技術內幕
http://www.ibm.com/developerworks/cn/linux/l-btloader/
和 Pt1 提到的不同, 我使用的是 raspberrypi 官方提供的 toolchain (
https://goo.gl/UXR4Sg )。
在 os 下的程式有 os 提供的 loader 來幫我們載入程式, rpi2 bare-metal 程式呢? 正
常來說應該是 cpu 幫我們載入, 不過目前看來只能透過 star.elf 來載入我們的
bare-metal 程式, 把它想成 pc 的 bios/uefi 載入作業系統那樣的感覺, os kernel 也
是 bare-metal 程式。
那 star.elf 從哪裡載入 0x8000? 所以你知道 linker script 要設定 0x8000 為
enter point, 為什麼? 說來複雜, 你照辦就是了, 除非你的程式可以 relocation, 搬到
任意位址都可以正常執行。c.sh L3 就是在做這件事情。
c.sh
1 arm-linux-gnueabihf-gcc -O2 -mfpu=neon-vfpv4 -mfloat-abi=hard
-march=armv7-a -mtune=cortex-a7 -nostartfiles -g -c v.s
2 arm-linux-gnueabihf-gcc -O2 -mfpu=neon-vfpv4 -mfloat-abi=hard
-march=armv7-a -mtune=cortex-a7 -nostartfiles -g -c armc-02.c
3 arm-linux-gnueabihf-ld -Ttext 0x8000 v.o armc-02.o -o armc-02.elf
4 arm-linux-gnueabihf-objcopy armc-02.elf -O binary armc-02.bin
5 mv armc-02.bin kernel.img
該使用的 cpu 參數作者也一並列出來了, 我們不用辛苦的找這些資料。
我們的目的在點亮 OK led 燈, 就是那個綠色的 led, 這顆接在 gpio 47 和 rpi 1 不同
哦, Pt1 提供的資訊。
以下的 gpio 資料是從 bcm2835 datasheet 節錄出來的, 咦 ... 我知道你的疑惑, 沒有
bcm2836 datasheet, bcm2835 勉強撐著用了, 玩 rpi2 真辛苦, 我真佩服 Pt1 作者是
從哪裡得到這些資料。當然還有最重要的 physical address, 要不然就不知道要寫入哪
個位址了。
bcm2835 datasheet gpio
1 0x 7E20 0000 GPFSEL0 GPIO Function Select 0 32 R/W
2 0x 7E20 0000 GPFSEL0 GPIO Function Select 0 32 R/W
3 0x 7E20 0004 GPFSEL1 GPIO Function Select 1 32 R/W
4 0x 7E20 0008 GPFSEL2 GPIO Function Select 2 32 R/W
5 0x 7E20 000C GPFSEL3 GPIO Function Select 3 32 R/W
6 0x 7E20 0010 GPFSEL4 GPIO Function Select 4 32 R/W
7 0x 7E20 0014 GPFSEL5 GPIO Function Select 5 32 R/W
8
9 0x 7E20 001C GPSET0 GPIO Pin Output Set 0 32 W
10 0x 7E20 0020 GPSET1 GPIO Pin Output Set 1 32 W
11
12 0x 7E20 0028 GPCLR0 GPIO Pin Output Clear 0 32 W
13 0x 7E20 002C GPCLR1 GPIO Pin Output Clear 1 32 W
Table 6-6 - GPIO Alternate function select register 4
1 Bit(s) Field Name Description
2 31-30

Links booklink

Contact Us: admin [ a t ] ucptt.com