在以下部分,当提及代码和示例项目时,SBL = flash_based_uart_sbl_with_lfu 和 LFU 应用 = lfu_uart_cpu1_application。
与 LFU 相关的详细步骤概述如下:
- 引导至 SBL 并执行应用:在器件复位时,在 SBL 中开始执行。通信外设经过初始化,执行转移到应用的 codestart 例程。在代码中,这发生在 SBL 的 main() 函数 (flash_based_uart_sbl.c) 中。
- 启动 LFU:用户通过主机发起的 LFU 命令在目标 MCU 上调用 LFU。
- 在应用中接收 LFU 命令:应用在其通信外设 ISR 中接收 LFU 命令。在代码中,这发生在 LFU 应用的 SBL_uartNotifyISR() (uart_led_blinky_cpu1.c) 中,该函数设置一个标志,指示应用跳回 SBL,以处理命令。
- 处理 LFU 命令:应用转移回 SBL,以解析和处理 LFU 命令。在代码中,这发生在 SBL 的 commandJumpTable() 函数 (flash_based_uart_sbl.c) 中,该函数读取命令并执行相应的操作。
- 将新固件和程序下载到闪存:SBL 中的 LFU 流从主机接收应用映像,并将其编程到非活动的闪存存储体中。旧固件中的后台任务函数已停止执行,但控制 ISR 继续可用,以保持应用功能不受影响。在代码中,这发生在 SBL 的 cpu1LFUFlow() 函数 (sbl_command_flow.c) 中。
- 返回到应用并报告成功:如果固件映像编程成功,SBL 转移回应用并报告成功的 LFU 命令
- 将 LFU 切换函数复制到 RAM 中:应用将新固件的 LFU 切换函数从不可执行的非活动的闪存复制到 RAM 中,然后转移到其中。由于旧固件执行新固件的切换函数的复制,因此它必须位于固定地址。在代码中,LFU 应用的 performLFUSwitchover() 函数 (lfu_switchover.c) 负责此操作。
- 初始化新 PIPE 矢量表:影子 PIPE 矢量表中会填充新固件的 ISR。在代码中,这在 LFU 应用的 lfuSwapBanks() 函数 (lfu_switchover.c) 中完成。
- 等待更优 LFU 切换点:使用一个带有软件标志的简单状态机来确定控制 ISR 的结束和空闲时间的开始。这是执行切换的更优时间,因为它更大限度地利用控制循环中断之间的空闲时间。在代码中,lfuSwapBanks 函数 (lfu_switchover.c) 通过读取 lfu_switchover_proceed 标志来实现这一点,该标志在 INT_myCPUTIMER0_ISR() 例程 (uart_led_blinky_cpu1.c) 末尾设置。
- 执行 LFU 切换:
- 禁用中断
- 交换中断表
- 交换活动和非活动的闪存存储体
- 堆栈指针重新初始化
- 重新启用中断
- 执行转移到新固件的 main() 例程
在代码中,这是 LFU 应用的 lfuSwapBanks() 函数 (lfu_switchover.c) 的一段,标记为时间关键型阶段。
- 在新固件中跳过器件初始化,后台控制循环立即开始执行