今天做的是个简单的启动代码以及电灯,我们这里用的硬件平台是i.mx6ull,我们需要用交叉编译去把启动代码下载到sd卡中,再从sd卡启动到板卡中。
我们跟着代码一起来学习:
首先是异常向量表的设置
.global _start
_start:
ldr pc,=_reset_handler
ldr pc,=_undefined_handler
ldr pc,=_svc_handler
ldr pc,=_prefetch_handler
ldr pc,=_data_handler
ldr pc,=_not_handler
ldr pc,=_irq_handler
ldr pc,=_fiq_handler
_svc_handler:
ldr pc,=_svc_handler
_undefined_handler:
ldr pc,=_undefined_handler
_prefetch_handler:
ldr pc,=_prefetch_handler
_data_handler:
ldr pc,=_data_handler
_not_handler:
ldr pc,=_not_handler
_irq_handler:
ldr pc,=_irq_handler
_fiq_handler:
ldr pc,=_fiq_handler
这里我们除了_reset_handler没有写出来以外,其余所有的异常向量我们都指向的是一个死循环。
_reset_handler:
cpsid i
cps #0x12
ldr sp ,=0x82000000
cps #0x1F
ldr sp , =0x84000000
cpsie i
bl enalbe_clock
bl init_led
bl led_on
b finished
这里就是reset_handler全部的代码,这里第一行代码 cpsid i 是指禁用irq中断 防止中断打断初始化操作 ,第二行就是切换工作模式(00010010)也就是irq模式,然后配置irq模式的栈寄存器,并且分配空间,然后就是及那个工作模式切换为sys模式(0001 1111)并且配置栈寄存器,下来就是将关闭的irq中断打开。
下来就是一个函数一个函数来说:
enalbe_clock:
mov r1 ,#0xFFFFFFFF
ldr r0,=0x020c4068
str r1,[r0]
ldr r0,=0x020c406C
str r1,[r0]
ldr r0,=0x020C4070
str r1,[r0]
ldr r0,=0x020C4074
str r1,[r0]
ldr r0,=0x020C4078
str r1,[r0]
ldr r0,=0x020C407C
str r1,[r0]
ldr r0,=0x020C4080
str r1,[r0]
bx lr
这个函数是将所有的时钟门打开也就是cg使其能正常工作。
这里门的地址也就在这张图里,从2068~4080都是我所需要设置的
init_led:
ldr r0 ,=0x020E0068
mov r1,#0x05
str r1 ,[r0]
ldr r0,=0x020E02F4
ldr r1,=0x10B0
str r1,[r0]
ldr r0,=0x0209C004
mov r1,#0
orr r1,r1,#(1<<3)
str r1,[r0]
bx lr
这里是我们的时钟初始化代码,我门首先需要设置复用模式为gpio模式,我们这里查询底板的原理图,led连接的复用端口为gpio1_03。我们在芯片的指导手册中查出gpio1_03的寄存器地址,将其设置为gpio模式图中可知(0x05)。
然后就是设置电器属性
我们这里根据手册,找到寄存器地址设置我们所需要的。
然后就是设置GPIO方向寄存器:
我们使用的是03所以就要将方向寄存器的第三位设置为1 。而方向寄存器的地址就需要结合这张图来看:
我们这里用的gpio是第一组gpio也就是209_C000 的基地址加上4的偏移地址就是0x0209C000.
这里设置完我们的led初始化就结束了。
然后就是电灯代码:
led_on:
ldr r0,=0x0209C000
ldr r1,[r0]
bic r1,r1,#(1<<3)
str r1,[r0]
bx lr
这里我放出完整代码:
.global _start
_start:
ldr pc,=_reset_handler
ldr pc,=_undefined_handler
ldr pc,=_svc_handler
ldr pc,=_prefetch_handler
ldr pc,=_data_handler
ldr pc,=_not_handler
ldr pc,=_irq_handler
ldr pc,=_fiq_handler
_svc_handler:
ldr pc,=_svc_handler
_undefined_handler:
ldr pc,=_undefined_handler
_prefetch_handler:
ldr pc,=_prefetch_handler
_data_handler:
ldr pc,=_data_handler
_not_handler:
ldr pc,=_not_handler
_irq_handler:
ldr pc,=_irq_handler
_fiq_handler:
ldr pc,=_fiq_handler
_reset_handler:
cpsid i
@ mrs r0 ,cpsr
@ bic r0,r0, #(0x1F<<0)
@ bic r0,r0, #(1<<7)
@ orr r0,r0, #(0x12<<0)
@ msr cpsr,r0
cps #0x12
ldr sp ,=0x82000000
@ mrs r0 ,cpsr
@ orr r0 ,r0,#(0x1F<<0)
@ msr cpsr ,r0
cps #0x1F
ldr sp , =0x84000000
cpsie i
bl enalbe_clock
bl init_led
bl led_on
b finished
led_on:
ldr r0,=0x0209C000
ldr r1,[r0]
bic r1,r1,#(1<<3)
str r1,[r0]
bx lr
led_off:
ldr r0,=0x0209C000
ldr r1,[r0]
orr r1,r1,#(1<<3)
str r1,[r0]
bx lr
asm_delay:
ldr r0,=0x7FFFF
loop:
sub r0,r0,#1
cmp r0,#0
bgt loop
bx lr
init_led:
ldr r0 ,=0x020E0068
mov r1,#0x05
str r1 ,[r0]
ldr r0,=0x020E02F4
ldr r1,=0x10B0
str r1,[r0]
ldr r0,=0x0209C004
mov r1,#0
orr r1,r1,#(1<<3)
str r1,[r0]
bx lr
enalbe_clock:
mov r1 ,#0xFFFFFFFF
ldr r0,=0x020c4068
str r1,[r0]
ldr r0,=0x020c406C
str r1,[r0]
ldr r0,=0x020C4070
str r1,[r0]
ldr r0,=0x020C4074
str r1,[r0]
ldr r0,=0x020C4078
str r1,[r0]
ldr r0,=0x020C407C
str r1,[r0]
ldr r0,=0x020C4080
str r1,[r0]
bx lr
finished:
bl led_on
bl asm_delay
bl led_off
bl asm_delay
b finished
交叉编译的方法还是比较复杂的如果需要的人多我后面就会出一期交叉编译器的下载安装以及使用。