嵌入式学习-uboot-lesson9.1-C语言环境初始化

来源:互联网 发布:大庆石化公司网络培训 编辑:程序博客网 时间:2024/04/20 08:21

C语言环境的初始化是为了完成另外一些外设的初始化,如网口、串口等。毕竟在某些方面使用汇编没有C方便。
C语言环境的初始化主要完成以下几个方面的内容:
栈的初始化,BSS段的清除。

一、栈初始化

查找了一些网络资料,栈的主要作用是:保护现场/上下文,传递参数。更详细的解释,请参考uboot start.s 分析
因此在接下来要使用C语言,必须要对栈进行相应的初始化。

1 栈

栈是一种具有先进后出性质的数据组织方式,也就是说后存放的先取出,先存放的
后取出。栈底是第一个进栈的数据所处的位置,栈顶是最后一个进栈的数据所处的
位置。

1.1 满/空栈

根据SP指针指向的位置,栈可以分为满栈和空栈。
1. 满栈:当堆栈指针SP总是指向最后压入堆栈的数据
2. 空栈:当堆栈指针SP总是指向下一个将要放入数据的空位置
ARM采用满栈!

1.2概念-升/降栈

根据SP指针移动的方向,栈可以分为升栈和降栈。
1. 升栈:随着数据的入栈,SP指针从低地址->高地址移动
2. 降栈:随着数据的入栈,SP指针从高地址->低地址移动
ARM采用降栈!

根据以前的知识可以得知,内存的其实地址为0x50000000 ,并且ARM是采用满降栈的方式,因此可以将栈的起始位置设置在0x50000000 + 64MB = 0x54000000,64MB这个值可以随意设置,只要不超过内存的0x57ffffff,这个地址即可。

        init_stack:        ldr sp,=0x54000000        mov pc,lr

二、bss初始化

BSS段:存放未初始化全局变量,对BSS段全部清零,防止数据出错

clean_bss: ldr r0, =bss_start ldr r1,=bss_end cmp r0,r1 @将r0r1进行比较,如果相等,说明没有数据,则不需要进行清除moveq pc ,lr @如果相等,则返回

以下是全部代码:

@****************************@file name: start.S@author   : stone@date     : 2016.6.30@function : @     异常向量表@         设置SVC模式@         关闭看门狗@         关闭中断@         关闭MMU@         外设基地址初始化@         点亮LED@         时钟初始化@         内存初始化@         代码搬移@         初始化栈@         清除BSS段@****************************.text.global _start  @将_start声明为全局变量_start:        b   reset                               ldr pc, _undefined_instruction          ldr pc, _software_interrupt             ldr pc, _prefetch_abort                 ldr pc, _data_abort                     ldr pc, _not_used                       ldr pc, _irq                            ldr pc, _fiq_undefined_instruction: .word undefined_instruction_software_interrupt:    .word software_interrupt_prefetch_abort:    .word prefetch_abort_data_abort:        .word data_abort_not_used:      .word not_used_irq:           .word irq_fiq:           .word fiq                   undefined_instruction:  @处理未定义指令异常        nopsoftware_interrupt:     @软中断        nopprefetch_abort:         @预取指令异常        nopdata_abort:             @数据访问异常        nopnot_used:               @空位        nopirq:                    @中断        nopfiq:                    @快速中断        nopreset:                          @reset    bl set_svc              @设置为SVC模式    bl set_peri_port        @外设基地址初始化    bl disable_watchdog     @关闭看门狗    bl disable_interrupt    @关闭中断    bl disable_mmu          @关闭mmu    bl init_clock           @时钟初始化    bl mem_init             @内存初始化    bl copy_to_ram          @代码搬移    bl init_stack           @初始化栈    bl clean_bss            @初始化bss段    bl light_led            @点亮LEDset_svc:            mrs r0, cpsr        @将值取出cpsr寄存器    bic r0, r0, #0x1f   @将后5位 即M[4:0]清零     orr r0, r0, #0xd3   @0b10011 转化为16进制为0x13 同时为了屏蔽irq和fiq,可以将其设置为0b11010011即0xd3      msr cpsr, r0        @将值送回cpsr寄存器    mov pc, lr              @返回set_peri_port:    ldr r0, =0x70000000     @基地址    orr r0, r0, #0x13       @256MB    mcr p15,0,r0,c15,c2,4   @写入cp15    mov pc, lr#define pwTCON 0x7E004000       @WTCON寄存器disable_watchdog:         ldr r0, =pwTCON         @把地址装载到R0        mov r1, #0x0            @置0,关闭看门狗        str r1,[r0]             mov pc,lrdisable_interrupt:        mvn r1,#0x0             @0x0 取反,给r1        ldr r0,=0x71200014      @VIC0        str r1,[r0]        ldr r0,=0x71300014      @VIC1        str r1,[r0]        mov pc,lrdisable_mmu:        mcr p15,0,r0,c7,c7,0    @使ICACHE 和DCACHE 无效    mrc p15,0,r0,c1,c0,0    @read control register    bic r0,r0,#0x00000007   @mmu 和 dcache置零    mcr p15,0,r0,c1,c0,0    @write control register    mov pc,lr#define CLK_DIV0 0x7e00f020#define CLK_SRC  0x7e00f01c#define OTHERS   0x7e00f900#define MPLL_CON 0X7E00F010#define APLL_CON 0X7E00F00c#define PLL_VAL ((1<<31)|(266<<16)|(3<<8)|(1<<0))#define DIV_VAL ((0X0<<0)|(0X1<<9)|(0X1<<8)|(0X3<<12))init_clock:ldr r0,=CLK_DIV0        @设置分频系数    ldr r1,=DIV_VAL    str r1,[r0]    ldr r0,=OTHERS      @设置异步工作模式 第7位为06位为0(时钟选择器)    ldr r1,[r0]    bic r1,r1,#0xc0    str r1,[r0]    ldr r0,=APLL_CON    @APLL设置为533Mhz    ldr r1,=PLL_VAL    str r1,[r0]    ldr r0,=MPLL_CON    @MPLL设置为533Mhz    ldr r1,=PLL_VAL    str r1,[r0]    ldr r0, =CLK_SRC    @选择时钟源为APLL MPLL还是外部    mov r1, #0x3        @APLL MPLL    str r1, [r0]            mov pc,lrcopy_to_ram:        ldr r0, =0x0c000000     @起始地址        ldr r1, =0x50008000     @搬移地址        add r3, r0, #1024*4     @复制4KB数据copy_loop:        ldr r2, [r0], #4        @从r0中读取数据        str r2, [r1], #4        @写入r1中        cmp r0, r3              @比较r0是否已经移动到了末尾    bne copy_loop        mov pc, lrinit_stack:    ldr sp,=0x54000000      @50000000 + 64     mov pc,lrclean_bss:    ldr r0,=bss_start    ldr r1,=bss_end    cmp r0,r1               @将r0r1进行比较,如果相等,说明没有数据,则不需要进行清除    moveq pc,lr             @如果相等,则返回 clean_loop:    mov r2,#0    str r2,[r0],#4    cmp r0,r1    bne clean_loop    mov pc,lr#define GPMCON 0x7F008820       @控制寄存器#define GPMDAT 0x7F008824   @数据寄存器  light_led:    ldr r0,=GPMCON    ldr r1,=0x1111          @输出模式    str r1,[r0]    ldr r0,=GPMDAT    ldr r1,=0x00            @低电平点亮    str r1,[r0]     mov pc,lr

菜鸟一枚,如有错误,多多指教。。。

0 0
原创粉丝点击