We have inherited a project which targets Renesas RX231 microcontroller that I have been looking at.
This uC has only one instruction that locks the bus for atomicity (XCHG).
Because the processor is the only component that accesses RAM memory (no DMA or DTC being used), to manipulate variables in user code that are shared with interrupts, the interrupts are disabled (in the processor status word register) for the access time i.e.
disable_interrupts(); /* set_psw(get_psw() & ~(1 << 16)); */
/* access or modify shared variables */
enable_interrupts(); /* set_psw(get_psw() | (1 << 16)); */
However, there are also "flags" being shared without guarding, which are set in interrupts and polled in user code in the following way:
volatile unsigned char event_request_message = 0;
unsigned char condition_sending_message = 0;
#pragma interrupt
void on_request_message()
{
...
event_request_message = 1; // mov.l #0x3df5, r14
// mov.b #1, [r14]
...
}
void user_code()
{
for(;;)
{
...
/* might be evaluated multiple times before transmit message is completed */
if(event_request_message && !condition_sending_message) // mov.l #0x3df5, r14
// movu.b [r14], r14
// cmp #0, r14
// beq.b 0xfff8e17b <user_code+185>
// mov.l #0x5990, r14
// movu.b [r14], r14
// cmp #0, r14
// bne.b 0xfff8e16f <user_code+173>
{
event_request_message = 0; // mov.l #0x3df5, r14
// mov.b #0, [r14]
condition_sending_message = 1; // mov.l #0x5990, r14
// mov.b #1, [r14]
/* transmit message */
...
}
...
}
}
My understanding of no guarding (by disabling interrupts in user code) in this case would be:
- To read, set or clear a "flag" always two instructions are used, one to put the memory address in a register and one to read/set/clear
- Memory addresses are always the same so can be discarded from consideration
- Each read/set/clear operation then is a single instruction and therefore the access/manipulation is atomic
The question is: is my understanding correct? Is such "flag" variables access and manipulation safe in this case?
Or could there be any possible bugs/errors?
- Assume the compiler used and compiler options are always the same.
- Assume that the operations described are the only way such "flags" are accessed/manipulated (set to 0 or 1, read (all shown in assembly code)) (no addition, multiplication, etc.)
What if we needed to upgrade the compiler or change compiler options?
Could such simple operations result in more than "one instruction"?
The justification of using such "flags" without guarding is too limit the amount time interrupts are disabled.
Looking at the code logic, the expected behaviour is that you can request a message one or more times but you only get one answer.
PS. I tried to use the following additional tags: "cc-rx", "rxv2-instruction-set", "rx231".