LV04-02-GPIO-03-裸机程序烧写
本文主要烧写裸机程序的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
Windows版本 | windows11 |
Ubuntu版本 | Ubuntu16.04的64位版本 |
VMware® Workstation 16 Pro | 16.2.3 build-19376536 |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) |
Linux开发板 | 正点原子 i.MX6ULL Linux 阿尔法开发板 |
uboot | NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03) |
linux内核 | linux-4.15(NXP官方提供) |
Win32DiskImager | Win32DiskImager v1.0 |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.nxp.com.cn/ | NXP官方网站 | |
https://www.nxpic.org.cn/ | NXP 官方社区 | |
https://u-boot.readthedocs.io/en/latest/ | u-boot官网 | |
https://www.kernel.org/ | linux内核官网 |
点击查看相关文件下载
分类 | 网址 | 说明 |
NXP | https://github.com/nxp-imx | NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库 |
https://elixir.bootlin.com/linux/latest/source | 在线阅读linux kernel源码 | |
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga | NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga | |
I.MX6ULL | i.MX 6ULL Applications Processors for Industrial Products | I.MX6ULL 芯片手册(datasheet,可以在线查看) |
i.MX 6ULL Applications ProcessorReference Manual | I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网) |
一、概述
我们之前学习STM32的时候知道编译完代码以后可以直接通过 MDK 或者 IAR下载到内部的 flash 中,也就是内部的ROM。I.MX6ULL有内部ROM嘛?我们翻开芯片手册看一眼:i.MX 6ULL Applications Processors for Consumer Products (nxp.com.cn)
我们看到内部有96KB的ROM和128KB的RAM,但是 I.MX6U 虽然内部有 96K 的 ROM,但是这 96K 的 ROM 是 NXP 自己用的,不向用户开放。所以相当于说 I.MX6ULL 是没有内部 flash 的,但是我们的代码得有地方存放啊,为此, I.MX6ULL 支持从外置的 NOR Flash、 NAND Flash、 SD/EMMC、 SPI NOR Flash和 QSPI Flash 这些存储介质中启动,所以我们可以将代码烧写到这些存储介质中。
在这些存储介质中,除了 SD 卡以外,其他的一般都是焊接到了板子上的,我们没法直接烧写。但是 SD卡是活动的,是可以从板子上插拔的,我们可以将 SD 卡插到电脑上,在电脑上使用软件将 .bin 文件烧写到 SD 卡中,然后再插到板子上就可以了。其他的几种存储介质是我们量产的时候用到的,量产的时候代码就不可能放到 SD 卡里面了,毕竟 SD 是活动的,不牢固,而其他的都是焊接到板子上的,很牢固。
因此,我们在调试裸机和 Uboot 的时候是将代码下载到 SD 中,因为方便嘛,当调试完成以后量产的时候要将裸机或者 u-boot 烧写到 SPI NOR Flash、 EMMC、 NAND 等这些存储介质中的。那么,如何将我们前面编译出来的 led.bin 烧写到 SD 卡中呢?
编译出来的可执行文件是怎么存放到 SD 中的,存放的位置是什么?这个 NXP 是有详细规定的!我们必须按照 NXP 的规定来将代码烧写到 SD 卡中,否则代码是绝对运行不起来的。《i.MX 6ULL Applications Processor Reference Manual》的第 8 章“Chapter 8 System Boot”就是专门讲解 I.MX6U 启动的,在前边我们已经学习过了。
接下来就来学习一下裸机程序烧写。
二、imxdownload工具
我们先来学习一下正点原子提供的这个imxdownload工具。
1. 工具源码
正点原子有提供源码的,路径在《阿尔法Linux开发板(A盘)-基础资料/05、开发工具/02、Ubuntu下裸机烧写软件》:
1.1 imxdownload.c
点击查看 imxdownload.c 源码
1 |
|
1.2 imxdownload.h
这个文件里边的就是DCD信息,不同的芯片可能都是不一样的,需要注意。这个DCD信息我们其实可以去uboot源码中找,这后面学习另一个工具的时候会学习。
点击查看 imxdownload.h 文件
1 |
|
2. 编译工具
上边只是源码,我们想要使用的话,还需要进行编译,我们由于是在ubuntu中使用此工具,所以直接在ubuntu中使用gcc编译即可。
1 | gcc imxdownload.c -o imxdownload -Wall |
然后我们就会得到一个 imxdownload 可执行文件,我们运行这个文件就可以将相应的uboot烧写到sd卡中。我们也可以写一个makefile文件来编译:
1 | TARGET := imxdownload |
3. 使用方式
我们之前已经生成好了led.bin文件,然后就是在ubuntu下降此文件烧写到sd卡中。我们可以执行以下命令查看一下SD卡在ubuntu中的节点:
1 | sudo fdisk -l |
然后可以看到自己的SD卡的节点:
或者直接用这个命令看:
1 | ls /dev/sd* |
注意使用的是这个/dev/sdc节点,sdc1是SD卡的1分区,不要用这个。然后我们可以执行以下命令完成烧写:
1 | ./imxdownload <.bin file> <SD Card> |
在这里的话就是:
1 | ../../tool/imxdownload/imxdownload led.bin /dev/sdc |
烧写的过程中可能会让输入密码,输入 ubuntu 密码即可完成烧写,烧写过程如下:
烧写的最后一行会显示烧写大小、用时和速度,比如 led.bin 烧写到 SD 卡中的大小是 3.2KB,用时 0.15951s,烧写速度是 20.3 KB/s。注意这个烧写速度,如果这个烧写速度在几百 KB/s 以下那么就是正常烧写。如果这个烧写速度大于几十 MB/s、甚至几百 MB/s 那么肯定是烧写失败了! 这个时候我们会发现目录中多了一个imx文件:
其实前面学习启动方式的时候学习过,imx文件会比bin文件多一些IVT等数据,我们可以看一下:
我们看一下开头就会发现链接地址:
解决方法就是重新插拔 SD 卡,一般出现这种情况,重新插拔 SD 卡基本没啥用,只有重启 ubuntu,至于原因嘛,不详。
三、mkimage工具
1. uboot生成的imx文件
我们知道,生成了bin文件后,还需要将这个bin文件变为.imx文件,上边我们知道imxdownload这个工具可以直接将bin文件生成imx文件,然后烧写到sd卡中去,那不使用这个工具呢?其实也是有办法的。办法需要从u-boot中找,后边学习u-boot就会知道,编译u-boot的话,会生成bin文件,也会生成imx文件。我这里编译的是这个Release rel_imx_4.19.35_1.1.0: MLK-22866 imx8: Remove the optee shared memory from DDR banks · nxp-imx/uboot-imx (github.com),编译完毕后如下图:
会发现上面会生成imx文件。这个文件我们就可以用于烧写到SD卡中。
2. DCD数据去哪里找?
前边学习映像文件的时候,有提到过这个DCD数据。那么这个DCD数据去哪找?我们去找一下怎么生成的imx文件:
这个文件要编译完才有,先不管这个文件怎么来的以及原理,这里只看这个命令:
1 | cmd_u-boot-dtb.imx := ./tools/mkimage -n u-boot-dtb.cfgout -T imximage -e 0x87800000 -d u-boot-dtb.bin u-boot-dtb.imx >u-boot-dtb.imx.log |
大概分析一些可以知道是用了这个u-boot-dtb.cfgout,我们打开看一眼:
其实这个文件就来源于imximage.cfg文件。这个文件在哪? i.mx6ull的imximage.cfg 文件位于u-boot 源码的 board/freescale/mx6ullevk/ 目录下:
这个imximage.cfg文件中就是厂家提供的DCD数据啦。会发现上面的u-boot-dtb.cfgout会比imximage.cfg多一些东西,但是这个DATA的行都是一样的:
2. mkimage
这个工具的是u-boot编译完成后,会在tools目录下生成的,它的源码及可执行文件如下:
这个工具与具体的开发板无关,是u-boot的工具,所以这里可以直接拿来用。该工具的使用命令如下:
1 | ./mkimage -n ./imximage.cfg -T imximage -e <链接地址> -d <.bin文件> <.imx文件> |
【注意】这里的链接地址要与生成bin文件的时候使用的链接地址一样。
3. 生成.imx文件
我们拷贝上边的 imximage 工具和 board/freescale/mx6ullevk/imximage.cfg 文件到我们的下载工具目录下:
1 | cp ~/7Linux/imx6ull-uboot/tools/mkimage* tool/mkimage/ |
拷贝完后tool/mkimage/目录如下所示:
我们现在用u-boot中的工具imximage 试一下生成一个imx文件,命令格式是这样的:
1 | ./mkimage -n ./imximage.cfg -T imximage -e 0X87800000 -d led.bin led.imx |
按照我的目录结构,在这里应该是:
1 | ../../tool/mkimage/mkimage -n ../../tool/mkimage/imximage.cfg -T imximage -e 0X87800000 -d led.bin led.imx |
额,然后就直接报错了:
怀疑是文件不对?其实刚才已经多拷贝了一个文件u-boot-dtb.cfgout,这个是编译uboot的时候,调用mkimage工具生成的imx文件的时候用的,里面会多一些东西,可能就是这些多的东西的原因,那我们呢直接用这个文件试一下:
1 | ../../tool/mkimage/mkimage -n ../../tool/mkimage/u-boot-dtb.cfgout -T imximage -e 0X87800000 -d led.bin led.imx |
然后就可以了:
其实数据还是那些,不过还有一些带#号的行出现,没有深究,就直接用就是了。
4. 对比区别
我们通过两种途径生成了imx文件,它们的IVT和DCD一样吗?我们用对比工具对比一下看看:
发现还是有一些不一样,可能是因为我用的新的uboot的原因吧,之前用的Release rel_imx_4.1.15_2.1.0_ga: MLK-14707 fsl_esdhc: Fix eMMC 1.8v setting issue · nxp-imx/uboot-imx (github.com)这个版本,最后用这个工具生成的和正点原子的工具生成的是一样的:
不过问题不大,可以直接烧写一下看 看能不能跑就知道了。烧写后会发现其实是一样的。
那有啥区别?区别就在于,正点原子提供给我们的imxdownload软件把链接地址写死为0x87800000,这意味着什么?这就意味着我们在后面编写链接脚本的时候只能用这个地址作为链接地址,我们的程序都将从这个地址开始存放,想修改怎么办?抱歉,没办法,除非修改imxdownload的源码,但是mkimage这个软件不一样,是在使用软件的时候指定了链接地址,这样我们就可以自定义啦。所以推荐还是用这个软件比较好。
5. 烧写到SD卡
上面我们只是生成了imx文件,这里我们还要烧写到SD卡中,我们可以使用以下命令烧写:
1 | sudo dd if=led.imx of=/dev/sdc bs=1k seek=1 conv=fsync |
注意一定要加sudo,否则会提示权限不够。为什么要留1KB?前面学习映像文件的时候其实了解过了,从SD卡启动的时候,内部的boot ROM代码会从1KB的位置开始读,好像是因为我们常用的SD卡一个扇区的大小是512字节。前面两个扇区是不可以写入用户数据的,一般存的是SD卡相关的信息。而且imx6ull数据手册也写到SD/EMMC启动是从地址偏移0x400字节的地方开始,所以这里不能直接覆盖。
我们会看到如下提示信息:
这样就烧写完毕了。
6. 编译mkimage
我们这里是有源码的,我们自己编译一下呢?Makefile如下:
1 | TARGET := mkimage |
但是吧,报错了,看一眼,里面包含了不少的uboot内部的头文件,这里感觉没啥必要深究,就直接拿来用吧,以后有空再说。
四、mkImage.sh工具
这个其实是个脚本,这是NXP官方的SDK提供的,需要我们后面编译官方的SDK,所以后面学习到SDK的时候再来了解一下这种方式。可以看这里:《01嵌入式开发/02IMX6ULL平台/LV04-裸机开发/LV04-03-BSP工程管理-01-NXP官方SDK.md》
五、烧写img文件到SD卡
上边我们通过正点原子的imxdownload工具直接在ubuntu下完成imx文件的生成和烧写,那我们现在有一个imx文件,怎么办?回到bin文件?肯定不是啦,在ubuntu和windows下都有烧写的办法,这一节就来了解一下如何将imx文件烧写到sd卡中吧。
1. img文件
1.1 1K字节的空文件
为什么要有一个1K字节的空文件?原因就在于这个IVT,如下图:
IVT的偏移的话,在sd卡中,mmc都需要偏移1KB,而我们生成的imx文件,IVT直接从0开始,所以需要制作一个IVT偏移了1K的文件。我们在ubuntu编译好了imx文件后,可以先做一个1K字节的空文件:
1 | dd if=/dev/zero of=1k.bin bs=1024 count=1 |
dd命令 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。上边的命令含义就是以/dev/zero作为输入文件,1k.bin作为输出文件,同时设置读入/输出的块大小为1024个字节(1KB),仅拷贝1个块。这样我们就会生成一个1KB的1k.bin文件啦:
1.2 生成img文件
接下来将imx文件和1k.bin文件合并起来,注意1k.bin文件要在前,这样才能保证生成的img文件的IVT在1K的偏移处:
1 | cat 1k.bin led.imx > led.img |
2. windows下烧写img文件
2.1 Win32DiskImager软件
我们需要借助Win32DiskImager这个软件来吧img文件写入到sd卡中去,我们可以在这里下载这个软件:Win32 Disk Imager download | SourceForge.net,这个软件安装一路默认就好了,打开如下图所示:
2.2 烧写img文件
如上图所示:【选择img文件】→【选中要烧写的sd卡盘符】→【写入】,写入完成则会有以下提示:
然后点击OK,再退出即可。
3. ubuntu下烧写img文件
ubuntu下的话,可以使用dd命令,使用该命令我们甚至可以不需要1k的哪个空文件,直接通过这个命令将imx文件烧写到sd卡挂载节点的1k处:
1 | sudo dd if=led.imx of=/dev/sdc bs=1k seek=1 conv=fsync |
烧写完成会有如下提示:
除了上面的命令,我们还可以使用正点原子提供的哪个烧写工具,那个其实也一样的,只是它是通过c语言的system函数来执行了dd这个shell命令。如果想要烧img文件,直接dd命令不偏移就可以了,不过还是直接烧到1KB处方便,毕竟少生成一个文件。
六、启动测试
代码已经烧写到了 SD 卡中了,接下来就是将 SD 卡插到开发板的 SD 卡槽中,然后设置拨码开关为 SD 卡启动,拨码开关设置如图 :
设置好以后按一下开发板的复位键,如果代码运行正常的话 LED0 就会被点亮 :