|
Learn lumit Step 2 : 第一个嵌入式程序 点灯大法
++++++++++++++++++++++++++++++++++++++++++++++++++++++
我在刚开始做嵌入式开发的时候,还不知道什么是 led,什么是 gpio。
从纯软件的开发转到嵌入式开发,比从做单片机转行过来要困难的多,主要还是
在开发习惯上。对于编程高手来说,几乎没有什么程序是调试不出来的。嵌入式
开发则不这样,它总是和一个具体的硬件平台联系在一起,想停下来看变量或者
寄存器,总归是一件麻烦事,调试反而成了最后的选择。
这一节就从“点灯大法”开始吧,就好像很多介绍编程书里的 helloworld,
应该说学习嵌入式第一个需要编写的程序就是点灯。板子上总是有 led ,但不是
总能够让你用 printf 输出。如果要选择最强的 debuger ,无疑是“点灯大法”,
因为没有其他调试方法比它更容易实现,占用更少的资源,耗费更短的时间。
一个点灯的程序,可以简单到只用几行汇编代码就能完成而不用C语言实现,
可以直接在 Flash 里面运行而不需要用到 SDRAM,可以只占用几个时钟周期就能
执行而不会影响系统的性能。特别是在一个实时系统里面,通常中断和硬件驱动
的时间要求至少是毫秒级的,要想插入一个 printf 来看看变量或者是停下来观察
寄存器都将导致系统无法正确执行。这种情况下,我所知道除了点灯,似乎就没有
其他更好的办法了。
lumit 网站上提供了一个 ARM 汇编写的最简单的点灯程序 led_1111.s ,这个
程序的二进制代码 led_1111.bin 可以直接烧入 Flash 中执行,将 lumit4510 开发
板上的 4 个 led 小灯点亮。类似的,led_0000.s 是将 4 个小灯熄灭,led_blink.s
是使得它们不停地点亮、熄灭,显示出闪烁的效果。
实现原理上也很简单,led 灯是和 s3c4510 提供的 IO 相连,具体连接方式如下:
;
; hardware connection
; IO17 IO04 IO05 IO06 (gpio)
; D6 D7 D8 D9 (led)
; so output value = 0x00020070 = (0b0000 0000 0000 0010 0000 0000 0111 0000)
;
在硬件设计的原理图 lumit-sch-1.4.0.pdf 中,也可以看出这个连接关系。
led_1111.s 分为两个部分,首先是设置 gpio 的输入/输出方向,这个是通过设置
S3C4510B 内部 IO 端口模式寄存器 IOPMOD (地址: 0x03FF5000) 来实现的:
ldr r0, =0x03FF5000
ldr r1, =0x0003FFFF ; set all 18 gpios' direction to output
str r1, [r0]
这里简单地设置为全部输出。然后就是设置相关的 gpio 输出 1 ,即点亮相连的 led 。
这个是通过设置 S3C4510B 内部 IO 端口数据寄存器 IOPDATA (地址: 0x03FF500 来实现的:
( 相关资料可以参考 um_s3c4510b_rev1.pdf 中的 Page 12-2 ~ 12-5 )
ldr r1, =0x00020070 ; show led = 1111
loop
ldr r0, =0x03FF5008
str r1, [r0]
B loop
类似的,熄灭相连的 led 实现为
ldr r1, =0x00000000 ; show led = 0000
loop
ldr r0, =0x03FF5008
str r1, [r0]
B loop
通过 ADS 1.2 的编译器,执行编译、链接、得到二进制可执行代码:
armasm led_1111.s -o led_1111.o
armlink -ro-base 0x0 -entry 0x0 led_1111.o -o led_1111.axf
fromelf led_1111.axf -bin -output led_1111.bin
一块自己制作,焊接,调试的板子,能够首先把点灯的程序烧进去运行,看到 led 在
闪烁的时候,至少说明 cpu 和 flash 的连接,焊接都没有问题,晶振也在正常工作。
printf 无法输出之前,led 总是我们最可信赖的 debuger 。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
×
|