2

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

在第一个练习中,您将了解如何处理负责打开绿色 OK 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 灯不亮,所以我可以学习,我应该去哪里获取有关如何调试的信息?其次,我错过了什么?

如果有用,这里是我正在添加到 SD 卡的 img 文件的 hexdump。

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 的字节序,您会看到它与 .list 文件对齐。

e59f0018
e3a01001
e1a01901
e5801004
e3a01001
e1a01801
e5801028
eafffffe
20200000
4

1 回答 1

3

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

我被卡住的地方是,在数据表中我看不到地址 0x20200000

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

外设的物理地址范围从 0x20000000 到 0x20FFFFFF。外设的总线地址设置为映射到从 0x7E000000 开始的外设总线地址范围。因此,此处在总线地址 0x7Ennnnnn 处通告的外设在物理地址 0x20nnnnnn 处可用。

从示例程序中获取信息 0x20200000 变为 0x7E200000 这是 gpio 寄存器,

特别是 0x7E200004 是 GPFSEL1

GPFSEL1 的描述说位模式 001 使引脚成为输出,并且它表明 gpio 16 的该寄存器中的位是位 18-20,因此我们要将位模式 001 放在位 18 上,因此 1<<18写入 0x7E200004

十进制的 40 是十六进制的 28,因此第二个感兴趣的寄存器是 0x7E200028,即 GPCLR0

GPCLRn 描述说如果设置了一个位,则清除 gpio 输出。因此,将 1<<16 写入该寄存器以将输出拉为零,从而打开 LED

然后进入一个无限循环,这样就不会发生其他任何事情(到/从 ARM)。

您的十六进制文件(带有更新/编辑)很好。您想要在 sd 卡上或至少在第一个分区的根目录中的唯一文件是http://github.com/raspberrypi固件目录中的 bootcode.bin 和 start.elf不需要/获取任何其他文件那里。你的二进制文件 kernel.img 也在 sd 卡上。没有其他的。插上sd卡,插上树莓派。如果它不能立即工作,则拔下并重新插入(可能会发生缓存的事情),它应该第二次工作。如果这不起作用,请重新分区并重新格式化 sd 卡并重试,我已经发生了很多次阻止 sd 卡在树莓派中工作的事情。

编辑:

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

于 2013-05-05T02:52:58.480 回答