目录
[3.1 开启时钟](#3.1 开启时钟)
[3.2 配置IO复用功能与电器属性](#3.2 配置IO复用功能与电器属性)
[3.5 Makefile](#3.5 Makefile)
[4.2 文件发送虚拟机------使用FTP传输协议](#4.2 文件发送虚拟机——使用FTP传输协议)
[4.3 编译下载](#4.3 编译下载)
一、汇编启动代码
完善的汇编启动代码如下:
-
keil版:
;汇编启动代码_keil
;"方言版"汇编启动代码area reset ,readonly,code preserve8 code32 entry ;中断向量表的这个顺序不能变 ldr pc,=_reset_handler ldr pc,=_undefine_handler ldr pc,=_svc_handler ldr pc,=_prefetch_abort_handler ldr pc,=_data_abort_handler ldr pc,=_reserved_handler ldr pc,=_irq_handler ldr pc,=_fiq_handler_fiq_handler
ldr pc, =_fiq_handler_irq_handler
ldr pc, =_irq_handler_reserved_handler
ldr pc, =_reserved_handler_data_abort_handler
ldr pc, =_data_abort_handler_prefetch_abort_handler
ldr pc, =_prefetch_abort_handler_svc_handler
import c_svc_handler
stmfd sp!,{r0-r12,lr}
bl c_svc_handler
ldmfd sp!,{r0-r12,pc}^ ;^代表恢复时 恢复工作模式_undefine_handler
ldr pc, =_undefine_handler_reset_handler
;设置SVC模式下的栈
ldr sp,=0x40001000;切换到USR模式 mrs r0,cpsr bic r0,r0,#0x1F orr r0,r0,#0x10 msr cpsr_c,r0 ;设置USR模式下的栈 ldr sp,=0x40001000 sub sp,sp,#1024 import main b main ;跳过去就不回来了finished
b finished ;防止程序跑飞end -
vscode版本
;汇编启动代码_vs code
;以后用这个,这是符合GNU标准的.global _start //全局变量_start: //加冒号代表函数
ldr pc, =_reset_handler
ldr pc, =_undefine_handler
ldr pc, =_svc_handler
ldr pc, =_prefetch_abort_handler
ldr pc, =_data_abort_handler
ldr pc, =_reserved_handler
ldr pc, =_irq_handler
ldr pc, =_fiq_handler_fiq_handler:
ldr pc, =_fiq_handler_irq_handler:
ldr pc, =_irq_handler_reserved_handler:
ldr pc, =_reserved_handler_data_abort_handler:
ldr pc, =_data_abort_handler_prefetch_abort_handler:
ldr pc, =_prefetch_abort_handler_svc_handler:
ldr pc, =_svc_handler_undefine_handler:
ldr pc, =_undefine_handler_reset_handler:
// irq mode
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x12
msr cpsr, r0
// irq stack
ldr sp, =0x86000000// system mode mrs r0, cpsr bic r0, r0, #0x1F orr r0, r0, #0x1F msr cpsr, r0 // system stack ldr sp, =0x84000000 //bss清零 bl _bss_clear //go main //GNU组织下,不用导入函数 b main_bss_clear:
ldr r0, =_bss_start
ldr r1, =_bss_end
loop:
mov r2, #0
str r2, [r0]
add r0, r0, #4
cmp r0, r1
blt loopb mainfinished:
b finished
二、开发板介绍
正点原子:mini版、阿尔法版
本次课程实验使用的开发板是由正点原子提供的IMX6ULL-Mini。大多数情况下,一个嵌入式系统硬件部分包括核心板和底板两个部分。核心板 主要是将Soc所需的必要器件如RAM,NAND(eMMC)等器件组织在一起,这部分电路设计难度相对较大。底板部分通常是由集成商设计。二者通过接插件连接起来。这样的设计大大降低了开发难度,节约了开发时间。

核心板资源:

启动方式设置:
LED:
蓝色的LED1:器件丝印
红色LED0:网络标号
**GPIO:**有五组(GPIO1-GPIO5)
三、代码编写
- 配置寄存器(根据参考手册)
- IOMUXC:引脚复用功能寄存器
IOMUXC_SW_MUX _CTL_PAD_GPIO1 IO03:配置为GPIO功能 0x05
- IOMUXC_SW_PAD _CTL_PAD_GPIO1 I003 配置电器属性寄存器:如上拉电阻下拉电阻(减轻硬件工程师工作量)0x10B
- GPIO_DR:写0或写1控制led状态0x0209C000
- GPIO_GDIR:配置为输出模式0209C004
3.1 开启时钟
为后续编程方便,这里编写时钟开启函数,打开所有时钟,后续可直接调用此函数
cpp
_enable_clocks:
// CCGR0 clock
ldr r0, =0x020C4068
ldr r1, =0xFFFFFFFF
str r1, [r0]
// CCGR1 clock
ldr r0, =0x020C406C
str r1, [r0]
// CCGR2 clock
ldr r0, =0x020C4070
str r1, [r0]
// CCGR3 clock
ldr r0, =0x020C4074
str r1, [r0]
// CCGR4 clock
ldr r0, =0x020C4078
str r1, [r0]
// CCGR5 clock
ldr r0, =0x020C407C
str r1, [r0]
// CCGR6 clock
ldr r0, = 0x020C4080
str r1, [r0]
bx lr
3.2 配置IO复用功能与电器属性
cpp
_init_led:
// gpio1_io03 iomuxmode
ldr r0, =0x020E0068
mov r1, #0x05
str r1, [r0]
// gpio1_io03 pad
ldr r0, =0x020E02F4
ldr r1, =0x10B0
str r1, [r0]
// gpio1_io03 output
ldr r0, =0x0209C004
ldr r1, [r0]
orr r1, r1, #(1 << 3)
str r1, [r0]
bx lr
3.3GPIO配置
cpp
_led_on:
// led on
ldr r0, =0x0209C000
ldr r1, [r0]
bic r1, r1, #(1 << 3)
str r1, [r0]
bx lr
3.4复位异常函数
cpp
_reset_handler:
// irq mode
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x12
msr cpsr, r0
// irq stack
ldr sp, =0x86000000
// system mode
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x1F
msr cpsr, r0
// system stack
ldr sp, =0x84000000
// enable clock
bl _enable_clocks
// led init
bl _init_led
// led on
bl _led_on
b finished
finished:
b finished
3.5 Makefile
cppled.bin : led.S #使用arm-linux-gnueabihf-gcc编译文件 arm-linux-gnueabihf-gcc -g -c led.S -o led_.o #使用arm-linux-gnueabihf-ld 链接文件 arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf #用arm-linux-gnueabihf-objcopy 格式转换 arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin #使用arm-linux-gnueabihf-objdump 反汇编 arm-linux-gnueabihf-objdump -D led.elf > led.dis clear: rm -rf*.o led.bin led.elf led.dis
四、代码的编译
4.1环境配置
- 虚拟机配置:

- 乌班图环境配置
- 下载vsftpd
重启FTP服务
- 配置:
- 安装编译器
装编译器
修改编译器路径
重启虚拟机
- Windows系统环境配置
下载软件
4.2 文件发送虚拟机------使用FTP传输协议
讲Windows下编辑好的程序传输的虚拟机
4.3 编译下载
- 使用make将汇编程序编译为led.bin
- 使用imxdownload将led.bin下载到SD卡
五、实验现象
代码烧写到SD卡后,一上电板载led就亮起了

六、重要概念
- 什么是编译器、连接器、格式转换器和反汇编器?
编译器(gcc):将汇编源文件(.S)转为目标文件(.o),进行语法检查和指令翻译;
链接器(ld):将目标文件链接到指定内存地址,解决符号引用(如程序入口 _start);
格式转换器(objcopy):将 ELF 文件(包含调试 / 符号信息)转为开发板可直接执行的二进制文件(.bin);
反汇编器(objdump):将 ELF 文件转回汇编代码,用于调试(验证指令是否正确翻译)。



















