• 裸机配置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
  • 相关阅读:
    线程之Thread
    如何通过HTTP优雅调用第三方-Feign
    Spring AOP核心源码
    Spring-beans之BeanFactory初始化
    spring-core源码走读
    power of two
    排序算法(二)两种选择排序
    排序算法(一)四种冒泡排序
    约瑟夫问题
    我理解的CLH
  • 原文地址:https://www.cnblogs.com/PengfeiSong/p/6345605.html
Copyright © 2020-2023  润新知