etmr mask寄存器软件触发偶发不更新问题
-
1.问题背景
- 软件:SDK1_4_1版本及之前版本
- 硬件:YTM32B1系列
- 问题描述:

执行软件触发mask更新操作时,偶发出现 PWM 通道波形无变化,写入的 CHMASK 值未生效
2. 问题分析
2.1 代码分析
2.1.1 chmask软件触发更新驱动代码
eTMR_DRV_SetChnOutMask()根据softwareTrigger选择 CHMASK 的加载方式。软件触发分支会暂存原有加载配置,设置软件触发源,写入新的 CHMASK 值并触发加载,最后恢复原配置;另一分支则随寄存器同步加载。status_t eTMR_DRV_SetChnOutMask(uint32_t instance, uint8_t maskEn, uint16_t maskVal, bool softwareTrigger) { DEV_ASSERT(instance < 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; }
2.1.2 软件触发路径的寄存器写入顺序
在 softwareTrigger 为 true 的分支中,与 CHMASK 加载直接相关的寄存器写入可概括为以下四步:
① eTMR0->SYNC |= CLDOK; // 清 LDOK,锁定本次加载 ② eTMR0->CHMASK = ...; // 写入新值(暂存 buffer) ③ eTMR0->SYNC |= LDOK; // 置 LDOK,允许加载 ④ eTMR0->SYNC |= SWTRIG; // 软件触发,将 CHMASK 从 buffer 载入输出LDOK 是"加载许可"标志:只有 LDOK=1 时,软件触发才能将 CHMASK buffer 载入实际输出。一次加载完成或到达 MOD 加载点后,硬件自动将 LDOK 清零。
2.1.3 失效场景的 SYNC 配置:
在本次失效场景中,软件触发已启用(softwareTrigger=true),SYNC 寄存器的相关位域如下:
SYNC 寄存器位域 配置值 含义 REGLD[7:6]0x01 REG 寄存器(VAL0/VAL1/MOD 等)在 CNT 到达 MOD 点时加载 MASKLD[15:14]0x01 CHMASK 寄存器仅在触发源到来时加载 TRIGS2[13:12]0x01 CHMASK 加载触发源 = 软件触发(写 SYNC[16] SWTRIG)关键点:
REGLD[7:6]=01(MOD 同步),MASKLD[15:14]=01(触发同步)。这意味着 MOD 点会加载 REG 并清零LDOK[0],但不会加载 CHMASK(CHMASK 只等SWTRIG[16]软件触发)。2.2 问题原因

-
正常段: SWTRIG 发生在 CNT 到达 MOD 之前。此时 LDOK 仍为 1,缓冲区中的 CHMASK 新值随软件触发加载为生效值,输出开始使用新掩码;本次加载完成后 LDOK 清零。
-
失效段: 置位 LDOK 后,CNT 先到达 MOD。该时刻 REG 按配置加载并清零 LDOK,而配置为触发加载的 CHMASK 仍停留在缓冲区。随后 SWTRIG 到来时 LDOK 已为 0,新的 CHMASK 不能成为生效值,输出继续使用旧掩码。
3. 规避方案
3.1 修复方案:合并 LDOK 与 SWTRIG 写操作(最小改动,推荐优先实施)

-
优点:改动最小,消除 CPU 周期级竞态窗口
-
局限:理论上仍存在硬件内部 LDOK 置位与 SWTRIG 处理之间的极短窗口(纳秒级),实际几乎不可触发
3.2 修复方案波形测试记录

3.3 测试例程
快速上手云途开发生态
发帖前请查看
帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...