Raspberry Pi:嵌入式编程练习,入门

时间:2013-05-04 17:18:29

标签: arm cross-compiling raspberry-pi

首先,我在这里(http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/)遵循本教程。

在第一个练习中,您将学习如何寻址负责打开绿色正常LED的GPIO引脚。我有Raspberry pi的rev C,据我所知,它使用Broadcom(BCM2835)微处理器,它的外围设备有以下数据表:(http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/downloads/SoC-Peripherals.pdf)。

我已阅读数据表第89至104页,但我仍然输了。即使提供了交叉编译器构建链,作者提供的程序似乎也不会运行。从我作者提供的来源中删除评论:

.section .init
.global _start
_start:
  ldr r0, =0x20200000

  /* Enable output on the 16th pin */
  mov r1, #1
  lsl r1, #18
  str r1, [r0, #4]

  /* Turn the pin off to turn LED light on */
  mov r1,#1
  lsl r1,#16
  str r1, [r0, #40]

loop$:
  /* Keep the system running */
  b loop$

我被困的地方是,在数据表中我没有看到地址0x20200000。从表6-2中的第91页开始,我们看到描述前32位的表。在表6-1中,我们看到了寄存器描述。第一个寄存器的地址是0x7E200000。我试图在它的位置使用这个地址,但我仍然没有运气灯开启。

底线LED指示灯没有亮起,所以我可以了解,我应该去哪里获取有关如何调试此信息的信息?其次,我错过了什么?

如果它有用,这里是img文件的一个hexdump,我正在使用SD卡。

mehoggan@mehoggan-desktop:~/Devel/scripts/assembly/raspberry-pi-mini-os/example1$ make clean all
rm -f build/*.o 
rm -f build/output.elf
rm -f kernel.img
rm -f kernel.list
rm -f kernel.map
../arm-2008q3/bin/arm-none-eabi-as -I source/ source/main.s -o build/main.o
../arm-2008q3/bin/arm-none-eabi-ld --no-undefined build/main.o -Map kernel.map -o build/output.elf -T kernel.ld
../arm-2008q3/bin/arm-none-eabi-objcopy build/output.elf -O binary kernel.img 
../arm-2008q3/bin/arm-none-eabi-objdump -d build/output.elf > kernel.list
mehoggan@mehoggan-desktop:~/Devel/scripts/assembly/raspberry-pi-mini-os/example1$ 

hexdump -C ./kernel.img 
00000000  18 00 9f e5 01 10 a0 e3  01 19 a0 e1 04 10 80 e5  |................|
00000010  01 10 a0 e3 01 18 a0 e1  28 10 80 e5 fe ff ff ea  |........(.......|
00000020  00 00 20 20                                       |..  |

修改
这是.list文件

00000000 <_start>:
   0:   e59f0018    ldr r0, [pc, #24]   ; 20 <loop$+0x4>
   4:   e3a01001    mov r1, #1  ; 0x1
   8:   e1a01901    lsl r1, r1, #18
   c:   e5801004    str r1, [r0, #4]
  10:   e3a01001    mov r1, #1  ; 0x1
  14:   e1a01801    lsl r1, r1, #16
  18:   e5801028    str r1, [r0, #40]

0000001c <loop$>:
  1c:   eafffffe    b   1c <loop$>
  20:   20200000    .word   0x20200000

如果您反转hexdump的endianess,您会看到它与.list文件对齐。

e59f0018
e3a01001
e1a01901
e5801004
e3a01001
e1a01801
e5801028
eafffffe
20200000

1 个答案:

答案 0 :(得分:3)

从原理图(以及您找到此代码的链接页面)gpio 16连接到该状态led

  

我被困的地方是,在数据表中我没有看到地址   0x20200000

不是这样,bcm手册的第6页:

外围设备的物理地址范围为0x20000000到0x20FFFFFF。外设的总线地址设置为映射到从0x7E000000开始的外设总线地址范围。因此,这里公布的总线地址为0x7Ennnnnn的外设可用于 物理地址0x20nnnnnn。

使用该示例程序0x20200000的信息变为0x7E200000,这是gpio寄存器,

特别是0x7E200004是GPFSEL1

GPFSEL1的描述表示位模式001使引脚成为输出,并且它表明该寄存器中gpio 16的位是18-20位,因此我们希望将位模式001置于第18位,因此1&lt; ;&lt; 18写入0x7E200004

40十进制是28十六进制,所以第二个感兴趣的寄存器是0x7E200028,这是GPCLR0

GPCLRn说明如果设置了一个位,则清除gpio输出。因此,向该寄存器写入1&lt;&lt; 16以将输出拉至零,从而打开LED

然后进入一个无限循环,所以没有其他事情发生(进出ARM)。

你的hex文件(带有更新/编辑)没问题。您想要在SD卡或至少在第一个分区的根目录中的唯一文件是bootcode.bin和http://github.com/raspberrypi的固件目录中的start.elf不需要/从那里获取任何其他文件。你的二进制文件kernel.img也在sd卡上。没有其他的。插上SD卡,插上树莓派。如果它不能正常工作,那么拔掉并重新插入(有可能发生的缓存),它应该第二次工作。如果这不起作用,重新分区并重新格式化SD卡并再试一次,我发生了多次事情,导致SD卡无法在覆盆子pi中工作。

编辑:

随着链接器脚本显然正在构建基于地址0x0000而不是0x8000的二进制文件,您可能会遇到麻烦。您可以将config.txt文件放在SD卡的根目录中,并在启用旧内核模式的行内,或者告诉GPU将kernel.img加载到地址0x0000而不是0x8000,或者修改链接器脚本以便.text(以及其他所有内容)从0x8000开始。具体的OK01示例程序恰好与位置无关,因此可以从任何地址运行,因此最小的三个文件(bootcode.bin,start.elf,kernel.img)将起作用。