您的位置:首页 > 运维架构 > Linux

《嵌入式linux应用程序开发完全手册》LED裸板硬件编程(C语言) 学习笔记

2009-09-26 19:17 609 查看
《嵌入式linux应用程序开发完全手册》LED裸板硬件编程(C语言) 学习笔记

刚刚学习ARM的朋友,我建议先用汇编写一段时间的程序,对基本的ARM汇编有了一个基本的掌握后再改用C语言+汇编的方式进行程序设计,我们先来看一下C语言执行的过程,主要关注它的执行需要的条件和环境,然后根据这些环境在我们的裸板上搭建这些环境,让我们的C语言可以执行。
C语言执行的第一条指令其实并不是main函数,在生成一个C程序的可执行文件时,编译器通常会在我们的代码中加上几个称之为启动文件的的代码--- crt1.o,crti.o,crtend.o,crtn.o等,它们是标准的库文件,这些代码用来设置C程序运行所需的堆栈等,完成一些环境设置后,再调用main函数,生成的这些文件信赖于操作系统,在裸板上没有这些的编译器,这些代码根本无法运行,所以需要为我们真正的C语言写一代码环境配置的代码。以下代码都是简单的几行,就不作详细分析。

设置堆栈的程序如下:

@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@******************************************************************************

.text
.global _start
_start:
ldr     r0, =0x53000000     @ WATCHDOG寄存器地址
mov     r1, #0x0
str   r1, [r0]              @ 写入0,禁止WATCHDOG,否则CPU会不断重启

ldr     sp, =1024*4         @ 设置堆栈,注意:不能大于4k, 因为现在可用的内存只有4K
@ nand flash中的代码在复位后会移到内部ram中,此ram只有4K
bl      main                @ 调用C程序中的main函数
halt_loop:
b       halt_loop


点亮LED的C语言 代码如下:

#define GPBCON      (*(volatile unsigned long *)0x56000010)
#define GPBDAT      (*(volatile unsigned long *)0x56000014)

void delay(int t)
{
for(;t>0;t--);
}
int main()
{
while(1)
{
GPBCON = 0x00000400;    // 设置GPB5为输出口, 位[11:10]=0b01
GPBDAT = 0x00000000;    // GPB5输出0,LED1点亮
delay(30000);

GPBCON = 0x00001000;    // 设置GPB6为输出口, 位[13:12]=0b01
GPBDAT = 0x00000000;    // GPB6输出0,LED2点亮
delay(30000);

GPBCON = 0x00004000;    // 设置GPB7为输出口, 位[15:14]=0b01
GPBDAT = 0x00000000;    // GPB5输出0,LED3点亮
delay(30000);

GPBCON = 0x00010000;    // 设置GPB8为输出口, 位[17:16]=0b01
GPBDAT = 0x00000000;    // GPB5输出0,LED4点亮
delay(30000);
}
return 0;
}


上面实现了依次点亮一个LED1~LED4的功能,如果你感觉这一个灯一个一个地孤单的闪烁太寂寞,那现在我们将实现一个类似跑马灯的功能,让LED1~4按计数方式循环点亮,规律如下:

以下为1的位被点亮,由于LED1~4与I/O的连接如关系为led1~4连接GPB5~8,故规律如下示。

000000000
000100000
001000000
001100000
010000000
010100000
011000000
011100000
100000000
100100000
101000000
101100000
110000000
110100000
111000000
111100000


于是这样一个类似跑马灯的程序就自然而然的出来了:

#define	GPBCON		(*(volatile unsigned long *)0x56000010)
#define	GPBDAT		(*(volatile unsigned long *)0x56000014)

#define	GPB5_out	(1<<(5*2))
#define	GPB6_out	(1<<(6*2))
#define	GPB7_out	(1<<(7*2))
#define	GPB8_out	(1<<(8*2))

void  wait(unsigned long dly)
{
for(; dly > 0; dly--);
}

int main(void)
{
unsigned long i = 0;

GPBCON = GPB5_out|GPB6_out|GPB7_out|GPB8_out;		// 将LED1-4对应的GPB5/6/7/8四个引脚设为输出

while(1){
wait(30000);
GPBDAT = (~(i<<5));	 	// 根据i的值,按计数方式循环点亮LED1-4
if(++i == 16)
i = 0;
}

return 0;
}


Makefile文件如下:

led_on_c.bin : crt0.S  led_on_c.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o led_on_c.o led_on_c.c
arm-linux-ld -Ttext 0x0000000 -g  crt0.o led_on_c.o -o led_on_c_elf
arm-linux-objcopy -O binary -S led_on_c_elf led_on_c.bin
arm-linux-objdump -D -m arm  led_on_c_elf > led_on_c.dis
clean:
rm -f led_on_c.dis led_on_c.bin led_on_c_elf *.o


调试程序的方法见前面所述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐