Open
Description
The function resetTC() waits for timer counter sync or reset in an infinite loop because it is interrupted by an ISR that also calls resetTC()
resetTC() is called from:
- Tone_Handler() (Interrupt Service Routine)
- tone() (but interrupts are disabled when it's called)
- noTone() (HANG)
It can happen that an interrupt can occur while noTone() is performing resetTC(). The interrupt service routine will also perform resetTC(), and when execution returns to noTone() in the middle of performing resetTC() it will hang.
File: Tone.cpp
Function: void noTone (uint8_t outputPin)
void noTone (uint8_t outputPin)
{
if(firstTimeRunning)
{
resetTC(TONE_TC);
digitalWrite(outputPin, LOW);
toneIsActive = false;
}
}
Hang Fix:
void noTone (uint8_t outputPin)
{
if(firstTimeRunning)
{
NVIC_DisableIRQ(TONE_TC_IRQn);
resetTC(TONE_TC);
NVIC_EnableIRQ(TONE_TC_IRQn);
digitalWrite(outputPin, LOW);
toneIsActive = false;
}
}
resetTC():
static inline void resetTC (Tc* TCx)
{
// Disable TCx
TCx->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
WAIT_TC16_REGS_SYNC(TCx)
// Reset TCx
TCx->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
WAIT_TC16_REGS_SYNC(TCx)
while (TCx->COUNT16.CTRLA.bit.SWRST);
}
Interrupt Service Routine:
void Tone_Handler (void)
{
if (toggleCount != 0)
{
// Toggle the ouput pin
*portToggleRegister = portBitMask;
if (toggleCount > 0)
--toggleCount;
// Clear the interrupt
TONE_TC->COUNT16.INTFLAG.bit.MC0 = 1;
}
else
{
resetTC(TONE_TC);
*portClearRegister = portBitMask;
toneIsActive = false;
}
}
Metadata
Metadata
Assignees
Labels
No labels