I'm developing a custom driver (C++) for the SPI master. Somewhere I've made a mistake, where the first received byte is written with a memory offset in SPI mode 1. I.e. we expect the slave to return three bytes [0x0C 0xA3 0xC0], but we must read four bytes and we receive [0x?? 0x0C 0xA3 0x33]. We've verified with an oscilloscope that the slave responds as expected and that the SPI mode is correct and the slave is selected correctly.
To initiate the transfer we use this code:
// Static variables
static constexpr uint8_t kBufferSize = 4U;
static volatile rx_buffer[kBufferSize];
static volatile tx_buffer[kBufferSize];
// Transaction start
// (Since we're only reading we could set the TX values to something more
// elegant, but for simplicitly we set them explicitly)
NRF_SPIM0->CONFIG = (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) |
(SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos);
NRF_SPIM0->TXD.PTR = reinterpret_cast<uint32_t>(tx_buffer);
NRF_SPIM0->RXD.PTR = reinterpret_cast<uint32_t>(rx_buffer);
NRF_SPIM0->TXD.MAXCNT = kBufferSize;
NRF_SPIM0->RXD.MAXCNT = kBufferSize;
NRF_SPIM0->TASKS_START = 0x01U;
// Interrupt service routine
NRF_SPIM0->EVENTS_END = 0U;
NRF_SPIM0->EVENTS_STOPPED = 0U;
NRF_SPIM0->EVENTS_ENDRX = 0U;
NRF_SPIM0->EVENTS_ENDTX = 0U;
NRF_SPIM0->EVENTS_STARTED = 0U;
// Slave transmits [0x0C 0xA3 0xC0 0xFF]
// Rx buffer contains [0x?? 0x0C 0xA3 0xC0]
Do you have a screenshot of CSN, SCK, MISO, and MOSI when this occurs? Are you sure you are taking into account that there will be a byte in parallel on MISO when for instance the command byte is sent on MOSI.
Yes, here is a screenshot from the oscilloscope. In this case we're also outputting a command, but its not relevant for this case. What I expected to receive from this was a RX buffer of 0x0C 0xC4 0x75 0xFF, but instead it contained 0x?? 0x0C 0xC4 0x75.
Yes, I'm aware of the parallel byte. This is (in my opinion) a slightly odd IC in that it doesn't receive a command prior to outputting the data.
My suggestion here is to take the \nRF5_SDK_15.2.0_9412b96\examples\peripheral\spi and use that as reference. The NRF_SPIM_TASK_START is called in spim_xfer() for example, you may set a breakpoint prior to this to check all spim configuration.
Good idea! I'll poke around in the examples and drivers and see what I can find.
Edit: Somehow, this seems to magically have resolved itself. Suddenly, it started spitting out garbage data again, and when I troubleshoot it, lo and behold, the data was now stored correctly in the buffer. I could swear I cleaned the build several times, but I'm going to blame bad build for now.