Electrical – TIM1 appears to not stop

stm32timer

I am using TIM1 to drive a DMA channel which is sending bytes to GPIOF on an STM32F407. TIM1 is started by an OC channel on a different timer. In the DMA stream interrupt handler, I am attempting to stop TIM1 and also reset the counter by generating an Update event. For troubleshooting purposes I have configured an OC channel on TIM1 so I can confirm it is starting and stopping as expected.

It does appear to start and stop at the correct times when viewing the pin output using a logic analyzer, but when stepping through the interrupt handler in the debugger I see that the CEN bit is still set after clearing it. Also, TIM1->CNT continues to increment as I step through each line.

The interrupt handler is as follows:

void __attribute__((interrupt("IRQ"))) DMA2_Stream5_IRQHandler(void)
{
    // Clear interrupt flags
    do
    {
        DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;
    }
    while(DMA2->HISR & DMA_HISR_TCIF5);

    // Stop TIM1, TIM5 will re-enable it
    //TIM1->CR1 &= (u16)~TIM_CR1_CEN;
    do
    {
        TIM1->CR1 &= (u16)~TIM_CR1_CEN;
    }
    while(TIM1->CR1 & TIM_CR1_CEN);
    TIM1->EGR = TIM_EventSource_Update;     // Trigger an Update to reset the counter

    // Re-enable DMA for next TIM5 event
    DMA2_Stream5->CR |= DMA_SxCR_EN;
}

The code does exit the loop which clears CEN, but afterwards viewing the TIM1 registers shows CEN is still set. How can I ensure the timer is really stopped and will start counting from 0 next time it is started?

Best Answer

It appears that clearing the enabled flag has no effect when the timer is in slave mode. I have changed my interrupt handler as follows, and now it is working as expected. The timer is stopped and reset, until started again by TIM5.

// Clear interrupt flags
DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;

// Disable slave move, can't stop the timer unless we do this first
TIM1->SMCR = 0;

// Stop TIM1, TIM5 will re-enable it
TIM1->CR1 = 0;// &= (u16)~TIM_CR1_CEN;
TIM1->EGR = TIM_EventSource_Update;     // Trigger an Update to reset the counter

// Re-enable slave mode
TIM1->SMCR = TIM_SlaveMode_Trigger;
Related Topic