Problems when accessing Global variables in ISR and Source code

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Problems when accessing Global variables in ISR and Source code

4,157 次查看
vahbiz1
Contributor I

Hello Sir

I am using CodeWarrior V5.6 to program freescale's Power Quicc processor MPC852T. I am having a problem with Global variables which are being used in both source code and ISR. I have a code in which a global variable "Count" gets incremented in the ISR and is being decremented in a function in the source code. Now it so happens that an interrupt comes while this function (in the source code) is executing. Most of the times this code works fine, ie at the end of the function this "count" value shows the increment. But sometime, at random this does not happen, althought the ISR has got executed ie  this "count" value shows NO increment and is not updated. What can be the cause of this problem? How can i avoid it? Are there any special compiller options that i need to set?

Also i have not enabled any optimisation setting in Codewarrior IDEand i also tried making this global variable "volatile" but there was no effect

Thanks,

Vahbiz

标签 (1)
标记 (1)
0 项奖励
回复
4 回复数

2,196 次查看
vahbiz1
Contributor I

Hello Sir,

I have been trying to use the lwarx/stwcx. instruction pair to make my code atomic. I have encountered 2 problems.
1.  These synchronizing instructions are for WORD (32-bit ) type. So I am forced to convert the global variables from 8-bit to 32-bit. Is there any other way around this?
2.  This lwarx/stwcx. instruction pair has been implemented in the source code only and not in the ISR routine, but my problem still stays ie. the update of the global variable in ISR is still not taking place in the source code. By debugging I have found out that a normal “stw” instruction (present in ISR, placed by compiler) does not clear the RESERVATION Flag (as the theory says) and only a “stwcx.” instruction clears this Flag.
Now, placing this lwarx/stwcx. instruction pair in the ISR as well, solves THIS problem.
But I have 4 ISR’s and about 10 more global variables for which I need to make parts of the code, atomic. And as you know the “lwarx” instruction holds a reservation only for the latest “reservation address” addressed by the last “lwarx” instruction. So placing the lwarx/stwcx. instruction pair in the ISR as well as in the source code is not the solution.
Why does the “stw” instr not clear the RESERVATION Flag? Is some "memory coherency" required to implement this? 

Regards,

Vahbiz.

0 项奖励
回复

2,196 次查看
vahbiz1
Contributor I
Hello Sir,
Thankyou very much,
I masked the interrupt before the experssion and unmasked it after the expression, and it has worked.
But i still have a question, do i need to do  this masking and unmasking of intr (in the source code) only when this global variable is getting updated/modified? Or do i also need to do this (masking and unmasking of intr) even when this global variable is being used in conditional statements like in "if" and "while"  loops?
Regards,
Vahbiz
0 项奖励
回复

2,196 次查看
rocco
Senior Contributor II
Hi, Vahbiz:

The answer really depends on the code that the compiler creates. You need to consider whether the compare in the 'if' statement is atomic.

If the value is able to be loaded into a register in a single operation that cannot be interrupted, then it is safe to not disable interrupts. An ISR could still modify the variable before or after its value is loaded into the register, but the value loaded will still be a valid value (although possibly out-of-date). This is likely the case for your example.

If, on the other hand, the value needs to be loaded with multiple instructions, such as comparing an integer in an 8-bit microcontroller, then the interrupts would need to be blocked. An ISR could change the value after the low byte was tested, but before the high byte was tested, giving unpredictable results.

The only way to know for sure is to look at the assembly code that the compiler generates.
0 项奖励
回复

2,196 次查看
rocco
Senior Contributor II
Hi, Vahbiz:

What you need to implement is called a "critical section".

In your main routine you are decrementing a value that can be asynchronously incremented by an ISR. The decrement is probably not "atomic", which means that the operation requires a number of instructions, any one of which can be interrupted by the ISR.

Consider the following sequence:

In the main code, the value of "Count" is loaded into a register for decrementing.
The value in the register is then decremented.
-- The interrupt occurs. The following sequence occurs in the ISR:
-- The value of "Count" is loaded into a register for incrementing.
-- The value in the register is incremented.
-- The incremented value in the register is stored in "Count".
-- The interrupt returns
Back in the main code, the value of the decremented register is stored in "Count", overwriting the incremented value stored by the ISR.

So it appears that no increment took place, because the increment occurred during the critical section.

The solution is to make the decrement atomic (non-interruptible). Simply disable interrupts prior to the decrement, and re-enable them after a decrement.

In general, you need a critical section anytime an asynchronously-shared resource is manipulated. An ISR is typically treated as a critical section automatically by the hardware, by it raising the priority level. But you need to maintain the critical sections in the rest of your code.

Let me know if I didn't make sense. When I read what I have written, it often sounds like techno-babble.
0 项奖励
回复