查看底板原理图可知:
功能管脚 | 芯片引脚 |
---|---|
LED0 | GPIO3 |
使用指令集:ARMv7-A 汇编指令集,32位,load/store架构。
大多数ARM处理器支持超过一种指令集:
> ARM —— 一种32位指令集
> Thumb —— 一种16位指令集,具有更好的代码密度(但是相比ARM代码,性能有所降低)
在程序的控制之下,处理器可以在这两种指令集之间来回切换。
所有的 Cortex-A 系列处理器实现了 Thumb-2 技术,它扩展了Thumb指令集。混合使用32位和16位指令,以Thumb指令集的代码密度和接近ARM指令集的性能。自从所有的Cortex-A系列处理器支持这一扩展,针对它们的软件常被编译成Thumb指令集。
label: instruction @ comment
域 | 说明 | 备注 |
---|---|---|
label | 标号 | 可不写 |
instruction | 指令 | 必须写 |
@ comment | 注释 | 可不写 |
GNU汇编语言,函数定义
函数名:
函数体
返回语句
预定义段名 | 含义 |
---|---|
.text | 代码段 |
.data | 初始化的数据段 |
.bss | 未初始化的数据段 |
.rodata | 只读数据段 |
.global _start
_start:
ldr r0, =0x12 @ r0=0x12
操作数是立即数,以“#”为前缀,表示 16 进制数值时以“0x”表示。
例:
MOV R0, #0xFF00 @ 0xFF00 -> R0
SUBS R0, R0, #1 @ R0 – 1 -> R0
操作数的值在寄存器中,指令执行时直接取出寄存器值操作。
例:
MOV R1, R2 @ R2 -> R1
SUB R0, R1, R2 @ R1 - R2 -> R0
当第二操作数是寄存器偏移方式时,第二个寄存器操作数在与第一个操作数结合之前,选择进行移位操作。
例:
MOV R0, R2, LSL #3 @ R2 的值左移 3 位,结果放入 R0,即 R0 = R2 * 8
ANDS R1, R1, R2, LSL #3 @ R2 的值左移 3 位,然后和 R1 相与操作,结果放入 R1
可采用的移位操作:
指令 | 解释 | 补充说明 |
---|---|---|
LSL | 逻辑左移(Logical Shift Left) | 低端空出位补 0 |
LSR | 逻辑右移(Logical Shift Right) | 高端空出位补 0 |
ASR | 算术右移(Arithmetic Shift Right) | 移位过程中符号位不变,即源操作数为正数,则高端空出位补 0,否则补 1 |
ROR | 循环右移(Rotate Right) | 由低端移出位填入高端空出位 |
RRX | 带扩展的循环右移(Rotate Right eXtended by 1 place) | 操作数右移一位,高端空出位用原 C 标志值填充。 |
操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。
例:
LDR R1, [R2] @ 将 R2 中的数值作为地址,取出此地址中的数据保存在 R1 中
SWP R1, R1, [R2] @ 将R2中的数值作为地址,取出此地址中的数值与 R1 中的值**
将基址寄存器的值与偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能寄存器访问等。
例:
LDR R2, [R3,#0x0F] @ 将R3中的数值加 0x0F 作为地址,取此地址的值保存在 R2 中
STR R1, [R0,#-2] @ 将R0中的数值减 2 作为地址,把 R1的值保存到此地址中
一次传送多个寄存器值,允许一条指令传送 16 个寄存器的任何子集或所有寄存器。多寄存器寻址时,寄存器子集按由小到大的顺序排列,连续的寄存器可用“-”连接,否则,用“,”分隔书写。
例:
LDMIA R1!, {R2-R7,R12} @ 将 R1的值读出到 R2-R7,R12,过程中R1 自动加 1
STMIA R0!, {R3-R6,R10} @ 将 R3-R6,R10的值保存到 R0 指向的地址,过程中R0 自动加 1
堆栈寻址使用堆栈指针SP,即R13,指向堆栈的栈顶。堆栈可分为两种:
向上生长:向高地址方向生长,称为递增堆栈,
向下生长:向低地址方向生长,称为递减堆栈,
堆栈指针指向最后压入的有效数据项,称为满堆栈,
堆栈指针指向下一个要放入的空位置,称为空堆栈,这样就有 4 种类型的堆栈。
A) 满递增:堆栈地址向上增长,堆栈指针指向有效数据的最高地址。如 LDMFA,STMFA。
B) 空递增:堆栈地址向上增长,堆栈指针指向堆栈上的第一个空位置。如 LDMEA,STMEA 。
C) 满递减:堆栈地址向下增长,堆栈指针指向有效数据项的最低地址。如 LDMFD,STMFD。
D) 空递减:堆栈地址向下增长,堆栈指针指向堆栈下的第一个空位置。如 LDMED,STMED 。
例:
STMFD SP!, {R1-R7,LR} @ 将 R1~R7,LR 入栈。满递减堆栈。
LDMFD SP!, {R1-R7,LR} @ 数据出栈,放入 R1~R7,LR 寄存器。满递减堆栈。
用于将一块数据从存储器的某一位置拷贝到另一位置。
例:
STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向上增长。
STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向上增长。
STMDA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之后增加,增长方向为向下增长。
STMDB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中,存储器指针在保存第一个值之前增加,增长方向为向下增长。
相对寻址是基址寻址的一种变通,由程序计数器 PC 提供基准地址,指令中的地址
码字段作为偏移量,两者相加后得到有效地址。
例:
BL ROUTE1 @ 调用ROUTE1 子程序
BEQ LOOP @ 条件跳转到 LOOP 标号处
…
LOOP MOV R2,#2
…
ROUTE1
…
0x8000_0000 提供2G空间,用于16位 DDR内存。
MMDC——multiple model DDR controller,多模式DDR控制器。
0x0200_0000, AIPS-1, ARM IP Bus,
/**
@brief 实现点亮led功能,led——GPIO1_IO03
@note 要学习的寄存器: CCM_CCGR0 ~ CCM_CCGR6
*/
.global _start
_start:
/**
开启时钟:CCM_CCGR0
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4068
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR0
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4068
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR1
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C406C
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR2
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4070
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR3
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4074
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR4
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4078
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR5
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C407C
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR6
i.MX6ULL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4080
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
配置复用寄存器:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
低四位:MUX_MODE[3:0] = ALT5(0101) —— GPIO1_IO03
*/
ldr r0, =0x020E0068
ldr r1, =0x5
str r1, [r0]
/**
配置电气属性寄存器:IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
SRE[0] 压摆率,0 —— 低压摆率
Reserved[2:1]
DSE[5:3] 驱动能力,110 —— R0/6
SPEED[7:6] 速度,10 —— 100MHz
Reserved[10:8]
ODE[11] 开漏输出,0 —— 关闭开漏输出
PKE[12] 上拉/保持使能位,1 —— 使能上拉/保持控制
PUE[13] 上拉/保持选择,0 —— 保持
PUS[15:14] 上拉/下拉电阻, 00 —— 100K欧姆下拉;10 —— 100K欧姆上拉
HYS[16] 施密特触发器使能位,0 —— 不使能
Reserved[31:17]
*/
ldr r0, =0x020E02F4
ldr r1, =0x10B0
str r1, [r0]
/**
配置GPIO方向:GPIO1_GDIR
0 —— 输入 1 —— 输出
*/
ldr r0, =0x0209C004
ldr r1, =1<<3
str r1, [r0]
/**
配置GPIO数据:GPIO1_DR
0 —— 低电平 1 —— 高电平
*/
ldr r0, =0x0209C000
ldr r1, =0<<3
str r1, [r0]
loop:
b loop
led.bin : leds.s
arm-linux-gnueabihf-gcc -g -c leds.S -o led.o
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean :
rm -rf *.o led.elf led.bin led.dis
/**
@brief 实现点亮led功能,led——GPIO1_IO09
@note 要学习的寄存器: CCM_CCGR0 ~ CCM_CCGR6
*/
.global _start
_start:
/**
开启时钟:CCM_CCGR0
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4068
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR1
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C406C
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR2
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4070
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR3
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4074
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR4
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4078
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR5
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C407C
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
开启时钟:CCM_CCGR6
i.MX6UL参考手册:第18章(CCM)
*/
ldr r0, =0x020C4080
ldr r1, =0xFFFFFFFF
str r1, [r0]
/**
配置复用寄存器:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09
低四位:MUX_MODE[3:0] = ALT5(0101) —— GPIO1_IO09
*/
ldr r0, =0x020E0080
ldr r1, =0x5
str r1, [r0]
/**
配置电气属性寄存器:IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO09
SRE[0] 压摆率,0 —— 低压摆率
Reserved[2:1]
DSE[5:3] 驱动能力,110 —— R0/6
SPEED[7:6] 速度,10 —— 100MHz
Reserved[10:8]
ODE[11] 开漏输出,0 —— 关闭开漏输出
PKE[12] 上拉/保持使能位,1 —— 使能上拉/保持控制
PUE[13] 上拉/保持选择,0 —— 保持
PUS[15:14] 上拉/下拉电阻, 00 —— 100K欧姆下拉;10 —— 100K欧姆上拉
HYS[16] 施密特触发器使能位,0 —— 不使能
Reserved[31:17]
*/
ldr r0, =0x020E030C
ldr r1, =0x10B0
str r1, [r0]
/**
配置GPIO方向:GPIO1_GDIR
0 —— 输入 1 —— 输出
*/
ldr r0, =0x0209C004
ldr r1, =1<<9
str r1, [r0]
/**
配置GPIO数据:GPIO1_DR
0 —— 低电平 1 —— 高电平
*/
ldr r0, =0x0209C000
ldr r1, =0<<9
str r1, [r0]
/**
配置复用寄存器:IOMUXC_SW_MUX_CTL_PAD_SNVS_TAMPER9
低四位:MUX_MODE[3:0] = ALT5(0101) —— GPIO1_IO09
*/
ldr r0, =0x020E0080
ldr r1, =0x5
str r1, [r0]
/**
配置电气属性寄存器:IOMUXC_SW_PAD_CTL_PAD_SNVS_TAMPER9
SRE[0] 压摆率,0 —— 低压摆率
Reserved[2:1]
DSE[5:3] 驱动能力,110 —— R0/6
SPEED[7:6] 速度,10 —— 100MHz
Reserved[10:8]
ODE[11] 开漏输出,0 —— 关闭开漏输出
PKE[12] 上拉/保持使能位,1 —— 使能上拉/保持控制
PUE[13] 上拉/保持选择,0 —— 保持
PUS[15:14] 上拉/下拉电阻, 00 —— 100K欧姆下拉;10 —— 100K欧姆上拉
HYS[16] 施密特触发器使能位,0 —— 不使能
Reserved[31:17]
*/
ldr r0, =0x020E02CC
ldr r1, =0x10B0
str r1, [r0]
/**
配置GPIO方向:GPIO5_GDIR
0 —— 输入 1 —— 输出
*/
ldr r0, =0x020AC004
ldr r1, =1<<9
str r1, [r0]
/**
配置GPIO数据:GPIO5_DR
0 —— 低电平 1 —— 高电平
*/
ldr r0, =0x020AC000
ldr r1, =0<<9
str r1, [r0]
loop:
b loop
leds.bin : leds.S
arm-linux-gnueabihf-gcc -g -c $< -o leds.o
arm-linux-gnueabihf-ld -Ttext 0x87800000 leds.o -o leds.elf
arm-linux-gnueabihf-objcopy -O binary -S -g leds.elf $@
arm-linux-gnueabihf-objdump -D leds.elf > leds.dis
clean :
rm -rf *.o leds.elf leds.bin leds.dis