ASM 板


LINE

看板 ASM  RSS
这是我第三个平台的 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 --- Reserved 3 29-27 FSEL49 FSEL49 - Function Select 49 4 000 = GPIO Pin 49 is an input 5 001 = GPIO Pin 49 is an output 6 100 = GPIO Pin 49 takes alternate functio 7 101 = GPIO Pin 49 takes alternate functio 8 110 = GPIO Pin 49 takes alternate functio 9 111 = GPIO Pin 49 takes alternate functio 10 011 = GPIO Pin 49 takes alternate functio 11 010 = GPIO Pin 49 takes alternate functio 12 26-24 FSEL48 FSEL48 - Function Select 48 13 23-21 FSEL47 FSEL47 - Function Select 47 14 20-18 FSEL46 FSEL46 - Function Select 46 15 17-15 FSEL45 FSEL45 - Function Select 45 16 14-12 FSEL44 FSEL44 - Function Select 44 17 11-9 FSEL43 FSEL43 - Function Select 43 18 8-6 FSEL42 FSEL42 - Function Select 42 19 5-3 FSEL41 FSEL41 - Function Select 41 20 2-0 FSEL40 FSEL40 - Function Select 40 这个要怎麽看呢? 呼 ... 比 stm32f4 简单多了。我们要做几件事情: 把 gpio 47 设定为 output - Table 6-6 L13, 把 bit 21, 22, 23 设定为 001 就是 ouput 把 gpio 47 写入 0, led 暗, gpio bit 47 在 GPCLR1 bit 15 把 gpio 47 写入 1, led 亮, gpio bit 47 在 GPSET1 bit 15 就这样, 不用设像 stm32f4 那麽复杂的属性。 该文章的程式码, 我在 rpi2 上测试, 只能亮 led, 灭 led 後就无法再亮 led, 我做了 些修改。 https://github.com/descent/arm-tutorial-rpi/tree/master/part-1/armc-02 gpio[11] 就是 gpclr1 的位址 gpio[8] 就是 gpset1 的位址 针对这个位址写入 bit 0/1 就是针对 gpio 47 写入 bit 0/1。 bit 15 写 1 到 gpio[8] 就是将gpio 47 写入 1 bit 15 写 1 到 gpio[11] 就是将gpio 47 写入 0, bit 0 是 gpio 32, bit 1 是 gpio 33 ... bit 15 就是 gpio 47 很奇怪对吧, 不过人家这麽设计你就这麽用吧! ok_led.c L30 很重要, 这是 GPIO base phyical address。 ok_led.c 29 30 #define GPIO_BASE 0x3F200000UL 31 86 87 88 #define DELAY_MAX 1000 89 90 /** Main function - we'll never return from here */ 91 int notmain(void) 92 { 93 /** GPIO Register set */ 94 volatile unsigned int* gpio; 95 96 /** Simple loop variable */ 97 volatile unsigned int i,j; 98 99 /* Assign the address of the GPIO peripheral (Using ARM Physical Address) */ 100 gpio = (unsigned int*)GPIO_BASE; 101 102 /* Write 1 to the GPIO16 init nibble in the Function Select 1 GPIO 103 peripheral register to enable GPIO16 as an output */ 104 gpio[4] &= (~(7 << 21)); 105 gpio[4] |= (1 << 21); 106 107 while(1) 108 { 109 // gpclr1 110 gpio[11] = (1 << 15); // led off 111 for(i = 0; i < DELAY_MAX; i++) 112 for(j = 0; j < 1000; j++) ; 113 114 // gpset1 115 gpio[8] = (1 << 15); // led on 116 for(i = 0; i < DELAY_MAX; i++) 117 for(j = 0; j < 1000; j++) ; 118 119 // gpclr1 120 gpio[11] = (1 << 15); // led off 121 for(i = 0; i < DELAY_MAX; i++) 122 for(j = 0; j < 1000; j++) ; 123 124 // gpset1 125 gpio[8] = (1 << 15); // led on 126 while(1); 127 137 } 138 return 0; 139 } v.s 1 2 .globl _start 3 _start: 4 mov sp,#0x8000 5 bl notmain 6 7 hang: b hang 8 .globl PUT32 9 PUT32: 10 str r1,[r0] 11 bx lr 12 13 .globl GET32 14 GET32: 15 ldr r0,[r0] 16 bx lr ref: ok_led.c, v.s, makefile 这是参考 https://github.com/dwelch67/raspberrypi 改出来的。 由於我没有 jtag, 我只能猜测是 stack 问题, 但是 armc-02.c 实在看不出来哪里和 stack 有关。 ok_led.c 已经开始用 auto variable, 由於在 v.s 设定了 stack, 所以就放心的用 auto variable。编译出来的 .bin 档复制到 kernel.img 的那个分割区, 盖掉 kernel.img, kernel7.img, 再插回 rpi2, 上电应该就可以看到 led 在闪烁。 我改变了闪灯的逻辑, 先暗 led, 再亮 led, 再暗 led, 然後永远亮着, 以便确定有正常 亮灭。绿色的那个 led 灯就是 ok led, 请参考以下影片。 有了 bootcode 之後的 bare-metal 程式简单不少, 不用设定 dram controller 参数, 这样才能存取 1g ram, 不用作 remap, 将 address 0 map to dram, 有些不过瘾, 这些 都被 bootcode 做完了, 又少学了不少东西。以这个例子来说, 从组合语言设定好 sp register 後, 就可以使用 stack, 再来便可以使用 c 语言了, 不过 bss 因为没有作初 始化, 会有不预期的行为, 但其实影响不大。也因为没使用中断, 所以也看不到中断部份 的程式码, 慢慢来补上他们吧! 最後提一下有关 bootcode.bin, start.elf 我直接复制这些档案到 fat partition 上, 似乎无法正确 work, 一定要用 2015-05-05-raspbian-wheezy.img dd 後产生的 partition fat 才能正确载入 kernel7.img, 真是奇怪。 Preparing Raspberry PI for JTAG Debugging ( http://goo.gl/niWmEU ), 我不确定能 不能在 rpi2 上使用, 我们没有 datasheet 记得吗? 就算有, 我也看不懂, 硬体是我的 弱点。 Raspberry Pi: Boot Process http://output.to/sideway/default.asp?qno=140100001 // 本文使用 Blog2BBS 自动将Blog文章转成缩址的BBS纯文字 http://goo.gl/TZ4E17 // blog 版本: http://descent-incoming.blogspot.tw/2015/06/for-rpi2-0-led-by-c.html --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 180.217.248.108
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/ASM/M.1438787150.A.B0D.html







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Soft_Job站内搜寻

TOP