您的位置:首页 > 其它

Tiny4412使用汇编点亮LED,实现流水灯效果

2018-02-18 12:08 387 查看
本文转自:http://www.techbulo.com/1313.html

从今天开始就正式进入到tiny4412的开发学习中了,今天主要看了一下Tiny4412的启动流程及存储器映射及Exynos4412数据手册,用汇编写了一个跑马灯程序(后续会有C语言版本的出来),先说一下我的开发环境吧:

开发板:Tiny4412 增强版 (底板是Tiny4412ADK 1312)

开发工具:UltraEdit

宿主机:VmWare Ubuntu12.04(64bit)

编译工具:arm-linux-gcc4.5.1

一、控制原理说明



先看一下原理图:





如上图可知,Tiny4412有4个用户LED灯,控制它们四个引脚分别是GPM4_0~ GPM4_3,由原理可知,当IO引脚为高电平时,LED灯灭,当IO引脚为低电平时LED亮。我们要做的工作就是设置GPM4_0~ GPM4_3为输出功能,且控制且输出电平高低即可。

二、程序说明

1. led.S
由原理图可知,程序只进行了两步操作;
第一步:设置GPM4_0~GPM4_3相对应的控制寄存器GPM4CON,使GPM4_0~ GPM4_3四个引脚为输出功能。



第二步:设置其对应的数据寄存器GPM4DAT对应的4个bit位为0,使GPM4_0~ GPM4_3为低电平,4个LED灯全亮,等待一段时间将第0位设置为0,其余位设置为1,这样只有第一个灯亮;等待一段时间将第1位设置为0,其余位设置为1,这样只有第二个灯亮;等待一段时间将第2位设置为0,其余位设置为1,这样只有第三个灯亮;等待一段时间将第3位设置为0,其余位设置为1,这样只有第四个灯亮;等待一段时间使GPM4_0~ GPM4_3全为高电平,4个LED灯全灭。这样就实现了跑马灯效果。
程序代码中,也有相关解释这里不做过多说明。
.text
.globl _start
_start:

/* Setup GPM4_0、GPM4_1、GPM4_2、GPM4_3为输出 */
ldr r0, =0x110002E0		// GPM4CON的地址是0x110002E0
ldr r1, [r0]			// 先读出原值
bic r1, r1, #0xff00		// 清除bit[15:8]
bic r1, r1, #0xff		// 清除bit[7:0]
orr r1, r1, #0x1100		// 设置bit[15:8]为0b00010001
orr r1, r1, #0x11		// 设置bit[7:0]为0b00010001
str r1, [r0]			// 写入GPM4CON

/*
* set GPM4DAT as Low For leds
*/
ldr r0, =0x110002E4		// GPM4DAT的地址是0x110002E0
ldr r1, [r0]			// 读出原值

led_loop:
bic r1, r1, #0xf		// 清除bit[0-3]为0 全亮
str r1, [r0]			// 写入GPM4DAT
ldr r2, =0xffffff
bl led_delay

orr r1, r1, #0xe		/* GM4_0 亮 */
str r1, [r0]
ldr r2, =0xffffff
bl led_delay

bic r1, r1, #0x2		/* GM4_1 亮 */
orr r1, r1, #0x1
str r1, [r0]
ldr r2, =0xffffff
bl led_delay

bic r1, r1, #0x4		/* GM4_2 亮 */
orr r1, r1, #0x2
str r1, [r0]
ldr r2, =0xffffff
bl led_delay

bic r1, r1, #0x8		/* GM4_3 亮 */
orr r1, r1, #0x4
str r1, [r0]
ldr r2, =0xffffff
bl led_delay

bl led_loop

led_delay:				/* 循环 */
sub r2, r2, #0x1	//sub 减法
cmp r2, #0x0		//将r0 与0比较
bne led_delay		//b是跳ne是不相等,不相等就跳到led_delay
mov pc, lr			//lr里存的是调用函数时的下一条指令地址,将lr的值赋给pc程序计数器就可以完成返回

2. MakeFile说明
led.bin : led.S
arm-linux-gcc -c -o led.o led.S
arm-linux-ld -Tled.lds -N led.o -o led.elf
arm-linux-objcopy -O binary -S led.elf led.bin
arm-linux-objdump -D -m arm led.elf > led.dis
clean:
rm -f *.dis *.bin *.elf *.o

当我们在Makefile所在目录下执行make命令时,系统会进行如下操作:

第一步 执行arm-linux-gcc -c -o led.o led.S命令将当前目录下存在的汇编文件led.S编译成led.o文件;

第二步 执行arm-linux-ld -Tled.lds -N led.o -o led.elf将.o文件链接成elf文件,-Tled.lds 其中led.lds位链接脚本,告诉连接器如何对程序进行链接,以及链接地址等等(下面会有讲解);

第三步 执行arm-linux-objcopy -O binary -S led.elf led.bin将elf文件抽取为可在开发板上运行的bin文件;

第四步 执行arm-linux-objdump -D -m arm led.elf > led.dis将elf文件反汇编,便于我们对程序的分析,查找错误等等;

3. 链接脚本led.lds说明

SECTIONS {
. = 0x02023400;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : { *(.data*) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}

本文不对链接脚本的具体语法进行介绍,读者可以自已自行google了解

第2行表示程序的连接地址从0x02023400开始,这表示我们的程序运行之前应该位于内存地址0x02023400字节处,

BL1会把 BL2复制到0x02023400地址处,再启动它。

第 3~6行,表示从 0x02023400 开始,依次排放程序的代码段、 只读数据段、数据段、BSS段。

三、程序编译及烧写

1.编译

通过FTP或者其他工具将led.s、Makefile、led.lds 三个文件上传到服务器上去,输入make命令进行编译将得到led.bin文件。

2.烧写

将SD卡插入电脑,并让VmWare里的Ubuntu识别出来,然后执行如下命令:

./sd_fusing.sh /dev/sdb ../../hardware_code/led/led.bin



如图所示,SD卡烧写成功,将SD卡插到Tiny4412开发板上,并设置为SD卡启动,这时你就会看到LED灯在闪烁。

说明:sd_fusing.sh是一个shell脚本,这个脚本文件,一键烧写程序到SD卡中。我们会在下节分析这个脚本。

四、上电实验

如下图所示,可以看到4个led轮流着点亮及熄灭



五、链接脚本分析

以 led目录下的led.lds为例,它的内容如下:
SECTIONS {
. = 0x02023400;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata*)}
.data ALIGN(4) : { *(.data*) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}

第2行表示程序的连接地址从0x02023400开始,这表示我们的程序运行之前,应该位于内存地址
0x02023400字节处。 BL1会把BL2复制到0x02023400地址处,再启动它。
第3~6行,表示从0x02023400开始,依次排放程序的代码段、只读数据段、数据段、BSS段。
我们对这些“段”还没有概念,这将在后续章节介绍。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: