客制化启动方案
在一些应用场景下,开发者希望 D13x 上电即运行客制化开发的程序,而不是 Luban-Lite SDK 编译出来的程序。本文介绍:
1.如何让 CPU 上电立刻运行客制化的程序
2.如何使用进行烧录
3.如何初始化 PSRAM 内存,让应用程序可以使用 PSRAM
生成客制化的 Boot ROM 启动程序
启动镜像格式
芯片在上电启动时,首先运行芯片内部的 Boot ROM 程序,Boot ROM 程序加载并运行下一级程序。
Boot ROM 加载的程序需要按照一定的格式打包才会被运行。具体的打包格式可参考芯片手册的启动章节。此处节选镜像格式部分内容如下:
数据区域 | 数据分块 | 字段 | 字节 | 描述 |
---|---|---|---|---|
Signed Area | HEAD1 | Magic | 4 | 特征字符串,固定为 ”AIC” |
Checksum | 4 | 32 bit 累加和校验的校验值。安全启动方案设为0。 | ||
HEAD2 (248B) | Header version | 4 | 本文件头结构的版本号,当前版本为v1.1: 0x00010001 | |
Image length | 4 | 从文件开头到结束的总数据长度 | ||
Firmware version | 4 | 固件版本号,不同版本之间应单调递增 | ||
Loader length | 4 | 第一级引导程序的有效数据的长度,不包括填充数据 | ||
Load address | 4 | 镜像数据加载到内存的目标地址 | ||
Entry point | 4 | 第一级引导程序的可执行代码入口地址 | ||
Signature algorithm | 4 | 0:没有签名,仅计算 Checksum;1:RSA-2048; | ||
Encryption algorithm | 4 | 0:固件不加密;1:AES-128-CBC 加密 | ||
Signature result offset | 4 | 数字签名数据区域的偏移,从文件头开始计算 | ||
Signature result length | 4 | 数字签名的长度 | ||
Signature key offset | 4 | RSA 公钥数据区域的偏移 | ||
Signature key length | 4 | RSA 公钥数据的长度 | ||
IV data offset | 4 | AES-CBC IV 数据区域的偏移 | ||
IV data length | 4 | IV 的长度 | ||
Private data offset | 4 | 第一级引导程序私有数据区域的偏移 | ||
Private data length | 4 | 第一级引导程序私有数据区域的长度 | ||
PBP offset | 4 | PBP 数据区域的偏移 | ||
PBP length | 4 | PBP 数据的长度 | ||
Padding | 172 | 填充,使得头部刚好 256 字节 | ||
DATA1 | Loader binary data | X | 第一级引导程序的保存区域 | |
Padding | X | 增加填充,使得 256 字节对齐 | ||
DATA2 | Private data area | X | 存放镜像代码中可能使用的私有数据。 | |
Signature key area | X | 存放 RSA 公钥,DER 格式的密钥文件。应 4 字节对齐。 | ||
IV data area | 16 | 存放 AES IV 数据,16 字节,应 4 字节对齐。 | ||
PBP area | X | 存放 PBP 程序。应 16 字节对齐。 | ||
Padding | X | 填充,使得 256 字节对齐,方便计算数字签名 | ||
SIGN | Signature result area | 256 | 前面所有内容的数字签名或 MD5 |
其中几个关键的字段有:
Loader binary data
客制化程序存放的区域。
Load address
启动镜像的加载地址。
Entry point
客制化程序的程序入口地址,对应程序的链接地址。
内存空间规划
制作启动镜像时,需要做好内存使用规划。几个重要的内存信息:
1.D13x SRAM 的开始地址为 0x30040000
2.SRAM 的最开始 16K Byte,Boot ROM 运行时在使用,因此启动镜像不能被加载到该区间。
3/启动镜像头信息占用 256 字节,因此 Load address 和 Entry point 之间至少预留 256 字节。
因此启动镜像加载的内存地址,应该是 0x30044000 之后:
- 0x30044000
Load address
最小的地址 - 0x30044100
Entry point
最小的地址
做客制化启动程序开发的时候,应该参照上面的信息做好相关的连接地址、内存空间分配等规划。
生成启动镜像
使用 Luban-Lite 中的 mk_image.exe 或 mk_image.py 工具,可以单独生成启动镜像。
- tools/scripts/mk_image.exe
- tools/scripts/mk_image.py
- 相关工具请从 Luban-Lite 的最新 SDK 获取
步骤一:
假设编译的应用为 app.bin
可以参考下面的image_cfg.json
文件配置进行打包生成 app.aic
:
{
"pre-process": { // Pre-proccess to generate image components from raw data
"aicimage": { // Create aic boot image
"app.aic": {
"loader": {
"file": "app.bin",
"load address": "0x30044000",
"entry point": "0x30044100", // 256 byte aic header
},
},
},
},
}
2
3
4
5
6
7
8
9
10
11
12
13
此处 image_cfg.json
描述了将app.bin
打包生成 app.aic
,放到 loader 区域,并且设置了加载地址和入口地址。
步骤二:
执行的命令如下:
mk_image.py -p -c <path_to_image_cfg_dir>/image_cfg.json -d <path_to_app_dir>
如果将 mk_image.py`` image_cfg.json ``app.bin
都放在一个目录,则命令为:
mk_image.py -p -c image_cfg.json -d .
在当前目录下会生成 app.aic
,此文件为芯片 Boot ROM 可加载的镜像文件。
运行和烧录客制化程序
要运行上面生成的 app.aic
程序,有三个途径:
1.使用 USB/UART 工具下载运行
2.放到 SD卡 中运行
3.烧录到 Flash 中运行
使用 USB/UART 工具下载运行
当 Flash 中没有可启动的镜像时,Boot ROM 启动失败,自动进入 USB/UART 升级模式,此时:
1.使用 USB 线连接板子和电脑,电脑可识别设备
2.或者使用串口线,连接板子的 UART0
注意 需要安装 AiBurn 工具,并且在安装过程中选择安装 USB 驱动。 |
注意 如果需要使用 UART 升级,则板子不能使用 USB 线连接电脑。Boot ROM 中的升级模式, 在没有连接成功之前,同时检测 USB 和 UART 的连接。只要其中一个连接成功,则不会再做交替检查。 因此如果使用 USB 线连接电脑,一旦电脑识别并连接上板子,则不会再进入 UART 升级模式。 |
此时可使用 AiBurn 安装目录下的 upgcmd.exe
工具下载并运行 app.aic
:
USB 下载:
upgcmd.exe -l # 确认板子连接成功
upgcmd.exe write 0x30044000 app.aic # 将 app.aic 下载到 Load address 处
upgcmd.exe exec 0x30044000 # 跳转运行 app.aic
2
3
4
此时 Boot ROM 校验并且运行 app.aic
。
UART 下载:
upgcmd.exe -u COM3 -l # 确认板子连接成功,此处的 COM3 应根据实际情况做修改
upgcmd.exe -u COM3 write 0x30044000 app.aic # 将 app.aic 下载到 Load address 处
upgcmd.exe -u COM3 exec 0x30044000 # 跳转运行 app.aic
2
3
4
当 Flash 有合法的启动镜像时,上电芯片会优先从 Flash 启动,不会进入升级模式。
放到 SD卡中运行
如果 SDMC1 对应的卡座上插入了 SD 卡,上电启动过程中,总是优先检查 SD 卡,因此将 app.aic 放到 SD 卡中总是会被执行。
具体如下:
1.准备一张市面上常见的 SD卡,即TF卡
2.格式化为 FAT32/exFAT 文件系统,确保只有一个分区
3.参照下面的格式写一个 bootcfg.txt
文件,并且将 bootcfg.txt
和app.aic
一起复制到 SD 卡文件系统的根目录
4.插卡到 SDMC1 对应的卡座,重启板子,即可运行 app.aic
bootcfg.txt 的内容如下:
boot0=app.aic # 此处 boot0 是一个关键字,app.aic 可根据实际情况修改
bootcfg.txt 中如有换行符,请确保使用 UNIX 格式的换行符,即 ‘\n’,不能是 ‘\r\n’。
烧录到 Flash 中运行
D13x 支持的存储介质有:
- SPINOR
- SPINAND
- SD/eMMC
自定义烧录
Boot ROM 升级模式不支持烧录 Flash。 如果不使用 Luban-Lite 的烧录方案,则需要自行实现烧录功能。
开发者需要自行实现一个带烧录功能的程序如 flashwriter.aic
,通过 USB/UART/SD卡等方式运行起来,然后将 app.aic
烧录到指定的存储介质中。
通过 USB/UART 烧录:
1.通过 USB/UART,使用 upgcmd.exe write 命令将app.aic
先写到一个预设的 SRAM 空间
2.下载运行 flashwriter.aic
, flashwriter.aic
从该位置读取 app.aic
的数据,并写入到 Flash
通过 SD 卡烧录: 1.SD 卡启动运行 flashwriter.aic
2.flashwriter.aic
从文件系统中读取 app.aic
的数据,并写入到 Flash
烧录位置:
- 对于 SPINOR,只需将 app.aic 直接烧录到 Flash 的最开始位置即可,即 Flash 0 位置。
- 对于 SD/eMMC,开始处需要预留17K Byte 的 GPT 分区头,因此从第 34 个 Sector 的位置烧录 app.aic。
对于 SPINAND,由于需要进行坏块管理等,处理较为复杂,建议使用 SDK 的 BootLoader 进行烧录,此处不进行详细描述。
使用 SDK 的 BootLoader 烧录
参考下面的配置,可以完成将app.aic
烧录到指定的分区。
1.编译一个对应项目的 BootLoader
2.生成烧录镜像
3.使用 AiBurn 或者 upgcmd.exe 进行烧录
编译对应项目的 BootLoader:
例如 SPINOR 的方案,根据相近配置板子的项目,修改配置后,编译生成 BootLoader 程序。
如 output/d13x_demo88-nor_baremetal_bootloader/images/d13x.bin
即为编译后的 BootLoader 程序,可重命名为 bootloader.bin
对于没有 PSRAM 的项目,可以参考 G73x 的项目编译 BootLoader。
生成烧录镜像:
需要准备下列内容
工具:
tools/scripts/mk_image.py/mk_image.exe
tools/scripts/gen_partition_table.py
tools/scripts/mk_private_resource.py
文件: 参考相近存储的 demo 板的配置,如demo88-nor,如果没有 PSRAM,可参考 G73x 的对应文件
bsp/artinchip/sys/d13x/d13x.pbp
target/d13x/demo88-nor/pack/image_cfg.json
target/d13x/demo88-nor/pack/pbp_cfg.json
配置修改
image_cfg.json 需要修改,可参考附录的配置
将下列文件放到一个目录:
- mk_image.py/mk_image.exe
- gen_partition_table.py
- mk_private_resource.py
- d13x.pbp
- image_cfg.json
- pbp_cfg.json
- app.bin
执行命令生成烧录镜像:
gen_partition_table.py -c image_cfg.json -o partition.h -j partition.json
mk_private_resource.py -l pbp_cfg.json,partition.json pbp_cfg.bin
mk_image.py -v -d . -c image_cfg.json
2
3
烧录镜像:
upgcmd.exe 烧录
upgcmd.exe image d13x_demo88-nor_v1.0.0.img
AiBurn 烧录,与 SDK 镜像文件烧录方法一致。
注意,上述配置下,烧录完成后,重启时 Boot ROM 直接运行
app.aic
,因此如果需要重新进入 Boot ROM 升级模式, 需要通过短接 Flash 引脚,让芯片读取 Flash 内容失败然后进入升级模式。 初始化并使用 PSRAM
对于合封 PSRAM 的芯片,如果需要使用 PSRAM,可以使用 PBP 程序对 PSRAM 进行初始化。
PBP 程序是 Boot ROM 运行的程序,设计为 Boot ROM 的扩展,用于做 DRAM/PSRAM 的初始化。 PBP 程序运行完之后,可以直接返回 Boot ROM 然后继续跳转执行用户的程序。
当前 PBP 程序可以完成以下功能:
1.PSRAM 初始化
2.升级按键的检测,然后进入 Boot ROM 的升级模式
通过下列配置,可以完成 PSRAM 的初始化。
步骤1:工具和文件
需要使用下列工具:
- tools/scripts/mk_image.py
- tools/scripts/mk_private_resource.py
需要使用下列文件:
- bsp/artinchip/sys/d13x/d13x.pbp
- target/d13x/demo88-nor/pack/pbp_cfg.json
步骤2:启动镜像配置
image_cfg.json 参考下列配置:
{
"pre-process": { // Pre-proccess to generate image components from raw data
"aicimage": { // Create aic boot image
"app.aic": {
"loader": {
"file": "app.bin",
"load address": "0x30044000",
"entry point": "0x30044100", // 256 byte aic header
},
"resource": {
"pbp": "d13x.pbp",
"private": "pbp_cfg.bin",
},
},
},
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
步骤3:生成镜像
将上述文件放到一个目录:
app.bin
d13x.pbp
pbp_cfg.json
mk_image.py
mk_private_resource.py
mk_private_resource.py -l pbp_cfg.json -o pbp_cfg.bin
mk_image.py -p -c image_cfg.json -d .
2
此时生成的app.aic
即包含了 PSRAM 初始化代码,并且在 app.aic
运行之前已经执行。
Boot ROM 直接加载的限制与注意事项¶
1.启动速度
Boot ROM 运行时:
CPU 仅跑在 24 MHz
没有使能 Cache
没有使能中断
因此如果 APP 较大,可能出现加载速度较慢的情况。
2.SPINAND/eMMC 加载的镜像大小
SPINAND:APP 不能超过2个物理块的大小,如果超过,则应该使用 BootLoader
eMMC :APP 不能超过 512K Byte,如果超过,则应该使用 BootLoader
附录配置
image_cfg.json 的配置
本配置为 SPINOR,使用 SDK 的 BootLoader 进行烧录的参考配置。
{
"spi-nor": {
"size": "16m", // Size of SPI NOR
"partitions": {
"spl": { "size": "1m" },
},
},
"image": {
"info": { // Header information about image
"platform": "d13x",
"product": "demo88-nor",
"version": "1.0.0",
"media": {
"type": "spi-nor",
"device_id": 0,
}
},
"updater": { // Image writer which is downloaded to RAM by USB
"psram": {
"file": "usbupg-psram-init.aic",
"attr": ["required", "run"],
"ram": "0x30044000"
},
"spl": {
"file": "bootloader.aic",
"attr": ["required", "run"],
"ram": "0x40100000"
},
},
"target": { // Image components which will be burn to device's partitions
"spl": {
"file": "app.aic",
"attr": ["mtd", "required"],
"part": ["spl"]
},
},
},
"pre-process": { // Pre-proccess to generate image components from raw data
"aicimage": { // Create aic boot image
"usbupg-psram-init.aic": {
"head_ver": "0x00010001",
"resource": {
"private": "pbp_cfg.bin",
"pbp": "d13x.pbp",
},
},
"pbp_ext.aic": {
"head_ver": "0x00010001",
"resource": {
"pbp": "d13x.pbp",
"private": "pbp_cfg.bin",
},
// combine to use with loader.aic
"with_ext": "true",
},
"loader.aic": {
"head_ver": "0x00010001",
"loader": {
"file": "bootloader.bin",
"load address": "0x40200000",
"entry point": "0x40200100", // 256 byte aic header
},
"resource": {
"private": "pbp_cfg.bin",
},
},
"app.aic": {
"head_ver": "0x00010001",
"loader": {
"file": "app.bin",
"load address": "0x40200000",
"entry point": "0x40200100", // 256 byte aic header
},
"resource": {
"private": "pbp_cfg.bin",
},
},
},
"concatenate": { // cat files in order
"bootloader.aic": ["pbp_ext.aic", "loader.aic"],
},
},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83