<?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[etmr mask寄存器软件触发偶发不更新问题]]></title><description><![CDATA[<h1>1.问题背景</h1>
<ol>
<li>软件：SDK1_4_1版本及之前版本</li>
<li>硬件：YTM32B1系列</li>
<li>问题描述：<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/168aa5f4-9aa3-4b3d-a307-66a7f8af235d.png" alt="29f7e312-1bdd-4491-87e8-1dc050315286-image.png" class=" img-fluid img-markdown" /></li>
</ol>
<p dir="auto">执行软件触发mask更新操作时，偶发出现 PWM 通道波形无变化，写入的 CHMASK 值未生效</p>
<h1>2. 问题分析</h1>
<h2>2.1 代码分析</h2>
<h3>2.1.1 chmask软件触发更新驱动代码</h3>
<p dir="auto"><code>eTMR_DRV_SetChnOutMask()</code> 根据 <code>softwareTrigger</code> 选择 CHMASK 的加载方式。软件触发分支会暂存原有加载配置，设置软件触发源，写入新的 CHMASK 值并触发加载，最后恢复原配置；另一分支则随寄存器同步加载。</p>
<pre><code class="language-C++">status_t eTMR_DRV_SetChnOutMask(uint32_t instance, uint8_t maskEn, uint16_t maskVal, bool softwareTrigger)
{
    DEV_ASSERT(instance &lt; eTMR_INSTANCE_COUNT);
    eTMR_Type *etmrBase = g_etmrBase[instance];
    etmr_sync_trig_src_t trigSrc;
    etmr_mask_sync_sel_t opportunity;
    eTMR_ClearLdok(etmrBase);

    if (softwareTrigger)
    {
        /* keep mask loading trigger source */
        trigSrc = (etmr_sync_trig_src_t)eTMR_GetMaskLoadTrigSrc(etmrBase);
        /* keep mask loading opportunity */
        opportunity = (etmr_mask_sync_sel_t)eTMR_GetMaskLoadOpportunity(etmrBase);
        /* select CHMASK loading trigger source */
        eTMR_SetMaskLoadTrigSrc(etmrBase, SW_TRIGGER);
        /* select CHMASK loading opportunity */
        eTMR_SetMaskLoadOpportunity(etmrBase, CHMASK_SYNC_WITH_TRIG);
    }
    else // sync with register loading
    {
        /* select CHMASK loading trigger source */
        eTMR_SetMaskLoadTrigSrc(etmrBase, DISABLE_TRIGGER);
        /* select CHMASK loading opportunity */
        eTMR_SetMaskLoadOpportunity(etmrBase, CHMASK_SYNC_WITH_REG);
    }
    /* set channel Mask enable and value */
    eTMR_SetChnOutMask(etmrBase, maskVal, maskEn);
    /* set ldok */
    eTMR_SetLdok(etmrBase);

    if (softwareTrigger)
    {
        /* generate one bus clock cycle pulse trigger */
        eTMR_GenSoftwareTrigger(etmrBase, true);
        /* restore CHMASK loading trigger source */
        eTMR_SetMaskLoadTrigSrc(etmrBase, trigSrc);
        /* restore CHMASK loading opportunity */
        eTMR_SetMaskLoadOpportunity(etmrBase, opportunity);
    }

    return STATUS_SUCCESS;
}
</code></pre>
<p dir="auto"><img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/0428090e-baff-4974-9316-52b0788b4082.png" alt="2d4f461f-3243-4d04-b11e-76ced0fcd753-image.png" class=" img-fluid img-markdown" /></p>
<h3>2.1.2 软件触发路径的寄存器写入顺序</h3>
<p dir="auto">在 softwareTrigger 为 true 的分支中，与 CHMASK 加载直接相关的寄存器写入可概括为以下四步：</p>
<pre><code class="language-Plaintext">① eTMR0-&gt;SYNC |= CLDOK;     // 清 LDOK，锁定本次加载
② eTMR0-&gt;CHMASK = ...;       // 写入新值（暂存 buffer）
③ eTMR0-&gt;SYNC |= LDOK;       // 置 LDOK，允许加载
④ eTMR0-&gt;SYNC |= SWTRIG;     // 软件触发，将 CHMASK 从 buffer 载入输出
</code></pre>
<p dir="auto">LDOK 是"加载许可"标志：只有 LDOK=1 时，软件触发才能将 CHMASK buffer 载入实际输出。一次加载完成或到达 MOD 加载点后，硬件自动将 LDOK 清零。</p>
<h3>2.1.3 失效场景的 SYNC 配置：</h3>
<p dir="auto">在本次失效场景中，软件触发已启用（softwareTrigger=true），SYNC 寄存器的相关位域如下：</p>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>SYNC 寄存器位域</th>
<th>配置值</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>REGLD</code>[7:6]</td>
<td>0x01</td>
<td>REG 寄存器（VAL0/VAL1/MOD 等）在 CNT 到达 MOD 点时加载</td>
</tr>
<tr>
<td><code>MASKLD</code>[15:14]</td>
<td>0x01</td>
<td>CHMASK 寄存器仅在触发源到来时加载</td>
</tr>
<tr>
<td><code>TRIGS2</code>[13:12]</td>
<td>0x01</td>
<td>CHMASK 加载触发源 = 软件触发（写<code>SYNC[16] SWTRIG</code>）</td>
</tr>
</tbody>
</table>
<p dir="auto">关键点：<strong><code>REGLD[7:6]</code><strong><strong>=01（MOD 同步），</strong></strong><code>MASKLD[15:14]</code></strong> <strong>=01（触发同步）</strong>。这意味着 MOD 点会加载 REG 并清零 <code>LDOK[0]</code>，但<strong>不会加载 CHMASK</strong>（CHMASK 只等 <code>SWTRIG[16]</code> 软件触发）。</p>
<h2>2.2 问题原因</h2>
<p dir="auto"><img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/9657f7d8-ca54-415c-85d8-58cd580e9e9d.png" alt="9a2c7c57-b28a-443d-857d-e33ac8266b38-image.png" class=" img-fluid img-markdown" /></p>
<ul>
<li>
<p dir="auto"><strong>正常段：</strong> SWTRIG 发生在 CNT 到达 MOD 之前。此时 LDOK 仍为 1，缓冲区中的 CHMASK 新值随软件触发加载为生效值，输出开始使用新掩码；本次加载完成后 LDOK 清零。</p>
</li>
<li>
<p dir="auto"><strong>失效段：</strong> 置位 LDOK 后，CNT 先到达 MOD。该时刻 REG 按配置加载并清零 LDOK，而配置为触发加载的 CHMASK 仍停留在缓冲区。随后 SWTRIG 到来时 LDOK 已为 0，新的 CHMASK 不能成为生效值，输出继续使用旧掩码。</p>
</li>
</ul>
<h1>3. 规避方案</h1>
<h2>3.1 修复方案：合并 LDOK 与 SWTRIG 写操作（最小改动，推荐优先实施）</h2>
<p dir="auto"><img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/47a21991-883d-46ea-b20f-eaef7141d110.png" alt="d7a7bf05-6e61-4211-9443-6222b205c79b-image.png" class=" img-fluid img-markdown" /></p>
<ul>
<li>
<p dir="auto">优点：改动最小，消除 CPU 周期级竞态窗口</p>
</li>
<li>
<p dir="auto">局限：理论上仍存在硬件内部 LDOK 置位与 SWTRIG 处理之间的极短窗口（纳秒级），实际几乎不可触发</p>
</li>
</ul>
<h2>3.2 修复方案波形测试记录</h2>
<p dir="auto"><img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/545/ccd180f4-e537-4b8c-9098-4823153f4fe7.png" alt="c085020d-868f-4c44-a2fa-7888f43ba10b-image.png" class=" img-fluid img-markdown" /></p>
<h2>3.3 测试例程</h2>
]]></description><link>https://forum.ytmicro.com/topic/2268/etmr-mask寄存器软件触发偶发不更新问题</link><generator>RSS for Node</generator><lastBuildDate>Mon, 28 Sep 2026 22:50:32 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/2268.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 28 Sep 2026 06:53:38 GMT</pubDate><ttl>60</ttl></channel></rss>