0

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?

Futience
  • 1
  • 2
  • The CPU frequency is set to 180MHz so with an systick interrupt every 1ms this should not cause any trouble for the timer perhipheral I would think? – Futience Apr 28 '16 at 17:26

2 Answers2

0

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

  • Thanks for your response. I started with the code mentioned above where no OS specific functions where called before and after everything in the timer interrupt. But somehow the output of the timer is influenced when the OS is running and i can't find the reason why that happens. Adding the OS functions didn't help either but was the last status i had. – Futience May 01 '16 at 14:23
  • As soon as the OS functions inside the systick handler are disabled the timer runs perfectly. Has someone any idea where to start looking for the problems when running the OS? – Futience May 12 '16 at 18:00
  • Today I tried again to find the cause of this mysterious problem. Unfortunately without succes. When I measure the active channels I can see a short "active" pulse which occurs almost every second, with quite a precise periode of 1 sec in between the pulses. these pulses are the flashes I notice which are indeed roughly every second when I look at the LEDs. Whenever I disable the output of the timer for one of the channels this channel also doesn't have this pulse with 1 sec interval but stays constantly inactive as i would expect. Someone any idea what else to try? – Futience Jun 12 '16 at 00:02
0

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);
Futience
  • 1
  • 2