我正在关注Baking Pi,在 ARMv6 程序集中为 Raspberry Pi 构建一个非常基本的操作系统。我们已经从通过 GPIO 控制器打开 OK LED 到使用系统计时器使其闪烁,再到根据存储在.int
值中的位图表示的模式使其闪烁。最后一个解决方案似乎不起作用。起初我以为我一定是错误地解决了问题,但无论我用这里提供的功能解决方案检查我的解决方案,我都看不出有什么明显的不同。
我屈服了,最后下载了实际的解决方案,编译并安装在我的 Pi 上。它表现出与我自己的解决方案相同的损坏行为。也就是说,LED 会亮起,但会一直亮着。我假设程序已经崩溃,或者and
指令没有按照导师的要求做。
像这样的解决方案:
bitmap .req r4
seq .req r5
ldr bitmap,=pattern
ldr bitmap,[bitmap]
mov seq,#0 /* start at the zeroth bit */
loop$:
mov r0,#16 /* set gpio pin 16: OK LED */
mov r1,#1 /* bitmask starts with a 1 */
lsl r1,seq /* shift to the correct bit */
and r1,bitmap /* mask according to the pattern */
bl SetGpio /* set the LED state (r1 zero = off, non-zero = on) */
bl Wait /* wait for a short interval */
add seq,#1 /* increment the sequence counter */
and seq,#0b11111 /* reset seq to 0 if >= 32 */
b loop$ /* loop forever */
.section .data
.align 2
pattern:
.int 0b11111111101010100010001000101010
现在我知道Wait
andSetGpio
函数可以正常工作,因为上一课只是按设定的时间间隔闪烁 LED 灯,我是通过EOR
在每次迭代loop$
. 这里引入的唯一重要的新概念是表示 SOS 模式的位图。我对位图和位掩码很满意,因为我经常在高级语言中使用它们,所以我认为逻辑没问题,但还有其他问题,也许.int
是存储/填充的方式?
上面的逻辑有什么问题吗?的合同SetGpio
是:
- r0 必须设置为 GPIO 引脚号,在本例中为 16
- 如果 LED 应该打开,r1 必须设置为非零,否则设置为零以将其关闭
- 返回值不重要
该Wait
函数如下所示:
/* Sleep for 500 milliseconds */
Wait:
push {lr}
ldr r0,=500
bl SleepForDelay
pop {pc}
编辑 | 实际上,我和导师的解决方案中的行为是:
- LED 会短暂亮起(我猜是一个点)
- LED 再次熄灭
- LED 亮起并一直亮着
我实际上认为第一次闪烁只是引导加载程序在运行,但如果我在程序早期故意引入崩溃,LED 根本就不会亮起。