note - telink soc boot flow without bootloader
telink soc 分为了两大类:
- b825x/827x 等自研架构系列,采用 tc32 toolchain;
- b9218/8518 等基于开源架构 risc-v,采用 risc-v toolchain;
两者从启动方式来讲比较类似。
多地址启动
telink soc 根据 flash size 512k(0x80000)/1M(0x100000) 支持多地址启动,以支持固件在线更新后可以不用拷贝到固定运行地址,所以多地址启动另一方面也限定了固件大小,以 1M 为例:
- 0 地址启动,固件默认最大 512k;
- 0x20000 地址启动,则第一个固件区 0-0x20000,第二个固件区为 0x20000-0x40000,最大128k,但由于 soc 设计原因,当实现非 0 地址启动,默认最后 4k 用于数据备份(应该是多地址计算设计缺陷),导致无法使用,实际最大 124k,即 0x20000-0x3f000;
- 0x40000 地址启动,参照上述,最大252k;
- 0x80000 地址启动,最大 508k;注:512k 由于 size 限制,不支持此项。
通常 flash 最后一段空间用于保留预配置信息,例如 mac,calibration,serial num 等,需要依据实际情况对应设计 flash mapping。
当确定了运行地址后,硬件会设置地址偏移寄存器 multi_addr,当 mcu 取址会自行累加偏移地址,即当启动地址为 0x80000 时,mcu 取址 0x10000,实际取址为 0x10000+0x80000=0x90000。
低功耗模式
telink soc 支持三种低功耗模式:
- suspend,芯片 stall 在当前指令,唤醒后继续执行,mcu 暂停运行可降低部分功耗,大多数模块保持供电,功耗相对较高,如果手动关闭其他模块,功耗约为几十uA;
- deepsleep with retention,只有 pm 模块和 sram retention 部分保持上电(通常 sram retention size可自定义,16k/32k/64k,相对电流区别不大),其他全部掉线,(analog register 不掉电,包括上下拉配置寄存器可保持芯片在低功耗模式下保证 io 电平;retention register 8bytes,用户可用于保存状态,通常按位使用),唤醒后从 sram 0 地址运行,功耗较低,通常为10uA 级;
- deepsleep,只要 pm 模块保持上电,以及 analog register(上下拉配置寄存器和 retention register),唤醒后类似重新上电的流程,可通过 retention register 区分,功耗较 deepsleep with retention 更低,通常为 5uA 以下。
注:以上为实测功耗,datasheet 标定数据更优,暂以实际为准;同时 deepsleep with retention 由于从 sram 启动,并且主要数据保留,所以启动时间相对 deepsleep 要快。
以 ble 为例,通常 ble 保持连接过程中,对包期间为空闲状态,可休眠,但 deepsleep 会导致连接数据丢失,所以采用 deepsleep with retention,当断开连接并持续一段时间无操作后,才会选择进入 deepsleep。
程序链接段定义
通常链接阶段可自定程序分为以下几个段:
- retention data - 数据段,用于保存低功耗不掉电数据,通过 attribute 指定段来定义相关变量;
- ram code - 程序段,通常保存在不掉电 sram 中,attribute 指定段来定义相关函数,通常为 flash 操作函数,启动汇编函数,irq 函数,或部分需要提供运行速度之类的函数,如语音编码等;
- text - 程序段,即 .c 中定义的函数;
- ro - read only,通常为 const 类型数据或直接自定的字符串;
- data - 数据段,在定义中直接有初值的数据,需存入生成的固件,在上电运行时由启动汇编函数复制到 sram 中;
- bss - 数据段,在定义中为 0 或未初始化的数据,此段不需要存入生成的固件,在上电运行时由启动汇编函数初始化为 0。
启动流程
首次上电:
- 硬件/rom 程序检查 0/0x20000/0x40000/0x80000 对应偏移是否有 “TLNK” 启动标志位(通常 telink 在 startup.s 文件中定义 “TLNK” 到指定偏移,b85和b91不同,参考代码),按顺序检测,检测到即执行;通常可依据这一特定实现在线升级后的固件切换,参考下一节在线升级和固件切换;
- 读取 0 地址(通常为 reset 指令或地址),跳转到 reset;此处 0 地址会累加实际启动地址;
- 设置栈地址,通常为 sram 最大值,准备 c语言 执行环境;
- 将 retention data + ram code 拷贝至 sram;
- 初始化 data 段,将对应 flash 保存的 data 段 copy 到 sram 中;
- 初始化 bss 段,初始化为0;
- 跳转到 main,执行 c语言。
suspend 唤醒:
从暂停处继续运行;
deepsleep with retention 唤醒:
从 sram 0 地址运行,此时 sram 不掉电,sram 中保存了首次上电时 step 4 时的 startup.s,执行 reset 指令,但无需重新拷贝 retention data + ram code,只需从 step 5 继续执行即可,因此节省了时间;
deepsleep 唤醒:
同首次上电。
此时可通过 retention register 区分是否首次上电,部分应用设计为只有首次上电前 5s 按键或者其他操作,才可进入某种模式等。
在线升级和固件切换
由于上电后硬件通过检查 “TLNK” 来指定需要运行的固件,以 0/0x20000 为在线更新 AB 区为例:
- 烧录 0 地址,首次上电检查到 0 地址有 “TLNK”,运行 0 地址固件;
- 执行在线更新,烧录新固件到 0x20000,完整性检查通过后,擦除 0 地址 “TLNK” 标志位;
- 重启后,硬件检查到 0 地址没有匹配标志位,按顺序检查 0x20000,标志位匹配,则运行 0x20000 地址固件。