There are several possibilities to protect critical sections of code from being interrupted:
1. Temporarily disabling and enabling interrupts:
void function(void) { EA = 0; // atomic_section... EA = 1; }
Disadvantage: This will change the status of EA if interrupts had not been enabled before.
2. Saving and restoring EA: http://www.keil.com/forum/1080/
bit ea_saved; void function(void) { ea_saved = EA; EA = 0; // atomic_section... EA = ea_saved; }
Disadvantage: if this code can be interrupted between ea_saved=EA and EA=0. If the interrupt service routine decides to disable interrupts, the interrupts will become enabled again when doing EA=ea_saved after the critical section.
3. Using #pragma disable http://www.keil.com/support/man/docs/c51/c51_disable.htm http://www.keil.com/forum/1080/
#pragma disable void function (void) { // atomic_section... }
Advantage: Avoids the above problem because the JBC opcode is used to evaluate the current state of EA and clear EA with the same instruction:
; FUNCTION function (BEGIN) SETB C JBC EA,IS_CLEARED CLR C IS_CLEARED: PUSH PSW // atomic_section... POP PSW MOV EA,C RET ; FUNCTION function (END)
Disadvantage: Can be applied to whole functions only. Requires 1 Byte on the stack.
4. Combination of 2. and 3.
#include <intrins.h> #define ATOMIC_SECTION_BEGIN { ea_saved = 1; if (!(_testbit_(EA))) { ea_saved = 0; } } #define ATOMIC_SECTION_END { EA = ea_saved; } #define INTERRUPTS_DISABLE { EA = 0; ea_saved = 0; } #define INTERRUPTS_ENABLE { EA = 1; ea_saved = 1; } bit ea_saved; void function(void) { ATOMIC_SECTION_BEGIN // atomic_section... ATOMIC_SECTION_END }
This results in
ATOMIC_SECTION_BEGIN SETB ea_saved JBC EA,?C0007?HB CLR ea_saved ?C0007?HB: // atomic_section... ATOMIC_SECTION_END MOV C,ea_saved MOV EA,C
Advantages: Pure source code, no inline assembly. Atomic section can remain inline, no sub-function required. Only one bit for status saving required.
You missed the actual issue. I did not thr OP: "Disadvantage: if this code can be interrupted between ea_saved=EA and EA=0. If the interrupt service routine decides to disable interrupts,"
can you just imagine the effects of the above?
Erik
thr OP:
Erik, when you write a one-line reply to a 100-line posting, your reply only relates to one aspect of one of its paragraphs, you really should leave some indication what you're referring to. Otherwise how was anyone (e.g. me) supposed to know that "no need" referred to that small shred, instead of the whole posting?
Human language creates enough unavoidable misunderstandings --- no need to make it worse by being obscure.
I did not
Which is worse, erik?
a) you missed the point or b) you didn't know that you missed the point.