Flag in struct is not working properly

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Flag in struct is not working properly

Jump to solution
1,191 Views
FredericoLuiz
Contributor II

Hello everyone,

I'm using systick interrupt of the MKL05Z32 every 100us to build a base time in my program like this.

void SysTick_Handler(){

...

     if(!--time200ms){

          time200ms=TIME_200_MS;

          flag.change=1;

     }

...

}

So I hope I get the flag "flag.change" set every 200ms. This flag is declared inside a struct with many others like this:

struct{

     unsigned char change:1;

}flag;

I'm using this flag to change a pwm frequency. I want to use 2 frequencies and change each other every 200ms. So my code is:

void FTM1_IRQHandler(){

     TPM1_SC |= TPM_SC_TOF_MASK;

     if(flag.change){

          flag.change=0;

          if(!step.pwm){

               //Configure to frequency 1

               step.pwm=1;

          }

          else{

               //Configure to frequency 2

               step.pwm=0;

          }

     }

}

Unfortunately this is not working properly. It got this result:

NewFile0.png

Sometimes it seems the variable "flag.change" is not cleared in the FTM1 interrupt, leading to another frequency change in the next FTM1 interrupt. The strange thing is the waveforms change, thery are not periodic, meaning the strange behavior of flags.

I did many things to test and I saw when I changed the "flag.change" to a variable "flagChange" declared as unsigned char I got this:

NewFile1.png

The above figure is the result I expect to have. It is okay I know it is working this way, but I'm not satisfied because there are many others flags in structs and I want they work properly. So I would like to understand what is happening.

Facts:

1-Variable "flag.change" and " step.pwm" are used only in these functions.

2-Variables are set every 200ms properly.

Any ideas will be appreciated. Thanks.

Labels (1)
Tags (1)
0 Kudos
1 Solution
1,004 Views
ndavies
Contributor V

Are your interrupts at different priority levels?  If so, you may have one interrupt, interrupting the other interrupt.

The bit flag change ( flag.change =1) is a multiple operation command.  If the flag.change is interrupted by the other ISR in between those operations, it will corrupt the data.

The flagchange = 1 command is an atomic instruction. The higher priority interrupt can't modify flagchange in the middle of the lower priority interrupt

The interrupts either need to be at the same priority or you need to block the higher priority interrupt from running while the lower priority interrupt modifies the variable.

Norm

View solution in original post

8 Replies
1,005 Views
ndavies
Contributor V

Are your interrupts at different priority levels?  If so, you may have one interrupt, interrupting the other interrupt.

The bit flag change ( flag.change =1) is a multiple operation command.  If the flag.change is interrupted by the other ISR in between those operations, it will corrupt the data.

The flagchange = 1 command is an atomic instruction. The higher priority interrupt can't modify flagchange in the middle of the lower priority interrupt

The interrupts either need to be at the same priority or you need to block the higher priority interrupt from running while the lower priority interrupt modifies the variable.

Norm

1,004 Views
FredericoLuiz
Contributor II

Hello Norm,

Yes I have other. I'm using:

Systick Interrupt to create base time at 100us.

UART0 interrupt for sending and receiving data      -   Priority 0

TPM1 for pwm purposes -                                            Priority 4

PIT - Peripheral Interrupt Timer for multi tasks delay - Priority 4

ADC0 -                                                                          Priority 4

After reading your comment I made a test. I disabled all interrupts except FTM1. It worked ok!!! I added all other interrupts except UART0 and it worked as well. SO I think the 0 priority of UART0 is causing my headaches.

If I cannot atend for example a UART0 interrupt at, let suppose 9600kbps, is there a safe way to use priority 0 and flags in structs?

Many thanks!

0 Kudos
1,004 Views
ndavies
Contributor V

Hello Frederico,

When I do this:  In the lower priority thread, I disable the interrupts, make the flag.change = 1, and then re-enable interrupts.

So the lower  priority interrupt would look something like this

interrupt DummyISR()

{

     unsigned long previous_interrupt_state;

...

     previous_interrupt_state = disableinterrupts()

     flag.change = 1;

....

     enableInterrupts(previous_interrupt_State);

....

}

The higher priority interrupt can stay the same as it currently is.

We constructed our operating system from scratch. (It's actually a port of an OS we built years ago.) The enable and disable interrupt routines are our own. You will have to look up those functions for the OS/bareboard configuration you're using.

You will also need to do this in non-interrupt routines if they share the bit defined data with an interrupt. This is also a problem if you use |= or &= on a variable shared between interrupts or between interrupt and non interrupt code.

Keep the amount of time you have interrupts disabled to a minimum otherwise you may break the interrupt priority scheme.

This is the only way I know to do it. I don't know if anyone has a different solution.

Norm

0 Kudos
1,004 Views
FredericoLuiz
Contributor II

Hello Norm,

I will consider that now I have to reorganise my ISRs and priorities.

I'm doing a scheme like this for flash programming. Maybe I can use for this also.

Many thanks for your suggestions.

Best regards,

Frederico

0 Kudos
1,004 Views
EarlOrlando
Senior Contributor II

Hello Federico,

Could you please share the project to debug it?

What is the period of the PIT and the FTM interrupts? I recommend to toggle a pin on every FTM interrupt and another in every PIT interrupt to ensure that the periods are configured OK.

Best regards,

Earl.

0 Kudos
1,004 Views
FredericoLuiz
Contributor II

Hello Earl Orlando,

Unfortunately I can not share the complete code. But I will let here some functions.

Core Clock is 48MHz.

Bus/Flash clock is 24MHz.

FTM1 prescale = 16.

TP_SIR_PER_1 = 0x1F4     will give 3kHz

TP_SIR_PER_2 = 0x3E8     will give 1,5kHz

Yes, I checked with pins the configurations are OK.

The first time I turn on the pwm using this function. After I change the duty cicle using FTM1 interrupt

void initPwm(unsigned int mod){

  SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK;

  SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1);                         // MCGFLLCLK clock source

  PORTB_PCR5 = PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x2);

  TPM1_CNT=0;

  TPM1_MOD=mod; //TMP_PERIOD

  TPM1_SC=0x5; //PRESCALER=16

  TPM1_SC |=0x08|TPM_SC_TOIE_MASK;

  TPM1_C1SC=TPM_CnSC_MSB_MASK| TPM_CnSC_ELSA_MASK;

  TPM1_C1V=mod/2; //DUTY CYCLE  50%

  turnOnInt(INT_IRQ_TPM1);

}

void FTM1_IRQHandler(){

       TPM1_SC |= TPM_SC_TOF_MASK;

   

       if(flag.change){

          flag.change=0;

          if(!step.pwm){

                 TPM1_CNT = 0;

                 TPM1_MOD= TP_SIR_PER_1;

                 TPM1_C1V = TP_SIR_DC_1; // DUTY CYCLE EM 50%

                   step.pwm=1;

          }

          else{

                 TPM1_CNT = 0;

                 TPM1_MOD = TP_SIR_PER_2;

                 TPM1_C1V = TP_SIR_DC_2; // DUTY CYCLE EM 50%

                 step.pwm=0;

          }

     }

}

I modified somethings because the code and comments were in another language.

Thanks!

0 Kudos
1,004 Views
egoodii
Senior Contributor III

Are these flags declared 'volatile'?  Anything that can be modified outside the 'normal instruction sequence' the compiler can see must be declared so, to inform the compiler that every evaluation MUST fetch a new copy.

0 Kudos
1,004 Views
FredericoLuiz
Contributor II

Earl Goodrich II,

I added this modifyer in both flags, but the problem still happens.

I've been wondering if it could be related with stack overflow. Right now I'm checking some addresses in order to find the problem.

Thanks.

0 Kudos