Re: ATOMIC OPERATIONS?
Posted: Wed Feb 23, 2022 9:26 am
Continuing the original discussion here: viewtopic.php?f=9&t=618&start=0
Cc'ing participants: @Necromant @jcmvbkbc @Nurgak @dkinzer
(opened a new topic as it's an old post and I'm not sure what's the forum policy regarding 'necroposting')
Do you really need to disable all interrupts? Similar to spin_lock/unlock operations as in the linux kernel, if all you want is to synchronize access to critical data between code that could end up being run 'simultaneously', why can't you just use a `uint8_t` global variable as a semaphore?
That's what I'm doing here to synchronize access to a ESP-Now message buffer between the ESP-Now receive callbacks and the main loop() code:
Surely loading a single-byte constant into a uint8_t, can't be interrupted?
Or am I misunderstanding something?
Cheers,
-- Durval.
Cc'ing participants: @Necromant @jcmvbkbc @Nurgak @dkinzer
(opened a new topic as it's an old post and I'm not sure what's the forum policy regarding 'necroposting')
Necromant wrote:Is there a proper way to make an atomic section to be 100% sure no interrupt kicks in during it?
is there something likeCode: Select allATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
...
}
we had on avr or spin_lock_irqsave/spin_unlock_irqrestore calls in linux kernel?
Do you really need to disable all interrupts? Similar to spin_lock/unlock operations as in the linux kernel, if all you want is to synchronize access to critical data between code that could end up being run 'simultaneously', why can't you just use a `uint8_t` global variable as a semaphore?
That's what I'm doing here to synchronize access to a ESP-Now message buffer between the ESP-Now receive callbacks and the main loop() code:
Code: Select all
#define ESPNOW_MAXMSGSIZE 250 //maximum message size, from specs
#define ESPNOW_RECV_MSG_STATUS_FREE 0 //Receive buffer message is free (no message received yet, or received and already processed)
#define ESPNOW_RECV_MSG_STATUS_READY 1 //Message in buffer ready to be processed
char espNowRecvMsgBuf[ESPNOW_MAXMSGSIZE]; //Receive message buffer
uint8_t espNowRecvMsgStatus; //Ditto, access semaphore
[...]
//ESPNow receive callback function
void espNowRecvCB(uint8_t *mac_addr, uint8_t *incomingData, uint8_t len)
{
[...]
while (espNowRecvMsgStatus != ESPNOW_RECV_MSG_STATUS_FREE) {
//wait for pending receive to be processed so we don't overwrite an unprocessed message in the buffer
yield();
}
//Copy the incoming message into buffer to be processed by program's main execution flow, and set flag
memcpy(espNowRecvMsgBuf, incomingData, len);
espNowRecvMsgStatus = ESPNOW_RECV_MSG_STATUS_READY;
}
[...]
loop()
{
[...]
//copy the ESP-Now message from the callback receive buffer and reset the semaphore
if (espNowRecvMsgStatus == ESPNOW_RECV_MSG_STATUS_READY) {
strcpy(remoteData.espNowLastMsg, espNowRecvMsgBuf);
espNowRecvMsgStatus = ESPNOW_RECV_MSG_STATUS_FREE;
}
#endif
[...]
}
Surely loading a single-byte constant into a uint8_t, can't be interrupted?
Or am I misunderstanding something?
Cheers,
-- Durval.