Skip to content

QTMR ClearStatusFlags() can accidentally clear unrequested flag #24

@TomasKet

Description

@TomasKet

In fsl_qtmr.c QTMR_ClearStatusFlags() and a flag that was not included in mask parameter may be accidentally cleared.

Example:

  1. Multiple interrupt flags are used - OverflowFlag and EdgeFlag
  2. OverflowFlag gets raised and triggers ISR
  3. Inside the ISR QTMR_ClearStatusFlags(kQTMR_CompareFlag) is called
  4. Inside QTMR_ClearStatusFlags(), EdgeFlag gets raised right after reading SCTRL register
  5. EdgeFlag is cleared in the same function, before being handled. Sad face
    reg = base->CHANNEL[channel].SCTRL;                        // [reg]:OverflowFlag==1, EdgeFlag==0       [SCTRL]:OverflowFlag==1, EdgeFlag==0
    /* Timer compare flag */
    if ((mask & (uint32_t)kQTMR_CompareFlag) != 0U)            // <----- EdgeFlag raised here
    {
        reg &= MCUX_MASK_INVERT_16(TMR_SCTRL_TCF_MASK);        // [reg]:OverflowFlag==0, EdgeFlag==0       [SCTRL]:OverflowFlag==1, EdgeFlag==1
    }
    /* Timer overflow flag */
    if ((mask & (uint32_t)kQTMR_OverflowFlag) != 0U)
    {
        reg &= MCUX_MASK_INVERT_16(TMR_SCTRL_TOF_MASK);
    }
    /* Input edge flag */
    if ((mask & (uint32_t)kQTMR_EdgeFlag) != 0U)
    {
        reg &= MCUX_MASK_INVERT_16(TMR_SCTRL_IEF_MASK);
    }
    base->CHANNEL[channel].SCTRL = reg;                       // [SCTRL]: OverflowFlag==0, EdgeFlag==0

Mitigation:
Mask flag bits when reading SCTRL and CSCTRL registers:

    reg = base->CHANNEL[channel].SCTRL | TMR_SCTRL_TCF_MASK | TMR_SCTRL_TOF_MASK | TMR_SCTRL_IEF_MASK;
    reg = base->CHANNEL[channel].CSCTRL | TMR_CSCTRL_TCF1_MASK | TMR_CSCTRL_TCF2_MASK;

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions