2025-02-02 07:49 PM
I have some data that is accessed from a normal context and also from an IRQ. I am disabling the interrupt to prevent interrupted access. So no concerns there. However, what about forcing both the normal context and the interrupt context to have the same data? Do I need to declare every accessed variable as std::atomic? Or can I wrap the section of code in something else that ensures every variable inside of it gets flushed or something once that function is exited?
example code
void PRL_Receive::CleanStart()
{
uint32_t ien;
ien = NVIC_GetEnableIRQ(UCPD1_2_IRQn);
NVIC_DisableIRQ(UCPD1_2_IRQn);
state = PRL_Rx_Wait_for_PHY_Message;
entry = true;
bMsgReceivedFlag = false;
isSoftReset = false;
MessageID = 0U;
bMsgIDRecvd = false;
isCRCSent = false;
u8txResult=0;
bResultValid=false;
prlRxRecvBytes = 0U;
if(ien){
NVIC_EnableIRQ(UCPD1_2_IRQn);
}
}
after this is called by the IRQ I want the normal context to see all the updated values the next time it accesses any of these. Or if its called by the normal context, the next time the IRQ access them I want it to have the latest value as well. Apparently, in c/c++ volatile is not enough.
2025-02-02 10:54 PM
I suppose you are mixing up different things here.
> Do I need to declare every accessed variable as std::atomic?
> ...
> Apparently, in c/c++ volatile is not enough.
Surely "volatile" does not apply here. This just instructs to actually access the variable when the source code does so, and not try any optimisations based upon static analysis.
While I have limited experience with C++, "atomic" usually refers to the object / memory cell access alone. This will not prevent any interrupt from changing the value in between subsequent accesses. Because this is usually what happens - get a "state flag", perform an action, and update that "state flag".
Full-size OSes and multithreading environments (like Pthreds) provide proper tools for this problem, mutexes, semaphores, or critical sections.
> I have some data that is accessed from a normal context and also from an IRQ. I am disabling the interrupt to prevent interrupted access.
AFAIK those multithreading environments do it the same way, by disabling interrupts and task switching to avoid race conditions during accessing.
When you wrap each access from the application context in DI / EI, the variables should be consistent in every instance.