工程结构与公共运行时框架
本文档介绍杰理科技(Jieli)开源聚合仓库 gitee-repos-Other 的工程组织方式,以及 fw-Bootloader(JL 系列定制 user boot 固件)所承载的公共运行时框架——包括多芯片工程目录规范、编译入口、升级模式(串口 / USB_HID)、调试打印、升级触发机制与工具链约束。
Purpose and Scope
本页覆盖以下内容:
- 仓库顶层组织:
gitee-repos-Other聚合仓库包含哪些子仓库(fw-Bootloader、ac792n-ota-loader),以及它们与杰理 SDK 的关系。 - fw-Bootloader 工程结构:
user_boot/cpu/<cpu>/<cpu>_uboot.cbp的工程入口规范、app/src/user.c的运行时配置位置,以及依赖的命名规则库文件(lib.a)与子仓库。 - 公共运行时机制:升级模式选择(
USB_MODE宏)、调试打印(__DEBUG、isd_config.ini、uart_init)、升级触发方式(I/O 口检测与 SDK 软件复位USE_UPGRADE_MAGIC)、工具链与编译环境(Codeblock / Make)、产物uboot.boot的部署流程。
以下内容不属于本页边界,留给兄弟页面:
- AC792N 的 OTA Loader 具体实现细节:见 ac792n-ota-loader 对应页面。
- uboot 升级协议的逐包格式与状态机(数据包结构、命令字、时序细节):见 uboot 升级协议流程 相关页面。
- 各芯片 SDK 自身的应用层框架(非 boot 部分)不在本仓库内,仅通过本页的 SDK ↔ BootLoader 对应表建立索引。
Overview
杰理芯片的固件体系中,user boot(uboot) 是介于芯片 ROM 启动与 SDK 应用之间的引导固件。它的核心职责是:在设备上电或复位后,根据触发条件(I/O 电平或 SDK 软件复位 magic 字)决定是进入升级流程还是直接跳转到 SDK 应用;若进入升级流程,则通过串口或 USB_HID 与上位机通信,完成固件数据的接收、CRC 校验与烧写。
fw-Bootloader 仓库即为此公共运行时框架的参考实现,关键设计要点如下:
- 一仓多芯片:同一个仓库通过
user_boot/cpu/<cpu>目录隔离不同芯片系列的工程,例如bd19(AC693N)、br23(AC635N/AC695X)、br25(AC636N/AC696X)、br30(AC697N/AC897N)、br34(AC638N/AD698N)、sh54(AD14N/AD104N)、sh55(AD15N/AD105N)、wl82(AC791N)、br28(AC701N)。选择工程时只需按芯片型号打开对应的.cbp文件(Codeblock 工程)。 - 双编译环境:同时支持 Codeblock(
.cbp工程文件)与 Make 环境,便于不同工作流接入。 - 编译时配置驱动运行时:升级模式(
USB_MODE)、调试打印(__DEBUG)、软件复位触发(USE_UPGRADE_MAGIC)均通过编译宏在构建期决定,使同一套源码可以产出不同运行形态的 boot 固件。 - 依赖外部库与子仓库:
user boot并非完全独立,需要结合"对应命名规则的库文件(lib.a)"和对应的子仓库一起编译,这是仓库 README 中明确声明的约束。
该框架的典型使用场景:产品量产固件需要定制串口升级或 USB_HID 升级;调试阶段需要开启打印定位 boot 行为;整机升级触发既可以是硬件按键(I/O 检测),也可以是 SDK 运行时发起软复位。
Architecture
下图展示聚合仓库的顶层组织、fw-Bootloader 的工程结构,以及公共运行时框架各机制之间的关系:
flowchart TD
subgraph sg_Repo["gitee-repos-Other(聚合仓库)"]
FB["fw-Bootloader<br/>JL 系列定制 user boot"]
OL["ac792n-ota-loader<br/>AC792N OTA Loader"]
end
subgraph sg_Boot["fw-Bootloader 工程结构"]
CB["user_boot/cpu/<cpu>/<cpu>_uboot.cbp<br/>Codeblock 工程入口"]
UC["app/src/user.c<br/>ut_device_mode(tx, rx, bud)"]
LIB["命名规则 lib.a 库文件<br/>+ 对应子仓库"]
end
subgraph sg_Runtime["公共运行时机制"]
MODE["升级模式<br/>USB_MODE=0 串口 / USB_MODE=1 USB_HID"]
TRIG["触发方式<br/>I/O 电平检测 / USE_UPGRADE_MAGIC 软复位"]
DBG["调试打印<br/>__DEBUG + uart_init(uttx, ut_buad)"]
end
FB --> CB
CB --> UC
CB --> LIB
CB --> MODE
MODE --> TRIG
MODE --> DBG
TRIG --> DBG
架构分层说明:
- 聚合仓库层:
gitee-repos-Other只做整理与索引,包含两个与 boot 体系直接相关的子仓库;fw-Bootloader面向 JL 全系列芯片的 user boot,ac792n-ota-loader则面向 AC792N 的 OTA 引导场景,两者各自独立演进。 - 工程结构层:
fw-Bootloader以user_boot/cpu/<cpu>作为芯片工程隔离边界,.cbp是编译入口;app/src/user.c是运行时外设配置(串口引脚与波特率)的集中位置;lib.a库与子仓库提供芯片底层驱动与协议栈。 - 运行时机制层:升级模式决定 boot 启动后使用哪条外设通路;触发方式决定从 SDK 应用进入升级流程的路径;调试打印贯穿两条通路,方便定位问题。
工程结构详解
仓库顶层组织
根目录 README.md 以表格形式声明了聚合仓库包含的子仓库:
| 目录 | 说明 |
|---|---|
| fw-Bootloader | JL 系列定制 Bootloader |
| ac792n-ota-loader | JL AC792N系列定制 ota-loader |
设计意图:杰理将不属于主要 SDK 分类的仓库统一收敛到 gitee-repos-Other,通过 README 建立索引。读者应依据目标芯片与场景选择子仓库——全系列通用 boot 能力看 fw-Bootloader,AC792N 专属 OTA 场景看 ac792n-ota-loader。
fw-Bootloader 工程结构
fw-Bootloader/README.md 明确了该仓库的定位:JL 系列 user boot 固件程序,包含 user boot release 版本代码,支持自定义串口升级和 usb_hid 升级,且"线下线上支持同步发布"。
关键工程约束(README 原文要点):
本工程提供的例子,需要结合对应命名规则的库文件(lib.a) 和对应的子仓库进行编译。
这意味着 fw-Bootloader 本身不携带芯片底层库,必须与命名匹配的 lib.a 静态库及配套子仓库协同编译——这是理解该工程"结构上分层、编译上聚合"的核心。boot 的特殊性(直接操作 Flash 与硬件)决定了库必须精确匹配芯片系列,因此库文件命名规则与芯片 cpu 目录一一对应。
SDK 与 BootLoader 系列对应关系
fw-Bootloader/README.md 给出了完整的 SDK 型号 → BootLoader 工程目录映射:
| SDK型号 | BootLoader 对应 |
|---|---|
| AC693N/AC693X | bd19 |
| AC635N/AC695X/AC695N | br23 |
| AC636N/AC696X/AC696N | br25 |
| AC697N/AC897N | br30 |
| AC638N/AD698N | br34 |
| AD14N/AD104N | sh54 |
| AD15N/AD105N | sh55 |
| AC791N | wl82 |
| AC701N | br28 |
工程入口规则:user_boot\cpu\<cpu>\<cpu>_uboot.cbp。README 给出的示例:SDK型号使用的是AC701N, 使用user_boot\cpu\br28\br28_uboot.cbp作为工程入口;升级使用说明文档也以 AC632N 为例,指出需要打开 fw-Bootloader-main\user_boot\cpu\bd19\bd19_uboot.cbp。这一"按 cpu 目录选工程"的约定是公共运行时框架扩展多芯片的基础——新增芯片系列只需新增一个 cpu 目录与对应 .cbp 工程,运行时框架代码按宏与库区分行为。
编译环境与产物
fw-Bootloader/README.md 说明 SDK 同时支持 Codeblock 与 Make 编译环境:
- Codeblock 编译:进入对应工程目录,找到后缀为
.cbp的文件,双击打开即可编译。 - 产物部署:生成的
uboot.boot需要添加到原 SDK 下载目录调试(流程见升级使用说明文档)。 - 工具链:与标准 SDK 一致;若遇到
"错误: uboot.boot数据的CRC校验错误"或"生成失败,无效的F文件"等错误,需要更新最新的工具(文档指向杰理工具下载页)。
公共运行时机制
升级模式选择(USB_MODE 宏)
uboot 升级支持两种模式,通过编译期 #defines 切换(见 升级使用说明):
- 串口升级模式:在 Project build options → Compiler settings →
#defines中添加USB_MODE=0。串口的 TX 脚、RX 脚、波特率由app\src\user.c中的ut_device_mode(tx, rx, bud)函数设置。 - USB_HID 升级模式:在
#defines中添加USB_MODE=1。此时 uboot 工程的usb_vid、usb_pid必须与 usb_hid 上位机的usb_vid、usb_pid保持一致,否则设备无法被上位机识别;上位机的 VID/PID 在pc_demo\usb_hid\main.cpp中修改。
设计意图:用编译宏而非运行时配置来决定升级通路,可以在不增加 boot 体积与运行分支的前提下,为不同产品线产出定制化的最小 boot 固件;同时将"外设引脚"与"协议栈"两件事解耦——引脚配置留在 user.c,协议栈由库提供。
调试打印配置
调试打印的使能与配置同样采用"宏 + 配置源"组合(见 升级使用说明):
- 使能:在
#defines中添加__DEBUG宏。 - 方法一(配置文件):使用
isd_config.ini配置文件中的引脚和波特率配置;在main函数中调用uart_init(uttx, ut_buad)应用配置。 - 方法二(代码直设):直接在代码中设置打印脚和波特率(文档示例:PA5,1000000 波特率)。
升级触发方式
升级触发有两条路径(见 升级使用说明):
- I/O 口检测触发:进入 uboot 后,在
main函数中通过检测某个 I/O 的电平状态,决定是否跳转到升级流程。典型用于量产/售后模式:按键或治具拉低引脚进入升级。 - SDK 软件复位触发:在
user.h中使能USE_UPGRADE_MAGIC宏;随后在 SDK 工程(任意位置)添加 magic 字写入代码,实现 SDK 运行时主动发起软复位并携带"进入升级"的标记。uboot 复位后读到该标记即进入升级流程。
设计意图:两种触发方式覆盖了"外部强制"与"软件主动"两类升级场景。I/O 检测不依赖 SDK 状态,适合设备死机、无法进入应用时的兜底恢复;magic 字方案由 SDK 控制升级时机,适合 OTA/在线升级流程,二者互为补充。
工具链与常见构建错误
fw-Bootloader/README.md 提示:使用的工具链与标准 SDK 一致。构建期可能出现以下典型错误,均指向工具版本问题:
错误: uboot.boot数据的CRC校验错误—— 生成的 boot 数据 CRC 校验不通过。生成失败,无效的F文件,请重新选择系统找不到指定的文件—— 工具链或文件路径异常。
处理方式:更新到最新的工具(杰理官方工具文档),而不是修改工程代码。这反映了 boot 构建链对工具版本的高度敏感:CRC 由构建工具生成,工具过旧会导致校验算法或烧录格式不匹配。
核心流程
升级流程总览
下图将"触发 → 引导 → 模式选择 → 协议交互 → 校验烧写 → 复位"的完整控制流串起来:
flowchart TD
Start([上电 / 复位]) --> Trigger{"触发源判断"}
Trigger -->|"I/O 电平检测"| IO["main() 检测 I/O 电平状态"]
Trigger -->|"SDK 软件复位 magic"| SDK["USE_UPGRADE_MAGIC + nvram_list 写入"]
IO --> Boot["进入 uboot 引导"]
SDK --> Boot
Boot --> Mode{"升级模式"}
Mode -->|"USB_MODE=0"| UART["串口升级<br/>ut_device_mode(tx, rx, bud)"]
Mode -->|"USB_MODE=1"| HID["USB_HID 升级<br/>VID/PID 与上位机一致"]
UART --> Proto["升级协议交互<br/>(上位机 ↔ uboot)"]
HID --> Proto
Proto --> CRC{"CRC 校验"}
CRC -->|"通过"| Flash["烧写固件到 Flash"]
CRC -->|"失败"| Err["报错:uboot.boot CRC 校验错误"]
Flash --> Reboot([重启进入 SDK 应用])
Err --> Reboot
流程要点:
- 触发源判断是 uboot 运行时第一个决策点:I/O 电平路径由硬件决定,magic 路径由 SDK 软件决定;二者最终汇合到"进入 uboot 引导"。
- 升级模式在编译期由
USB_MODE固定,运行时只走一条外设通路,不存在运行时切换。 - CRC 校验是烧写前的最后一道闸门,校验失败即报错(对应 README 中提到的工具链错误信息),避免将损坏数据写入 Flash。
- 无论升级成功与否,最终都复位进入 SDK 应用——boot 不常驻业务逻辑,保证系统启动路径简洁。
升级交互时序
下图描述一次典型升级中 SDK 应用、uboot、上位机与 Flash 的交互顺序:
sequenceDiagram
participant SDK as SDK 应用
participant UB as uboot(user boot)
participant PC as 上位机
participant FM as Flash 存储
SDK->>UB: 软件复位(USE_UPGRADE_MAGIC)
Note over UB: main() 检测触发源并初始化升级外设
PC->>UB: 建立连接(串口 / USB_HID,VID/PID 匹配)
PC->>UB: 下发升级数据包
UB->>UB: 校验数据(CRC)
UB->>FM: 写入固件
FM-->>UB: 写入完成
UB-->>PC: 应答结果
UB->>UB: 复位跳转
UB->>SDK: 启动 SDK 应用
时序设计的要点:uboot 与上位机之间采用"请求-应答"式交互(协议细节见 uboot 升级协议流程),数据在写入 Flash 前先做 CRC 校验,保证传输与写入的一致性;升级完成后通过复位切换控制权,避免 boot 与 SDK 应用共存导致的资源冲突。
使用示例
以下示例均提取自仓库文档中的实际配置说明,展示了公共运行时框架的典型定制方式。
选择芯片工程入口(AC632N 示例)
升级使用说明 指出,根据芯片型号选择对应的 uboot 工程,以 AC632N 为例:
fw-Bootloader-main\user_boot\cpu\bd19\bd19_uboot.cbp
Source: uboot升级使用说明v1.1.2.md
工程入口与 README 的 SDK 对应表 配合使用:先查表得到 cpu 目录名,再打开对应 .cbp。
配置串口升级引脚与波特率
串口模式下,在 app\src\user.c 中调用 ut_device_mode(tx, rx, bud) 设置串口 TX 脚、RX 脚与波特率(升级使用说明):
// app/src/user.c —— 串口升级模式下的外设配置入口
// 参数依次为:TX 引脚、RX 引脚、波特率
ut_device_mode(tx, rx, bud);
Source: uboot升级使用说明v1.1.2.md
使能调试打印
方法一:在 main 函数中调用 uart_init(uttx, ut_buad),引脚与波特率取自 isd_config.ini 配置文件(升级使用说明):
// main() 中使能调试打印,引脚/波特率由 isd_config.ini 提供
uart_init(uttx, ut_buad);
Source: uboot升级使用说明v1.1.2.md
方法二:代码中直接设置打印脚和波特率(文档示例:PA5,1000000 波特率)。
SDK 软件复位触发升级
在 user.h 中使能 USE_UPGRADE_MAGIC 宏后,在 SDK 工程任意位置添加以下代码,即可实现 SDK 软件复位触发升级(升级使用说明):
// 在 sdk 工程中,添加以下代码实现 SDK 软件复位触发(任意位置)
extern u32 nvram_list[];
#define NV_RAM_LIST_ADDR nvram_list
// ...(写入升级 magic 后触发软复位)
Source: uboot升级使用说明v1.1.2.md
该示例展示了公共运行时框架的跨工程协作模式:SDK 侧写标记 → 复位 → uboot 侧读标记。nvram_list 是 SDK 侧暴露的 NVRAM 地址符号,NV_RAM_LIST_ADDR 将其映射为 magic 字的存放位置,uboot 复位后在 main 中检查该地址决定是否进入升级。
配置选项
公共运行时框架的配置集中在编译宏与代码调用两层,均可在构建前按产品需求定制:
| 选项 | 类型 | 默认/取值 | 说明 |
|---|---|---|---|
USB_MODE | 编译宏(#defines) | 0 / 1 | 0 = 串口升级模式;1 = USB_HID 升级模式 |
__DEBUG | 编译宏(#defines) | 未定义 | 定义后使能 uboot 调试打印功能 |
USE_UPGRADE_MAGIC | 编译宏(user.h) | 未定义 | 定义后使能 SDK 软件复位触发升级 |
usb_vid / usb_pid | 数值常量 | 需与上位机一致 | USB_HID 模式下 uboot 的设备标识,与 pc_demo\usb_hid\main.cpp 保持一致 |
isd_config.ini | 配置文件 | — | 调试打印引脚与波特率的配置文件源(方法一) |
ut_device_mode(tx, rx, bud) | 函数调用 | — | 串口升级模式下设置 TX 脚、RX 脚、波特率 |
uart_init(uttx, ut_buad) | 函数调用 | — | 在 main 中应用调试打印配置 |
配置原则总结:
- 构建期决定形态:
USB_MODE、__DEBUG、USE_UPGRADE_MAGIC三个宏共同决定 boot 固件的运行形态,同一源码可产出"纯串口版"、"纯 USB_HID 版"、"带调试版"等不同组合。 - 外设参数分散在代码与配置文件:引脚/波特率既可通过
ut_device_mode硬编码,也可通过isd_config.ini间接提供,前者适合固定产品,后者适合工具链统一管理。 - VID/PID 是跨工程契约:uboot 与上位机必须成对修改,否则 USB 枚举失败。
API 参考(运行时入口)
| 函数/符号 | 位置 | 说明 |
|---|---|---|
ut_device_mode(tx, rx, bud) | app\src\user.c | 设置串口升级的 TX 引脚、RX 引脚与波特率 |
uart_init(uttx, ut_buad) | main 函数 | 初始化调试打印串口,参数来自 isd_config.ini |
main() | uboot 入口 | 检测 I/O 电平 / magic 标记,决定进入升级流程还是跳转 SDK |
nvram_list[] | SDK 工程 | SDK 侧暴露的 NVRAM 符号,配合 NV_RAM_LIST_ADDR 承载升级 magic |
USE_UPGRADE_MAGIC | user.h | 编译宏,使能软件复位触发路径 |
说明:以上函数签名来自仓库文档的调用描述(升级使用说明 与 L81)。仓库以文档+库文件形式分发,
lib.a内部的完整函数原型未在仓库中展开;如需逐参类型,请以对应芯片 SDK 头文件为准。
故障模式、边界情况与并发考量
构建期故障
| 故障现象 | 根因 | 处理 |
|---|---|---|
错误: uboot.boot数据的CRC校验错误 | 工具链过旧,生成的 boot 数据 CRC 与烧录格式不匹配 | 更新到最新工具(见 README 工具链说明) |
生成失败,无效的F文件 / 系统找不到指定的文件 | 工具链或工程文件路径异常 | 更新工具并核对 .cbp 工程路径 |
| 编译失败 | 未配套对应命名规则的 lib.a 库与子仓库 | 严格按 SDK 型号查对应表选库(README L8) |
运行期边界情况
- 升级模式误配:
USB_MODE定义缺失或取值非 0/1 时,boot 无法确定外设通路。配置必须显式写在编译#defines中。 - USB_HID 无法识别:uboot 与上位机的
usb_vid/usb_pid不一致时,设备无法枚举。修改时必须两侧同步(uboot 工程 +pc_demo\usb_hid\main.cpp)。 - 触发路径失效:I/O 检测依赖具体引脚电平与上电时序,量产治具需与硬件原理图对齐;magic 路径依赖 SDK 在复位前正确写入
nvram_list地址,若 SDK 版本与 boot 不匹配(如 cpu 目录选错),复位后读不到标记,设备将直接进入 SDK 应用而非升级流程。 - boot 特殊性:README 明确"鉴于 boot 的特殊性,请务必进行充分测试"。boot 直接操作 Flash 与底层外设,任何库/工程错配都可能造成升级失败甚至变砖,量产前必须全流程验证。
并发与一致性
- boot 运行于复位后的单任务环境,升级期间不存在多线程并发;一致性风险集中在数据完整性上——通过 CRC 校验在"写入前"拦截损坏数据。
- 升级过程中的意外断电属于主要中断场景:协议层(见协议流程文档)通过包序号与应答机制保证可重传恢复;本仓库文档层面给出的兜底手段是 I/O 触发——设备变砖后仍可强制进入升级模式重新烧写。
- 多次升级之间需保证 Flash 写入的原子性由库层处理,本仓库不暴露该细节。
性能与运维要点
- boot 体积与启动时间:升级通路按宏裁剪(只编入所选模式),有助于控制 boot 体积、缩短启动跳转时间;调试打印(
__DEBUG)会显著增加输出开销,量产固件应关闭。 - 部署流程:编译产物
uboot.boot必须放入原 SDK 下载目录调试,遵循标准 SDK 的下载流程(README L55)。 - 多系列维护:每新增一个芯片系列即新增一个
user_boot/cpu/<cpu>工程目录;线上/线下同步发布机制要求发布时各 cpu 目录的lib.a与文档版本保持一致。 - 升级协议版本:当前协议版本 v1.1.2(初始版本),协议变更会直接影响上位机与 boot 的兼容性,升级上位机与 boot 固件需配套发布。
扩展点
公共运行时框架通过以下方式支持定制与扩展:
- 新增芯片系列:在
user_boot/cpu/下新增 cpu 目录与.cbp工程,同时在 README 的 SDK 对应表中登记映射关系。这是框架最主要的结构化扩展点。 - 自定义串口参数:修改
app\src\user.c的ut_device_mode(tx, rx, bud)调用,或通过isd_config.ini统一管理引脚与波特率。 - 自定义 I/O 触发:在
main函数中按产品需求检测任意 I/O 电平组合,决定是否进入升级流程(文档仅给出"检测一个 I/O 的电平状态"的范式)。 - 升级通路扩展:当前框架内置串口与 USB_HID 两条通路;若要新增其他传输通道(如 BLE OTA),需要在上位机与 boot 两侧同时扩展协议处理,并保持 CRC 校验与 magic 触发机制不变。
- 上位机定制:
pc_demo\usb_hid\main.cpp是 USB_HID 上位机的修改入口(VID/PID、交互逻辑),可作为自定义升级工具的起点。