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扇区都写入。
这个程序已经写了很久了,感觉程序没什么问题,但是一运行就出问题,就是按键没什么反应,不能控制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扇区都写入。
相关文章推荐
- 嵌入式bootloader开发之十一-------裸机程序LED开发(Tiny 6410)
- Tiny6410_SD卡启动_闪烁的led裸机程序
- ARM裸机程序开发——按键控制LED灯
- 《tiny6410裸机程序》第九章:tiny6410按键控制蜂鸣器程序
- 从ARM裸机看驱动之按键中断方式控制LED(二)
- 4412裸机程序按键控制led灯
- ARM裸机——FS2410按键控制LED(中断方式)
- ARM裸机——FS2410按键控制LED灯(查询方式)
- 4412裸机程序之按键控制LED
- Tiny4412裸机程序,按键检测(轮询方式)
- 关于mini2440的一个裸机程序——LED与按键中断
- 【OK6410裸机程序】按键中断
- ok6410 LED/GPIO 控制 C#程序
- mini2440(2) LED灯裸机硬件控制程序
- 关于mini2440的一个裸机程序——LED与按键中断
- 按键控制LED实现启动、停止按钮
- OK6410利用矢量中断通过按键控制LED灯
- mini2440(2) LED灯裸机硬件控制程序
- 2.STM32中对Key_GPIO_Config()函数的理解(自定义)之轮询控制按键LED
- ARM裸机程序开发10(LED控制程序)