中国Linux公社论坛's Archiver

limingth 发表于 2005-5-24 15:00

Learn lumit Step 2 : 第一个嵌入式程序

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 (地址: 0x03FF5008) 来实现的:
( 相关资料可以参考 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 。

ywchen2000 发表于 2005-7-22 10:10

呵呵,代码很经典呀

limingth 发表于 2005-8-4 10:35

因为经典,所以永恒!  :P  开个玩笑,呵呵

lanair04 发表于 2005-9-5 18:56

大部分弄明白了,可还有点小问题
ldr r1, =0x00020070 ; show led = 1111
loop
ldr r0, =0x03FF5008
str r1, [r0]

第一行为什么是=0x00020070 ,
  我觉得应该是=0x000001E0
   不是要D6,D7.D8,D9亮么
那就应该是0x000001E0=0b0000 0000 0000 0000 0000 0001 1110 0000
谁能给个解释啊~~
[/quote]

limingth 发表于 2005-9-6 09:15

请留意上面的这个注释部分:
实现原理上也很简单,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)
;

zyz1016 发表于 2006-2-18 22:17

为什么我下载不了

页: [1]

Powered by Discuz! Archiver 6.1.0F  © 2001-2007 Comsenz Inc.