在本文中,我們使用匯編跳轉到C代碼,來實現點亮led,其中注意的一點是sp的設置,其他就比較簡單。
bootsect代碼如下:
@****************************************************************************** @ File:bootsect.s @ 功能: @****************************************************************************** .equ WATCHDOGCON, 0x7e004000 .equ LEDCON, 0x7f008800 .equ LEDDAT, 0X7f008808 .text .global _start _start: bl setup_peri_port bl disable_watch_dog bl setup_sp bl display_led bl main MAIN_LOOP: b MAIN_LOOP disable_watch_dog: @往WATCHDOG寄存器寫0即可 ldr r0,=WATCHDOGCON mov r1,#0x0 str r1,[r0] mov pc,lr setup_sp: ldr sp, =1024*8 @ 設置堆棧,注意:不能大於8k, 因為現在可用的內存只有8K @ nand flash中的代碼在復位後會移到內部ram中,此ram只有8K mov pc,lr setup_peri_port: ldr r0,=0x70000013 @base addres:0x70000000,size:256MB mcr p15,0,r0,c15,c2,4 mov pc,lr display_led: ldr r0,=LEDCON @ R0設為LEDCON,即GPKCON0寄存器。此寄存器 @ 用於選擇端口K各引腳的功能: @ 是輸出、是輸入、還是其他 mov r1,#0x110000 str r1,[r0] @ 設置GPK4,5為輸出口 ldr r0,=LEDDAT @ R0設為GPKDAT寄存器。此寄存器 @ 用於讀/寫端口B各引腳的數據 mov r1,#0x00000000 @ 此值為0x000000,低電平點亮led str r1,[r0] @ GPK4,5輸出0,LED4,5點亮 mov pc,lr
main.c文件如下:
#define rGPKCON0 (*(volatile unsigned *)(0x7F008800)) #define rGPKCON1 (*(volatile unsigned *)(0x7F008804)) #define rGPKDAT (*(volatile unsigned *)(0x7F008808)) #define rGPKPUD (*(volatile unsigned *)(0x7F00880C)) void Port_Init(void) { rGPKCON0 = (rGPKCON0 & ~(0xffffU<<16))|(0x1111U<<16); rGPKPUD = (rGPKPUD & ~(0xffU << 8))|(0x00U<<8); } void Led_Display(int data) { rGPKDAT = (rGPKDAT & ~(0xf<<4)) | ((data & 0xf)<<4); } static void LedDelay(void) { volatile unsigned int k; for(k = 0; k < 200000; k++); } int main() { Port_Init(); for(;;) { Led_Display(0x1); // LedDelay(); Led_Display(0x2); // LedDelay(); Led_Display(0x4); // LedDelay(); Led_Display(0x8); // LedDelay(); } return 0; }
Makefile文件如下:
led_on_c.bin : bootsect.s main.c arm-linux-gcc -g -c -o bootsect.o bootsect.s arm-linux-gcc -g -c -o main.o main.c arm-linux-ld -Ttext 0x0000000 -g bootsect.o main.o -o linux_kernel_elf arm-linux-objcopy -O binary -S linux_kernel_elf linux_kernel.bin arm-linux-objdump -D -b binary -m arm linux_kernel.bin > linux_kernel.dis clean: rm -f *.dis *.bin *elf *.o
本欄目更多精彩內容:http://www.bianceng.cn/OS/Linux/