ctimerpwmucosmicrium

uC/OS-III Systick & Peripheral timer0 for PWM interfere


I'm having trouble in getting a PWM signal for LEDs running smoothly on a NXP LPC1857 running uC/OS-III. Only when I disable the OS systick running at 1ms the flickering which regulary occurs stops.

I have set up my timer with 4 match registers, one for each color (Red, Green, Blue) and one for the complete period. The first three match outputs are clearing the physical output pins for each color. The last period match generates an interrupt to set all three color outputs for the next period.

i tried to disable interrupts from the OS during the timer0 interrupt by adding the following code arround the interrupts:

void TIMER0_IRQHandler(void)
{
    CPU_SR_ALLOC();
    OS_CRITICAL_ENTER();
    OSIntEnter();
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_RED))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_RED);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_RED);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_GREEN))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_GREEN);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_GREEN);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_BLUE))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_BLUE);
        PWM_TIMER->EMR &= ~(((uint32_t) 0x01) << PWM_BLUE);
    }
    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
    }
    OS_CRITICAL_EXIT();
    OSIntExit();
}

Does anyone has an idea why the systick could cause the flickering in the PWM signal?


Solution

  • Finally found a solution although I do not completely understand why :P.

    After completely stripping the OS from my own tasks except for the PWM task the issues still remained. So I turned back to the timer code.

    The only thing I had to add to get rid of the flickering was a reset of the timer after I got a period interrupt:

    Old:

    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
    }
    

    New:

    if (Chip_TIMER_MatchPending(PWM_TIMER, PWM_MATCH))
    {
        Chip_TIMER_ClearMatch(PWM_TIMER, PWM_MATCH);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_RED);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_GREEN);
        PWM_TIMER->EMR |= (((uint32_t) 0x01) << PWM_BLUE);
        Chip_TIMER_Reset(PWM_TIMER);
    }
    

    Could someone explain why this reset is necessary?

    I expected the following line would take care of this (which is in my initialization routine):

    Chip_TIMER_ResetOnMatchEnable(PWM_TIMER, PWM_MATCH);