1、首先需要一个包含GPIO引脚地址的文件micro2440_GPX.h
/*
* mini2440开发板的GPIO操作宏定义头文件
* author: jimmy
* website: http://www.visky.cublog.cn
*/
#define GPIOBASE 0x56000000
#define GPXCON_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x))
#define GPXDAT_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x + 4))
#define GPXUP_ADDR(x) (*(volatile unsigned long *)(GPIOBASE + x + 8))
#define GPA 0x0
#define GPB 0x10
#define GPC 0x20
#define GPD 0x30
#define GPE 0x40
#define GPF 0x50
#define GPG 0x60
#define GPH 0x70
#define GPJ 0xd0
/*GPX的属性配置寄存器 X代表不同的类型*/
#define GPACON GPXCON_ADDR(GPA)
#define GPBCON GPXCON_ADDR(GPB)
#define GPCCON GPXCON_ADDR(GPC)
#define GPDCON GPXCON_ADDR(GPD)
#define GPECON GPXCON_ADDR(GPE)
#define GPFCON GPXCON_ADDR(GPF)
#define GPGCON GPXCON_ADDR(GPG)
#define GPHCON GPXCON_ADDR(GPH)
#define GPJCON GPXCON_ADDR(GPJ)
/*GPX的数据寄存器*/
#define GPADAT GPXDAT_ADDR(GPA)
#define GPBDAT GPXDAT_ADDR(GPB)
#define GPCDAT GPXDAT_ADDR(GPC)
#define GPDDAT GPXDAT_ADDR(GPD)
#define GPEDAT GPXDAT_ADDR(GPE)
#define GPFDAT GPXDAT_ADDR(GPF)
#define GPGDAT GPXDAT_ADDR(GPG)
#define GPHDAT GPXDAT_ADDR(GPH)
#define GPJDAT GPXDAT_ADDR(GPJ)
#define GPBUP GPXUP_ADDR(GPB)
#define GPCUP GPXUP_ADDR(GPC)
#define GPDUP GPXUP_ADDR(GPD)
#define GPEUP GPXUP_ADDR(GPE)
#define GPFUP GPXUP_ADDR(GPF)
#define GPGUP GPXUP_ADDR(GPG)
#define GPHUP GPXUP_ADDR(GPH)
#define GPJUP GPXUP_ADDR(GPJ)
#define GPAXOUT(x) (GPACON & (GPXMASK & (0x0 << x))) /*GPA比较特殊*/
/******************************************************************************
设置GPIO控制端口GPXCON的x位为输出,GPXCON必须为GPBCON~GPJCON,
x必须<=16
把对应bit变为01即设置为输出
******************************************************************************/
#define GPXXOUT(GPXCON,x) (GPXCON |= (0x1 << (2 * x)))
/******************************************************************************
设置GPIO控制端口GPXCON的x位为输入,GPXCON必须为GPBCON~GPJCON,
x必须<=16
把对应bit变为00即设置为输出
******************************************************************************/
#define GPXXIN(GPXCON,x) (GPXCON &= ((GPXCON & ~(0x3 << (2 * x)))))
/********************************************************************************
设置GPIO端口GPXDAT的x位为高电平,GPXCON必须为GPBCON~GPJCON,
x视不同的BANK拥有的I/O口的个数而定
********************************************************************************/
#define GPXXSET(GPXDAT, x) GPXDAT = GPXDAT | (1 << x)
/********************************************************************************
设置GPIO端口GPXDAT的x位为低电平,GPXCON必须为GPBCON~GPJCON,
x视不同的BANK拥有的I/O口的个数而定
********************************************************************************/
#define GPXXCLR(GPXDAT, x) GPXDAT = GPXDAT & ~(1 << x)
/*******************************************************************************
拉高GPXUP端口的x位,GPXCON必须为GPBCON~GPJCON,
x视不同的BANK拥有的I/O口的个数而定
*******************************************************************************/
#define GPXUPSET(GPXUP, x) GPXUP = GPXUP | (1 << x)
/*******************************************************************************
拉低GPXUP端口的x位,GPXCON必须为GPBCON~GPJCON,
x视不同的BANK拥有的I/O口的个数而定
*******************************************************************************/
#define GPXUPCLR(GPXUP, x) GPXUP = GPXUP & ~(1 << x)
2、建立启动文件crt0.S
@******************************************************************************
@ File: crt0.S
@ 功能:通过它转入C程序
@******************************************************************************
.text
.global _start
_start:
ldr r0, =0x53000000 @ WATCHDOG @WATCHDOG寄存器地址
mov r1, #0x0
str r1, [r0] @ 写入0,禁止WATCHDOG,否则CPU会不断重启
ldr sp, =1024*4 @ 设置堆栈,注意不能大于4KB,因为现在可用的内存只有4KB
@ nand flash中的代码在复位后会移到内部ram(只有4KB)
bl main @ 调用C程序中的main函数
halt_loop:
b halt_loop @ 死循环
3、创建主程序文件key_led.c
#include "micro2440_GPX.h"
/**
* nfs 0x32000000 192.168.0.13:/work/nfs_root/key_led.bin
* nand erase 0x0 0x10000 -----64K
* nand erase write.jffs2 0x32000000 0x0 $(filesize)
* 务必设置跳线从nand flash启动
* 按键按下时为低电平
* 00表示输入,01表示输出
*/
int main()
{
unsigned long dwData;
/* 设置4个LED灯处于输出状态 */
GPXXOUT(GPBCON, 5); /* GPB5 led1 */
GPXXOUT(GPBCON, 6); /* GPB6 led2 */
GPXXOUT(GPBCON, 7); /* GPB7 led3 */
GPXXOUT(GPBCON, 8); /* GPB8 led4 */
/* 设置六个按键处于输入状态 */
GPXXIN(GPGCON, 0); /* GPG0 key1 */
GPXXIN(GPGCON, 3); /* GPG3 key2 */
GPXXIN(GPGCON, 5); /* GPG5 key3 */
GPXXIN(GPGCON, 6); /* GPG6 key4 */
GPXXIN(GPGCON, 7); /* GPG7 key5 */
GPXXIN(GPGCON, 11); /* GPG11 key6 */
while(1) {
dwData = GPGDAT;
/* GPG11的状态 */
if(dwData & (1<<11))
GPBDAT |= (1<<5); /* 设置GPB5的值为1 */
else
GPBDAT &= ~(1<<5); /* 设置GPB5的值为0, led1点亮 */
/* GPG7的状态 */
if(dwData & (1<<7))
GPBDAT |= (1<<6); /* 设置GPB6的值为1 */
else
GPBDAT &= ~(1<<6); /* 设置GPB6的值为0, led2点亮 */
/* GPG6的状态 */
if(dwData & (1<<6))
GPBDAT |= (1<<7); /* 设置GPB7的值为1 */
else
GPBDAT &= ~(1<<7); /* 设置GPB7的值为0, led3点亮 */
/* GPG5的状态 */
if(dwData & (1<<5))
GPBDAT |= (1<<8); /* 设置GPB8的值为1 */
else
GPBDAT &= ~(1<<8); /* 设置GPB8的值为0, led4点亮 */
/* GPG3的状态 */
if(dwData & (1<<3))
GPBDAT |= (1<<5)|(1<<6); /* 设置GPB5/6的值为1 */
else
GPBDAT &= ~((1<<5) | (1<<6) ); /*设置GPB5/6的值为0, led1, led2点亮 */
/* GPG0的状态 */
if(dwData & (1<<0))
GPBDAT |= (1<<8)|(1<<7); /* 设置GPB7/8的值为1 */
else
GPBDAT &= ~((1<<7) |(1<<8)); /* 设置GPB7/8的值为0, led3, led4点亮 */
}
return 0;
}
4、创建Makefile
led_on_c.bin : crt0.S key_led.c
arm-linux-gcc -g -c -o crt0.o crt0.S
arm-linux-gcc -g -c -o key_led.o key_led.c
arm-linux-ld -Ttext 0x00000000 -g crt0.o key_led.o -o key_led_elf
arm-linux-objcopy -O binary -S key_led_elf key_led.bin
arm-linux-objdump -D -m arm key_led_elf > key_led.dis
clean:
rm -f key_led.dis key_led.bin key_led_elf *.o
第2、3行分别编译crt0.S、key_led.c
第4行将编译的结果链接起来
第5行把链接得到的ELF格式可执行文件key_led_elf转换成key_led.bin
第6行将结果转换为汇编代码以供查看
5、总结:程序本身不难,但需要参考所对应开发板的手册来查看各个GPIO的地址以及输入输出设置为低电平还是高电平,参考嵌入式Linux应用开发完全手册和micro2440开发板相关手册
阅读(1580) | 评论(0) | 转发(0) |