<?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[MD14 BootSwap与DisJTAG组合使用方案]]></title><description><![CDATA[<p dir="auto">版本：<br />
<strong>YCT：3.2.0</strong><br />
<strong>MCU：YTM32B1MD14</strong></p>
<h1>1. BootSwap和 DisJTAG 原理</h1>
<p dir="auto">BootSwap 用于切换芯片下一次启动使用的 Flash Bank，DisJTAG 用于关闭 JTAG/SWD 调试连接。</p>
<p dir="auto"><strong>CUSNVR：CUS_NVR</strong>（Customized NVR）是芯片中存放客户定制信息的非易失性 Flash 区域，断电后数据保留，也用于保存调试口禁用和、Flash 地址保护和BOOT_SWAP配置。</p>
<p dir="auto"><strong>BootSwap：A/B面切换。</strong> 芯片把<strong>BOOT_SWAP</strong>配置保存在 CUS_NVR 中。程序调用<strong>BootSwap</strong>命令后会更改<strong>CUSNVR</strong>中的<strong>BOOT_SWAP</strong>字节段的内容**（A面是0xFF，B面是0x5A）**来实现A/B面的切换</p>
<p dir="auto"><strong>DisJTAG：决定是否允许调试器连接。</strong> 芯片把调试禁用配置同样保存在 <strong>CUS_NVR</strong> 中。程序通过更改<strong>CUSNVR</strong>中的<strong>Disable JTAG</strong>字节段的内容**（禁用是0x5A，启用是0xFF)**来实现调试口的状态。</p>
<p dir="auto"><strong>芯片差异说明：</strong> <strong>MD14</strong> 的 <strong>BootSwap</strong> 与 DisJTAG 配置均保存在 <strong>CUS_NVR</strong> 中，因此对该区域的擦写可能影响另一项配置。L 系列不支持 <strong>BootSwap</strong>；M 系列的其他芯片将 <strong>BootSwap</strong> 配置保存在 <strong>BOOTNVR</strong> 中，<strong>DisJTAG</strong> 配置保存在 <strong>CUSNVR</strong> 中，两项配置位于不同的存储区域，不存在因共用同一配置区域而产生的擦写影响。<strong><code>下文的组合使用注意事项及处理方案仅针对 MD14 芯片</code></strong>。</p>
<h1>2. BootSwap 和 DisJTAG 组合使用注意事项</h1>
<h2>2.1 B→A 切换时会清除原调试配置</h2>
<p dir="auto">《YTM32B1MD1x_RM》“Embedded Flash Module (EFM) → Boot Swap Operation”说明：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/9dd95255-585b-48cf-8de9-98fe3c73fb49.png" alt="d05af363-c330-412d-a58e-b880e855f1b1-image.png" class=" img-fluid img-markdown" /><br />
即：如果 STS [BOOT_INFO] 为 1，在执行 BOOT_SWAP 命令后，CUS_NVR 将会被擦除，这意味着用户需要重新配置 Disable_JTAG/SSWD 以及地址保护（Address_Protection）。</p>
<p dir="auto">例如：当芯片所在程序位于B面且调试口的状态为禁用时，如果此时执行<strong>BootSwap</strong>命令此时<strong>CUSNVR</strong>中调试字节段上的内容<strong>0x5A（禁用调试口）<strong>会被擦除变成</strong>0xFF（启用调试口）</strong>，调试口的状态就由禁用变成了启用</p>
<h2>2.2 Disable Jtag可能误修改 Boot Swap</h2>
<p dir="auto">执行<code>CUSNVR</code>写入操作之前需要执行<code>CUSNVR</code>擦除操作，但<code>CUSNVR</code>擦除以扇区为单位，代码中的 <code>FLASH_DRV_EraseNVR()</code> 会清空整个 1 KB CUS_NVR 扇区。如果擦除后只向其中的调试字段写入 <code>0x5A5A5A5A5A5A5A5A</code>，其他原有配置就没有被保留下来。</p>
<p dir="auto">所以代码需要通过“先保存、再修改、最后写回”处理这个影响：</p>
<ol>
<li>
<p dir="auto">将整个 1 KB 扇区读到 RAM 中。</p>
</li>
<li>
<p dir="auto">在 RAM 中只修改调试字段，保留其余内容。</p>
</li>
<li>
<p dir="auto">擦除 CUS_NVR，再将修改后的整个扇区写回。</p>
</li>
</ol>
<p dir="auto">在读取、擦除和编程均成功的条件下，这个流程可以保留调用时的其他配置。<code>Enable_Jtag()</code> 采用相同流程，只是把调试字段改为全 1。这说明组合使用时要处理好共享区域的擦写，不能仅凭一次擦除操作推断 BootSwap 一定会被改变。</p>
<h1>3. BootSwap 和 DisJTAG 并行组合方案</h1>
<h2>程序执行流程介绍</h2>
<p dir="auto">程序主线如下：</p>
<pre><code class="language-Plaintext">Board_Init()
    → 初始化时钟、引脚、Flash 和 UART 日志
    → 启用 GPIOB/GPIOC 中断
    → 读取 BlockFlag()，打印当前 Bank 及 CTRL_OVRD
    → 进入无限循环：
         根据 BlockFlag() 翻转绿灯或红灯，延时约 1 秒
         → 处理 SwFlag：按当前 Bank 选择切换路径
         → 处理 Jtag_log：执行共用的调试开关逻辑
</code></pre>
<p dir="auto"><code>Board_Init()</code> 当前没有检查初始化调用的返回值。串口使用 LINFlexD2，115200、8 数据位、无校验、1 停止位。LED 每隔约 1 秒翻转一次，完整亮灭周期约为 2 秒；按键请求在主循环延时结束后处理。</p>
<h2>3.2 同一份代码如何判断当前启动面</h2>
<p dir="auto"><code>BlockFlag()</code> 的定义为：</p>
<pre><code class="language-C">#define BlockFlag() ((EFM-&gt;STS &amp; EFM_STS_BOOT_INFO_MASK) &gt;&gt; EFM_STS_BOOT_INFO_SHIFT)
#define ABANKFlag   0
#define BBANKFlag   1
</code></pre>
<p dir="auto">该宏读取 <code>EFM-&gt;STS</code> 的 <code>BOOT_INFO</code> 位，将返回值与 <code>ABANKFlag</code>、<code>BBANKFlag</code> 比较。初始化、按键中断、Flash 驱动、NVR 缓冲区和调试开关函数均共用；运行时按当前状态选择 LED 和切换处理。</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>BlockFlag() 返回值</th>
<th>应用状态约定</th>
<th>启动日志</th>
<th>LED 指示</th>
<th>SW2 切换方向</th>
</tr>
</thead>
<tbody>
<tr>
<td>0，即 <code>ABANKFlag</code></td>
<td>当前为 A 面</td>
<td><code>code run in pflash0!</code></td>
<td>PB5，绿色 LED</td>
<td>A→B</td>
</tr>
<tr>
<td>1，即 <code>BBANKFlag</code></td>
<td>当前为 B 面</td>
<td><code>CODE RUN IN PFLASH1!</code></td>
<td>PE8，红色 LED</td>
<td>B→A</td>
</tr>
</tbody>
</table>
<h2>3.3 共用的按键中断与请求标志</h2>
<p dir="auto">SW2 为 PB2 上升沿中断，SW3 为 PC1 上升沿中断，Flash 操作均在主循环执行：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/cd3295b6-c1e4-4645-9b48-f88397258286.png" alt="8c0889d8-cfc0-4635-9f1b-3bf131a2ec17-image.png" class=" img-fluid img-markdown" /><br />
<code>GPIOB_IRQHandler()</code> 检查 PTB2 标志，设置 <code>SwFlag=1</code> 并清除引脚中断标志；<code>GPIOC_IRQHandler()</code> 对 PTC1 执行相同处理，设置 <code>Jtag_log=1</code>。<code>Jtag_log</code> 是调试开关请求标志，并非日志缓冲区。</p>
<h2>3.4 共用的 Disable_Jtag 与 Enable_Jtag</h2>
<h3>3.4.1 Disable_Jtag：先读取整扇区，再修改并写回</h3>
<p dir="auto">当前禁用函数如下图所示：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/48d66c4c-9e2a-4f47-a21f-183fb6e58abf.png" alt="021a06cd-c991-4927-acfa-ab507146d5ee-image.png" class=" img-fluid img-markdown" /></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>顺序</th>
<th>当前操作</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>关闭全局中断</td>
<td>保护本次配置操作</td>
</tr>
<tr>
<td>2</td>
<td>写入 <code>CUS_KEY=0x4DFF32</code></td>
<td>满足受保护 NVR 操作的 Key 条件</td>
</tr>
<tr>
<td>3</td>
<td>从 <code>0x10000400</code> 读取 <code>0x400</code> 字节</td>
<td>将当前整个 1 KB 扇区读入 <code>CUS_NVR_data</code></td>
</tr>
<tr>
<td>4</td>
<td>修改数组索引 2、3</td>
<td>将偏移 <code>0x08</code>、<code>0x0C</code> 的两个 32 位字设为 <code>0x5A5A5A5A</code>（禁用调试口操作）</td>
</tr>
<tr>
<td>5</td>
<td>擦除 <code>0x10000400</code> 扇区</td>
<td>为重新编程准备目标区域</td>
</tr>
<tr>
<td>6</td>
<td>从扇区起始地址编程 <code>0x400</code> 字节</td>
<td>将修改后的整个缓冲区写回</td>
</tr>
<tr>
<td>7</td>
<td>恢复全局中断</td>
<td>结束本次配置操作</td>
</tr>
</tbody>
</table>
<p dir="auto"><code>FEATURE_EFM_NVR_ARRAY_SECTOR_SIZE=0x400</code>，缓冲区为 <code>volatile uint32_t CUS_NVR_data[256]</code>。逻辑修改范围是调试字段的 8 字节，实际读取和编程范围均为整个 1 KB 扇区。</p>
<p dir="auto">在读取、擦除和编程均成功的条件下，函数可以保留CUSNVR中写保护和BootSwap配置</p>
<h3>3.4.2 Enable_Jtag：将调试字段改为全 1 后整扇区写回</h3>
<p dir="auto">当前启用函数如下：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/355cb35a-675b-42ce-9627-9c1038fddc86.png" alt="d4f58b9f-6df4-4bb9-be2a-6f6990abcb06-image.png" class=" img-fluid img-markdown" /></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>顺序</th>
<th>当前操作</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>关闭全局中断</td>
<td>保护本次配置操作</td>
</tr>
<tr>
<td>2</td>
<td>写入 <code>CUS_KEY=0x4DFF32</code></td>
<td>满足受保护 NVR 操作的 Key 条件</td>
</tr>
<tr>
<td>3</td>
<td>从 <code>0x10000400</code> 读取 <code>0x400</code> 字节</td>
<td>将当前整个 1 KB 扇区读入 <code>CUS_NVR_data</code></td>
</tr>
<tr>
<td>4</td>
<td>修改数组索引 2、3</td>
<td>将偏移 <code>0x08</code>、<code>0x0C</code> 的两个 32 位字设为 <code>0xFFFFFFFF</code>（启用调试口操作）</td>
</tr>
<tr>
<td>5</td>
<td>擦除 <code>0x10000400</code> 扇区</td>
<td>为重新编程准备目标区域</td>
</tr>
<tr>
<td>6</td>
<td>从扇区起始地址编程 <code>0x400</code> 字节</td>
<td>将修改后的整个缓冲区写回</td>
</tr>
<tr>
<td>7</td>
<td>恢复全局中断</td>
<td>结束本次配置操作</td>
</tr>
</tbody>
</table>
<p dir="auto">在读取、擦除和编程均成功的条件下，函数可以保留CUSNVR中写保护和BootSwap配置</p>
<h2>3.5 A 面处理：切换后直接复位，不重建调试禁用字段</h2>
<p dir="auto"><img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/49bf3e78-32bc-4b65-8ab3-d077eea73c1d.png" alt="435507b6-5c22-40b2-9146-eff17afa813b-image.png" class=" img-fluid img-markdown" /><br />
SW2 请求进入主循环后，先执行 <code>SwFlag=0</code>。当 <code>BlockFlag()==ABANKFlag</code> 时，进入 A 面分支：</p>
<p dir="auto">当前执行顺序为：</p>
<ol>
<li>
<p dir="auto">调用 <code>FLASH_DRV_BootSwap(FLASH_INST)</code>，其中 <code>FLASH_INST=0</code>。</p>
</li>
<li>
<p dir="auto">若返回 <code>STATUS_SUCCESS</code>，立即调用 <code>SystemSoftwareReset()</code>。</p>
</li>
<li>
<p dir="auto">若返回非成功，打印 <code>Boot swap failed, status: ...</code>。</p>
</li>
<li>
<p dir="auto">失败路径随后仍会执行 SW2 处理末尾共用的 <code>SystemSoftwareReset()</code>。</p>
</li>
</ol>
<p dir="auto"><strong>A 面分支没有调用 <strong><strong><code>Disable_Jtag()</code></strong></strong>，切换后直接请求复位。</strong> 原因是正常 A→B 场景的切换前 <code>BOOT_INFO=0</code>，不满足手册所述“<code>BOOT_INFO=1</code> 时正常 Boot Swap 擦除 CUS_NVR”的条件，所以没有采用 B 面同样的正常切换补偿。</p>
<h2>3.6 B 面处理：切换后按条件重建调试禁用字段，再复位</h2>
<p dir="auto">当 <code>BlockFlag()==BBANKFlag</code> 时，进入 B 面分支：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/4f3d009d-0653-4612-872b-df74c998d092.png" alt="cb053016-e145-4553-b22e-b2c546435f53-image.png" class=" img-fluid img-markdown" /><br />
当前执行顺序为：</p>
<ol>
<li>
<p dir="auto">调用 <code>FLASH_DRV_BootSwap(0)</code>。</p>
</li>
<li>
<p dir="auto">切换命令返回后，判断 <code>EFM-&gt;CTRL_OVRD==0x02</code>。</p>
</li>
<li>
<p dir="auto">条件成立时，调用共用的 <code>Disable_Jtag()</code>，重新写入调试禁用配置。</p>
</li>
<li>
<p dir="auto">执行 SW2 处理末尾共用的 <code>SystemSoftwareReset()</code>。</p>
</li>
</ol>
<p dir="auto"><strong>B 面比 A 面多了一步“切换后、复位前重建调试禁用配置”。</strong> 这是因为 B→A 的切换前 <code>BOOT_INFO=1</code>，正常 Boot Swap 本身就会擦除 CUS_NVR。原禁用字段一旦被清除，直接复位就不能依靠原 NVR 值保持禁用状态，因此需要在切换命令结束后重新写入。</p>
<p dir="auto">调用顺序是关键：</p>
<pre><code class="language-Plaintext">A 面：BlockFlag() == 0
    → Boot Swap
    → 请求软件复位

B 面：BlockFlag() == 1
    → Boot Swap（该状态下会擦除 CUS_NVR）
    → CTRL_OVRD == 0x02 时调用 Disable_Jtag()
         读取切换后的整个扇区
         修改调试禁用字段
         擦除并整扇区写回
    → 请求软件复位
</code></pre>
<p dir="auto">如果先写禁用值，再执行会擦除 CUS_NVR 的切换命令，刚写入的值仍可能被清除。因此，补偿必须放在切换之后、复位之前。若切换返回时 <code>CTRL_OVRD</code> 不等于 <code>0x02</code>，当前 B 面分支跳过补偿，直接请求复位。</p>
<h2>3.7 两条切换路径的差异汇总</h2>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>对比项</th>
<th>A 面分支</th>
<th>B 面分支</th>
</tr>
</thead>
<tbody>
<tr>
<td>入口条件</td>
<td><code>BlockFlag()==ABANKFlag</code>，即 0</td>
<td><code>BlockFlag()==BBANKFlag</code>，即 1</td>
</tr>
<tr>
<td>预期切换方向</td>
<td>A→B</td>
<td>B→A</td>
</tr>
<tr>
<td>调用接口</td>
<td><code>FLASH_DRV_BootSwap(``0``)</code></td>
<td><code>FLASH_DRV_BootSwap(0)</code></td>
</tr>
<tr>
<td>执行BootSwap命令下的 CUS_NVR 擦除条件</td>
<td>不满足 <code>BOOT_INFO=1</code> 条件</td>
<td>满足该条件，会擦除</td>
</tr>
<tr>
<td>切换后调试禁用补偿&lt;br&gt;</td>
<td>不调用</td>
<td><code>CTRL_OVRD==0x02</code> 时调用 <code>Disable_Jtag()</code></td>
</tr>
<tr>
<td>复位前操作</td>
<td>直接复位；失败时先打印错误</td>
<td>先判断并按条件补偿，再复位</td>
</tr>
</tbody>
</table>
<p dir="auto">两条路径共用请求标志、NVR 缓冲区、调试开关函数及 Flash 驱动。<strong>主要区别来自切换前的硬件 Bank 状态，以及 B→A 擦除 CUS_NVR 后增加的补偿操作。</strong></p>
<h3>3.7.1 补偿能恢复什么</h3>
<p dir="auto"><code>Disable_Jtag()</code> 会保留调用时读到的其他字段，但 B 面补偿中的读取发生在 Boot Swap 之后。若切换前的地址保护等配置已经被擦除，函数无法从切换后的 NVR 恢复其原值。</p>
<p dir="auto">当前实现重建的是调试禁用字段，没有在切换前备份并恢复全部 CUS_NVR 配置。此外，补偿依据切换后的整个 <code>CTRL_OVRD</code> 值是否恰好为 <code>0x02</code>，没有提前保存调试策略，也没有只按 bit 1 掩码判断。</p>
<h2>3.8 SW3 触发的调试开关：A/B 面共用相同流程</h2>
<p dir="auto">SW3 处理没有使用 <code>BlockFlag()</code> 分支，而是清除 <code>Jtag_log</code> 后，直接依据 <code>CTRL_OVRD</code> 执行相同逻辑：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/5a5d671c-d52c-4f12-b9b3-c293f0af4c3e.png" alt="11a0f5a9-6418-44b2-9f85-1ba7d65e4b47-image.png" class=" img-fluid img-markdown" /></p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>条件</th>
<th>当前操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CTRL_OVRD==0x00</code></td>
<td>打印禁用信息，调用 <code>Disable_Jtag()</code>，打印 SUCCESS，然后软件复位</td>
</tr>
<tr>
<td><code>CTRL_OVRD==0x02</code></td>
<td>打印启用信息，调用 <code>Enable_Jtag()</code>，打印 SUCCESS，然后软件复位</td>
</tr>
<tr>
<td>其他值</td>
<td>本次调试开关请求不执行配置操作或复位</td>
</tr>
</tbody>
</table>
<h1>4.测试验证</h1>
<h2>4.1 将程序烧录到 PFlash0</h2>
<h3>4.1.1 加载当前工程编译产物</h3>
<p dir="auto">将当前工程编译生成的镜像加载到 J-Flash。当前程序按逻辑地址 <code>0x00000000</code> 链接，可将同一编译产物分别烧录到两个物理 Bank，运行时由 <code>BlockFlag()</code> 区分当前启动面。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/fb9f87b2-6d4a-45fd-a9aa-0e36cb951b9e.png" alt="8167a51b-8439-4786-85bf-6685e53c9b87-image.png" class=" img-fluid img-markdown" /></p>
<h3>4.1.2 擦除并烧录 PFlash0</h3>
<p dir="auto">在初始调试连接可用、Bank 映射为默认状态时，先完成芯片擦除，再把当前镜像烧录到 PFlash0。擦除和编程命令以当前 J-Flash 版本及配置为准。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/32f20e89-d7a9-4b05-a209-36d8864e0599.png" alt="986c1f07-a7e6-4696-8b3a-4917c4c1b432-image.png" class=" img-fluid img-markdown" /><br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/b450aecc-883c-4189-bbc4-0ef179b8b10d.png" alt="e18a293c-3979-4c46-bb22-776367b9dc5f-image.png" class=" img-fluid img-markdown" /></p>
<h2>4.2 将同一程序烧录到 PFlash1</h2>
<h3>4.2.1 设置地址偏移</h3>
<p dir="auto">《YTM32B1MD1x_DS》说明 PFlash 总大小为 512 KB，由两个 256 KB Block 组成；当前 SDK 定义的主 Flash 地址范围为 <code>0x00000000～0x0007FFFF</code>。</p>
<p dir="auto">使用同一份按零地址链接的镜像。在默认 Bank 映射下，将镜像的烧录地址整体偏移 <code>0x00040000</code>，使其放入 PFlash1。这里修改的是烧录位置，不是将代码重新链接到 <code>0x00040000</code>；已处于交换映射时需先核对当前物理 Bank 对应关系。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/c6bb61a3-61ad-4a06-98ed-4466bd7608f8.png" alt="467557d4-1472-42e7-8465-87d857d3d08d-image.png" class=" img-fluid img-markdown" /><br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/82fdc01a-c7c7-4cfa-99fc-da018ce2ab2d.png" alt="e8bf99e9-673d-487c-9bc8-d34fb74ade71-image.png" class=" img-fluid img-markdown" /><br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/bff5d0a0-2ea2-4a08-b60a-b0c0912d5b78.png" alt="3a069f19-3290-4126-8743-b4a3bc04c1aa-image.png" class=" img-fluid img-markdown" /></p>
<h3>4.2.2 烧录 PFlash1</h3>
<p dir="auto">完成 PFlash1 烧录，保留已经写入 PFlash0 的程序，避免在此步骤再次整片擦除。<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/1d35bc2d-ba1c-4d1f-a365-9a2b65eb0169.png" alt="f41d13d2-8a3d-4f7f-9d67-e50c5db3a796-image.png" class=" img-fluid img-markdown" /></p>
<h2>4.3 重新上电与基本操作</h2>
<ul>
<li>
<p dir="auto"><code>BlockFlag()==0</code> 时，程序按 A 面逻辑运行，PB5 绿灯约每 1 秒翻转一次。</p>
</li>
<li>
<p dir="auto"><code>BlockFlag()==1</code> 时，同一程序按 B 面逻辑运行，PE8 红灯约每 1 秒翻转一次。</p>
</li>
<li>
<p dir="auto">按 SW2 切换执行BootSwap操作，切换程序的启动面。</p>
</li>
<li>
<p dir="auto">按 SW3 切换调试口的状态。</p>
</li>
</ul>
<p dir="auto">串口打印数据如下：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/d888a821-65b1-43a9-bfd1-ddbbd6550414.png" alt="2230ae93-589b-4c89-936e-543dd7f47dc3-image.png" class=" img-fluid img-markdown" /></p>
<h1>项目代码</h1>
<p dir="auto"><a href="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/bc80755c-b126-49a7-80c3-be598ab24b9e.zip" rel="nofollow ugc">project.zip</a></p>
]]></description><link>https://forum.ytmicro.com/topic/2295/md14-bootswap与disjtag组合使用方案</link><generator>RSS for Node</generator><lastBuildDate>Wed, 14 Oct 2026 04:22:23 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/2295.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 14 Oct 2026 02:42:18 GMT</pubDate><ttl>60</ttl></channel></rss>