imx6ull的学习过程(2)-- 用汇编点亮LED灯
1.汇编语法简介(这部分可以先不看,用到再查)
我们要编写的是 ARM汇编,编译使用的 GCC 交叉编译器,所以我们的汇编代码要符合 GNU 语法。
基本格式如下:
label: instruction @ comment
标号:指令 @ 注释
任何以“:”结尾的标识符都会被识别为一个标号。
实例:
add: MOVS R0, #0X12 @设置 R0=0X12
一般的,汇编代码若大写就要全部大写,小写就全部小写,不能大小写混合
用户可以使用 .section 伪操作来定义一个段,汇编系统预定义了一些段名:
.text 表示代码段。
.data 初始化的数据段。
.bss 未初始化的数据段。
.rodata 只读数据段。
我们当然可以自己使用 .section 来定义一个段,每个段以段名开始,以下一段名或者文件结
尾结束,比如:
.section .testsection @定义一个 testsetcion 段
- 1
汇编程序的默认入口标号是 _start
,不过我们也可以在链接脚本中使用 ENTRY
来指明其它
的入口点,下面的代码就是使用_start
作为入口标号:
.global _start
_start:
ldr r0, =0x12 @r0=0x12
- 1
- 2
- 3
上面代码中.global
是伪操作,表示_start
是一个全局标号,类似 C 语言里面的全局变量一
样,常见的伪操作有:
.byte 定义单字节数据,比如.byte 0x12。
.short 定义双字节数据,比如.short 0x1234。
.long 定义一个 4 字节数据,比如.long 0x12345678。
.equ 赋值语句,格式为: .equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。
.align 数据字节对齐,比如: .align 4 表示 4 字节对齐。
.end 表示源文件结束。
.global 定义一个全局符号,格式为: .global symbol,比如: .global _start。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
GNU 汇编同样也支持函数,函数格式如下:
函数名:
函数体
返回语句
- 1
- 2
- 3
具体实例如下:
/* SVC 中断 */
SVC_Handler:
ldr r0, =SVC_Handler
bx r0
- 1
- 2
- 3
- 4
2.汇编代码编写
简单介绍完汇编,开始写汇编代码
1.处理器内部数据传输指令
数据传输常用的指令有三个: `MOV、 MRS 和 MSR`
- 1
2.存储器访问指令
ARM 不能直接访问存储器,比如 RAM 中的数据, I.MX6UL 中的寄存器就是 RAM 类型
的,我们用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器,就是访问内存RAM中的数据
存储器访问指令有 `LDR STR`
- 1
简单介绍这些后贴出led
具体代码:
3.编译与下载程序
1.编译程序
1.使用arm-linux-gnueabihf-gcc
将汇编文件编译成.o文件
2.将所有的.o
文件链接成.elf
格式的文件
3.将elf
文件转成bin
文件
4.将elf
文件转成反汇编文件
注:
本文的链接
链接就是讲所有的.o文件链接在一起,并连接的指定的地方,链接的起始地址就是代码运行的起始地址,对于IMX6ULL来说,应该指向RAM(内部RAM和内部RAM 都可以),内部RAM的地址范围0x900000-0x91FFFF,外部ddr的地址范围是0x80000000-0x9FFFFFFF(512M)
或者0x80000000-0x8FFFFFFF(256M)
为什么会有地址呢,这个地址其实是物理地址,由厂商和架构上共同决定的,厂商决定了哪里改接入FLASH
,哪里该接入DDR
,以及他们最大可以支持多大的DDR
和FLASH
链接起始地址我们设置为
0x8780 0000
编译为.o文件
arm-linux-gnueabihf-gcc led.s -o led.o
- 1
生成elf文件
arm-linux-gnueabihf-ld -Ttext 0x87800000 led.o -o led.elf
- 1
转换成.bin文件,-O binary
是指定输出bin
文件
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
- 1
反汇编,反汇编是将.elf
文件转换成dis文件,-D
是反汇编所有的段
arm-linux-gnueabihf-objdump -D led.elf > led.dis
- 1
编译的部分也可以写成Makefile文件,那样更方便
不知道为什么图片上会显示网址,哎。。。。。。。。
编译的部分已经介绍完了,下面就要烧写进入SD
卡,然后运行程序
2.烧写bin文件进入SD卡
一般情况下,比如stm32
将代码烧写进入内部flash
中,但是我们知道IMX6ULL是没有内部FLASH
的,所以我们先将代码烧录进sd
卡中
烧写是将bin文件加一个头部 然后烧写进入SD卡,烧写工具使用imxdownload
imxdownload led.bin /dev/sdb
- 1
烧写工具是正点原子的,要注意的是:显示的烧写速度应该是几十到几百k 若显示几十M 就证明烧写失败,需要重启linux虚拟机
文章来源: blog.csdn.net,作者:迷途小唐同学,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_41940487/article/details/113832433