How to use flags and exit interrupts.

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

cross mob
HappyPotamus
Level 1
Level 1
10 sign-ins 5 sign-ins First reply posted

Hello everyone, this is my second question on this lovely community.

If the person who had helped in my previous question sees this, I posted this in a new post so the other one doesn't get out of context and doesn't become too long 🙂

Last time, a member helped solve my previous problem, which is to generate a 45 kHz signal over a period of 10 ms every second. I will post below the build and the code, and what my new problem is according to their suggestion.

HappyPotamus_0-1631778600865.png

The idea is to use a timer, and call an interrupt one overflow of the timer counter to generate the signal over 10 ms and disable the PWM afterwards.

Here is the m04 code:

 

 

 

#include "project.h"
#include <stdio.h>

void Counter_Int_Handler()                                                //Counter interrupt handler
{   
    printf("Handler is here \r\n");
    Cy_TCPWM_ClearInterrupt(Timer_HW, Timer_CNT_NUM, CY_TCPWM_INT_ON_TC); //Clearing the interrupt
    Cy_GPIO_Inv(LED_PORT, LED_NUM);
    CyDelay(10);
    Cy_GPIO_Inv(LED_PORT, LED_NUM);
    PWM_Disable();
    CyDelay(990);
    PWM_Start();
    printf("End of Handler \r\n\n");
}

int main(void)
{
    UART_Start();  
    Timer_Start();
    PWM_Start();
    
    bool flag = true;
    
    Cy_GPIO_Write(LED_PORT,LED_NUM,1);
    
    Cy_SysInt_Init(&SysInt_1_cfg,Counter_Int_Handler);                    //Configuring the interrupt
    NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc);                           //Clearing the interrupt
    NVIC_EnableIRQ(SysInt_1_cfg.intrSrc);                                 //Calling the interrupt handler
    __enable_irq();                                                       //Enable global interrupts
    
    //(void)Cy_TCPWM_Counter_Init(Timer_HW, Timer_CNT_NUM, &Timer_config);
    Cy_TCPWM_Enable_Multiple(Timer_HW, Timer_CNT_MASK);  //
    Cy_TCPWM_TriggerReloadOrIndex(Timer_HW, Timer_CNT_MASK); 
    
    printf ("\033[3J");                                                   //Clearing PuTTY's scrollback buffer
    printf ("\ec");                                                       //Clearing previous PuTTY outputs
    printf("UART link established \r\n\n");
    
    __enable_irq(); 
    for(;;)
    {   
        printf("Hello for loop! \r\n");
        Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}

 

 

 

The problem is that once the interrupt handler is called and start executing, it executes infinitely and never exits back to the for loop.

Also, although I am I managed to get the interrupt service routine to work, I am not quite sure if I understand how I exactly did it, nor what is the exact logic behind it as well; you could say I am following my sense and basic understanding of these matters.

My questions are as following:

1) Is the interrupt logic correct?

2) Could the interrupt logic used here be enhanced to be more efficient and/or exit to the for loop and back to the interrupt again without flags?

3) How to use flags?

I will post a weird attempt of mine to grasp the idea of flags, but in my opinion I failed miserably and most probably didn't actually understand anything.

Here is the miserable attempt on grasping flags:

 

 

 

#include "project.h"
#include <stdio.h>

void Counter_Int_Handler()                                                //Counter interrupt handler
{   
    bool flag = true;
    printf("Handler is here \r\n");
    Cy_TCPWM_ClearInterrupt(Timer_HW, Timer_CNT_NUM, CY_TCPWM_INT_ON_TC); //Clearing the interrupt
    Cy_GPIO_Inv(LED_PORT, LED_NUM);
    CyDelay(10);
    Cy_GPIO_Inv(LED_PORT, LED_NUM);
    PWM_Disable();
    CyDelay(990);
    PWM_Start();
    if (flag == true){
    printf("End of Handler flag trigered \r\n\n");
    NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc);
    __NVIC_DisableIRQ(SysInt_1_cfg.intrSrc);
    }
}

int main(void)
{
    UART_Start();  
    Timer_Start();
    PWM_Start();
    
    bool flag = false;
    
    Cy_GPIO_Write(LED_PORT,LED_NUM,1);
    
    Cy_SysInt_Init(&SysInt_1_cfg,Counter_Int_Handler);                    //Configuring the interrupt
    NVIC_ClearPendingIRQ(SysInt_1_cfg.intrSrc);                           //Clearing the interrupt
    NVIC_EnableIRQ(SysInt_1_cfg.intrSrc);                                 //Calling the interrupt handler
    __enable_irq();                                                       //Enable global interrupts
    
    //(void)Cy_TCPWM_Counter_Init(Timer_HW, Timer_CNT_NUM, &Timer_config);
    Cy_TCPWM_Enable_Multiple(Timer_HW, Timer_CNT_MASK);  //
    Cy_TCPWM_TriggerReloadOrIndex(Timer_HW, Timer_CNT_MASK); 
    
    printf ("\033[3J");                                                   //Clearing PuTTY's scrollback buffer
    printf ("\ec");                                                       //Clearing previous PuTTY outputs
    printf("UART link established \r\n\n");
    
    if (flag == true){
        for(;;){   
            printf("Hello for loop! flag is true \r\n");
            NVIC_EnableIRQ(SysInt_1_cfg.intrSrc);                         //Calling the interrupt handler
            flag = false;
            Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
                }
                       }
    else {
        printf("Flag is flase! \r\n");
        flag = true;
        return flag;
          }
}

 

 

 

and here is the output of the last attempt with the flag:

HappyPotamus_1-1631779209065.png

 

I am excited and looking forward everyone's suggestions/solutions!

Thank you and best regards,

HappyPotamus.

0 Likes
1 Solution
ARH
Level 3
Level 3
10 replies posted 5 replies posted 5 sign-ins

I can think of a bunch of ways to accomplish this task.

 

Method 1: (which I would never do)

1. Start the output pwm (which you called PWM)

2. Cydelay(10)

3. Stop the output pwm

4. CyDelay(990)

5. go back to step (1)

 

Method 2:

use the systick interrupt to make a software PWM to enable and disable the output pwm

 

Method 3:

Setup another pwm with a frequency of 1hz and a duty cycle of 990... then connect the output of that pwm to the count input of the output PWM 

 

Method 4:

use a udb and gate to and off the pwm signal using a pwm with a period of 1hz and a duty cycle of 990

 

Method 5: 

use the smart/o to gate the pwm with a source and signal from another PWM

 

Hopefully this helps.

ARH

View solution in original post

0 Likes
3 Replies
ARH
Level 3
Level 3
10 replies posted 5 replies posted 5 sign-ins

 

You definitely do not want to

1) printf

2) cydelay

Inside of an interrupt handler.

Both of these operation will take a long time and block the CPU.

 

I looked at your code... and I don't understand what you are trying to do... could you state simply what you are trying to achieve?

Alan

 

0 Likes

Hello @ARH ,

I am sorry that my code/commenting isn't clear, I am new to this entire thing 🙂 

I have a PWM that is a continuous generating 45 kHz signal. But, I want this signal to be generated for 10 ms out of an entire second (Square signal in 10 ms out of the entire second and the rest 990 ms is a flat line). The timer is configured for overflow interrupt, and the time is for 1 second.

So that basically is what I am trying to achieve. Now that you mentioned to me that I should not include printf nor CyDelay in an interrupt handler because it block the CPU, how can I achieve my goal? I am sorry if what I wrote here also doesn't make sense, if it doesn't, please tell me I will rephrase my goal.

Many thanks,

HappyPotamus.

0 Likes
ARH
Level 3
Level 3
10 replies posted 5 replies posted 5 sign-ins

I can think of a bunch of ways to accomplish this task.

 

Method 1: (which I would never do)

1. Start the output pwm (which you called PWM)

2. Cydelay(10)

3. Stop the output pwm

4. CyDelay(990)

5. go back to step (1)

 

Method 2:

use the systick interrupt to make a software PWM to enable and disable the output pwm

 

Method 3:

Setup another pwm with a frequency of 1hz and a duty cycle of 990... then connect the output of that pwm to the count input of the output PWM 

 

Method 4:

use a udb and gate to and off the pwm signal using a pwm with a period of 1hz and a duty cycle of 990

 

Method 5: 

use the smart/o to gate the pwm with a source and signal from another PWM

 

Hopefully this helps.

ARH

0 Likes