Title: How to exploit double buffering for reading digital inputs state?
Tags: c++;embedded;real-time;microcontroller;spi
Question: I have following situation. I have a microcontroller which communicates with two external I/O expander chips via one SPI peripheral. Each of the chips has eight digital inputs and is equiped with the latch input which ensures that both bytes of the digital inputs can be sampled at one instant in time. To communicate the state of both the bytes into my microcontroller I need to do two SPI transactions. At the same time I need to ensure that the software in my microcontroller will work with consistent state of both the bytes.
My first idea how to solve this problem was to use sort of double buffer. Below is a pseudocode describing my idea.
uint8_t di_array_01[2] = {0};
uint8_t di_array_02[2] = {0};
uint8_t *ready_data = di_array_01;
uint8_t *shadow_data = di_array_02;
uint8_t *temp;
if(chip_0_data_received) {
*shadow_data = di_state_chip_0;
chip_0_data_received = false;
} else if(chip_1_data_received) {
*(shadow_data + 1) = di_state_chip_1;
temp = ready_data;
ready_data = shadow_data;
shadow_data = temp;
chip_1_data_received = false;
The higher software layer will always work with the content of the array pointed by the ready_data pointer.  My intention is that setting of the boolean flags chip_0_data_received (chip_1_data_received) will be done in the &quot;end of transaction&quot; interrupt and the code below will be invoked from the background loop along with code for starting of the SPI transaction.
Does anybody see any potential problem which I have omitted?
Comment: You can't set `shadow_data = ready_data` immediately after setting `ready_data = shadow_data` because `shadow_data` will remain unchanged.  If you intend to swap the pointers then maybe use a temporary pointer like `temp = ready; ready = shadow; shadow = temp;`.  But why are the arrays named `di_ready` and `di_shadow` if you intend for their roles to be swapped?

Comment: Is this an 8-bit microcontroller or 16/32 bit?

Comment: @TomV it is 32 bits microcontroller.


Here is another answer: If your data is only 16 bits in total you can read and write it atomically.
uint16_t combined_data;
// in reading function
if (chip_0_data_received &amp;&amp; chip_1_data_received)
combined_data = (((uint16_t)di_state_chip_1 << 8) | di_state_chip_0);
// in using function
uint16_t get_combined_data = combined_data;
uint8_t data_chip_1 = ((get_combined_data &gt;&gt; 8) &amp; 0xFF);
uint8_t data_chip_0 = ((get_combined_data &gt;&gt; 0) &amp; 0xFF);

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 3, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2021:00:02/18/21', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<c++><embedded><real-time><microcontroller><spi>', 'Title': 'How to exploit double buffering for reading digital inputs state?', 'ViewCount': 76, 'id': 66265587, 'user_AboutMe': None, 'user_AccountId': 20673538.0, 'user_DisplayName': 'Professor Jimatura', 'user_Reputation': 79.0, 'user_Views': 9.0, 'user_id': 15178715.0}}