嵌入式学习-uboot-lesson9.2-C点亮LED

在进行了前面的栈的初始化和BSS段的清除之后,可以使用C进行程序的编写,这里直接对LED进行操作,看其效果。

新建一个main.c

/********************************************
*file name: main.c
*author   : stone
*date     : 2016.6.30
*function : 进行LED的点亮
*********************************************/
#define GPMCON (*(volatile unsigned long *)0x7F008820)
#define GPMDAT (*(volatile unsigned long *)0x7F008824) 

int gboot_main()
{
 GPMCON = 0x1111; 
 GPMDAT = 0x00; //低电平点亮

 return 0;
}

然后在start.S中让其跳转到man函数。

ldr pc,=gboot_main @跳转到gboot_main

代码就不详细解释了。

贴出全部代码。
Makefile

all: start.o mem.o main.o
    arm-linux-ld -Tgboot.lds -o gboot.elf $^
    arm-linux-objcopy -O binary gboot.elf gboot.bin

%.o : %.S
    arm-linux-gcc -g -c $^

%.o : %.c
    arm-linux-gcc -g -c $^

.PHONY: clean
clean:
    rm *.o *.elf *.bin

start.S

@****************************
@file name: start.S
@author   : stone
@date     : 2016.6.30
@function : 
@     异常向量表
@         设置SVC模式
@         关闭看门狗
@         关闭中断
@         关闭MMU
@         外设基地址初始化
@         点亮LED
@         时钟初始化
@         内存初始化
@         代码搬移
@         初始化栈
@         清除BSS段
@         跳转到gboot_main
@****************************

.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:  @处理未定义指令异常
        nop

software_interrupt:     @软中断
        nop

prefetch_abort:         @预取指令异常
        nop

data_abort:             @数据访问异常
        nop

not_used:               @空位
        nop

irq:                    @中断
        nop

fiq:                    @快速中断
        nop

reset:                          @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段
    ldr pc,=gboot_main      @跳转到gboot_main
    @bl light_led           @点亮LED

set_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,lr

disable_interrupt:
        mvn r1,#0x0 @0x0 取反,给r1
        ldr r0,=0x71200014      @VIC0
        str r1,[r0]
        ldr r0,=0x71300014      @VIC1
        str r1,[r0]
        mov pc,lr

disable_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,lr

copy_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, lr

init_stack:
    ldr sp,=0x54000000      @50000000 + 64 
    mov pc,lr

clean_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

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

你可能感兴趣的:(嵌入式,C语言,uboot,OK6410)