烤派宝典第二章之OK02

TurnToJPG -->


#烤派宝典第二章之OK02 OK02 这一章建立在OK01的基础上,将反复点亮/熄灭’OK’或’ACT’ LED。我们假定你已经有了第一章烤派宝典第一章之OK01提到过的操作系统知识作为基础。

内容
1 等待
2 整合

###等待 出乎意料的是,等待在操作系统开发里是一个非常有用的特性。通常操作系统发现自己无事可做时,会选择等待。在我们的例子里,我们需要让LED一闪一灭。如果你只是把管脚状态置为on或是off,那么LED在我们视线里依然是可见的,因为计算机在一秒内会成千上万次的开关该GPIO端口。在以后的章节里我们会涉及到精准定时,但是现在为了效率起见,我们可以简单的把CPU的时间浪费掉。

	mov r2,#0x3F0000
	wait1$:
	sub r2,#1
	cmp r2,#0
	bne wait1$

上述的代码简单的通过计算一个大数的减法创建了一个延迟,得益于每一块Raspberry Pi基本上都相同,上面得到的延迟时间也差不多。上述代码可以简单解释为,使用mov指令把十六进制数0x3F0000传递给r2,然后对此数执行减1运算,直到变为0。这里引入了3个新指令分别是sub,cmp和bne。

sub是减法指令(substract)的简写,从第一个参数中减第二个参数的值。
> sub reg,#val 意思是从reg存储的值中减掉val大小。

cmp是一条有意思得多的指令。它比较第一个参数和第二个参数的值,将比较的结果存入到一个特殊的寄存器中,这个寄存器叫CPSR寄存器,意思是当前处理器状态寄存器(Current Processor Status Register)。你不需要太担心这个,简单的说,她就是能记住两个数字谁比谁大或是谁比谁小,或是相等[^1]。
> cmp reg,#val 意思是把寄存器reg中的值和数值val做比较。比较的结果在CPSR中。

bne事实上是分支命令的变种。在ARM汇编语言家族里,所有的指令都可以条件执行。这也就是说,指令只有在上一条比较指令有确切的结果才会被执行到。以后的教程中我们将频繁的在有趣的场合使用到它,但现在我们在b指令后加上ne代表只有上一次比较的结果不相等时候才会执行bne后的指令。ne后缀可以在任意命令后被使用,有多达16个条件可以供选择,比较常用的有eq(用于判断是否相等),和lt(小于)。
> ne后缀使得该条命令只会在上一次比较的结果不等时才会被执行到。

###整合 我以前提起过LED状态可以通过写入GPIO控制器后28位移的地址置为开启状态,也可以通过写入GPIO控制器后40位移的地址置为关闭状态。据此你可以修改OK01中的代码,首先把LED点亮,而后运行等待代码,再将其关闭,再次运行等待代码,而后调用分支代码回到初始状态,以继续循环。需要注意的是,我们不需要再次激活GPIO16口,激活一次就足够了。如果你追求高效的话,我强烈建议你重用r1的值。在所有的课程里,你都可以在下载页面找到完整的解决方案。注意你需要保证在你的代码里,标号都是唯一的。如果你已经定义了wait1$,那么你不能再将另一行也定义为wait1$。

在我的Raspberry Pi上,闪烁频率大约是一秒钟两次。闪烁频率可以很方便的通过改变r2的初始值来调节。然而,不幸的是我们现在还不能非常精确的控制LED灯的闪烁频率。如果你没有得到预期的结果,请翻阅troubleshooting页,如果你成功了,恭喜你!

本章中我们学习了两个汇编指令,sub和cmp,还领略了ARM中的条件执行方法。

下一章烤派宝典之OK03中,,我们将评估我们编程的方式,我们将建立我们的代码规则,以便我们可以重用代码,如果可以的话,我们将同时使用使用C/C++代码来工作。