<?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[BootSwap A&#x2F;B面切换时间差异]]></title><description><![CDATA[<h1>1. 前言</h1>
<ul>
<li>BootSwap 是一种 A/B 双区启动切换机制，用于在 MCU 的两个 Flash 启动块之间进行切换。</li>
<li>云途芯片 M 系列、H 系列均支持 BootSwap。</li>
<li>BootSwap 的操作本质是对 BOOT_NVR 扇区进行擦写操作。A -&gt; B 和 B -&gt; A 的擦写操作不同，导致 A/B 面切换时间不同，在一些应用中可能带来超时，如诊断超时、看门狗超时等。</li>
<li>本文以 HA01 芯片为例，介绍 <strong>BootSwap 的原理</strong>、<strong>A/B 面切换的时间差异</strong>，以及 <strong>ABSwap 操作不支持异步</strong>的原因。</li>
</ul>
<h1>2. BootSwap原理</h1>
<ul>
<li>YTM32B1HA0 片上集成了 2 片容量为 1M 的 flash，称为 pflash0 和 pflash1，总计 2MB，上电从 Rom Boot启动，按照BVT解析出地址跳转；默认是跳转到到pflash0 起始地址 0x200_0000 启动。</li>
<li>默认情况下，pflash0 被映射在 0x200_0000 开始的地址空间，pflash1 拼接在 pflash0 之后。</li>
<li>当执行了 BootSwap 命令后复位，pflash1 的物理存储被映射到 0x200_0000 开始的地址空间，pflash0 拼接在 pflash1 之后。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/67d32c2a-e4a0-41df-93d6-7c7d3f88269b.png" alt="86e2b2bb-e4c5-4cbe-af9a-5b887af65885-image.png" class=" img-fluid img-markdown" /></li>
</ul>
<h2>2.1 EFM命令和BOOT_INFO</h2>
<ul>
<li>执行 BootSwap 命令的具体操作，就是向 EFM 模块的 CMD 寄存器写入 BootSwap 的命令码 0x30，如下图所示。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/5ac3b18b-283a-48ef-8505-178ff02b1a41.png" alt="8737189b-ead3-4d7b-b01a-6bc6e205f665-image.png" class=" img-fluid img-markdown" /></li>
<li>在 EFM 模块的 STS 状态寄存器中，可以通过 BOOT_INFO 标志判断当前 0x200_0000 开始的区域映射在哪块 pflash 上，如下图所示。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/870fe271-f2ed-46cf-bd5d-19ddc7ad372f.png" alt="07b0d895-2b47-4f1a-b0fe-b276afbc5c72-image.png" class=" img-fluid img-markdown" /></li>
</ul>
<pre><code>tips：只有当芯片复位之后，新的设置才能生效。通常在软件中，执行 BootSwap 命令后，再调用NVIC_SystemReset()函数复位生效。
</code></pre>
<h1>3. 核心一：A/B 面切换时间差异</h1>
<h2>3.1 原理：写入 vs 擦除</h2>
<ul>
<li>HA01 的 BOOT_NVR 区域视图如下（BOOT_NVR 在 Block0）：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/7653d01b-3716-4e57-83a1-2b5b904dade0.png" alt="49ca1c01-58cc-4266-adc2-47a6735c08d9-image.png" class=" img-fluid img-markdown" /></li>
<li>A面 -&gt; B面：EFM 在 STS[BOOT_INFO]=0 的状态下（A面）接收到 BOOT_SWAP 命令时，会向 BOOT_NVR 扇区的前三个地址依次写入 SWAP_TAG（0x5A5A5A5A5A5A5A5A）。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/2a304764-be38-41d6-b688-23fc095931fb.png" alt="5e9a479e-e3d7-42bb-97a2-48bd05d0c4f1-image.png" class=" img-fluid img-markdown" /></li>
<li>B面 -&gt; A面：EFM 在 STS[BOOT_INFO]=1 时（B面）收到 BOOT_SWAP 命令，EFM 会擦除 BOOT_NVR 扇区。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/c9847636-c938-4ccc-ad95-ac18aa6594ee.png" alt="ce673841-60e3-49ac-bea7-ea50b1694b62-image.png" class=" img-fluid img-markdown" /></li>
<li>MCU 复位后的 EFM 硬件初始化过程会读 BOOT_NVR 扇区的前三个地址：如果读回的数据有至少两个等于 SWAP_TAG（0x5A5A5A5A5A5A5A5A），硬件会将 STS[BOOT_INFO] 置 1（0x200_0000 映射到 B 面），表明进入 PFlash 逻辑地址重映射模式；否则 STS[BOOT_INFO] 保持复位值 0（0x200_0000 映射到 A 面）。</li>
</ul>
<h2>3.2 时间数据</h2>
<ul>
<li>STS[BOOT_INFO]=0 的状态下，A面 -&gt; B面 时，EFM 会对 BOOT_NVR 扇区进行写入操作（Program），耗时很短（约82us）。</li>
<li>STS[BOOT_INFO]=1 的状态下，B面 -&gt; A面 时，EFM 会对 BOOT_NVR 扇区进行擦除操作（Erase），耗时较长，擦除一个扇区需要 20ms。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/906ff24a-b06f-4eae-a745-911e6bc6510d.png" alt="c5515a45-e8fe-44e0-ad40-e4151447ab90-image.png" class=" img-fluid img-markdown" /></li>
<li>实测配置如下：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/4aff5759-68ee-4777-a4d7-7bc3e8ae77a8.png" alt="d73d87a6-8146-4a8a-8baa-ceef86e9ac6d-image.png" class=" img-fluid img-markdown" /></li>
<li>A面 -&gt; B面，耗时78us：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/5889971c-e880-4212-9cd5-91010a6a21f4.png" alt="8544a8a0-fbc0-47e4-b33f-0742ffaf48b8-image.png" class=" img-fluid img-markdown" /></li>
<li>B面 -&gt; A面，耗时约19ms：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/5acfc2ab-6867-443f-956d-d1007edf21a0.png" alt="3d5d205e-5918-4499-aeac-c32feb148922-image.png" class=" img-fluid img-markdown" /></li>
</ul>
<h1>4. 核心二：ABSwap 操作不支持异步</h1>
<ul>
<li>因为 BOOT_NVR 区域和 PFlash0（A面）同在一个 Block0 上，所以从理论上来讲，A面 -&gt; B面 时 EFM 对 BOOT_NVR 区域只能进行同步操作，即对 BOOT_SWAP 区域写入 TAG 需要关闭全局中断，等待写入完成。</li>
<li>而 B面 -&gt; A面 时，程序在 B面（Block1）上运行，对 BOOT_NVR 区域（Block0）是可以异步操作的，即在对 BOOT_NVR 擦除的 19ms 内，CPU 可以异步继续执行别的代码。</li>
<li>SDK 的 ABSwap 操作是统一同步操作：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/a85770dc-65df-41c5-a60b-f386dfae9a13.png" alt="1a3b27d8-dd23-47de-b0b3-12486cd36bde-image.png" class=" img-fluid img-markdown" /></li>
</ul>
<pre><code>因为 A面 -&gt; B面 只能同步，B面 -&gt; A面 可同步可异步，为了操作统一，SDK 的 ABSwap 只支持同步操作，不支持异步。
</code></pre>
<h1>5. 小结</h1>
<ul>
<li>A/B 面切换的时间差异源于操作类型不同：A面 -&gt; B面 是向 BOOT_NVR 写入 SWAP_TAG（约 80us），而 B面 -&gt; A面 是擦除 BOOT_NVR 扇区（约 19ms），两者相差两个数量级。</li>
<li>由于 BOOT_NVR 与 A面（PFlash0）同处 Block0，A面 -&gt; B面 只能同步操作；SDK 为统一行为，ABSwap 仅提供同步接口，不支持异步。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/25c149de-64ec-47de-9900-591fc3b3cd49.png" alt="bfc29439-02e4-446e-b540-108cd77e2041-image.png" class=" img-fluid img-markdown" /></li>
</ul>
<pre><code>tips：在一些对时序要求较高的场景中，要特别注意 A/B Swap 时间差异带来的时序影响。例如诊断帧超时和看门狗超时。
其他系列芯片原理一样（MD1是操作CUS_NVR），BOOT_NVR（CUS_NVR）所属Block和Sector擦除时间不同，都可参考本文进行评估。
</code></pre>
<h1>6. 测试验证</h1>
<h2>6.1 环境</h2>
<p dir="auto">Config Tool Version：3.1.0<br />
HA01 SDK version：1.4.1<br />
EVB version: YTM32B1HA0-EVB-LQFP176</p>
<h2>6.2 下载说明</h2>
<ul>
<li>在运行用例时，需要进行两次下载：第一次下载程序，下载到从 0x200_0000 开始的 pflash0 中，运行程序后，0x200_0000 地址切换到 pflash1 上，此时还需要再下载一次程序，程序会覆盖到 pflash1 上。</li>
<li>注意，第一次下载程序后运行，从 pflash1 开始启动，pflash1 此时没有可执行的程序，可能会出现“卡死”的状态，此时需要再次下载，无需修改 link 文件将程序地址映射到 pflash1。<br />
<a href="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/671/d1f2572d-022c-4163-ab72-d3274d93fedf.zip" rel="nofollow ugc">Flash_Demo_ABSwap.zip</a></li>
</ul>
]]></description><link>https://forum.ytmicro.com/topic/2206/bootswap-a-b面切换时间差异</link><generator>RSS for Node</generator><lastBuildDate>Fri, 21 Aug 2026 18:28:51 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/2206.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 21 Aug 2026 09:05:45 GMT</pubDate><ttl>60</ttl></channel></rss>