2021-02-17

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,以及他们最大可以支持多大的DDRFLASH

链接起始地址我们设置为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

(完)