裸機配置C語言運行環境


  C語言程序的執行需要棧的支持。部分soc未初始化棧的情況下調用C語言程序會發生錯誤。

   start.S中一共配置了看門狗,svc棧,icache。

  在x210中看門狗默認關閉,svc棧默認開啟,icahe默認開啟。

  因為系統在復位后默認是進入SVC模式的,所以我們去配置SVC模式的sp就可以,(在ARM中,ATPCS(ARM關於程序應該怎么實現的一個規范)要求使用滿減棧,所以不出意外都是用滿減棧)通過X210數據手冊結合iROM_application_note中的memory map,可知SVC棧應該設置為0xd0037D80。(x210中在內存中默認設置了一段地方作為棧地址)

  icahe為高速緩沖區  

  cache是一種內存,叫高速緩存。
  從容量來說:CPU < 寄存器 < cache < DDR
  從速度來說:CPU > 寄存器 > cache > DDR

  cache工作時,會把我們CPU正在運行的指令的旁邊幾句指令事先給讀取到icache中(CPU設計有一個基本原理:代碼執行時,下一句執行當前一句代碼旁邊代碼的可能性要大很多)。當下一句CPU要指令時,cache首先檢查自己事先准備的緩存指令中有沒這句,如果有就直接拿給CPU,如果沒有則需要從DDR中重新去讀取拿給CPU,並同時做一系列的動作:清緩存、重新緩存。

  icache在X210默認是開啟的,由協處理器進行設置。

  mrc p15,0,r0,c1,c0,0; // 讀出cp15的c1到r0中
  bic r0, r0, #(1<<12) // bit12 置0 關icache
  orr r0, r0, #(1<<12) // bit12 置1 開icache
  mcr p15,0,r0,c1,c0,0;

  

 start.S

#define WTCON        0xE2700000
#define SVC_STACK    0xd0037d80
.global _start                    // 把_start鏈接屬性改為外部,這樣其他文件就可以看見_start了
_start:
    // 第1步:關看門狗(向WTCON的bit5寫入0即可)(默認關閉)
    ldr r0, =WTCON
    ldr r1, =0x0
    str r1, [r0]
    //第二步:設置SVC棧(默認開啟)
    ldr sp,=SVC_STACK //可以調用C語言了
    
    //開關icache
    
    mrc p15,0,r0,c1,c0,0; // 讀出cp15的c1到r0中(默認開啟)
    
    //bic r0, r0, #(1<<12)  // bit12 置0  關icache
    orr r0, r0, #(1<<12)  // bit12 置1  開icache
    
    mcr p15,0,r0,c1,c0,0; // 讀出cp15的c1到r0中
    
    bl led_blink//調用C函數
    
    b .  
    

led.c

C語言訪問寄存器是通過指針訪問。

led.c

#define GPJ0CON        0xE0200240
#define GPJ0DAT        0xE0200244
#define rGPJ0CON        *((volatile unsigned int*)GPJ0CON)
#define rGPJ0DAT        *((volatile unsigned int*)GPJ0DAT)
void delay(void);
void led_blink(void)
{    
    rGPJ0CON=0x11111111;    
    while(1)
    {
    rGPJ0DAT    =~(1<<3);
    delay();
    rGPJ0DAT    =~(1<<4);
    delay();
    rGPJ0DAT    =~(1<<5);
    delay();
    }     
    
    
}
void delay(void)
{
    volatile unsigned int i=500000;//volatile 避免編譯器優化
    while(i--);
}

Makefile

led.bin: start.o led.o
arm-linux-ld -Ttext 0x0 -o led.elf $^      (將.o文件進行鏈接生成可執行程序,鏈接地址為0x0) arm-linux-objcopy -O binary led.elf led.bin (將可執行程序制作成鏡像文件.bin) arm-linux-objdump -D led.elf > led_elf.dis (將可執行程序進行反匯編) gcc mkv210_image.c -o mkx210 (后兩句是為了處理SD卡燒錄文件制作) ./mkx210 led.bin 210.bin %.o : %.S(將.S文件編譯成.O) arm-linux-gcc -o $@ $< -c -nostdlib (nostdlib就是不使用標准函數庫。標准函數庫就是編譯器中自帶的函數庫,用-nostdlib可以讓編譯器鏈接器優先選擇我程序內自己寫的函數庫。) %.o : %.c(將.c文件編譯成.O)
arm-linux-gcc -o $@ $< -c -nostdlib 
clean:
rm *.o *.elf *.bin *.dis mkx210 -f

Makefile

led.bin: start.o led.o
arm-linux-ld -Ttext 0x0 -o led.elf $^      
arm-linux-objcopy -O binary led.elf led.bin
arm-linux-objdump -D led.elf > led_elf.dis
gcc mkv210_image.c -o mkx210
./mkx210 led.bin 210.bin

%.o : %.S
arm-linux-gcc -o $@ $< -c -nostdlib

%.o : %.c
arm-linux-gcc -o $@ $< -c -nostdlib

clean:
rm *.o *.elf *.bin *.dis mkx210 -f

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM