Hi, I am using the nRF51822 with SDK 12.3.0
I am trying to make use of nrf_drv_spis driver included in the SDK.
My purpose is to have nRF51822 constantly be RX-ing over SPI - which means it will TX exactly 1B: 0x00.
However every now and then, it will need to TX some data too. This raises the question:
While buffers are already set, after the BUFFERS_SET_DONE has been received, how can I SAFELY change buffers?
This is not about safely changing DMA buffers etc. This is about not losing data during a potential SPI session. Let me explain.
There are two possible scenarios:
1. SPI is idle, I call nrf_drv_spis_buffers_set with the new RX and TX buffer
- semaphore is idle, instantly ACQUIRED by CPU and BUFFERS_SET_DONE event is received even before nrf_drv_spis_buffers_set.
- when a future SPI transaction completes, COMPLETED event is received, for the new buffers
In other words, previous buffers are discarded since they were never exchanged. This makes sense.
2. SPI is in the middle of a transaction (CS low) therefore semaphore is owned by SPI when I call nrf_drv_spis_buffers_set with new RX and TX buffers
- nrf_drv_spis_buffers_set returns
- SPI transaction completes (CS high)
- semaphore is ACQUIRED by CPU as a result of END_ACQUIRE short being enabled in driver
- BUFFERS_SET_DONE event is received for the new buffers (since it is checked first in ISR)
- immediately after, COMPLETED event is received for the original buffers
- when a future SPI transaction completes, COMPLETED event is received, for the new buffers
In other words, previous buffers contain valid data and need to be processed.
Therefore the question becomes:
Programatically, how do I differentiate between 1 and 2? How do I know if the first COMPLETED event is referring to the original set of buffers or to the ones just posted?
This also matters whether I need to call nrf_drv_spis_buffers_set during COMPLETED event - since for case 2, I don't need to for the first COMPLETED. Getting this wrong would mean SPIS lockout with semaphore always held by CPU if I fail to call nrf_drv_spis_buffers_set.
I thought about poisoning the RX buffer with impossible values (protocol-dependent) but then I realized a SPI transaction can have 0 bytes read and is still a valid transaction, buffers contain valid data etc. And this just doesn't feel right.
What I would really need is either:
- COMPLETED called before BUFFERS_SET_DONE in 2nd scenario - but driver comment states that would be wrong, likely due to driver state machine limitations
- BUFFERS_SET_DONE reporting whether they are due to a COMPLETED event - not sure if this can be made safe against race conditions
- COMPLETED reporting whether there was an outstanding buffer set that was queued in the same ISR by ACQUIRED event - again this may be racey
Is there any technique that I missed which can be used to achieve reliable TX during a potential SPI transaction
Thanks!