以下是控制循环在 CLA 上运行时的简要 LFU 流程。
- 闪存分区和高级 LFU 软件流都保持不变。
- 用户通过 Windows 命令提示符调用 LFU 命令 8 Live DFU。
- 目标器件在 SCI 接收中断 ISR 中接收命令 ID 0x700。
- 在 main() 中,在后台循环中调用函数 BUCK_LFU_runLFU()。当命令 ID 与 0x700 匹配时,将禁用 SCI 中断,执行分支到自定义引导加载程序中 Live DFU 函数的地址。如果组 0 中的应用程序正在执行,则分支到组 0 中的自定义引导加载程序(地址 0x81000)。如果组 1 中的应用程序正在执行,则分支到组 1 中的自定义引导加载程序(地址 0x91000)。
- 自定义引导加载程序中的 liveDFU() 从主机接收应用程序映像并将其编程到闪存中。完成后,执行取决于是否定义了宏 LFU_WITH_RESET。如果是,则看门狗配置为生成复位信号,然后启用,因此发生器件复位。如果未定义宏,则执行分支到新应用程序映像的 LFU 入口点。这是组 0 的 0x8EFF8 和组 1 的 0x9EFF8。这与常规的闪存启动入口点不同。
- 函数 c_int_lfu() 位于组 0 上的 0x8eff8 和组 1 上的 0x9eff8。该函数可在不复位器件的情况下执行 LFU 切换。在该函数中:
- 调用编译器的 LFU 初始化例程 (__TI_auto_init_warm())。这将初始化已指示为需要初始化的任何变量。因此,它将初始化在 BANK1_Flash 构建配置中定义的 25 个新浮点变量。
- 设置一个标志以指示 LFU 正在进行中。在 F28004x 上,这是使用软件变量 lfuSwitch 实现的。在 F28003x 上,这是通过使用 LFU_setLFUCPU() 设置 LFUConfig SysCtl 寄存器的 LFU.CPU 位实现的。
- 调用 main()
- 在 main() 中,初始化进程取决于 LFU 是否正在进行中。这是通过访问 F28003x 上的 LFUConfig SysCtl 寄存器的 LFU.CPU 位或 F28004x 上的 lfuSwitch 实现的。如果该值为 0,则初始化会像发生器件复位一样进行。
- 如果该值不为 0,则执行有限初始化。首先,执行 init_lfu() 并执行上一节中描述的操作。
- 在这种情况下,在 CLA 上运行控制时,需要使用 memcpy() 将代码从闪存复制到 RAM。这对应于链接器命令文件中的 Cla1Prog 和 .const_cla 段以及控制循环 ISR。在准备此 memcpy 时,应将相应的 LSRAM 段重新配置,确保 CPU 是这些段的主器件。在 memcpy 之后,这些 LSRAM 段再次配置为在 CPU 和 CLA 之间共享。
- 禁用 CLA 后台任务。
- 当控制循环在 CLA 上运行并且存在 CLA 后台任务时,为了确定执行 LFU 切换的正确时间,逻辑略有不同。首先,BUCK_LFU_getBackgroundTaskControlRegister() 用于读取 MCTLBGRND 寄存器的 BGSTART 位。如果回读值为 0,则表示 CLA BGRND 任务既没有运行,也没有挂起。应用程序会视为已准备好进行 LFU 切换。如果读回值为 1,则 CPU 将变量 lfuSwitch_start 设置为 Lfu_switch_waiting_to_switch_cla。从 CLA BGRND 任务到 CPU 的任务结束中断会引发执行 ISR BUCK_LFU_CLA_BGRND_ISR,其中 lfuSwitch_start 从 Lfu_switch_waiting_to_switch_cla 更改为 Lfu_switch_ready_to_switch_cla。
注: LFU 切换会等待,直到 CLA 后台任务停止,因为与其他 CLA 任务不同,可以抢占 CLA 后台任务,而不必运行到结束。如果切换导致执行中的后台任务停止,它可能会将该任务保留为“非干净”状态。目标是让切换仅在旧固件中的所有任务都完成执行后发生。
- 此外,在 BUCK_LFU_CLA_BGRND_ISR 内部,在上述变量更改后会调用 BUCK_LFU_setupCLALFU(),其中会执行以下步骤:
- CLA 任务向量和后台任务向量映射到相应的任务。
- 注册对应于从 CLA BGRND 任务到 CPU 的任务结束中断的 ISR。
- 启用 CLA 后台任务。
- 更新 CLA 任务向量后,外设中断将继续发生。但是,CLA 任务始终运行到结束。由于这一属性,不会发生上下文冲突。
- 这里要注意的另一个要点是:.scratchpad 段(对应于 CLA 任务和函数)需要分配给一个单独的存储器段(不同于 .bss 和 .bss_cla 段)。在 LFU 期间,当 C28x CPU 初始化新变量时,CLA ISR 可能正在运行。ISR 可能正在访问位于 .bss 和 .bss_cla 段中的变量,可能也在使用 .scratchpad。同时,变量初始化将更新 .bss_cla 段。为避免任何 .scratchpad 损坏,它们的分离很重要。
- 另请注意,在这种情况下,LFU 切换期间的 CLA ISR 时间可能会略微增加。这是 CLA 和 C28x CPU 之间的 LSRAM 内存访问冲突造成的。CLA ISR 使用 .scratchpad 和 .bss(两者均位于 RAMLS7 块内)运行,而 C28x CPU 在 .bss_cla(也位于 RAMLS7 块内)中初始化 CLA 的新变量。
- 图 3-10 显示了另一个 LFU 用例,其中将在固件升级期间更新控制循环参数。在实践中,这可以使用 Compensation Designer 实时完成,这里提供了这方面的用例进行说明。这对应于 buck_F28004x_lfu_controlloop 工程,该工程使用编译器预定义符号 BUCK_CONTROL_RUNNING_ON_CLA 进行构建。在此工程中,BANK0_FLASH 构建配置包含对应于较小增益 (Kdc = 4000) 的系数。BANK1_FLASH 构建配置包含对应于较大增益 Kdc=38904 的系数(请参阅 buck.h 中的函数 BUCK_initControlLoopGlobals())。当启用有源负载时,这会导致 BANK0_FLASH 构建配置的瞬态性能较差,而 BANK1_FLASH 构建配置的瞬态性能更佳。如果器件已经包含与 buck_f28004x_lfu 工程(或甚至 CLA)对应的应用程序文件,则可以使用与上一节相同的 LFU 命令运行此更新,但与此工程对应的已更新的 .txt 名称除外,如表 3-1 所示。在 buck_f28004x_lfu_controlloop 工程中,在器件复位时(而不是在 LFU 切换之后)在 main() 中启用有源负载,因此在运行 LFU 后复位器件非常重要,可为执行此初始化提供便利。例如,在 CPU 上运行控制循环时,假设最后更新了 BANK1_FLASH。这意味着组 1 上的固件正在执行。因此,用户需要执行 LFU 命令来更新 BANK0_FLASH(使用 CLA controlloop 工程可执行文件),而非 BANK1_FLASH。LFU 更新完成后,需要复位器件。器件复位只需执行一次。
然后,用户可以使用 controlloop 工程可执行文件,在不复位器件的情况下执行其他 LFU 更新。