裸机系列代码地址:链接:http://pan.baidu.com/s/1pLHOd0v 密码:4x5s
离找工作只有不到三个月的时间,为了复习嵌入式方面的知识,这里会写一系列的博客,包含裸机,内核移植,驱动。为了督促自己遇到难点时不要放弃,这里粘贴一条《高质量程序设计指南C++C语言》中的一段名言:如果放弃一次,那么碰到下一个挫折时我就会继续放弃;如果坚持而成功,那么碰到下一个挑战时我就会激励自己再次取得成功
废话不多说,直接开始粘贴代码
(1)纯汇编写的控制点亮LED的代码,总共两个文件,led.S汇编文件,Makefile文件
led.S文件
#define ledout ((1<<12)|(1<<10)|(1<<8))
.text
.global _start
_start:
LDR r0,=0x56000050
LDR r1,=ledout
str r1,[r0]
LDR r0,=0x56000054
mov r1,#0x00000000
str r1,[r0]
mainloop:
b mainloop
Makefile文件
led.bin:led.s
arm-linux-gcc -g -c led.s -o led.o
arm-linux-ld -Ttext 0x00000000 -g led.o -o led_elf
arm-linux-objcopy -O binary -S led_elf led.bin
clean:
rm -f led.bin led_elf *.o
从jz2440的原理图中可以得知,led1,led2,led3分别接在了GPF4,GPF5,GPF6三个引脚上。
控制通用GPIO引脚使用如下三个寄存器
GPXCON(GPIO引脚控制寄存器):用它来配置引脚的功能(输入,输出,还是其他功能)
GPXDAT(GPIO数据寄存器):读写引脚状态,当引脚作为输入功能时,读此寄存器可以知道引脚的电平是高或低,当引脚作为输出是,写此寄存器可以控制引脚的输出电平。
GPXUP寄存器:某位为1时,相应引脚内部无上拉电阻,为0时,内部有上拉电阻
在写程序控制led时,首先应该是GPF端口的相应位为输出功能(写GPFCON),然后往GPF相应位输出低电平(写GPFDAT)。
(2)C和汇编混合写的点亮LED的程序
led.s文件
.text
.global _start
_start:
ldr r0 ,=0x56000010
mov r1,#0x00000000
str r1,[r0]
ldr sp,=1024*4 /*在调用C函数之前必须设置堆栈指针,这里设定为steppingstone末尾处*/
bl main
halt_loop:
bl halt_loop
main.c文件
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDATA (*(volatile unsigned long *)0x56000054)
#define out ((1<<12)|(1<<10)|(1<<8))
int main()
{
GPFCON=out;
GPFDATA=0X00000000;
return 0;
}
Makefile文件
ledc.bin:led.s main.c
arm-linux-gcc -g -c led.s -o led.o
arm-linux-gcc -g -c main.c -o main.o
arm-linux-ld -Ttext 0x00000000 -g led.o main.o -o ledc_elf
arm-linux-objcopy -O binary -S ledc_elf ledc.bin
arm-linux-objdump -D -m arm ledc_elf > ledc.dis
clean:
rm ledc.bin ledc_elf ledc.dis *.o
led_and_key.S文件
#define WATCHDOG 0x53000000
.text
.global _start
_start:
/*关看门狗*/
LDR r1,=WATCHDOG
mov r0,#0x00000000
str r1,[r0]
/*设置堆栈指针*/
ldr sp,=1024*4 /*堆栈位置为steppingstone的末尾处*/
bl main
halt_loop:
b halt_loop
main.c文件
#define GPFCON (*(volatile unsigned long *)0x56000050)
#define GPFDAT (*(volatile unsigned long *)0x56000054)
#define GPGCON (*(volatile unsigned long *)0x56000060)
#define GPGDAT (*(volatile unsigned long *)0x56000064)
#define GPF4_5_6_OUT ((0x01<<12)|(0x01<<10)|(0x01<<8))
#define GPF0_2_IN (~((0x3<<4)&(0x3)))
#define GPG3_IN (~(0X3<<6))
#define GPF4_5_6_OFF ((1<<4)|(1<<5)|(1<<6))
int main()
{
GPFCON|=GPF4_5_6_OUT;
GPFCON&=GPF0_2_IN;
GPGCON&=GPG3_IN;
GPFDAT|=GPF4_5_6_OFF;
unsigned long gpfval;
unsigned long gpgval;
while(1)
{
gpfval=GPFDAT;
if(gpfval&1)
GPFDAT|=(1<<4);
else
GPFDAT&=(~(1<<4));
if((gpfval>>2)&1)
GPFDAT|=(1<<5);
else
GPFDAT&=(~(1<<5));
gpgval=GPGDAT;
if((gpgval>>3)&1)
GPFDAT|=(1<<6);
else
GPFDAT&=(~(1<<6));
}
return 0;
}
Makefile文件
led_and_key.bin:led_and_key.S main.c
arm-linux-gcc -g -c led_and_key.S -o led_and_key.o
arm-linux-gcc -g -c main.c -o main.o
arm-linux-ld -Ttext 0x00000000 -g led_and_key.o main.o -o led_and_key_elf
arm-linux-objcopy -O binary -S led_and_key_elf led_and_key.bin
arm-linux-objdump -D -m arm led_and_key_elf > led_and_key.dis
clean:
rm -f led_and_key.elf led_and_key.bin led_and_key.dis *.o