Greetings!
I'm trying to set up an nRF52 board as an SPI slave so that it would receive chunks of data irregularly from the master device (a Raspberry Pi in this case, if it's important). However, I am not sure if I understand correctly the purpose of the SPIS API and how exactly should I use it. Here is how I'm doing it currently:
#include "nrfx_spis.h" static nrfx_spis_t m_spis = NRFX_SPIS_INSTANCE(0); static uint8_t rx_buffer[64]; static uint8_t tx_buffer[] = "HELLO"; static void spis_event_handler(nrfx_spis_evt_t const *p_event, void *p_context) { nrfx_err_t err_code; switch (p_event->evt_type) { case NRFX_SPIS_BUFFERS_SET_DONE: NRF_LOG_DEBUG("Buffers Set Done"); break; case NRFX_SPIS_XFER_DONE: NRF_LOG_DEBUG("XFer Done; RX %d / TX %d, Received: ", p_event->rx_amount, p_event->tx_amount); for (size_t i = 0; i < p_event->rx_amount; i++) { NRF_LOG_DEBUG("%d: %x", i, rx_buffer[i]); } memset(rx_buffer, 0, 64); err_code = nrfx_spis_buffers_set(&m_spis, tx_buffer, 6, rx_buffer, 63); APP_ERROR_CHECK(err_code); break; default: break; }; } static void spis_init() { nrfx_err_t err_code; nrfx_spis_config_t spis_config = { .mosi_pin = 11, .miso_pin = 12, .sck_pin = 13, .csn_pin = 14, .mode = NRF_SPIS_MODE_0, .bit_order = NRF_SPIS_BIT_ORDER_MSB_FIRST, .csn_pullup = NRFX_SPIS_DEFAULT_CSN_PULLUP, .miso_drive = NRFX_SPIS_DEFAULT_MISO_DRIVE, .def = NRFX_SPIS_DEFAULT_DEF, .orc = NRFX_SPIS_DEFAULT_ORC, .irq_priority = NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY, }; memset(rx_buffer, 0, 64); err_code = nrfx_spis_init(&m_spis, &spis_config, spis_event_handler, NULL); APP_ERROR_CHECK(err_code); err_code = nrfx_spis_buffers_set(&m_spis, tx_buffer, 6, rx_buffer, 63); APP_ERROR_CHECK(err_code); } int main(void) { // ... spis_init(); // ... for (;;) { idle_state_handle(); }
(I understand that I suppose to adjust buffers after transfers, but I don't think it's important for now).
Issue is, I'm not sure I completely understand the
nrfx_spis_buffers_set
function.I.e, here is how I understand what I am doing. Please correct me if I misunderstood anything:
1. Init SPI device
2. Tell SPI that I have a RX and TX buffers ready with
nrfx_spis_buffers_set
3. When Master initiates transfer, Master and Slave exchange bytes, up to
tx_buffer_length
bytes sent and rx_buffer_length
received4. After the transfer, event handler is called with
NRFX_SPIS_XFER_DONE
event type, tx_amount bytes transferred and rx_amount bytes received5. Within the event handler, I must updates buffers if necessary and call
nrfx_spis_buffers_set
again with new data to be read/sentFor reference, here is the code for raspberry pi:
#!/usr/bin/env python3 import pigpio pi = pigpio.pi() if not pi.connected: print("connection failed") exit() # slave 0, speed 50000, mode 0 s = pi.spi_open(0, 50000, 0) data = bytearray("hello, world", "utf-8") (count, rx_data) = pi.spi_xfer(s, data) print("Received %s bytes: %s" % (count, rx_data))
So I'm trying to exchange "hello, world" string from raspberry pi and "HELLO" string from nRF52. However, in the end, I get something messed up:
<debug> app: XFer Done; RX 8 / TX 6, Received: <debug> app: 0: 68 (h) <debug> app: 1: 65 (e) <debug> app: 2: 6C (l) <debug> app: 3: 6C (l) <debug> app: 4: 6F (o) <debug> app: 5: 2C (,) <debug> app: 6: 20 ( ) <debug> app: 7: 77 (w) <debug> app: Buffers Set Done <debug> app: XFer Done; RX 2 / TX 2, Received: <debug> app: 0: 6F (o) <debug> app: 1: 72 (r) <debug> app: Buffers Set Done
And on raspberry pi side:
Received 12 bytes: bytearray(b'HELLO\x00\xff\xff\xffHD\xff')
(I understand that I keep sending HELLO over and over again, but where did that D even came from?)
I was able to get a proper result once (i.e. withtin a single transfer, 12 bytes in one direction, 6 in another, all properly sent), but I was never able to get that again.
I think I should also mention that I tried enabling anomaly 109 workaround, but then I can't even init SPIS because of NRFX_ERROR_INTERNAL.
What am I doing wrong? I have a suspicion that I'm messing up buffers by declaring them like that; But is my understand of the process of SPI transfer correct? What here could cause those incomplete (and sometimes incorrect) transfers? What could be improved in the code?
Thanks in advance.