This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI Slave Example Data transfer issue

Hi,

I am using spis example from "SDK v17.0.2" with slight modification in the code as given below

#include "sdk_config.h"
#include "nrf_drv_spis.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#define SPIS_INSTANCE 1 /**< SPIS instance index. */
static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE);/**< SPIS instance. */

#define TEST_STRING "STM32TS"
static uint8_t       m_tx_buf[] = TEST_STRING;           /**< TX buffer. */
static uint8_t       m_rx_buf[sizeof(TEST_STRING) + 1];    /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf);        /**< Transfer length. */

static volatile bool spis_xfer_done; /**< Flag used to indicate that SPIS instance completed the transfer. */

static uint8_t Tx = 0;
static uint8_t Rx = 0;
uint8_t cnt= 0;

/**
 * @brief SPIS user event handler.
 *
 * @param event
 */
void spis_event_handler(nrf_drv_spis_event_t event)
{
    if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
    {
        spis_xfer_done = true;
		Tx = m_tx_buf[cnt];
		APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, &Tx, 1, &Rx, 1));
		cnt++;
	}
}

int main(void)
{
    // Enable the constant latency sub power mode to minimize the time it takes
    // for the SPIS peripheral to become active after the CSN line is asserted
    // (when the CPU is in sleep mode).
    NRF_POWER->TASKS_CONSTLAT = 1;

    //bsp_board_init(BSP_INIT_LEDS);

    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();

    NRF_LOG_INFO("SPIS example");

    nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
    spis_config.csn_pin               = APP_SPIS_CS_PIN;
    spis_config.miso_pin              = APP_SPIS_MISO_PIN;
    spis_config.mosi_pin              = APP_SPIS_MOSI_PIN;
    spis_config.sck_pin               = APP_SPIS_SCK_PIN;

    APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));

    Tx = m_tx_buf[cnt];
    APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, &Tx, 1, &Rx, 1));
    cnt++;

    while (1)
    {
        memset(m_rx_buf, 0, m_length);
        spis_xfer_done = false;        

        while (!spis_xfer_done)
        {
            __WFE();
        }

        NRF_LOG_FLUSH();

        bsp_board_led_invert(BSP_BOARD_LED_0);
    }
}

On the Master end CS pin is pulled low and send 1 byte(0x45) only at a time. On the BLE I defined "nrf_drv_spis_buffers_set" inside "spis_event_handler" in order to read the next byte in the buffer  and add to the buffer automatically.

When the chip selection is low, I received the first byte as correct followed by "0xFF" data as shown below

I have to toggle the chip selection on the master end in order to read the second byte again followed by "0xFF"(MISO high state) data which you can see on the above picture and so on..

Why can't I read the bytes continuously (0x53,0x54,0x4D,...) without toggling chip selection?

As per the documentation "New buffers must be set by calling nrf_drv_spis_buffers_set after every finished transaction. Otherwise, the transaction is ignored, and the default character is clocked out."

Any suggestion on this would be much appreciated.

Regards

Siva

Parents Reply Children
  • Hi Einar,

    In our application we are reading only 1-Byte at a time from the master side. Once the transaction is complete, "spis_event_handler" will gets called and adds the second byte into first byte of the buffer register which I defined nrf_drv_buffers_set inside spis_event_handler to do this.

    Now the master will send another byte to read the second byte stored in the buffer registers first byte. 

    I don't know if I can do something like this? The above method working if I toggle the chip selection pin.

    Regards

    Siva

  • Hi Einar,

    It's the "Chip Select" and "nrf_drv_buffers_set" events that actually triggering "spis_event_handler" condition.

    Is there an spis event that can trigger after every byte of transaction completed?

    I guess SPIS uses Easy-DMA which is why I won't be able to read an interrupt between transactions. I guess I need to implement without using DMA but with interrupt driven correct me if I am wrong.

    Do you have an SPIS  example with interrupt driven?

    Regards

    Siva

  • Hi Siva,

    Siva@Tsien said:
    Is there an spis event that can trigger after every byte of transaction completed?

    No, the SPIS peripheral doe snot have any possibility to generate that. And the transaction is only considered completed when CNS goes high (see SPI slave operation).

    Siva@Tsien said:
    Do you have an SPIS  example with interrupt driven?

    No. The SPIS peripheral only operates on DMA. (For SPI master there is the SPI peripheral which does not rely on DMA, but there is no corresponding SPI slave peripheral in the nRF52832).

Related