<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[如何实现MCU更可靠的系统启动]]></title><description><![CDATA[<h1>介绍</h1>
<p dir="auto">稳定可靠的启动是嵌入式系统设计的一个重要方面。本文档介绍了如何通过使用MCU的看门狗定时器、芯片内部的异常处理机制来实现更可靠的系统启动。</p>
<h1>MCU的启动过程</h1>
<p dir="auto">MCU的启动过程是指MCU上电后，系统从复位状态到进入用户应用程序的过程。这个过程通常包括以下几个步骤：</p>
<ol>
<li>上电复位：MCU上电后，首先会进入复位状态，所有的寄存器和外设都被初始化为默认值。</li>
<li>SRAM ECC初始化：在复位状态下，MCU会对SRAM进行ECC初始化，以确保SRAM的正确性。</li>
<li>系统初始化调用接口：进行关键模块的初始化，主要包含WDG、Flash等外设</li>
<li>C语言运行环境初始化：MCU会初始化C语言运行环境，包括堆栈、全局变量等。</li>
<li>启动用户应用程序：MCU会跳转到用户应用程序的入口函数，开始执行用户代码，用户代码开始阶段会初始化时钟和引脚等外设。</li>
</ol>
<p dir="auto">如果上述过程中开启了MCU的Secure Boot功能，MCU会在启动时验证用户代码的完整性和合法性，以确保系统的安全性。Secure Boot本身基本也遵循上述的启动过程。</p>
<p dir="auto">为了实现更可靠的系统启动，我们需要假定系统在上述过程中因为一些原因（如电源不稳定、外设异常、时钟不稳定等）导致系统无法正常启动。为了避免这种情况，我们可以使用MCU的看门狗定时器和芯片内部的异常处理机制来实现更可靠的系统启动。整个过程中所有步骤都应该有可靠的保护，避免系统在某个步骤中卡死。导致系统无法正常启动。</p>
<h2>WDG看门狗定时器</h2>
<p dir="auto">WDG看门狗定时器是MCU内部的一种硬件定时器，用于监测系统的运行状态。当系统出现异常时，WDG会自动复位MCU，以确保系统能够重新启动。WDG是专门为MCU功能安全设计的，在芯片内部WDG可以选择和系统时钟独立的时钟源，即使在系统时钟异常情况下，WDG也能正常工作。因此WDG非常适合用来实现对代码运行过程中的异常监测。</p>
<p dir="auto">云途MCU的WDG根据不同项目的配置略有差异，具体可以参考如下表格：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>MCU型号</th>
<th>WDG可选时钟源</th>
<th>上电默认开启</th>
<th>默认复位时间</th>
<th>默认时钟源</th>
<th>计数器宽度</th>
</tr>
</thead>
<tbody>
<tr>
<td>YTM32B1LE0x</td>
<td>SIRC, SXOSC</td>
<td>否</td>
<td>-</td>
<td>-</td>
<td>32bit</td>
</tr>
<tr>
<td>YTM32B1LE1x</td>
<td>LPO,SIRC,-,SLOW BUS</td>
<td>是</td>
<td>0xC00 (96ms)</td>
<td>LPO</td>
<td>16bit</td>
</tr>
<tr>
<td>YTM32B1MC0x</td>
<td>LPO,SIRC,IPC_FUNC_CLK</td>
<td>是</td>
<td>0xC00 (96ms)</td>
<td>LPO</td>
<td>16bit</td>
</tr>
<tr>
<td>YTM32B1MD1x</td>
<td>IPC_FUNC_CLK,SLOW_BUS</td>
<td>否</td>
<td>-</td>
<td>-</td>
<td>32bit</td>
</tr>
<tr>
<td>YTM32B1MD2x</td>
<td>LPO,SIRC,IPC_FUNC_CLK,SLOW_BUS</td>
<td>是</td>
<td>-</td>
<td>-</td>
<td>16bit</td>
</tr>
<tr>
<td>YTM32B1ME0x</td>
<td>SIRC, SXOSC</td>
<td>否</td>
<td>-</td>
<td>-</td>
<td>32bit</td>
</tr>
<tr>
<td>YTM32B1ME1x</td>
<td>LPO,SIRC,IPC_FUNC_CLK, SLOW_BUS</td>
<td>是</td>
<td>0xC00 (96ms)</td>
<td>LPO</td>
<td>32bit</td>
</tr>
<tr>
<td>YTM32B1HA0x</td>
<td>IPC_FUNC_CLK,SLOW_BUS</td>
<td>否</td>
<td>-</td>
<td>-</td>
<td>32bit</td>
</tr>
</tbody>
</table>
<p dir="auto">上面表格中可以看到，新的MCU在上电时默认是开启的，这主要是为了增加对系统启动阶段的保护。对于上电默认关闭的MCU，用户可以根据实际应用需求，在系统初始化阶段手动开启WDG。WDG的复位时间和时钟源可以根据实际需求进行配置，用户可以根据实际需求选择合适的时钟源和复位时间。</p>
<p dir="auto">对于WDG的使用，原则上是越早开启越好，WDG的开启时机应该在系统初始化阶段的早期进行，这样可以确保在系统启动过程中，如果出现异常，WDG能够及时复位系统。一般情况下，建议在系统初始化阶段的第一个接口调用之后立即开启WDG。因为默认的软件环境中，启动代码一般是通过汇编实现的，可以参考如下的代码片段：</p>
<pre><code class="language-asm">    /* Enable WDG */
    ldr     r0, =0x40052000     /* WDG_SVCODE Address */
    ldr     r1, =0xB631         /* CR unlock code 0 */
    str     r1, [r0]
    ldr     r1, =0xC278         /* CR unlock code 1 */
    str     r1, [r0]

    ldr     r0, =0x4005200C     /* WDG_TOVR Address */
    ldr     r1, =200000         /* Timeout 100ms */
    str     r1, [r0]

    ldr     r0, =0x40052004      /* WDG_CR Address */
    ldr     r1, =0x0000004F      /* Enable WDG */
    str     r1, [r0]
</code></pre>
<p dir="auto">startup代码中开启WDG之后，用户代码可以通过<code>WDG_DRV_Trigger(0)</code>函数来刷新WDG计数器，确保WDG不会复位系统。一般情况下，用户代码应该在每次进入主循环之前调用<code>WDG_DRV_Trigger(0)</code>函数，以确保系统在正常运行时不会被复位。</p>
<p dir="auto">上述代码中的超时时间和WDG时钟源可以根据实际需求进行配置，用户可以根据实际需求选择合适的时钟源和复位时间。</p>
<h2>HardFault异常处理</h2>
<p dir="auto">HardFault异常是MCU内部的一种硬件异常，用于监测系统的运行状态。当系统出现异常时，MCU会自动进入HardFault异常处理程序，在SDK和MCAL中，HardFault本身并没有做特别的处理，不过在实际应用中，建议用户要自己实现HardFault的异常处理程序，HardFault处理程序可以在进行必要的现场信息保存之后进行系统复位操作。这样可以确保系统在出现异常时能够自动复位，避免系统卡死。</p>
<p dir="auto">针对HardFault异常，MCU中的RCU模块支持Lockup Reset的开关控制，Lockup Reset是指在MCU进入HardFault异常后，MCU会自动复位。Lockup Reset的开关控制可以通过RCU模块的寄存器进行配置，Lockup Reset的典型触发场景为在HardFault中再次触发HardFault异常。</p>
<p dir="auto">需要特别注意的是，HardFault的异常处理函数需要直接定义<code>HardFault_Handler</code>函数，而不是通过<code>INT_SYS_InstallHandler</code>函数进行注册，因为后面一种方式在程序初始化阶段实际还是使用的默认的<code>HardFault_Handler</code>函数，此时如果触发异常，系统并不会跳转到通过<code>INT_SYS_InstallHandler</code>注册的异常处理函数中，因为如果系统没有运行<code>INT_SYS_InstallHandler</code>位置，此时对应的中断向量表还没有更新。</p>
<p dir="auto">最简单的HardFault异常处理函数如下：</p>
<pre><code class="language-c">void HardFault_Handler(void) 
{ 
    /* Code to save the context of the current task */
    /* Reset the system */
    SystemSoftwareReset(); 
}
</code></pre>
<p dir="auto">注意：应用现场保护代码不应运行时间过长，避免影响系统的复位时间。另外，现场保护代码中也不应该有包含Block等待的代码，避免在异常处理过程中出现死锁的情况。</p>
<h2>复位引脚</h2>
<p dir="auto">复位引脚是MCU内部的一种硬件引脚，用于外部设备的复位控制。当MCU出现异常时，可以通过控制复位引脚来实现系统的复位操作。MCU的复位引脚支持复位输入和输出功能，默认情况下复位的输出功能是关闭的，当需要MCU在复位的同时对外部其它设备进行复位时，可以通过RCU模块对应的寄存器开启复位输出功能，注意MCU的复位输出受外部RC滤波电路的影响，脉冲宽度会有一定的变化。</p>
<p dir="auto">复位引脚的输入功能也是系统启动阶段的一个重要保护措施，MCU在上电时会对复位引脚进行检测，如果复位引脚处于低电平状态，MCU会自动进入复位状态。一般情况MCU的复位引脚外部会有通过一个上拉电阻和一个电容实现，可以实现延迟启动和滤波防止误触发。</p>
<p dir="auto">MCU的复位引脚本身带有模拟滤波的功能，滤波的截止带宽在30MHz左右，为了实现有效的复位，复位引脚上低电平保持时间应该&gt;100ns, 另外复位引脚也支持数字滤波功能，可以在RCU里面通过寄存器启动，开启滤波功能之后，复位引脚的有效输入电平宽度需要根据滤波时钟的频率和对应的滤波宽度进行计算，具体可以参考MCU的参考手册。</p>
<h2>MCU 复位源的差异</h2>
<p dir="auto">为了应对不同的应用场景和对MCU的各种异常复位事件进行记录，云途MCU提供了多种复位源的支持。每种复位源对应的产生条件和处理方式略有不同。对于MCU来讲，只有POR/LVD的复位是最深层的复位。另外因为物理限制，在产生POR或者LVD复位时，SRAM的内容因为供电不足也无法保持。另外在MCU中有一些寄存器是只能在POR/LVD复位时才能被清除的，这些寄存器在其他复位源下仍然保持原来的值。这部分寄存器一般和系统设置或者系统的安全性相关。比如芯片的复位原因寄存器（RCU-&gt;RSSR）在POR/LVD复位时会被清除，而在其他复位源下仍然保持原来的值。</p>
<p dir="auto">在进行软件开发过程中，应用程序通常需要读取芯片的复位原因，并根据系统的复位原因进行相应的处理。云途MCU中通过RCU模块实现对复位的管理和查询。RCU模块提供了多种复位源的支持，包括：</p>
<ul>
<li>POR（Power-On Reset）：上电复位，MCU上电时自动触发。</li>
<li>LVD（Low Voltage Detect）：低电压检测复位，当MCU的供电电压低于一定阈值时自动触发。</li>
<li>WDG（Watchdog Reset）：看门狗复位，当MCU的看门狗定时器超时时自动触发。</li>
<li>SW（Software Reset）：软件复位，通过软件指令触发。</li>
<li>LOCKUP（Lockup Reset）：当MCU进入HardFault异常时自动触发。</li>
<li>CMU (Clock Monitor Unit) Reset：时钟监控复位，当MCU的时钟异常时自动触发。</li>
<li>PIN (Pin Reset)：引脚复位，当MCU的复位引脚被拉低时自动触发。</li>
<li>DEEPSLEEPACK (Deep Sleep Acknowledge Reset)：深度睡眠确认复位，当MCU需要进入DeepSleep/Standby/PowerDown等低功耗模式时，如果MCU的部分外设仍在进行数据传输而没有响应进入低功耗的请求时，MCU会在超时之后自动触发DeepSleepACK复位。</li>
</ul>
<h2>硬件设计考虑</h2>
<p dir="auto">良好的MCU硬件工作环境是实现可靠系统启动的基础。以下是一些硬件设计的建议：</p>
<ol>
<li>
<p dir="auto"><strong>电源设计</strong>：确保MCU的供电稳定，使用高质量的电源模块和滤波电容，避免电源噪声对MCU的影响，确保MCU上电和掉电过程的单调性，在上下电过程中，电源电压应该单调变化，避免出现电源电压的波动和反弹现象。在MCU运行过程中，电源电压应该保持在MCU的工作范围内，避免出现低电压或者高电压的情况，也不应该有快速的电压变化，避免MCU内部的数字电路受到影响。</p>
<ul>
<li><strong>电源去耦</strong>：在MCU的电源引脚附近添加适当的去耦电容，以滤除高频噪声。一般建议使用0.1uF和10uF的组合，0.1uF用于滤除高频噪声，10uF用于滤除低频噪声。</li>
<li><strong>电源滤波</strong>：在MCU的电源输入端添加LC滤波器，以滤除低频和高频噪声，确保MCU的供电稳定。</li>
</ul>
</li>
<li>
<p dir="auto"><strong>时钟设计</strong>：使用高质量的时钟源，确保MCU的时钟稳定，避免时钟异常导致的系统启动失败。对于MCU的时钟源，建议使用外部晶振或者高精度的内部振荡器，另外对于外部晶振一方面要考虑不同温度的频率漂移，另一方面要考虑外部晶振的启动时间，还需要晶振负载电容的匹配，晶振硬件电路的屏蔽和隔离等。另外软件配置晶振时应该考虑晶振的增益系数，根据实际晶振的频率或者晶振的匹配结果来选择合适的增益系数，避免晶振启动失败。</p>
</li>
<li>
<p dir="auto"><strong>复位电路设计</strong>：在MCU的复位引脚上添加适当的上拉电阻和滤波电容，以确保MCU在上电时能够正确复位。一般建议使用10KΩ的上拉电阻和0.1uF的滤波电容，确保复位引脚在上电时能够快速拉高，同时滤除高频噪声。另外，芯片复位引脚本身也带有模拟滤波功能，同时支持芯片内部上拉电阻，这两个功能默认都是开启的，用户可以根据实际需求进行配置。</p>
</li>
</ol>
<h1>总结</h1>
<p dir="auto">通过使用MCU的看门狗定时器、芯片内部的异常处理机制和良好的硬件设计，可以实现更可靠的系统启动。看门狗定时器可以监测系统的运行状态，异常处理机制可以在系统出现异常时自动复位系统，而良好的硬件设计可以确保MCU的工作环境稳定。通过这些措施，可以有效避免系统在启动过程中出现异常，确保系统能够正常启动和运行。</p>
]]></description><link>https://forum.ytmicro.com/topic/1103/如何实现mcu更可靠的系统启动</link><generator>RSS for Node</generator><lastBuildDate>Fri, 14 Aug 2026 15:20:17 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/1103.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 16 Jun 2025 05:11:41 GMT</pubDate><ttl>60</ttl></channel></rss>