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

344 Views Asked by At

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?

2

There are 2 best solutions below

0
On BEST ANSWER

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);
3
On

You should not be using OS_CRITICAL_ENTER() and OS_CRITICAL_EXIT(). Instead, you should use CPU_CRITICAL() and CPU_CRITICAL_EXIT() in order to disable interrupts during the critical section.

Also, this ISR doesn't signal any task so, you should not need to call OSIntEnter() and OSIntExit(). I believe your code should simply be:

void TIMER0_IRQHandler(void)
{
    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);
    }
}

Jean