Cortex-A7常用汇编指令

1.处理器内部数据传输指令

 

2.存储器访问指令

 

 

[]括起来指向地址的值,不括指向地址。

3.压栈和出栈指令

 

 

 

4.跳转指令

 

 

 

 

示例 I.MX6U mini开发板的GPIO时钟配置

1arm-linux-gnueabihf-gcc编译文件

新建一个名为“1_leds”的文件夹,然后在“1_leds”这个目录下新建一个名为“led.s”的汇编文件和一个名为“.vscode”的目录,

​
.global _start  /* 全局标号 */
​
/*
 * 描述:  _start函数,程序从此函数开始执行此函数完成时钟使能、
 *        GPIO初始化、最终控制GPIO输出低电平来点亮LED灯。
 */
_start:
    /* 例程代码 */
    /* 1、使能所有时钟 */
    ldr r0, =0X020C4068     /* CCGR0 */
    ldr r1, =0XFFFFFFFF  
    str r1, [r0]        
    
    ldr r0, =0X020C406C     /* CCGR1 */
    str r1, [r0]
​
    ldr r0, =0X020C4070     /* CCGR2 */
    str r1, [r0]
    
    ldr r0, =0X020C4074     /* CCGR3 */
    str r1, [r0]
    
    ldr r0, =0X020C4078     /* CCGR4 */
    str r1, [r0]
    
    ldr r0, =0X020C407C     /* CCGR5 */
    str r1, [r0]
    
    ldr r0, =0X020C4080     /* CCGR6 */
    str r1, [r0]
    
​
    /* 2、设置GPIO1_IO03复用为GPIO1_IO03 */
    ldr r0, =0X020E0068 /* 将寄存器SW_MUX_GPIO1_IO03_BASE加载到r0中 */
    ldr r1, =0X5        /* 设置寄存器SW_MUX_GPIO1_IO03_BASE的MUX_MODE为5 */
    str r1,[r0]
​
    /* 3、配置GPIO1_IO03的IO属性  
     *bit 16:0 HYS关闭
     *bit [15:14]: 00 默认下拉
     *bit [13]: 0 kepper功能
     *bit [12]: 1 pull/keeper使能
     *bit [11]: 0 关闭开路输出
     *bit [7:6]: 10 速度100Mhz
     *bit [5:3]: 110 R0/6驱动能力
     *bit [0]: 0 低转换率
     */
    ldr r0, =0X020E02F4 /*寄存器SW_PAD_GPIO1_IO03_BASE */
    ldr r1, =0X10B0
    str r1,[r0]
​
    /* 4、设置GPIO1_IO03为输出 */
    ldr r0, =0X0209C004 /*寄存器GPIO1_GDIR */
    ldr r1, =0X0000008      
    str r1,[r0]
​
    /* 5、打开LED0
     * 设置GPIO1_IO03输出低电平
     */
    ldr r0, =0X0209C000 /*寄存器GPIO1_DR */
   ldr r1, =0       
   str r1,[r0]
​
/*
 * 描述:通过 b 指令,CPU 重复不断的跳到 loop 函数执行,进入一个死循环。
 */
loop:
    b loop        

编译出在 ARM 开发板上运行的可执行文件,所以要使用我们在 4.3 小节安装的交叉编译器 arm-linux-gnueabihf-gcc 来编译。因为本试验就一个 led.s 源文件,所以编译比较简单。先将 led.s 编译为对应的.o 文件,在终端中输入如下命令:

arm-linux-gnueabihf-gcc -g -c led.s -o led.o

上述命令就是将 led.s 编译为 led.o,其中“-g”选项是产生调试信息,GDB 能够使用这些调试信息进行代码调试。“-c”选项是编译源文件,但是不链接。“-o”选项是指定编译产生的文件名字,这里我们指定 led.s 编译完成以后的文件名字为 led.o。

执行上述命令以后就会编译生成一个 led.o 文件。led.o 文件并不是我们可以下载到开发板中运行的文件,一个工程中所有的 C文件和汇编文件都会编译生成一个对应的.o 文件,我们需要将这.o 文件链接起来组合成可执行文件。

2、arm-linux-gnueabihf-ld 链接文件

确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件链接到 0X87800000 这个地址,使用如下命令:

arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf

上述命令中-Ttext 就是指定链接地址led.elf 文件也不是我们最终烧写到 SD 卡中的可执行文件,我们要烧写的.bin 文件,因此还需要将 led.elf 文件转换为.bin 文件,这里我们就需要用到 arm-linux-gnueabihf-objcopy 这个工具了

3arm-linux-gnueabihf-objcopy 格式转换

arm-linux-gnueabihf-objcopy 更像一个格式转换工具,我们需要用它将 led.elf 文件转换为led.bin 文件,命令如下:

arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin

上述命令中,“-O”选项指定以什么格式输出,后面的“binary”表示以二进制格式输出,选项“-S”表示不要复制源文件中的重定位信息和符号信息,“-g”表示不复制源文件中的调试信息。

4arm-linux-gnueabihf-objdump 反汇编

大多数情况下我们都是用 C 语言写试验例程的,有时候需要查看其汇编代码来调试代码,因此就需要进行反汇编,一般可以将 elf 文件反汇编,比如如下命令:

arm-linux-gnueabihf-objdump -D led.elf > led.dis

上述代码中的“-D”选项表示反汇编所有的段,反汇编完成以后就会在当前目录下出现一个名为 led.dis 文件.可以打开 led.dis 文件看一下,看看是不是汇编代码

 

可以看出 led.dis 里面是汇编代码,而且还可以看到内存分配情况。在0X87800000 处就是全局标号_start,也就是程序开始的地方。通过 led.dis 这个反汇编文件可以明显的看出我们的代码已经链接到了以 0X87800000 为起始地址的区域。

4、创建 Makefile 文件

用“touch”命令在工程根目录下创建一个名为“Makefile”的文件

led.bin:led.s
arm-linux-gnueabihf-gcc -g -c led.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.bin led.elf led.dis

创建好 Makefile 以后我们就只需要执行一次“make”命令即可完成编译.如果我们要清理工程的话执行“make clean”即可.

 

5代码烧写

我们学习 STM32 等其他的单片机的时候,编译完代码以后可以直接通过 MDK 或者 IAR下载到内部的 flash 中。但是 I.MX6U 虽然内部有 96K 的 ROM,但是这 96K 的 ROM 是 NXP自己用的,不向用户开放。所以相当于说 I.MX6U 是没有内部 flash 的,但是我们的代码得有地方存放啊,为此,I.MX6U 支持从外置的 NOR Flash、NAND Flash、SD/EMMC、SPI NOR Flash和 QSPI Flash 这些存储介质中启动,所以我们可以将代码烧写到这些存储介质中中。在这些存储介质中,除了 SD 卡以外,其他的一般都是焊接到了板子上的,我们没法直接烧写。但是 SD卡是活动的,是可以从板子上插拔的,我们可以将 SD 卡插到电脑上,在电脑上使用软件将.bin文件烧写到 SD 卡中,然后再插到板子上就可以了。其他的几种存储介质是我们量产的时候用到的,量产的时候代码就不可能放到 SD 卡里面了,毕竟 SD 是活动的,不牢固,而其他的都是焊接到板子上的,很牢固。因此,我们在调试裸机和 Uboot 的时候是将代码下载到 SD 中,因为方便嘛,当调试完成以后量产的时候要将裸机或者 Uboot 烧写到 SPI NOR Flash、EMMC、NAND 等这些存储介质中的。那么,如何将我们前面编译出来的 led.bin 烧写到 SD 卡中呢?肯定有人会认为直接复制led.bin 到 SD 卡中不就行了,错!编译出来的可执行文件是怎么存放到 SD 中的,存放的位置是什么?这个 NXP 是有详细规定的!我们必须按照 NXP 的规定来将代码烧写到 SD 卡中,否则代码是绝对运行不起来的。

5.1 imxdownload 拷贝到工程根目录下

我们要将 imxdownload 拷贝到工程根目录下,也就是和 led.bin 处于同一个文件夹下,要不然烧写会失败的

5.2给予 imxdownload 可执行权限

我们直接将软件 imxdownload 从 Windows 下复制到 Ubuntu 中以后,imxdownload 默认是没有可执行权限的。我们需要给予 imxdownload 可执行权限,使用命令“chmod”.

当给予 imxdownload 可执行权限以后其名字变成了绿色的,如果没有可执行权限的话其名字颜色是白色的。所以在 Ubuntu 中我们可以初步的从文件名字的颜色判断其是否具有可执行权限。

5.3确定要烧写的 SD 卡。

准备一张新的 SD(TF)卡,确保 SD 卡里面没有数据,因为我们在烧写代码的时候可能会格式化 SD 卡!!!

Ubuntu 下所有的设备文件都在目录“/dev”里面,所以插上 SD 卡以后也会出现在“/dev”里面,其中存储设备都是以“/dev/sd”开头的。我们要先看一下不插 SD 卡的时候电脑都有哪些存储设备,以及插卡后有哪些存储设备,以防插入 SD 卡以后分不清谁是谁。输入如下所示命令:

ls /dev/sd*

5.4SD 卡烧写 bin 文件

使用 imxdownload 向 SD 卡烧写 led.bin 文件,命令格式如下:

./imxdownload <file.bin> <SD Card>

其中.bin 就是要烧写的.bin 文件,SD Card 就是你要烧写的 SD 卡,比如我的电脑使用如下命令烧写 led.bin 到/dev/sdd 中,不能烧写到/dev/sda 或 sda1 设备里面!那是系统磁盘:

./imxdownload led.bin /dev/sdd 

 

烧写的最后一行会显示烧写大小、用时和速度,比如 led.bin 烧写到 SD 卡中的大小是 3.2KB,用时 0.0160821s,烧写速度是 201KB/s。注意这个烧写速度,如果这个烧写速度在几百 KB/s 以下那么就是正常烧写。如果这个烧写速度大于几十 MB/s、甚至几百 MB/s 那么肯定是烧写失败了!解决方法就是重新插拔 SD 卡,一般出现这种情况,重新插拔 SD 卡基本没啥用,只有重启Ubuntu

烧写完成以后会在当前工程目录下生成一个 load.imx 的文件

load.imx 这个文件就是软件 imxdownload 根据 NXP 官方启动方式介绍的内容,在 led.bin 文件前面添加了一些数据头以后生成的。最终烧写到 SD 卡里面的就是这个 load.imx 文件,而非led.bin。

5.5代码验证

代码已经烧写到了 SD 卡中了,接下来就是将 SD 卡插到开发板的 SD 卡槽中,然后设置拨码开关为 SD 卡启动.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值