IMX6ULL裸机学习(4)— 编写汇编程序点亮LED
一、编写程序
新建一个led.S
文件,然后编写如下代码。
.global _start /* .global表示_start是一个全局符号 */
_start: /* 标签_start,汇编程序的默认入口是_start */
/* 1、设置 GPIO1_IO03 复用为 GPIO1_IO03 */
LDR R0, = 0X020E0068 /* 将GPIO1_IO03复用模式寄存器的值写入R0 */
LDR R1, [R0] /* 读取该寄存器的值 */
ORR R1, R1, #0X05 /* 修改读出的值 */
STR R1, [R0] /* 写入修改后的值到该寄存器 */
/* 2、把GPIO1_IO03设置为输出引脚 */
LDR R0, = 0X0209C004
LDR R1, [R0]
ORR R1, R1, #(1<<3)
STR R1, [R0]
/* 3、设置GPIO1_IO03输出低电平 */
LDR R0, = 0X0209C000
LDR R1, [R0]
BIC R1, R1, #(1<<3)
STR R1, [R0]
/* 4、loop死循环 */
loop:
b loop
二、生成二进制文件
使用如下命令对led.S
只编译不连接,其中-c
参数表示只编译不链接,-o
参数指定生成的文件名
arm-linux-gnueabihf-gcc led.S -c -o led.o
我们可以看到得到了led.o
文件
然后使用命令对得到的led.o
文件进行链接,其中-Ttext
参数指定text段即代码段的链接地址为0X80100000
,
arm-linux-gnueabihf-ld led.o -Ttext 0X80100000 -o led.elf
可以看到得到了led.elf
文件,但是led.elf
文件也不是我们最终需要的可供imx6ull芯片可执行的文件
因此需要将 led.elf 文件转换为.bin 文件,使用到 arm-linux-gnueabihf-objcopy 工具得到,-O
参数指定以什么格式输出,后面的binary
表示以二进制格式输出,-S
表示不要复制源文件中的重定位信息和符号信息,-g
表示不复制源文件中的调试信息。
arm-linux-gnueabihf-objcopy led.elf -O binary -S -g led.bin
可以看到得到了led.bin
文件,这就是我们要得到的文件
另外我们可以使用arm-linux-gnueabihf-objdump 来将 elf 文件反汇编,-D
选项表示反汇编所有的段,
arm-linux-gnueabihf-objdump -D led.elf > led.dis
完成以后就会在当前目录下得到 led.dis
文件,
然后我们可以打开led.dis
来看一下,可以看到,在0X80100000 处就是全局标号_start
,也就是程序开始的地方,也可以代码已经链接到了以 0X80100000 为起始地址的区域。
然后我们可以通过通过编写一个makefile来完成上述的操作
led.bin:led.S
arm-linux-gnueabihf-gcc led.S -c -o led.o
arm-linux-gnueabihf-ld led.o -Ttext 0X80100000 -o led.elf
arm-linux-gnueabihf-objcopy led.elf -O binary -S -g led.bin
arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
rm -rf *.o led.bin led.elf led.dis
另外可以在编译时加上-g
选项产生调试信息
arm-linux-gnueabihf-gcc led.S -c -g -o led.o
然后我们可以看到在反汇编文件中得到多出来了调试信息
同时可以看到led.o
的大小也改变了
但是led.bin
的大小可以看到没有改变,还是64个字节
而从反汇编文件中我们就可以看到这64字节就是存放着从80100000到8010003c这64个地址的内容
我们可以通过能查看二进制文件的软件来查看一下led.bin
,可以看到和反汇编文件中的内容一样
三、生成镜像文件
虽然我们已经得到了二进制文件,但是要得到可以烧写到SD卡的镜像文件还需要添加一些头部信息,包括三部分,如下所示为一个完整的镜像文件,其中我们的led.bin
文件该存放的位置就为【User code and data】
然后我们使用mkimage工具来给bin文件添加一个头部信息。其中-T
参数表示要生成的镜像类为imximage
,然后-n
参数在帮助上是说是镜像名字,但是在imximage
镜像类型下是用来指定配置文件的,imximage.cfg.cfgtmp
配置文件有NXP官方提供,-e
参数表示入口地址,-d
参数指定制作镜像的源文件,即【User code and data】位置存放的东西。
mkimage -T imximage -n ./tools/imximage.cfg.cfgtmp -e 0x80100000 -d led.bin led.imx
这样就得到了一个led.imx
文件,但这还不是我们可以烧录到SD卡中的文件
我们还需要让led.imx
偏移1K字节,在其前面写入1K字节的空数据,首先使用命令得到1K空字节的文件。dd
命令是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。首先if=/dev/zero
表示输入文件为/dev/zero
,
/dev/zero,是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目(设备提供的要多的多)。他可以用于向设备或文件写入字符串0。
of=1k.bin
表示输出的文件为1k.bin
,bs=1024
表示同时设置读入/输出的块大小为1024个字节。 count=1
表示拷贝1个块,块大小等于bs指定的字节数1024。
dd if=/dev/zero of=1k.bin bs=1024 count=1
得到1K.bin
文件后在使用cat命令将其与led.imx
合并为led.img
文件
cat 1k.bin led.imx > led.img
可以看到,成功得到led.img
文件
四、烧录到SD卡启动
接下来我们用Win32 磁盘映像工具
来将镜像烧录到SD卡
然后我们设置开发板为从SD卡启动,并上电,可以看到,LED已经成功点亮
五、验证程序
我们修改程序,将LED引脚设置为高电平
重新编译链接,制作镜像文件加载到开发板中
可以看到,红色LED灯不再亮起了
六、使用USB烧录程序
使用100ask提供的烧写工具,下载方式
git clone https://e.coding.net/weidongshan/noos/doc_and_source_for_mcu_mpu.git
在目录【IMX6ULL\开发板配套资料\软件\烧写工具\100ask_imx6ull烧写工具v4】下找到【100ask_imx6ull_flashing_tool_v4.0.exe】文件,双击打开,然后点击【专业版】
接着将开发板启动方式设置为USB启动,上电,注意不要插SD卡,然后可以看到,提示设备已连接
1、烧写到DDR
接着我们点击【固件/裸机】按钮,选择我们生成的【led.imx】文件
然后点击【运行】,可以看到,烧写成功,开发板上的LED也成功亮起
2、烧写到EMMC
将开发板启动方式设置为USB启动,注意不要插SD卡,上电,然后我们选择设备为EMMC,然后点击【Boot/裸机】按钮,选择我们生成的【led.imx】文件,然后点击【烧写Boot/裸机】,可以看到,烧写成功
然后将设备设置为从EMMC启动,重新上电,可以看到LED亮起
3、烧写到SD卡
将开发板启动方式设置为USB启动,注意不要插SD卡,上电,上电后再插入SD卡,然后我们选择设备为SD/TF,然后点击【Boot/裸机】按钮,选择我们生成的【led.imx】文件,然后点击【烧写Boot/裸机】,可以看到,烧写成功
然后将设备设置为从SD启动,重新上电,可以看到LED亮起
七、附录
上一篇:IMX6ULL裸机学习(3)— 在Windows下搭建开发环境
下一篇:IMX6ULL裸机学习(5)— 编写C语言程序点亮LED