non blocking delays

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
JeMc_3775591
Level 1
Level 1
First like given

When I used an Arduino for Ws2812 leds, I would use a non-blocking delay such as a millis() timer so I could control the speed of an animation but not lock up the processor and allow it to do other tasks at the same time. I saw an example on a PSOC4 that used a timer and a function to set the period of the required delay.

PSoC Timer Example - Microcontroller - eewiki

When I tried this on the Psoc6 BLE Kit I'm having difficulty somewhere. I might be doing the Interrupt wrong but this is how I understand it.

Using the function ms_delay(50);

     Sets the period of the timer, then enables the timer.

     When one period of the timer is complete it triggers the ISR which sets the flag to 1 and closes the while(!timer);

     Stops the timer and sets the flag back to 0

This is the condensed code from the link above and if found near the bottom of the page.

#define TIMER_CLOCK 24000000 // This value should match the clock input to the Timer

uint8 timer_flag = 0;

void ms_delay (uint32 ms);

CY_ISR(MY_ISR) {

    timer_flag = 1;

}

// This function can be used for delays in units of ms.

// Valid value of ms can be in the range [0 ~ 4,294,967,295].

void ms_delay (uint32 ms) {

    uint32 period = TIMER_CLOCK/1000*ms;

    Timer_1_WritePeriod(period);

    Timer_1_Enable(); // start the timeout counter

    while(!timer_flag);

    Timer_1_Stop();

    timer_flag = 0;

}

I'm still new to Psoc in general so any help or guidance is much appreciated

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I agree that the interrupt handling of PSoC 6 is much more complicated than PSoC 4,

and I'm still learning, too.

If you'd like to handle asynchronous events,

may be considering FreeRTOS is not a bad option.

Attached is my trial of using timer without RTOS using PSoC 6 BLE Pioneer kit.

I change color of RGB LED each 0.1 second, using polling method,

let's pretend this as your animation.

Meantime, with timer interrupt, one of LED_8 and LED_9 is ON/OFF each 1.0 sec.

So we can see that even while waiting, the animation is running.

My strategy is let ISR only set the flag.

Taking care of the flag is in the main loop.

So I hope this wait does not block the MCU.

===============================

#include "project.h"

#include <stdio.h>

#define LED_ON (0)

#define LED_OFF (1)

volatile uint8_t alarm_flag = 0 ;

void alarm_isr(void)

{

    NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;

    NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

    MS_Timer_Disable() ;

    MS_Timer_SetCounter(0) ;

    Clock_1kHz_Disable() ;

    alarm_flag = 1 ;

}

void init_hardware(void)

{

    __enable_irq(); /* Enable global interrupts. */

    UART_Start() ;

    Cy_SysInt_Init(&Alarm_INT_cfg, alarm_isr) ;

}

void set_alarm_ms(uint32_t wait_ms)

{

    NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;

    NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

    Clock_1kHz_Enable() ;

    MS_Timer_SetCounter(0) ;

    MS_Timer_SetCompare0(wait_ms) ;

    MS_Timer_Start() ;

   

    NVIC_EnableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

}

void doLEDs(uint8_t value)

{

    if (value & 0x01) {

        Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_OFF) ;

    }

    if (value & 0x02) {

        Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_OFF) ;

    }

    if (value & 0x04) {

        Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_OFF) ;

    }

}

void doTask1(void)

{

    static int turn = 0 ;

    if (alarm_flag) {

        if (turn) {

            Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_OFF) ;

            Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_ON) ;

            turn = 0 ;

        } else {

            Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_ON) ;

            Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_OFF) ;

            turn = 1 ;

        }

        alarm_flag = 0 ;

        set_alarm_ms(1000) ;

    }      

}

void doTask2(void)

{

    static int count = 0 ;

    doLEDs(count) ;

    count = (count + 1) % 8 ; /* 0~7 */

}

int main(void)

{

    uint32_t count = 0 ;

   

    init_hardware() ;

   

    set_alarm_ms(1000) ;

           

    for(;;) {

        doTask1() ;

        if ((count % 1000) == 0) {

            doTask2() ;

        }

        count++ ;

        CyDelayUs(100) ; /* 100us tick */

    }

}

/* [] END OF FILE */

===============================

moto

View solution in original post

2 Replies
ShipingW_81
Moderator
Moderator
Moderator
500 replies posted 250 solutions authored 250 replies posted

Of course you can use the timer of PSoC 6 to implement the functionality of delay you mentioned.

Please refer to code example ce220169 to know well about the implementation details.

However, it seems the ms_delay code snippet you listed above would also get core stuck in while loop, instead of handing other tasks.

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I agree that the interrupt handling of PSoC 6 is much more complicated than PSoC 4,

and I'm still learning, too.

If you'd like to handle asynchronous events,

may be considering FreeRTOS is not a bad option.

Attached is my trial of using timer without RTOS using PSoC 6 BLE Pioneer kit.

I change color of RGB LED each 0.1 second, using polling method,

let's pretend this as your animation.

Meantime, with timer interrupt, one of LED_8 and LED_9 is ON/OFF each 1.0 sec.

So we can see that even while waiting, the animation is running.

My strategy is let ISR only set the flag.

Taking care of the flag is in the main loop.

So I hope this wait does not block the MCU.

===============================

#include "project.h"

#include <stdio.h>

#define LED_ON (0)

#define LED_OFF (1)

volatile uint8_t alarm_flag = 0 ;

void alarm_isr(void)

{

    NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;

    NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

    MS_Timer_Disable() ;

    MS_Timer_SetCounter(0) ;

    Clock_1kHz_Disable() ;

    alarm_flag = 1 ;

}

void init_hardware(void)

{

    __enable_irq(); /* Enable global interrupts. */

    UART_Start() ;

    Cy_SysInt_Init(&Alarm_INT_cfg, alarm_isr) ;

}

void set_alarm_ms(uint32_t wait_ms)

{

    NVIC_ClearPendingIRQ(Alarm_INT_cfg.intrSrc) ;

    NVIC_DisableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

    Clock_1kHz_Enable() ;

    MS_Timer_SetCounter(0) ;

    MS_Timer_SetCompare0(wait_ms) ;

    MS_Timer_Start() ;

   

    NVIC_EnableIRQ((IRQn_Type)Alarm_INT_cfg.intrSrc) ;

}

void doLEDs(uint8_t value)

{

    if (value & 0x01) {

        Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_B_0_PORT, LED_B_0_NUM, LED_OFF) ;

    }

    if (value & 0x02) {

        Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_G_0_PORT, LED_G_0_NUM, LED_OFF) ;

    }

    if (value & 0x04) {

        Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_ON) ;

    } else {

        Cy_GPIO_Write(LED_R_0_PORT, LED_R_0_NUM, LED_OFF) ;

    }

}

void doTask1(void)

{

    static int turn = 0 ;

    if (alarm_flag) {

        if (turn) {

            Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_OFF) ;

            Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_ON) ;

            turn = 0 ;

        } else {

            Cy_GPIO_Write(LED_8_0_PORT, LED_8_0_NUM, LED_ON) ;

            Cy_GPIO_Write(LED_9_0_PORT, LED_9_0_NUM, LED_OFF) ;

            turn = 1 ;

        }

        alarm_flag = 0 ;

        set_alarm_ms(1000) ;

    }      

}

void doTask2(void)

{

    static int count = 0 ;

    doLEDs(count) ;

    count = (count + 1) % 8 ; /* 0~7 */

}

int main(void)

{

    uint32_t count = 0 ;

   

    init_hardware() ;

   

    set_alarm_ms(1000) ;

           

    for(;;) {

        doTask1() ;

        if ((count % 1000) == 0) {

            doTask2() ;

        }

        count++ ;

        CyDelayUs(100) ; /* 100us tick */

    }

}

/* [] END OF FILE */

===============================

moto