ARM启动代码以及点灯(i.mx6ull)

今天做的是个简单的启动代码以及电灯,我们这里用的硬件平台是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




交叉编译的方法还是比较复杂的如果需要的人多我后面就会出一期交叉编译器的下载安装以及使用。

### STM32 启动文件解释与使用 #### 文件概述 启动文件对于任何基于ARM Cortex-M系列微控制器的应用程序都是至关重要的组成部分。这些文件通常由芯片制造商提供,用于初始化硬件并设置堆栈指针和向量表地址等重要参数[^1]。 #### 结构解析 典型的STM32启动文件包含了多个部分: - **中断向量表**:位于文件顶部,定义了异常处理函数的位置以及外部设备触发的IRQ(Interrupt Request)响应位置。 - **Reset_Handler() 函数**:这是系统复位后的入口点,在这里会执行一些基本配置操作,比如设定SP寄存器指向初始栈顶地址,并跳转到主应用程序代码处继续运行。 - **其他弱声明的服务例程**:如NMI、HardFault等默认实现;如果开发者希望自定义特定行为,则可以在应用层重写它们。 ```c void Reset_Handler(void); __attribute__((weak)) void NMI_Handler (void) { while(1); } __attribute__((weak)) void HardFault_Handler(void) { while(1); } // ... 更多类似的弱链接函数... ``` #### 修改指南 当需要调整启动过程中的某些特性时,可以考虑如下几个方面: - 改变堆栈大小或位置; - 添加新的外设驱动支持; - 调整全局数据段(.data/.bss)加载方式以适应特殊需求场景。 需要注意的是,修改前应充分理解当前使用的工具链版本及其编译选项对最终二进制映像的影响。 #### 实际案例分析 针对不同型号的MCU可能有不同的优化策略。例如,在涉及低功耗设计的情况下,可以通过适当配置WFE等待事件机制来降低能耗而不影响对外部快速信号变化的捕捉能力[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值