第一课:GPIO操作——LED & 按键

前言

学习嵌入式已经快一年了,却是第一次正经的开始从ARM的裸板程序开始学习,有些汗颜……准备学习裸板程序的一部分,然后接着学习相应的设备驱动开发。第一次学博文,欢迎拍砖

第一课:GPIO操作——LED & 按键

环境:

软件:Ubuntu9.10 source insight3.5 oflash JTAG等驱动

硬件:ARM 2440 (韦东山配套教材)

参考教材:嵌入式Linux应用开发完全手册 韦东山著

一系列的环境搭建,操作步骤书中和视频教材解释也挺详细的

只是记录下学习过程的心得

按键点亮 LED     (C语言 )

最终文件: 

led_key.c :C程序文件,实现点亮led

crt0.s :裸板程序中的启动代码(汇编)

led_key.lds :连接脚本

Makefile :实现程序的预处理、编译、汇编和链接以及清除工作


实现: 

此处GPIO的操作需要:

1.判断key

2.点亮/灭led

a.配置功能:输出/输入/其他 key为输入,led引脚为输出功能

b.读key引脚,根据值来设置led引脚高电平LED熄灭,低电平LED点亮(参看电路图)


写程序之前先了解一下ARM2440的两种启动方式

1.Nand flash启动

a.在开发板上电启动的时候,CPU将Nand Flash开始的前4K数据复制到SRAM,即“Steppingstone”(此时内部RAM的起始地址为0);

b.CPU跳转地址0开始执行。

以上两步均为硬件执行

2.Nor flash启动

Nor flash可以像内存一样进行读操作,却不可想内存一样写

a.0地址指向Nor flash

b.CPU 从0地址取址执行

由于是裸板程序,因此需要在C语言文件之前实现一系列的初始化工作。

1)软件相关的初始化:

a.设置栈,即初始化SP指针,指向内存的某一块区域。如果是SRAM,可直接使用,如果是SDAM,还需要初始化(韦东山的板子都是直接映射到SRAM的,因此可以直接使用)

b.设置C语言中的main返回地址

c.调用main函数

(以上两步直接通过bl main可实现,返回地址保存到了LR寄存器)

d.清理工作

(通过死循环来实现的   

halt_loop : b halt_loop ) 

2)硬件初始化:

a.关看门狗,关中断

b.初始化时钟

c.初始化SDAM

(此次程序只关了看门狗)

这两步是由crt0.s来实现的,之后调用main函数


@******************************************************************************
@ File:crt0.S
@ 功能:通过它转入C程序
@****************************************************************************** 
@.text部分是处理器开始执行代码的地方
@.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用
@.global _start让_start符号成为链接器可见的标识符
@这样链接器就知道跳转到程序中的什么地方并开始执行
@linux寻找这个_start标签作为程序的默认进入点
@转载自:http://hi.baidu.com/ahauwangjie/item/10e988e740160ee5fb42baa5
.text
.global _start
_start:
	ldr r0,= 0x53000000;	@watchdog寄存器地址
	mov r1,#0x0
	str r1,[r0]
	ldr sp,= 1024 * 4

	bl main
halt_loop:
	b halt_loop

程序的具体实现:

//引脚定义
#define GPFCON	(*(volatile unsigned long *)0x56000050)
#define GPFDAT	(*(volatile unsigned long *)0x56000054)
#define GPGCON 	(*(volatile unsigned long *)0x56000060)
#define GPGDAT	(*(volatile unsigned long *)0x56000064)


//LED引脚初始化定义
#define GPF4_MSK	(3<<(4*2))
#define GPF5_MSK	(3<<(5*2))
#define GPF6_MSK	(3<<(6*2))

//按键引脚初始化定义
#define GPF0_MSK	(3<<(0*2))
#define GPF2_MSK	(3<<(2*2))
#define GPG3_MSK	(3<<(3*2))

//led引脚输出定义
#define GPF4_out		(1<<(4*2))
#define GPF5_out		(1<<(5*2))
#define GPF6_out		(1<<(6*2))


int main()
{

	unsigned long temp;
	//先将led相应引脚置0,其他位保留
	GPFCON &= ~(GPF4_MSK | GPF5_MSK |GPF6_MSK);
	//定义led引脚为输出
	GPFCON |= (GPF4_out | GPF5_out | GPF6_out);
	//定义按键引脚为输入
	GPFCON &= ~(GPF0_MSK | GPF2_MSK);
	GPGCON &= ~(GPG3_MSK);
	while(1)
	{
		//读取key值
		temp = GPFDAT;
		//key值为0说明按键按下,为1表示没有按下
		if(temp & (1<<0))
			GPFDAT |= (1<<4);	//熄灭led
		else
			GPFDAT &= ~(1<<4);	//点亮led
		if(temp & (1<<2))
			GPFDAT |= (1<<5);
		else 
			GPFDAT &= ~(1<<5);
		temp = GPGDAT;
		if(temp & (1<<3))
			GPFDAT |= (1<<6);
		else
			GPFDAT &= ~(1<<6);
	}
	
	return 0;
}


 

led_key.lds:

SECTIONS {
	. = 0x00;
  	.text          :   { *(.text) }
	.rodata ALIGN(4) : {*(.rodata)} 
  	.data ALIGN(4) : { *(.data) }
  	.bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}
关于连接脚本的细节,请参照相关文章:

http://blog.csdn.net/chepwavege/article/details/7401794

http://johnylai.i.sohu.com/blog/view/31725442.htm


Makefile:

led_key.bin : led_key.c crt0.s						#依赖关系
	arm-linux-gcc -g -c -o crt0.o crt0.s				#编译crt0.s
	arm-linux-gcc -g -c -o led_key.o led_key.c			#编译led_key.c
	arm-linux-ld -Tled_key.lds crt0.o led_key.o -o led_key_elf	#通过连接脚本链接,生成led_key_elf文件
	arm-linux-objcopy -O binary -S led_key_elf led_key.bin		#生成二进制可执行文件
	arm-linux-objdump -D -m arm led_key_elf > led_key.dis		#生成反汇编文件
clean:
	rm -f led_key_elf led_key.bin led_key.dis *.o *~		#make clean

至此按键控制led的裸板程序写好,中间还有不少迷惑的地方,诸如Makefile中诸多参数的定义,连接脚本的编写,启动汇编程序的完善……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值