目標:C語言實現點亮LED燈 首先是main函數,並不特殊,它是被系統調用來執行的,main函數結束後要返回調用main函數的地址處,那麼裸機程式,沒有操作系統做這些工作,就要自己寫調用main函數的程式了。軟體相關的初始化:1、設置棧 2、設置main函數返回地址 3、調用main 4、清理工作所 ...
目標:C語言實現點亮LED燈
首先是main函數,並不特殊,它是被系統調用來執行的,main函數結束後要返回調用main函數的地址處,那麼裸機程式,沒有操作系統做這些工作,就要自己寫調用main函數的程式了。
軟體相關的初始化:
1、設置棧 2、設置main函數返回地址 3、調用main 4、清理工作
所謂設置棧就是將棧指針SP指向某塊記憶體,在S3C2440中這塊記憶體可以是片內SRAM,這樣不用初始化記憶體了,如果指向SDRAM,那麼首先要初始化SDRAM。
硬體相關的初始化:
a、關閉看門狗;b、初始化時鐘;c、初始化SDRAM等
軟體相關初始化和硬體相關初始化結合一起就是啟動文件。
下麵是用C語言寫的代碼
這一段代碼是彙編語言,作用相當於啟動文件,在這裡為了簡單,在硬體方面初始化只關閉了看門狗,軟體方面初始化設置了棧。
crt.S
.text .global _start _start: ldr r0,=0x53000000 @看門狗地址 mov r1,#0x0 str r1,[r0] @寫入0,關閉看門狗 ldr sp,=1024*4 @設置堆棧,註意不能大於4K bl main halt_loop: b halt_loop
分析這段彙編程式,首先初始化硬體相關的,關閉看門狗,然後設置堆棧,在s3c2440不能大於4K,因為s3c2440片內SRAM只有4K,再然後就是調到main函數,用了bl指令,bl有兩個功能,一是跳轉,二是設置了返回地址,就是bl main指令的下一條指令b hail_loop,所以在這裡就初始化完返回地址了。
下麵就實現c語言的main函數。
#define GPFCON (*(volatile unsigned long *)0x56000050) #define GPFDAT (*(volatile unsigned long *)0x56000054) int main() { GPFCON = 0x00000100; GPFDAT = 0x00000000; return 0; }
2、用C語言輪流點亮LED
#define GPFCON (*(volatile unsigned long *)0x56000050) #define GPFDAT (*(volatile unsigned long *)0x56000054) #define GPF4_out ( 1 << 4*2 ) #define GPF5_out ( 1 << 5*2 ) #define GPF6_out ( 1 << 6*2 ) void delay(volatile unsigned long dly) { for(;dly > 0;dly--); } int main() { unsigned i = 1; GPFCON = GPF4_out | GPF5_out | GPF6_out; while(1) { GPFDAT = ( ~( i << 4 ) ); i *=2; if( i == 8) { i = 1; } delay(30000); } return 0; }
Makefile
CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding led_on.bin:ctr.S main.c arm-linux-gcc $(CFLAGS) -c -o ctr.o ctr.S arm-linux-gcc $(CFLAGS) -c -o main.o main.c arm-linux-ld -Ttext 0x00000000 ctr.o main.o -o led_on.elf arm-linux-objcopy -O binary -S led_on.elf led_on.bin arm-linux-objdump -D -m arm led_on.elf>led_on.dis clean: rm -f led_on.bin led_on.elf *.o led_on.dis
3、按鍵操作
#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_out ( 1 << 4*2 ) #define GPF5_out ( 1 << 5*2 ) #define GPF6_out ( 1 << 6*2 ) #define GPF4_msk ( 3 << ( 4*2 ) ) #define GPF5_msk ( 3 << ( 5*2 ) ) #define GPF6_msk ( 3 << ( 6*2 ) ) #define GPF0_in ( 0 << 0*2 ) #define GPF2_in ( 0 << 2*2 ) #define GPG3_in ( 0 << 3*2 ) #define GPF0_msk ( 3 << ( 0*2 ) ) #define GPF2_msk ( 3 << ( 2*2 ) ) #define GPG3_msk ( 3 << ( 3*2 ) ) int main( void ) { unsigned long ysdat; GPFCON &= ~( GPF4_msk | GPF5_msk | GPF6_msk ); GPFCON |= GPF4_out |GPF5_out | GPF5_out; GPFCON &= ~( GPF0_msk | GPF2_msk ); GPFCON |= GPF0_in |GPF2_in; GPGCON &= ~( GPG3_msk ); GPGCON |= GPG3_in; while(1) { ysdat = GPFDAT; if( ysdat & ( 1 << 0 ) ) { GPFDAT |= ( 1 << 4 ); } else { GPFDAT &= ~( 1 << 4 ); } if( ysdat & ( 1 << 2 ) ) { GPFDAT |= ( 1 << 5 ); } else { GPFDAT &= ~( 1 << 5 ); } ysdat = GPGDAT; if( ysdat & ( 1 << 3 ) ) { GPFDAT |= ( 1 << 6 ); } else { GPFDAT &= ~( 1 << 6 ); } } return 0; }
Makefile
CFLAGS := -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -ffreestanding led_on.bin:ctr.S main.c arm-linux-gcc $(CFLAGS) -c -o ctr.o ctr.S arm-linux-gcc $(CFLAGS) -c -o main.o main.c arm-linux-ld -Ttext 0x00000000 ctr.o main.o -o led_on.elf arm-linux-objcopy -O binary -S led_on.elf led_on.bin arm-linux-objdump -D -m arm led_on.elf>led_on.dis clean: rm -f led_on.bin led_on.elf *.o led_on.dis
通過嵌入式GPIO介面及操作(一)及這篇兩個程式的練習,能夠掌握對GPIO的操作,這是操作硬體的基本技能。