cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with multiple HRTIMER synced operation due to missing HRTIMER updates

DBein
Associate III

​We found a weird behavior on the STM32F334 device:

The requirement is to have 2 HRTIMER's which are locked in phase to generate output PWM's.

Currently we use HRTIMER1A and HRTIMER1B for the PWM's. The master timer is used to generate reset on MST period event.

The problem we found, is that sometimes the registers seem not to be updated.

It is really weird, but can be seen on all our devices, therefore it has to be something with the configuration.

Details about the configuration:

HRTIMERA and HRTIMERB uses CMP1,2,3,4 to generate PWM pulses on the two outputs.

HRTIMERMST and HRTIMERA and B have all the same clock with pre-scaler of 8.

All timers use the same period (period is changing constantly during operation).

All timers have preload enabled:

HRTIM_TimerCfg.PreloadEnable = HRTIM_PRELOAD_ENABLED;

HRTIMERA and B have update on roll over enabled:

HRTIM_TimerCfg.RepetitionUpdate = HRTIM_UPDATEONREPETITION_ENABLED;

HRTIMERMST is used to generate HRTIMERA and B reset with update enable:

HRTIM_TimerCfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_MASTER_PER;

HRTIM_TimerCfg.ResetUpdate = HRTIM_TIMUPDATEONRESET_ENABLED;

For the timer register update I turn off all TIMER updates to write multiple registers:

#define MG_REG_HRTIMER1_UPDATE_EN (HRTIM1->sCommonRegs.CR1 &= ~(HRTIM_CR1_MUDIS | HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))

#define MG_REG_HRTIMER1_UPDATE_DIS (HRTIM1->sCommonRegs.CR1 |= (HRTIM_CR1_MUDIS | HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))

MG_REG_HRTIMER1_UPDATE_DIS;

//Write registers here.....

MG_REG_HRTIMER1_UPDATE_EN;

What is happening now, is that when I read back the period registers PERxR I can see that they change constantly, however the applied frequency of output PWM stays the same. This happens sporadically and not all the time, but randomly over time. It is enought to cause a serious PWM displacement which will cause a device fail / shutdown.

The PWM's stay in phase, but the missing update is a serious problem!

Right now I found a working setup, BUT it can't be the final solution, cuz it has drawbacks.It's just good enough to keep our devices running without fail, but it causes component stress which we need to avoid.

When I do not stop the MST update, the HRTIMER's will be always updated with the prelaoded values. But it can happen, that the MST timer is out of sync for one cycle which can cause the duty cycle to be incorrect for this particular cycle.

Only disable HRTIMERA and B update:

#define MG_REG_HRTIMER1_UPDATE_EN (HRTIM1->sCommonRegs.CR1 &= ~(HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))

#define MG_REG_HRTIMER1_UPDATE_DIS (HRTIM1->sCommonRegs.CR1 |= (HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))

1 ACCEPTED SOLUTION

Accepted Solutions
DBein
Associate III

​Possibly an application issue. I found that the ISR frequency matches the frequency of the PWM when the issue happens. Possibly the ISR register update disable and period events are in phase and therefore no update is happening until a phase missmatch occurs.

View solution in original post

6 REPLIES 6
DBein
Associate III

Here the most important code snippets.

Please let me know if any further questions.

#define MG_REG_HRTIMER1_UPDATE_EN       (HRTIM1->sCommonRegs.CR1 &= ~(HRTIM_CR1_MUDIS | HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))
#define MG_REG_HRTIMER1_UPDATE_DIS      (HRTIM1->sCommonRegs.CR1 |= (HRTIM_CR1_MUDIS | HRTIM_CR1_TAUDIS | HRTIM_CR1_TBUDIS))
 
#define MG_REG_HRTIMER1_MST_PERIOD      (HRTIM1->sMasterRegs.MPER)
#define MG_REG_HRTIMER1_A_PERIOD        (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].PERxR)
#define MG_REG_HRTIMER1_B_PERIOD        (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].PERxR)
 
#define MG_REG_HRTIMER1_A_CMP1          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP1xR)
#define MG_REG_HRTIMER1_A_CMP2          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP2xR)
#define MG_REG_HRTIMER1_A_CMP3          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP3xR)
#define MG_REG_HRTIMER1_A_CMP4          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].CMP4xR)
 
#define MG_REG_HRTIMER1_B_CMP1          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].CMP1xR)
#define MG_REG_HRTIMER1_B_CMP2          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].CMP2xR)
#define MG_REG_HRTIMER1_B_CMP3          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].CMP3xR)
#define MG_REG_HRTIMER1_B_CMP4          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].CMP4xR)
 
#define MG_REG_HRTIMER1_E_CMP2          (HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_E].CMP2xR)
 
/** *****************************************************************************
 * \brief         Primary side LLC half bridge drive: Set period, determine compare values from duty cycle, set dead time
 *
 * \param[in]     Period in ns, duty cycle as Q16, dead time in ns
 * \param[in,out] -
 * \param[out]    -
 *
 * \return        -
 *
 ***************************************************************************** */
#pragma location = ".ccmram"
inline void HRTIMER_vHrTimerSetPwmCcRam(uint32 u321nsHrTimerPeriod, uint16 u16q16DutyCycle, uint16 u161nSLlcDeadTime, sint16 s161nsSrDeadTimeOn, sint16 s161nsSrDeadTimeOff)
{
  uint16 u16PwmPeriod;
  uint32 u32PwmHalfPeriod;
  uint16 u16PwmQuarterPeriod;
  sint32 s32LlcPwmOnTime;
  sint32 s32LlcPwmOn;
  sint32 s32LlcPwmOff;
  sint32 s32LlcPwmOn2;
  sint32 s32LlcPwmOff2;
  uint16 u16LlcPwmDeadTime;
  sint32 s32SrPwmOn;
  sint32 s32SrPwmOff;
  sint32 s32SrPwmOn2;
  sint32 s32SrPwmOff2;
  sint32 s32SrPwmDeadTimeOn;
  sint32 s32SrPwmDeadTimeOff;
 
  /*******************************************************************************
   * Determine period, duty cycle and dead time
   *******************************************************************************/
  /* Scale ns to timer value */
  u16PwmPeriod = ((mg_u32q12nsTimerMstConvFact * u321nsHrTimerPeriod) >> 12); 
  /* Scale ns to timer value */
  u16LlcPwmDeadTime = ((mg_u32q12nsTimerMstConvFact * u161nSLlcDeadTime) >> 12);
  u16LlcPwmDeadTime = SAT_L(u16LlcPwmDeadTime, (uint16)100U);
  /* Scale ns to timer value */
  s32SrPwmDeadTimeOn = (((sint32)mg_u32q12nsTimerMstConvFact * s161nsSrDeadTimeOn) >> 12); 
  /* Scale ns to timer value */
  s32SrPwmDeadTimeOff = (((sint32)mg_u32q12nsTimerMstConvFact * s161nsSrDeadTimeOff) >> 12);
 
  /* Get half and quarter period for further processing */
  u32PwmHalfPeriod = (u16PwmPeriod >> 1);
  u16PwmQuarterPeriod = (u16PwmPeriod >> 2);
 
  /* Limit the duty cycle to 0.49998474 */
  u16q16DutyCycle = SAT_H(u16q16DutyCycle, 32767);
 
  /* Determine LLC on time, half of the on time */
  s32LlcPwmOnTime = ((uint32)u32PwmHalfPeriod * u16q16DutyCycle) >> 16;
  /* Determine LLC turn on */
  s32LlcPwmOn = u16PwmQuarterPeriod - s32LlcPwmOnTime;
  s32LlcPwmOn = SAT_L(s32LlcPwmOn, u16LlcPwmDeadTime);
  /* Determine LLC turn off */
  s32LlcPwmOff = u32PwmHalfPeriod - s32LlcPwmOn;
  /* TA2 on setup */
  s32LlcPwmOn2 = (uint16)(s32LlcPwmOn + u32PwmHalfPeriod);
  /* TA2 off setup */
  s32LlcPwmOff2 = (uint16)(s32LlcPwmOff + u32PwmHalfPeriod);
 
  /* Determine SR turn on */
  s32SrPwmOn = s32LlcPwmOn + s32SrPwmDeadTimeOn;
  s32SrPwmOn = LIMIT(s32SrPwmOn, 100, s32LlcPwmOff);  /* 100 for minimum compare value (HRTIMER limitation) and minimum forced dead time; NOTE: do not change!!! */
  /* Determine SR turn off */
  s32SrPwmOff = s32LlcPwmOff - s32SrPwmDeadTimeOff;
  s32SrPwmOff = LIMIT(s32SrPwmOff, s32SrPwmOn, (sint32)u32PwmHalfPeriod); 
  /* TB2 on setup */
  s32SrPwmOn2 = (uint16)(s32SrPwmOn + u32PwmHalfPeriod);
  /* TB2 off setup */
  s32SrPwmOff2 = (uint16)(s32SrPwmOff + u32PwmHalfPeriod);
 
  /* Disable repetition update */
  MG_REG_HRTIMER1_UPDATE_DIS;
 
  /* Write new period values */
  MG_REG_HRTIMER1_MST_PERIOD = u16PwmPeriod;
  MG_REG_HRTIMER1_A_PERIOD = u16PwmPeriod;
  MG_REG_HRTIMER1_B_PERIOD = u16PwmPeriod;
 
  /* Due to push-pull mode, both outputs share the same compares */
  /* Set the compare 1 value (output A1 high) */
  MG_REG_HRTIMER1_A_CMP1 = s32LlcPwmOn;
  /* Set the compare 2 value (output A1 low) */
  MG_REG_HRTIMER1_A_CMP2 = s32LlcPwmOff;
  /* Set the compare 1 value (output A2 high) */
  MG_REG_HRTIMER1_A_CMP3 = s32LlcPwmOn2;
  /* Set the compare 2 value (output A2 low) */
  MG_REG_HRTIMER1_A_CMP4 = s32LlcPwmOff2;
 
  /* Due to push-pull mode, both outputs share the same compares */
  /* Set the compare 1 value (output B1 high) */
  MG_REG_HRTIMER1_B_CMP1 = s32SrPwmOn;
  /* Set the compare 2 value (output B1 low) */
  MG_REG_HRTIMER1_B_CMP2 = s32SrPwmOff;
 
  /* Set the compare 1 value (output B2 high) */
  MG_REG_HRTIMER1_B_CMP3 = s32SrPwmOn2;
  /* Set the compare 2 value (output B2 low) */
  MG_REG_HRTIMER1_B_CMP4 = s32SrPwmOff2;
 
  /* Set windowing for SR pulse detection */
  MG_REG_HRTIMER1_E_CMP2 = u32PwmHalfPeriod;
 
  /* Enable repetition update */
  MG_REG_HRTIMER1_UPDATE_EN;
}

DBein
Associate III
/** *****************************************************************************
 * \brief         Initialize the high resolution common setup
 *
 * \param[in]     -
 * \param[in,out] -
 * \param[out]    -
 *
 * \return        -
 *
 ***************************************************************************** */
static void HRTIMER_vHrTimerCommonInit(void)
{
  /***********************************************
   * High Resolution Timer
   * HRTIM global initialization: Clock, DLL init
   **********************************************/
  /* Enable HRTIM peripheral clock */
  __HAL_RCC_HRTIM1_CLK_ENABLE();
 
  /* Config HRTIMER */
  hhrtim1.Instance = HRTIM1;
  hhrtim1.Init.HRTIMInterruptResquests = HRTIM_IT_NONE;
  hhrtim1.Init.SyncOptions = HRTIM_SYNCOPTION_NONE;
  /* Init HRTIMER */
  HAL_HRTIM_Init(&hhrtim1);
  /* Start DLL calibration */
  HAL_HRTIM_DLLCalibrationStart(&hhrtim1, HRTIM_CALIBRATIONRATE_14);
  HAL_HRTIM_PollForDLLCalibration(&hhrtim1, 10);
}
 
/** *****************************************************************************
 * \brief         Initialize and configure high resolution master timer
 *
 * \param[in]     -
 * \param[in,out] -
 * \param[out]    -
 *
 * \return        -
 *
 ***************************************************************************** */
static void HRTIMER_vHrTimerMasterHwInit(void)
{
  /* Temporary typedefs */
  HRTIM_TimeBaseCfgTypeDef              HRTIM_BaseCfg = {0};   
  HRTIM_TimerCfgTypeDef                 HRTIM_TimerCfg = {0};   
 
  /***********************************************
   * MASTER TIMER
   **********************************************/
  /* PWM period initialized to base value */
  HRTIM_BaseCfg.Period = 0x1FFE;
  /* Repetition counter */
  HRTIM_BaseCfg.RepetitionCounter = 0;
  /* Set prescaler */
  HRTIM_BaseCfg.PrescalerRatio = HRTIM_MST_PRESCALERRATIO;
  /* Set mode to continous */
  HRTIM_BaseCfg.Mode = HRTIM_MODE_CONTINUOUS;
 
  /* Use initialized structure as abse configuration */
  HAL_HRTIM_TimeBaseConfig(&hhrtim1, HRTIM_TIMERINDEX_MASTER, &HRTIM_BaseCfg);
 
  /* Halfmode config */
  HRTIM_TimerCfg.HalfModeEnable = HRTIM_HALFMODE_DISABLED;
  /* Start, reset on sync and DAC sync disabled */
  HRTIM_TimerCfg.StartOnSync = HRTIM_SYNCSTART_DISABLED;
  HRTIM_TimerCfg.ResetOnSync = HRTIM_SYNCRESET_DISABLED;
  HRTIM_TimerCfg.DACSynchro = HRTIM_DACSYNC_NONE;
  /* Set HRTIM to independent updategating */
  HRTIM_TimerCfg.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;
  /* Burst mode maintained from clock */
  HRTIM_TimerCfg.BurstMode = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;
  /* Update on repetition disabled */
  HRTIM_TimerCfg.RepetitionUpdate = HRTIM_UPDATEONREPETITION_ENABLED;
  /* Preload enable (shadow register mode) */
  HRTIM_TimerCfg.PreloadEnable = HRTIM_PRELOAD_ENABLED;
  /* Interrupt requests */
  HRTIM_TimerCfg.InterruptRequests = HRTIM_MASTER_IT_NONE;
  /* DMA configuration */
  HRTIM_TimerCfg.DMARequests = HRTIM_MASTER_DMA_NONE;
  HRTIM_TimerCfg.DMASrcAddress = 0x0000;
  HRTIM_TimerCfg.DMADstAddress = 0x0000;
  HRTIM_TimerCfg.DMASize = 0x1;
 
  /* Use initialized structure for HRTIM waveform generation */
  HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_MASTER, &HRTIM_TimerCfg);
 
  /* Update configuration from preload register to Timer register */
  HRTIM1->sCommonRegs.CR2 |= (MG_HRTIMER1_MASTER_UPDATE);
}

DBein
Associate III
static void HRTIMER_vHrTimerAHwInit(void)
{
  /* Temporary typedefs */
  HRTIM_TimeBaseCfgTypeDef              HRTIM_BaseCfg = {0};        /*lint !e10 !e522 ; Associated with structures from ST libraries */
  HRTIM_TimerCfgTypeDef                 HRTIM_TimerCfg = {0};       
  HRTIM_OutputCfgTypeDef                HRTIM_OutputCfg = {0};      
  HRTIM_CompareCfgTypeDef               HRTIM_CompareCfg = {0};   
  HRTIM_EventCfgTypeDef                 HRTIM_EventCfg = {0};      
  HRTIM_DeadTimeCfgTypeDef              HRTIM_DeadTimeCfg = {0};   
 
  /***********************************************
   * HRTIMER1A
   **********************************************/
  /* PWM period initialized to base value */
  HRTIM_BaseCfg.Period = 0x0FFF;
  /* Repetition counter */
  HRTIM_BaseCfg.RepetitionCounter = 0;
  /* Set prescaler */
  HRTIM_BaseCfg.PrescalerRatio = HRTIM_A_PRESCALERRATIO;
  /* Set mode to continous */
  HRTIM_BaseCfg.Mode = HRTIM_MODE_CONTINUOUS;
  /* Use initialized structure as abse configuration */
  HAL_HRTIM_TimeBaseConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, &HRTIM_BaseCfg);
 
  /* Halfmode config */
  HRTIM_TimerCfg.HalfModeEnable = HRTIM_HALFMODE_DISABLED;
  /* Start, reset on sync and DAC sync disabled */
  HRTIM_TimerCfg.StartOnSync = HRTIM_SYNCSTART_DISABLED;
  HRTIM_TimerCfg.ResetOnSync = HRTIM_SYNCRESET_DISABLED;
  HRTIM_TimerCfg.DACSynchro = HRTIM_DACSYNC_NONE;
  /* Set HRTIM to independent updategating */
  HRTIM_TimerCfg.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;
  /* Burst mode maintained from clock */
  HRTIM_TimerCfg.BurstMode = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;
  /* Update on repetition disabled */
  HRTIM_TimerCfg.RepetitionUpdate = HRTIM_UPDATEONREPETITION_ENABLED;
  /* Preload enable (shadow register mode) */
  HRTIM_TimerCfg.PreloadEnable = HRTIM_PRELOAD_ENABLED;
  /* Use initialized structure for HRTIM waveform generation */
  HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, &HRTIM_TimerCfg);
 
  /* Interrupt requests */
  HRTIM_TimerCfg.InterruptRequests = HRTIM_TIM_IT_NONE;
  /* DMA configuration */
  HRTIM_TimerCfg.DMARequests = HRTIM_TIM_DMA_NONE;
  HRTIM_TimerCfg.DMASrcAddress = 0x0000;
  HRTIM_TimerCfg.DMADstAddress = 0x0000;
  HRTIM_TimerCfg.DMASize = 0x1;
  /* Push-pull disable */
  HRTIM_TimerCfg.PushPull = HRTIM_TIMPUSHPULLMODE_DISABLED;
  /* Fault condition defines */
  HRTIM_TimerCfg.FaultEnable = HRTIM_TIMFAULTENABLE_NONE;
  HRTIM_TimerCfg.FaultLock = HRTIM_TIMFAULTLOCK_READWRITE;
  /* Dead-time insertion disable */
  HRTIM_TimerCfg.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_DISABLED;
  #if ((FALSE == DEBUG_SECTION_PROTECT_DISABLE) && (FALSE == GLOBALDEFINES_HALT_STRIFE))
  /* Delayed protection mode enable */
  HRTIM_TimerCfg.DelayedProtectionMode = HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV6;
  #else
  /* Delayed protection mode disable */
  HRTIM_TimerCfg.DelayedProtectionMode = HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DISABLED;
  #endif
  /* No update trigger */
  HRTIM_TimerCfg.UpdateTrigger = HRTIM_TIMUPDATETRIGGER_NONE;
  /* No timer counter reset trigger */
  HRTIM_TimerCfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_MASTER_PER;
  /* Update timer registers on reset */
  HRTIM_TimerCfg.ResetUpdate = HRTIM_TIMUPDATEONRESET_ENABLED;
  /* Use initialized structure */
  HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, &HRTIM_TimerCfg);
 
  /* Choose polarity to active high */
  HRTIM_OutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
  /* Do nothing in idle mode and set output to inactive in idle and fault state (used only for ST burst mode) */
  HRTIM_OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
  HRTIM_OutputCfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
  HRTIM_OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
  /* Disable chopper mode */
  HRTIM_OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
  /* No delay when entering burst mode */
  HRTIM_OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
  /* Set output high at timer compare 1 */
  HRTIM_OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
  /* Set output low at timer compare 2 */
  HRTIM_OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP2 | HRTIM_OUTPUTRESET_TIMCMP3 | HRTIM_OUTPUTRESET_TIMPER;
  /* Use initialized structure as output configuration for output TA1 */
  HAL_HRTIM_WaveformOutputConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_OUTPUT_TA1, &HRTIM_OutputCfg);
 
  /* Choose polarity to active high */
  HRTIM_OutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
  /* Do nothing in idle mode and set output to inactive in idle and fault state (used only for ST burst mode) */
  HRTIM_OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
  HRTIM_OutputCfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
  HRTIM_OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
  /* Disable chopper mode */
  HRTIM_OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
  /* No delay when entering burst mode */
  HRTIM_OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
  /* Set output high at timer compare 1 */
  HRTIM_OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP3;
  /* Set output low at timer compare 2*/
  HRTIM_OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP4 | HRTIM_OUTPUTRESET_TIMCMP1 | HRTIM_OUTPUTRESET_TIMPER | HRTIM_OUTPUTRESET_MASTERPER;
  /* Use initialized structure as output configuration for output TA2 */
  HAL_HRTIM_WaveformOutputConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_OUTPUT_TA2, &HRTIM_OutputCfg);
 
  /* Auto-delay disabled */
  HRTIM_CompareCfg.AutoDelayedMode = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareCfg.AutoDelayedTimeout = 0;
 
  /*
   * Compare values:
   * NOTE: There are hardware limitations of the HRTIMER (Datasheet: 20.3.4 Timer A..E timing units table 78)
   * Minimum value must be greater than or equal to 3 periods of the fHRTIM clock
   * Maximum value must be less than or equal to 0xFFFF - 1 periods of the fHRTIM clock
   * If these conditions are violated, the related compares will be ignored!
   */
  /* PWM compare value 1 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_1, &HRTIM_CompareCfg);
  /* PWM compare value 2 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_2, &HRTIM_CompareCfg);
  /* PWM compare value 3 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_3, &HRTIM_CompareCfg);
  /* PWM compare value 4 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_4, &HRTIM_CompareCfg);
 
  /* Deadtime clock prescalor */
  HRTIM_DeadTimeCfg.Prescaler = MG_HRTIM_A_DTPRESCALERRATIO;
  /* Deadtime rising value, Bst Mosfet Deadtime */
  HRTIM_DeadTimeCfg.RisingValue = 60U;
  /* Deadtime rising sign */
  HRTIM_DeadTimeCfg.RisingSign = HRTIM_TIMDEADTIME_RISINGSIGN_POSITIVE;
  /* Deadtime rising value lock */
  HRTIM_DeadTimeCfg.RisingLock = HRTIM_TIMDEADTIME_RISINGLOCK_WRITE;
  /* Deadtime rising sign lock */
  HRTIM_DeadTimeCfg.RisingSignLock = HRTIM_TIMDEADTIME_RISINGSIGNLOCK_WRITE;
  /* Deadtime falling value, SR Deadtime*/
  HRTIM_DeadTimeCfg.FallingValue = 60U;
  /* Deadtime falling sign */
  HRTIM_DeadTimeCfg.FallingSign = HRTIM_TIMDEADTIME_RISINGSIGN_POSITIVE;
  /* Deadtime falling value lock */
  HRTIM_DeadTimeCfg.FallingLock = HRTIM_TIMDEADTIME_FALLINGLOCK_WRITE;
  /* Deadtime falling sign lock*/
  HRTIM_DeadTimeCfg.FallingSignLock = HRTIM_TIMDEADTIME_FALLINGSIGNLOCK_WRITE;
 
  /* Use initialized structure for PWMA (TIMER1A CH1 & CH2) Deadtime */
  HAL_HRTIM_DeadTimeConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, &HRTIM_DeadTimeCfg);
  /* Make sure that the DT sign locks are written */
  HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_A].DTxR |= (HRTIM_DTR_DTRSLK | HRTIM_DTR_DTFSLK);
 
  /*
   * Configure external events to reset PWM
   */
  HRTIM_EventCfg.Source = HRTIM_EVENTSRC_2;     /* Select comparators as event source */
  HRTIM_EventCfg.Polarity = HRTIM_EVENTPOLARITY_HIGH;
  HRTIM_EventCfg.Sensitivity = HRTIM_EVENTSENSITIVITY_LEVEL;
  HRTIM_EventCfg.Filter = HRTIM_EVENTFILTER_NONE;
  HRTIM_EventCfg.FastMode = HRTIM_EVENTFASTMODE_DISABLE; /* NOTE: there is/was a bug in ST library: make sure that DISABLE will write register to 0 */
  /* Use initialized structure for HRTIM1 */
  HAL_HRTIM_EventConfig(&hhrtim1, HRTIM_EVENT_6, &HRTIM_EventCfg);  /* Select COMP2 output */
 
  /* Disable TA1 and TA2 outputs to keep rails off */
  hhrtim1.Instance->sCommonRegs.ODISR = (HRTIM_OUTPUT_TA1 | HRTIM_OUTPUT_TA2);
 
  /* Update configuration from preload register to TimerA register */
  hhrtim1.Instance->sCommonRegs.CR2 |= (MG_HRTIMER1_A_UPDATE);  
}

DBein
Associate III
static void HRTIMER_vHrTimerBHwInit(void)
{
  /* Temporary typedefs */
  HRTIM_TimeBaseCfgTypeDef              HRTIM_BaseCfg = {0};  
  HRTIM_TimerCfgTypeDef                 HRTIM_TimerCfg = {0};  
  HRTIM_OutputCfgTypeDef                HRTIM_OutputCfg = {0};  
  HRTIM_CompareCfgTypeDef               HRTIM_CompareCfg = {0}; 
  HRTIM_EventCfgTypeDef                 HRTIM_EventCfg = {0}; 
  HRTIM_DeadTimeCfgTypeDef              HRTIM_DeadTimeCfg = {0};
 
  /***********************************************
   * HRTIMER1B
   **********************************************/
  /* PWM period initialized to base value */
  HRTIM_BaseCfg.Period = 0x0FFF;
  /* Repetition counter */
  HRTIM_BaseCfg.RepetitionCounter = 0;
  /* Set prescaler */
  HRTIM_BaseCfg.PrescalerRatio = HRTIM_B_PRESCALERRATIO;
  /* Set mode to continous */
  HRTIM_BaseCfg.Mode = HRTIM_MODE_CONTINUOUS;
  /* Use initialized structure as abse configuration */
  HAL_HRTIM_TimeBaseConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, &HRTIM_BaseCfg);
 
  /* Halfmode config */
  HRTIM_TimerCfg.HalfModeEnable = HRTIM_HALFMODE_DISABLED;
  /* Start, reset on sync and DAC sync disabled */
  HRTIM_TimerCfg.StartOnSync = HRTIM_SYNCSTART_DISABLED;
  HRTIM_TimerCfg.ResetOnSync = HRTIM_SYNCRESET_DISABLED;
  HRTIM_TimerCfg.DACSynchro = HRTIM_DACSYNC_NONE;
  /* Set HRTIM to independent updategating */
  HRTIM_TimerCfg.UpdateGating = HRTIM_UPDATEGATING_INDEPENDENT;
  /* Burst mode maintained from clock */
  HRTIM_TimerCfg.BurstMode = HRTIM_TIMERBURSTMODE_MAINTAINCLOCK;
  /* Update on repetition disabled */
  HRTIM_TimerCfg.RepetitionUpdate = HRTIM_UPDATEONREPETITION_ENABLED;
  /* Preload enable (shadow register mode) */
  HRTIM_TimerCfg.PreloadEnable = HRTIM_PRELOAD_ENABLED;
  /* Use initialized structure for HRTIM waveform generation */
  HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, &HRTIM_TimerCfg);
 
  /* Interrupt requests */
  HRTIM_TimerCfg.InterruptRequests = HRTIM_TIM_IT_NONE;
  /* DMA configuration */
  HRTIM_TimerCfg.DMARequests = HRTIM_TIM_DMA_NONE;
  HRTIM_TimerCfg.DMASrcAddress = 0x0000;
  HRTIM_TimerCfg.DMADstAddress = 0x0000;
  HRTIM_TimerCfg.DMASize = 0x1;
  /* Push-pull disable */
  HRTIM_TimerCfg.PushPull = HRTIM_TIMPUSHPULLMODE_DISABLED;
  /* Fault condition defines */
  HRTIM_TimerCfg.FaultEnable = HRTIM_TIMFAULTENABLE_NONE;
  HRTIM_TimerCfg.FaultLock = HRTIM_TIMFAULTLOCK_READWRITE;
  /* Dead-time insertion disable */
  HRTIM_TimerCfg.DeadTimeInsertion = HRTIM_TIMDEADTIMEINSERTION_DISABLED;
  #if (FALSE == DEBUG_SECTION_PROTECT_DISABLE)
  /* Delayed protection mode enable */
  HRTIM_TimerCfg.DelayedProtectionMode = HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DELAYEDBOTH_EEV6;
  #else
  /* Delayed protection mode disable */
  HRTIM_TimerCfg.DelayedProtectionMode = HRTIM_TIMER_A_B_C_DELAYEDPROTECTION_DISABLED;
  #endif
  /* No update trigger */
  HRTIM_TimerCfg.UpdateTrigger = HRTIM_TIMUPDATETRIGGER_NONE;
  /* No timer counter reset trigger */
  HRTIM_TimerCfg.ResetTrigger = HRTIM_TIMRESETTRIGGER_MASTER_PER;
  /* Update timer registers on reset */
  HRTIM_TimerCfg.ResetUpdate = HRTIM_TIMUPDATEONRESET_ENABLED;
  /* Use initialized structure */
  HAL_HRTIM_WaveformTimerConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, &HRTIM_TimerCfg);
 
  /* Choose polarity to active high */
  HRTIM_OutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
  /* Do nothing in idle mode and set output to inactive in idle and fault state (used only for ST burst mode) */
  HRTIM_OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
  HRTIM_OutputCfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
  HRTIM_OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
  /* Disable chopper mode */
  HRTIM_OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
  /* No delay when entering burst mode */
  HRTIM_OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
  /* Set output high at timer compare 1 */
  HRTIM_OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP1;
  /* Set output low at timer compare 2 */
  HRTIM_OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP2 | HRTIM_OUTPUTRESET_TIMCMP3 | HRTIM_OUTPUTRESET_TIMPER;
  /* Use initialized structure as output configuration for output TA1 */
  HAL_HRTIM_WaveformOutputConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_OUTPUT_TB1, &HRTIM_OutputCfg);
 
  /* Choose polarity to active high */
  HRTIM_OutputCfg.Polarity = HRTIM_OUTPUTPOLARITY_HIGH;
  /* Do nothing in idle mode and set output to inactive in idle and fault state (used only for ST burst mode) */
  HRTIM_OutputCfg.IdleMode = HRTIM_OUTPUTIDLEMODE_NONE;
  HRTIM_OutputCfg.IdleLevel = HRTIM_OUTPUTIDLELEVEL_INACTIVE;
  HRTIM_OutputCfg.FaultLevel = HRTIM_OUTPUTFAULTLEVEL_NONE;
  /* Disable chopper mode */
  HRTIM_OutputCfg.ChopperModeEnable = HRTIM_OUTPUTCHOPPERMODE_DISABLED;
  /* No delay when entering burst mode */
  HRTIM_OutputCfg.BurstModeEntryDelayed = HRTIM_OUTPUTBURSTMODEENTRY_REGULAR;
  /* Set output high at timer compare 1 */
  HRTIM_OutputCfg.SetSource = HRTIM_OUTPUTSET_TIMCMP3;
  /* Set output low at timer compare 2*/
  HRTIM_OutputCfg.ResetSource = HRTIM_OUTPUTRESET_TIMCMP4 | HRTIM_OUTPUTRESET_TIMCMP1 | HRTIM_OUTPUTRESET_TIMPER | HRTIM_OUTPUTRESET_MASTERPER;
  /* Use initialized structure as output configuration for output TB1 */
  HAL_HRTIM_WaveformOutputConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_OUTPUT_TB2, &HRTIM_OutputCfg);
 
  /* Auto-delay disabled */
  HRTIM_CompareCfg.AutoDelayedMode = HRTIM_AUTODELAYEDMODE_REGULAR;
  HRTIM_CompareCfg.AutoDelayedTimeout = 0;
 
  /*
   * Compare values:
   * NOTE: There are hardware limitations of the HRTIMER (Datasheet: 20.3.4 Timer A..E timing units table 78)
   * Minimum value must be greater than or equal to 3 periods of the fHRTIM clock
   * Maximum value must be less than or equal to 0xFFFF - 1 periods of the fHRTIM clock
   * If these conditions are violated, the related compares will be ignored!
   */
  /* PWM compare value 1 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_COMPAREUNIT_1, &HRTIM_CompareCfg);
  /* PWM compare value 2 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_COMPAREUNIT_2, &HRTIM_CompareCfg);
  /* PWM compare value 3 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_COMPAREUNIT_3, &HRTIM_CompareCfg);
  /* PWM compare value 4 init value */
  HRTIM_CompareCfg.CompareValue = 0;
  /* Use initialized structure */
  HAL_HRTIM_WaveformCompareConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, HRTIM_COMPAREUNIT_4, &HRTIM_CompareCfg);
 
  /* Deadtime clock prescalor */
  HRTIM_DeadTimeCfg.Prescaler = MG_HRTIM_B_DTPRESCALERRATIO;
  /* Deadtime rising value, Bst Mosfet Deadtime */
  HRTIM_DeadTimeCfg.RisingValue = 60U;
  /* Deadtime rising sign */
  HRTIM_DeadTimeCfg.RisingSign = HRTIM_TIMDEADTIME_RISINGSIGN_POSITIVE;
  /* Deadtime rising value lock */
  HRTIM_DeadTimeCfg.RisingLock = HRTIM_TIMDEADTIME_RISINGLOCK_WRITE;
  /* Deadtime rising sign lock */
  HRTIM_DeadTimeCfg.RisingSignLock = HRTIM_TIMDEADTIME_RISINGSIGNLOCK_WRITE;
  /* Deadtime falling value, SR Deadtime*/
  HRTIM_DeadTimeCfg.FallingValue = 60U;
  /* Deadtime falling sign */
  HRTIM_DeadTimeCfg.FallingSign = HRTIM_TIMDEADTIME_RISINGSIGN_POSITIVE;
  /* Deadtime falling value lock */
  HRTIM_DeadTimeCfg.FallingLock = HRTIM_TIMDEADTIME_FALLINGLOCK_WRITE;
  /* Deadtime falling sign lock*/
  HRTIM_DeadTimeCfg.FallingSignLock = HRTIM_TIMDEADTIME_FALLINGSIGNLOCK_WRITE;
 
  /* Use initialized structure for PWMB (TIMER1B CH1 & CH2) Deadtime */
  HAL_HRTIM_DeadTimeConfig(&hhrtim1, HRTIM_TIMERINDEX_TIMER_B, &HRTIM_DeadTimeCfg);
  /* Make sure that the DT sign locks are written */
  HRTIM1->sTimerxRegs[HRTIM_TIMERINDEX_TIMER_B].DTxR |= (HRTIM_DTR_DTRSLK | HRTIM_DTR_DTFSLK);
 
  /*
   * Configure external events to reset PWM
   */
  HRTIM_EventCfg.Source = HRTIM_EVENTSRC_2;     /* Select comparators as event source */
  HRTIM_EventCfg.Polarity = HRTIM_EVENTPOLARITY_HIGH;
  HRTIM_EventCfg.Sensitivity = HRTIM_EVENTSENSITIVITY_LEVEL;
  HRTIM_EventCfg.Filter = HRTIM_EVENTFILTER_NONE;
  HRTIM_EventCfg.FastMode = HRTIM_EVENTFASTMODE_DISABLE;/* NOTE: there is/was a bug in ST library: make sure that DISABLE will write register to 0 */
  /* Use initialized structure for HRTIM1 */
  HAL_HRTIM_EventConfig(&hhrtim1, HRTIM_EVENT_6, &HRTIM_EventCfg);  /* Select COMP2 output */
 
  /* Disable TB1 and TB2 outputs to keep rails off */
  hhrtim1.Instance->sCommonRegs.ODISR = (HRTIM_OUTPUT_TB1 | HRTIM_OUTPUT_TB2);
 
  /* Update configuration from preload register to TimerA register */
  hhrtim1.Instance->sCommonRegs.CR2 |= (MG_HRTIMER1_B_UPDATE);  
}

DBein
Associate III

​Possibly an application issue. I found that the ISR frequency matches the frequency of the PWM when the issue happens. Possibly the ISR register update disable and period events are in phase and therefore no update is happening until a phase missmatch occurs.

DBein
Associate III

​I can confirm that it was an application issue.

The problem is solved now.