作业系统之前的程式 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