day44-硬件学习之arm启动代码

发布于:2025-06-23 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、跳转指令实现函数调用

  • LR(链接寄存器):保留函数返回地址

1.1 bl指令

        跳转指令bl,使LR保存当前函数进入前的下一条指令的地址,使函数调用后可以返回下一条指令的地址;

1.2 bx指令

        跳到目标地址;


1.3 栈的使用方法 

函数调用前,保护现场,调用后恢复现场 :

        使用栈(先进后出的特性);


栈的使用方法:

1.3.1.空增

        保护时,SP先写,再加;

        恢复时,SP先减,再读;

1.3.2 满增 

        保护时,SP先加,再写;

        恢复时,SP先读,再减;

1.3.3 满减

        保护时,SP先减,再写;

        恢复时,SP先读,再加;

1.3.4 空减

        保护时,SP先写,再减;

        恢复时,SP先加,再读;


1.4 ARM内核使用满减栈,使用方法

1.4.1 stmfd指令

入栈保护时,使用stmfd指令;

        stmfd <c><Rn>{!}, <registers>:

        其中:

  • !是让栈指针的内容随程序发生变化
  • 命令含义是把多个寄存器保存到Rn寄存器中
  • 举例:stmfd sp!, {r0-r12, lr}

1.4.2 ldmfd指令 

出栈恢复时,使用ldmfd指令;

        如:ldmfd sp!, {r0-r12, lr}

二、汇编与C语言混合调用

注意:由主调者负责保护现场和恢复现场

2.1 汇编为主调

 步骤:

  1. 首先确保SP指针有效
  2. 对函数声明:import(导入)         export(导出)
  3. 保护现场
  4. 使用bl跳转
  5. 恢复现场

注意:

若参数4个以内,R0-R3传递参数;

若有第五个参数,只能用栈的方式来传参:

  •         stmfd sp!, {r4}
  •         ldmfd sp!, {r4}

main.c 

start.s 

2.2 c为主调

在汇编中,声明c的函数,import main

                                         export asm_add 

main.c 

start.s 

三、准备工作

3.1 切换模式

CPS命令修改CPSR寄存器的M[4:0]

        如,CPS #<mode>

        (但不支持keil) 

解决方法:

(1) msr指令:读取cpsr、spsr寄存器

mrs r0, cpsr

(2) 于r0中,设置相关数据,设为User模式(10000)

bic r0, r0, #(0x1F << 0)    //低5位清零
orr r0, r0, #0x10           //第5位置一

(3) msr指令:写入cpsr、spsr寄存器

msr cpsr_c, r0

(4)将User模式下的SP进行设置

ldr sp, =0x40001000
sub sp, sp, #1024

3.2 异常处理被占用(解决),初始化异常向量表 

3.3 产生软件中断异常

加^,表示恢复执行前cpsr寄存器的值

四、IMX6ULL入门

  • Windows编写代码
  • Ubuntu编写代码

主要部分:

  1. 搭建编程环境
  2. 汇编点灯
  3. 下载程序

4.1 引脚的功能复用

  • 说明哪些引脚归哪个外设使用
  • PAD:引脚
  • MUX:功能复用

以点亮LED为例:

        GPIO1组的3号引脚

数据寄存器        GPIO data register(GPIOx_DR) 

方向寄存器 

 


网站公告

今日签到

点亮在社区的每一天
去签到