您的位置:首页 > 其它

Tiny6410按键轮询方式控制LED的SD卡启动裸机程序

2013-02-12 09:55 375 查看
Tiny6410按键轮询方式控制LED的SD卡启动裸机程序
这个程序已经写了很久了,感觉程序没什么问题,但是一运行就出问题,就是按键没什么反应,不能控制LED灯的亮灭,上网找资料,大部分用按键控制LED的裸机程序都是用中断的方式进行的,我对中断还不是太了解,所以想用轮询的方式试试,所以一直以来也没试验成功。今天是大年初二,晚上闲来无事,加之又在网上搜了点别的程序,决定试试。试了以后还是不行,只好又编译自己以前写的这个程序再试。

我一直怀疑是Tiny6410启动方式导致这个按键不能控制LED(我是以SD卡启动的),但一直不能确定。因为从我查到的资料来看,选择SD卡启动时,GPN这一组GPIO口13到15位(GPN[15:13])被用来确定是否由SD卡启动,而Tiny6410的几个按键正好接在GPN这一组GPIO上,因此很可能是由这个原因引起的。如图:



但突然间我想起,如果以SD卡启动,启动以后把选择开关拨到Nand方式,是否能释放这几个按键呢,一试果然如此,真是太高兴了,两三个月的功夫没白费。编译环境是Linux gcc,程序如下:

程序保存为:led.c

#define GPKCON0 (*(volatile unsigned long *)(0x7f008800))

#define GPKDAT (*(volatile unsigned long *)(0x7f008808))

#define GPKPUD (*(volatile unsigned long *)(0x7f00880C))

#define GPNCON (*(volatile unsigned long *)(0x7f008830))

#define GPNDAT (*(volatile unsigned long *)(0x7f008834))

#define GPNPUD (*(volatile unsigned long *)(0x7f008838))

#define GPK4_msk (15<<4*4) //清空相应的位

#define GPK5_msk (15<<5*4)

#define GPK6_msk (15<<6*4)

#define GPK7_msk (15<<7*4)

#define GPK4_out (1<<4*4) //设置相应的位

#define GPK5_out (1<<5*4)

#define GPK6_out (1<<6*4)

#define GPK7_out (1<<7*4)

#define GPN0_msk (3<<0*2) //清空相应的位

#define GPN1_msk (3<<1*2)

#define GPN2_msk (3<<2*2)

#define GPN3_msk (3<<3*2)

#define GPN0_in (0<<0*2) //设置相应的位

#define GPN1_in (0<<1*2)

#define GPN2_in (0<<2*2)

#define GPN3_in (0<<3*2)

int main()

{

unsignedlong key_data=0;

GPKCON0&= ~(GPK4_msk | GPK5_msk | GPK6_msk | GPK7_msk);

GPKCON0|= (GPK4_out | GPK5_out | GPK6_out | GPK7_out);

GPKPUD= 0xaaaa;

GPNCON= 0;

//GPNCON&= ~(GPN0_msk | GPN1_msk | GPN2_msk | GPN3_msk);

//GPNCON|= (GPN0_in | GPN1_in | GPN2_in | GPN3_in);

GPNPUD=0xaaaa;

GPKDAT= 0xffff;

while(1)

{

key_data= GPNDAT;

if(key_data& (1<<0))

GPKDAT|= (1<<4);

else

GPKDAT&= ~(1<<4);

key_data= GPNDAT;

if(key_data& (1<<1))

GPKDAT|= (1<<5);

else

GPKDAT&= ~(1<<5);

key_data= GPNDAT;

if(key_data& (1<<2))

GPKDAT|= (1<<6);

else

GPKDAT&= ~(1<<6);

key_data= GPNDAT;

if(key_data& (1<<3))

GPKDAT|= (1<<7);

else

GPKDAT&= ~(1<<7);

}

return0;

}

程序保存为:start.S

.text

.global _start

_start:

@/* 关看门狗 */

@/* 往WTCON(0x7E004000)写0 */

ldr r0, =0x7E004000

mov r1, #0

strr1, [r0]

ldrsp, =8*1024

blmain

halt:

bhalt

其实我觉得没必要这一段汇编程序,因为Tiny6410一上电自动关闭了Watchdog,以及初始化了许多东东,但也许必要吧,因为好像它不自动设置堆栈!

程序保存为:makefile

led.bin: start.o led.o

arm-linux-ld-Ttext 0 -o led.elf start.o led.o

arm-linux-objcopy-O binary -S led.elf led.bin

arm-linux-objdump-D -m arm led.elf > led.dis

%.o: %.S

arm-linux-gcc-o $@ $< -c

%.o: %.c

arm-linux-gcc-o $@ $< -c

clean:

rm*.o led.elf led.bin led.dis

好了,以上便是所有的源程序了,用Tiny6410自带的编译工具链一下,写在SD卡上运行吧。



注意,一定是先由SD卡启动,这时按键是不起作用的,且有三盏Led灯是亮的,然后把启动选择开关拨到Nand方式(靠近铜柱支架那边),此时Led灯全灭,然后就可以按键控制了,就是这样!

在Linux下写SD卡请看http://blog.csdn.net/zzwpublic/article/details/8273846

如果是>2G的卡,只是写的位置不同,其余一样,下文有例子。也可参考/article/10560471.html

不>2G的卡叫SD卡,>2G的叫SDHC,区别就在于容量。对于sd卡,应写到
(totalSector - 18) 的扇区;对于sdhc卡,应写到(totalSector-1042)的扇区。

下面是一个led.bin写入的例子,使用的是2G的sd卡,所以应该写到 -512 * 18处。我使用的是linux环境,用dd命令就可以对绝对磁盘扇区做读写。还有一个问题就是要知道sd卡的大小,用fdisk命令就可以了:

$ sudo fdisk -l /dev/sdb

Disk /dev/sdb: 2059 MB, 2059403264 bytes

207 heads, 37 sectors/track, 525 cylinders

Units = cylinders of 7659 * 512 = 3921408 bytes

Sector size (logical/physical): 512 bytes / 512 bytes

I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk identifier: 0xb2a60e0e

Device Boot Start End Blocks Id System

/dev/sdb1 1 525 2010469 b W95 FAT32

所以要写入的地址为 2059403264 - 18 * 512 = 2059394048

然后用dd命令写入led.bin :

$ sudo dd if=./led.bin of=/dev/sdbseek=2059394048 bs=1

至此一张可启动的sd卡就完成了,插入tiny6410, 选择sd卡启动模式。

注:友善宣称它提供的SDFlasher.exe可以不论sd和sdhc卡都可以支持,从而优于三星提供的IROM_Flushing_Tool,三星的要选择是sd还是sdhc。其实原理很简单,SDFlasher.exe写入时不论是-18扇区还是-1042扇区都写入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: