新唐MCU技术
直播中

李艳

8年用户 1567经验值
私信 关注
[问答]

如何实现软件重置或 CPU 重置以使重置时间比硬件重置方法更短?

如何实现软件重置或 CPU 重置,以使重置时间比硬件重置方法更短?

回帖(2)

赵静

2025-8-28 16:46:08
在新唐8bit 8051 MCU中,有一个软件复位功能,其复位时间比硬件复位方法更短。
用户可以设置 SWRST 位 (CHPCON.7) 来实现软件复位。
示例代码:
TA = 0xAA; TA = 0x55;          //enable Time Access Protection (TA)
CHPCON = 0x80;                     //write 1 to SWRST to trigger a Software Reset
/* 捕获 CPU */
while(1); 
用户可以检查 SWRF (AUXR0.7) 以确定软件重置是否是最后的重置源。


而新唐 M0/M23/M4 MCU 具有 CPU 复位功能。
用户可以设置 CPURST 位 (SYS_IPRST0[1]) 来实现 CPU 复位。
示例代码:
SYS_REGLCTL = 0x59; SYS_REGLCTL = 0x16; SYS_REGLCTL = 0x88;          //enable Register Lock Control
SYS_IPRST0 = 0x02;                                                                                                    //write 1 to CPURST to trigger a CPU Reset
/* 捕获 CPU */
while(1); 
用户可以检查系统复位状态寄存器 (SYS_RSTSTS) 以识别上次作的复位源。例如,如果复位源是 CPU Reset,则将设置 CPU 复位标志 CPURF (SYS_RSTSTS[7])。


以MS51为例,RC充电硬件复位需要50ms,而下次从SWRST设置到主入口的时间约为800us,这是软件复位的复位时间。
举报

h1654155216.9102

2025-9-3 18:02:07

实现比硬件复位更快的软件复位/CPU复位的核心思路是绕过耗时的硬件初始化环节(如外部存储器、时钟树、外设等),仅恢复CPU核心状态并跳转到初始执行点。这需要深入理解硬件架构和利用芯片特性。


以下是关键策略和实现方式:


?️ 1. 内核复位 (Core Reset):



  • 原理: 许多现代微控制器/处理器(尤其是ARM Cortex-M系列)提供专门的寄存器位,用于仅复位处理器核心(CPU)和内部总线(如AHB, APB),而复位调试逻辑、内部SRAM和大部分外设。

  • 实现:

    • ARM Cortex-M: 使用应用程序中断和复位控制寄存器(AIRCR)中的 SYSRESETREQVECTRESET 位。

      • SYSRESETREQ: 请求系统复位控制器执行复位(具体复位范围由芯片厂商定义,通常是整个SoC,但有时可能更快)。操作方式:
        SCB->AIRCR = (0x05FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
        while(1); // 等待复位发生

      • VECTRESET: 仅复位处理器核心(Cortex-M3/M4/M7)。这是最快的软件复位方式之一,因为它只复位内核寄存器、NVIC、SCB和SysTick,保留外设状态和SRAM内容。操作方式:
        SCB->AIRCR = (0x05FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_VECTRESET_Msk;
        while(1); // 等待复位发生


        • ⚠️ 警告: VECTRESET 复位后,SRAM和外设状态保留。复位处理函数 (Reset_Handler) 必须检测此状态(例如通过复位原因寄存器或在特定RAM位置设置复位标志),并选择性初始化外设或清理残留状态,否则系统可能行为异常。




  • 优点: 速度极快(通常只需几个CPU周期),明确保留了内存状态。

  • 缺点: 需要芯片支持。使用VECTRESET需要精心设计复位处理函数(Reset_Handler)来处理残留的外设状态。


? 2. 跳转到复位向量 (Jump to Reset Vector):



  • 原理: 直接模仿硬件复位后CPU的行为:

    1. 将栈指针(SP)设置为复位向量处定义的初始值(通常是RAM最高地址)。

    2. 将程序计数器(PC)设置为复位向量(通常是中断向量表的第一个条目 Reset_Handler 的地址)。



  • 实现:


    // 函数指针类型,指向复位处理函数
    typedef void (*pFunction)(void);
    // 定义复位向量地址(通常是0x00000004,具体看芯片手册和链接脚本)
    #define RESET_VECTOR_ADDR 0x00000004
    // 定义初始栈顶地址(通常来自链接脚本定义的符号,如 __initial_sp)
    extern uint32_t __initial_sp; // 假设链接器提供了这个符号

    void software_reset(void) {
        // 1. 可选:禁用全局中断,避免在跳转过程中发生中断
        __disable_irq();

        // 2. 可选:清除关键外设状态或标志位(如果必要)
        // ... (例如清除中断挂起标志、停止DMA等) ...

        // 3. 设置主栈指针(MSP)为初始值
        __set_MSP((uint32_t)&__initial_sp);

        // 4. 获取复位处理函数的地址(复位向量内容)
        pFunction Jump_To_Reset_Handler;
        uint32_t reset_vector = *((volatile uint32_t *)RESET_VECTOR_ADDR);
        Jump_To_Reset_Handler = (pFunction)reset_vector;

        // 5. 跳转到复位处理函数
        Jump_To_Reset_Handler();

        // 6. 永远不会执行到这里
        while(1);
    }


  • 优点: 纯软件实现,不依赖特定硬件复位功能。理论上比硬件复位快,因为跳过了电压稳定等待、时钟锁相环锁定、Flash初始化等步骤。

  • 缺点:

    • 内存和外设状态不变: SRAM内容和所有外设寄存器保留之前的状态。Reset_Handler 必须检测这是软件复位(例如通过一个在特定RAM位置设置的标志 software_reset_flag),并执行:

      • 选择性初始化: 只初始化那些需要恢复到已知安全状态的关键外设(如时钟、看门狗、中断控制器),而不是所有外设。

      • 清理RAM: 选择性清除关键全局变量或数据结构,尤其是那些需要在启动时初始化的。可以不清除整个RAM。

      • 复位标志处理: 在准备好“干净”状态后,清除 software_reset_flag


    • 需要非常小心地管理中断和异常。建议在跳转前禁用全局中断。

    • 对运行时环境的依赖性强(栈指针设置、函数指针跳转)。



? 3. 内存保留复位 (Partial Reset with RAM Retention):



  • 原理: 一些芯片允许配置特定的复位源(如看门狗复位、软件复位)清除内部SRAM的内容。硬件复位通常总是清除SRAM。

  • 实现:

    1. 配置复位控制器(Reset Controller)寄存器,使能特定复位源下的SRAM保留(具体寄存器位名和位置查阅芯片手册)。

    2. 触发该复位源(例如触发看门狗复位或使用特定的软件复位命令寄存器)。

    3. Reset_Handler 中:

      • 检查复位原因(复位源状态寄存器)。

      • 发现是"软复位的SRAM保留复位"。

      • 执行类似"跳转到复位向量"方法中的选择性初始化和关键数据清理



  • 优点: 结合了硬件复位的可靠性和部分保留状态的快速性。复位逻辑由硬件处理。

  • 缺点: 高度依赖芯片是否支持该特性。复位时间可能比纯内核复位或跳转略慢,但通常仍远快于全硬件复位(因为跳过了Flash初始化、PLL锁定等)。仍然需要处理残留的外设状态。


? 优化关键点(缩短时间):



  1. 保留RAM内容: 这是最大的速度增益来源。避免重新加载代码和数据段到RAM(如果它们在复位后仍然存在且未被破坏),可以节省大量时间(毫秒级)。上述内核复位(保留RAM)、跳转到复位向量(保留RAM)和内存保留复位都利用了这一点。

  2. 跳过时钟初始化: 如果芯片本身运行在内部时钟(如HSI/HFXO已稳定),且复位不改变时钟源(如触发内核复位或跳转),则可以完全跳过时钟树(PLL配置、分频器等)的漫长初始化过程(尤其在PLL需要锁定时间时)。

  3. 选择性外设初始化: 复位处理函数 (Reset_Handler) 必须区分是冷启动(Hard Reset)还是软件启动。

    • 冷启动: 执行完整的初始化(时钟、所有外设、内存初始化等)。

    • 软件启动:

      • 只复位或重新配置那些绝对必要且可能处于不确定状态的外设(如看门狗、中断控制器、先前使用的通信接口)。

      • 不初始化未使用或状态相对安全的外设(如GPIO状态通常保留)。

      • 不清零整个RAM,只重置关键全局变量(如状态机、错误标志、软件看门狗计数器)。

      • 快速重建必要的运行时环境(设置栈指针、初始化关键数据结构)。



  4. 精简 Reset_Handler: 专注于软件复位路径的优化。


? 实现步骤总结:



  1. 确定目标芯片支持的最快软复位机制: 查阅芯片参考手册的复位控制器(RCC/RSTC)、系统控制块(SCB)章节。优先寻找内核复位 (VECTRESET) 或内存保留复位选项。

  2. 修改复位处理函数 (Reset_Handler):

    • 在最开始读取复位原因寄存器。

    • 根据复位原因(硬件复位/上电复位 vs. 软件内核复位/看门狗复位等)分支。

    • 对于软件复位路径:

      • 禁止中断(如果尚未禁止)。

      • 选择性复位关键外设(使用外设自己的复位寄存器或重新配置)。

      • 选择性清零关键全局变量或数据结构。

      • 避免: 初始化时钟(除非必须调整)、初始化未使用外设、清零整个RAM、初始化Flash接口(如果代码在RAM中运行或XIP)。

      • 重新初始化栈指针(如果使用了VECTRESET或跳转方法)。

      • 清除复位原因标志(如果芯片需要)。

      • 启用中断(如果需要)。

      • 跳转到 main() 或初始化后的入口点。



  3. 编写软复位触发函数:

    • 如果使用内核复位 (VECTRESET/SYSRESETREQ),写入相应寄存器。

    • 如果使用跳转到复位向量,按前述代码实现。

    • 如果使用带RAM保留的看门狗复位,配置看门狗超时并喂狗触发复位。


  4. 在应用程序需要复位的地方调用软复位触发函数。


⚠️ 重要注意事项与挑战:



  • 稳定性风险: 最大的挑战是处理残留的外设和内存状态。不彻底清理可能导致复位后系统立即进入错误状态(死锁、总线错误、意外中断)。必须进行极其充分的测试!

  • 外设依赖性: 软复位的效果很大程度上依赖于应用程序使用了哪些外设以及这些外设在复位后是否能容忍残留状态。

  • 中断处理: 在触发软复位前禁用中断是良好的做法。确保在精简的Reset_Handler软件路径中正确地重新初始化中断系统(NVIC)。

  • 看门狗: 如果使用看门狗,需要在精简的Reset_Handler中尽快处理(重启或配置),防止二次复位。

  • 非易失性设置: 软复位不会改变Flash、EEPROM或备份域(RTC、备份寄存器)的内容。

  • 调试: 软复位行为可能与硬件复位不同,给调试带来挑战。确保调试器连接不会干扰软复位过程(有些内核复位会保留调试连接)。


结论:


通过利用芯片提供的内核复位机制(如ARM VECTRESET)或直接跳转到复位向量,并结合精心设计的、区分软复位路径的复位处理函数(主要策略是保留RAM内容、跳过时钟初始化、选择性外设初始化和关键数据清理),可以显著缩短复位时间,使其远快于完整的硬件复位。内存保留复位(如果芯片支持)也是一个很好的折中方案,兼顾了速度和一定的硬件可靠性。


关键成功要素:



  1. 芯片硬件支持(内核复位、内存保留功能)。

  2. 复位处理函数 (Reset_Handler) 的精细化设计,能够智能处理软复位场景。

  3. 彻底测试,确保残留状态不会引发问题。??

举报

更多回帖

发帖
×
20
完善资料,
赚取积分