NRF52832 - Send and receive up to 300 bytes via SPI

Hello,

I have 2x PCA10040 dev kits connected via SPI.

Device #1 is talking to a custom board MCU by UART

Device #2 is connected by BT to my android app

The task is to relay communication between the android app and the custom board. Communication can happen at any time in any direction. Maximum payload is 300 bytes.

I set Device #1 as SPIM, and I created a test payload of 300 bytes which is to be sent every 500ms to the slave device (Device #2).

Since the maximum SPI payload is around 256, I put together some code that should send 2 transfers in case the payload is larger.

#define SPI_PACKET_SIZE 250
static uint8_t m_spi_tx_dma_buf[SPI_PACKET_SIZE + 1];
static uint8_t m_spi_rx_dma_buf[SPI_PACKET_SIZE + 1];

const nrfx_spim_t radio_spi = NRFX_SPIM_INSTANCE(0);

void radio_spi_init()
{
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.frequency      = NRF_SPIM_FREQ_8M;
    spi_config.ss_pin         = SPIRADIO_CS;
    spi_config.miso_pin       = SPIRADIO_MISO;
    spi_config.mosi_pin       = SPIRADIO_MOSI;
    spi_config.sck_pin        = SPIRADIO_SCK;
    spi_config.bit_order = NRF_SPI_BIT_ORDER_LSB_FIRST;
    spi_config.ss_active_high = false;
    APP_ERROR_CHECK(nrfx_spim_init(&radio_spi, &spi_config, radio_spi_handler, NULL));
}

uint32_t radio_spi_write(const uint8_t *data, uint16_t len)
{
  uint32_t err_code;
  uint32_t pos = 0;
  uint8_t spi_tx_one_byte = 0;

  while (len > 0) {
      radio_spi_transfer_finished = false;
      if (len < SPI_PACKET_SIZE) {
        spi_tx_one_byte = len;
        m_spi_tx_dma_buf[0] = spi_tx_one_byte;
        memcpy(m_spi_tx_dma_buf + 1, &data[pos], len);
        len = 0;
      } else {
        spi_tx_one_byte = SPI_PACKET_SIZE;
        m_spi_tx_dma_buf[0] = spi_tx_one_byte;
        memcpy(m_spi_tx_dma_buf + 1, &data[pos], SPI_PACKET_SIZE - 1);
        pos += (SPI_PACKET_SIZE - 1);
        len -= (SPI_PACKET_SIZE - 1);
      }
              
      uint8_t rx[1];
      nrf_delay_ms(1);
      nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(m_spi_tx_dma_buf, spi_tx_one_byte, rx, 0);
      
      if (NRFX_SUCCESS != nrfx_spim_xfer(&radio_spi, &xfer_desc, 0)) {
        NRF_LOG_INFO("SPI WRITE FAILED!");
        goto write_exit;
      } else {
        //NRF_LOG_INFO("Sent %i bytes!",spi_tx_one_byte);
      }
      while (!radio_spi_transfer_finished)
        ;
      
    }
write_exit:
    return 0;
}


//the 300 bytes test payload

uint8_t spi_test_payload[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
                                0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
                                0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
                                0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,0xDD, 0xDD, 0xDD, 0xDD, 0xDD,
                                0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,0xEE, 0xEE, 0xEE, 0xEE, 0xEE,
                                0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};


  //////////////////RADIO TEST/////////////////
  while(1){
    radio_spi_write(spi_test_payload, sizeof spi_test_payload);
    nrf_delay_ms(500);
  }

On the receiving side I have this code:

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

static uint8_t m_tx_buf[250];          /**< TX buffer. */
static uint8_t m_rx_buf[250]; /**< 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. */




/**
 * @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;
    send_data_ble(m_rx_buf);
  }
}




/**
 * @brief Send data via bluetooth.
 *
 * @param payload
 */

void send_data_ble(uint8_t *payload) {
  uint32_t err_code;
  do {
    uint16_t length = sizeof(payload);
    uint32_t err_code = ble_nus_data_send(&m_nus, payload, &length, m_conn_handle);
    if ((err_code != NRF_ERROR_INVALID_STATE) &&
        (err_code != NRF_ERROR_RESOURCES) &&
        (err_code != NRF_ERROR_NOT_FOUND)) {
      APP_ERROR_CHECK(err_code);
    }
  } while (err_code == NRF_ERROR_RESOURCES);
}





int main(void) {

  nrf_gpio_pin_dir_set(CUSTOM_SPI_IRQ_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
  nrf_gpio_pin_clear(CUSTOM_SPI_IRQ_PIN);

  bool erase_bonds;

  // Initialize.
  log_init();
  timers_init();
  power_management_init();
  ble_stack_init();
  gap_params_init();
  gatt_init();
  services_init();
  advertising_init();
  conn_params_init();

  // 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;

  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;
  spis_config.bit_order = 1;

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

  advertising_start();

  uint32_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, 4); //increase power to maximum
  APP_ERROR_CHECK(err_code); 

  // Enter main loop.
  static uint8_t test_ble[] = {0xAA,0xBB,0xCC};
  while (1) {

    memset(m_rx_buf, 0, m_length);
    spis_xfer_done = false;

    APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, m_tx_buf, m_length, m_rx_buf, m_length));

    while (!spis_xfer_done) {
      __WFE();
      
    }
  }
}

I am just getting started in the embedded dev space and this is all new to me. My question is, how can I make my slave process those 2 transactions in a single buffer and send it via Bluetooth? Is this the right approach? Anything else I can do to my code to optimize it? Is that 1ms delay on the master side required or is the system fast enough to process everything without it?

Thanks in advance

  • will this work for bi-directional transfers? master send to slave and slave send to master (using irq pin)

  • Hi 

    That is a bit less straight forward. It is the master that decides how many bytes to clock out, which the slave would have to tell it somehow. 

    This is another argument for including the packet length as the first bytes of the message. 

    Then you could have a basic approach like this:

    1) IRQ pin is asserted by the slave

    2) The master sets the chip select pin low and starts a 2 byte transaction to read the length

    3) Based on the length the master sets up the second transaction, to pick up the data (for the slave this looks like a continuation of the first transaction, since chip select was kept low)

    4) The master sets the chip select pin high

    5) If the data length was > 253 bytes, the spi master sends another command to pick up the remaining bytes

    Best regards
    Torbjørn

  • Ok, this is way above my coding capabilities. Is there any way someone your team can write some some sample code for this? I am sure it will benefit many users who want to use SPI on any device other than nrf52840.

    Time to get into the Christmas spirit and give the gift of code to the community.

  • Hi

    This code shouldn't have to be much more complicated than the code you've already written, but I don't mind writing a small example for it, Christmas or not Wink

    I'll try to have it done by the end of the week. 

    Best regards
    Torbjørn

  • Thank you for that.

    Meanwhile, I have put together some code, and I would like to know how it can be optimized.

    Master sends to slave.

    Slave sends to master

    but after slave sends to master, master cannot send to slave anymore...

    SPI Slave Code:

    uint16_t total_data_length = 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) {
      uint16_t real_len;
        
      if (!spis_tx_mode)
        {
    			
    			if(!data_read_pending)		//if this is first/single transaction, 
    			{
    				total_data_length = bytes_to_u16(m_spi_rx_dma_buf[0],m_spi_rx_dma_buf[1]);		//get the payload size from the first 2 bytes
    			}
    			if(total_data_length > 250)		//payload size is greater then 250 
    			{
    				if(!data_read_pending)		//is this the first transaction?
    				{
    					//this is first transaction
    					memcpy(rx_data1, m_spi_rx_dma_buf, 252);
    					rx_data_len = total_data_length;
    					data_read_pending = true;
    				}
    				else
    				{
    					//this is the second transaction
    					uint16_t bytes_left = total_data_length - 250;
    					memcpy(rx_data1+252, m_spi_rx_dma_buf, bytes_left);
    					rx_data_len = total_data_length;
                                            data_read_pending = false;
                                            NRF_LOG_INFO("cnt: %d, received: %d, one: %X, last %X\n", rcv_cnt,rx_data_len, rx_data1[0], rx_data1[299]);
                                            rcv_cnt = rcv_cnt+1;
                                            //send_data_ble(rx_data); //here we need to ship this data by bluetooth (complete frame)
    				    total_data_length = 0;
    				}
    			}
    			else //payload size less than 250, this is a single transaction
    			{
    				
    				if(!data_read_pending) //we should never have this flag set to true, since this is a single transaction
    				{
    					memcpy(rx_data1+252, m_spi_rx_dma_buf, total_data_length);
    					rx_data_len = total_data_length;
                                            NRF_LOG_INFO("cnt: %d, received: %d, one: %X, last %X\n", rcv_cnt,rx_data_len, rx_data1[0], rx_data1[299]);
                                            rcv_cnt = rcv_cnt+1;
                                            //send_data_ble(rx_data); //here we need to ship this data by bluetooth (complete mini-frame)
    				    total_data_length = 0;
    				}
    				else
    				{
                                            NRF_LOG_INFO("CRITICAL FAILURE"); //data_read_pending should never be true for less than 250 bytes frames
    					
    				}
    			}			
    			
    			nrf_drv_spis_buffers_set(&spis, NULL, 0, m_spi_rx_dma_buf, sizeof m_spi_rx_dma_buf - 1); // problem here
        }
    
        spis_xfer_done = true;
        
      }
    }
    
    /**
     * @brief SPIS TX function.
     *
     * @param event
     */
    uint32_t spi_tx(uint8_t *data, uint32_t len) {
      uint32_t err_code;
      int i = 0;
      spis_tx_mode = 1;
      // check how many packets need to be sent if we send only 1 packet at a time with max size of 250 bytes
      uint8_t total_packets = 0; // total packets to send
      uint8_t packet_len = 0;
      if (len > 250) {
        total_packets = 2;
        packet_len = 250;
      } else {
        total_packets = 1;
        packet_len = len;
      }
    
      while (i < total_packets) {
        // split each packet and send
        uint8_t a = 0;
        uint8_t packet_to_send[255];
        if (i == 0) {
          // add the headers
          for (a = 0; a < packet_len; a++) {
            // keep space for headers in the first transaction
            packet_to_send[a + 2] = data[(i * 250) + a];
          }
        } else {
          for (a = 0; a < packet_len; a++) {
            // do not add any headers
            packet_to_send[a] = data[(i * 250) + a];
          }
        }
        i++;
        if (i != total_packets) {
          // add packet length in the first 2 bytes
          packet_to_send[0] = len >> 8;
          packet_to_send[1] = len;
        }
        // send the packet
        spis_xfer_done = false;
        if (i != total_packets) {
          // if its the first transaction, add 2 bytes count in the packet length
          err_code = nrf_drv_spis_buffers_set(&spis, packet_to_send, packet_len + 2, NULL, 0); // length byte + data
          VERIFY_SUCCESS(err_code);
        } else {
          err_code = nrf_drv_spis_buffers_set(&spis, packet_to_send, packet_len, NULL, 0); // length byte + data
          VERIFY_SUCCESS(err_code);
        }
        // NRF_LOG_INFO("Prepared %i bytes", packet_len);
        if (i == 1) {
          nrf_gpio_pin_set(CUSTOM_SPI_IRQ_PIN);
          nrf_delay_us(100);
          nrf_gpio_pin_clear(CUSTOM_SPI_IRQ_PIN);
        }
        while (!spis_xfer_done) {
          __WFE();
        }
        int d = 0;
        // calculate next data length
        if (i == total_packets) {
          // all data is sent
        } else if ((total_packets - i) == 1) {
          // only one packet left
          packet_len = len - 250;
        }
      }
      spis_tx_mode = 0;
    
      return NRF_SUCCESS;
    }
    
    /**
     * @brief Send data via bluetooth.
     *
     * @param payload
     */
    
    void send_data_ble(uint8_t *payload, uint8_t size) {
      uint32_t err_code;
      do {
        uint16_t length = size;
        uint32_t err_code = ble_nus_data_send(&m_nus, payload, &length, m_conn_handle);
        if ((err_code != NRF_ERROR_INVALID_STATE) &&
            (err_code != NRF_ERROR_RESOURCES) &&
            (err_code != NRF_ERROR_NOT_FOUND)) {
          APP_ERROR_CHECK(err_code);
        }
      } while (err_code == NRF_ERROR_RESOURCES);
    }
    
    /**@brief Application main function.
     */
    int main(void) {
    
      nrf_gpio_pin_dir_set(CUSTOM_SPI_IRQ_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
      nrf_gpio_pin_clear(CUSTOM_SPI_IRQ_PIN);
    
      // Initialize.
      log_init();
      timers_init();
      power_management_init();
      ble_stack_init();
      gap_params_init();
      gatt_init();
      services_init();
      advertising_init();
      conn_params_init();
      // nrf_gpio_cfg_output(8);
    
      // 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;
    
      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;
      spis_config.orc = 0x55; // this one
      spis_config.bit_order = 1;
      uint32_t err_code;
      APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));
      err_code = nrf_drv_spis_buffers_set(&spis, NULL, 0, m_spi_rx_dma_buf, sizeof m_spi_rx_dma_buf - 1); // problem here
      VERIFY_SUCCESS(err_code);
    
      advertising_start();
    
      err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, 4); // increase power to maximum
      APP_ERROR_CHECK(err_code);
      uint8_t spi_test_payload[] = {0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
          0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
          0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
          0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
          0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
          0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44};
    
      // Enter main loop.
      uint8_t small_payload[14] = {0x2f, 0x38, 0xEF, 0xAB, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
    
      NRF_LOG_INFO("Slave SPI Started!");
      while (1) {
    
             if(!nrf_gpio_pin_read(BUTTON_1))
           {
                nrf_delay_ms(150);
                if(!nrf_gpio_pin_read(BUTTON_1))
                {
                   spi_tx(spi_test_payload, 300);
                }
           }
    
      }
    }

    SPI Master Code:

    static volatile uint8_t radio_spi_transfer_finished = 0;
    static void radio_spi_handler(nrfx_spi_evt_t const *p_event, void *p_context) {
      radio_spi_transfer_finished = 1;
    }
    
    uint32_t radio_is_ready_to_read() {
      nrf_gpio_cfg(SPIRADIO_IO1,
          NRF_GPIO_PIN_DIR_INPUT,
          NRF_GPIO_PIN_INPUT_CONNECT,
          NRF_GPIO_PIN_PULLDOWN,
          NRF_GPIO_PIN_S0S1,
          NRF_GPIO_PIN_NOSENSE);
    
      return nrf_gpio_pin_read(SPIRADIO_IO1);
    }
    
    uint32_t radio_spi_read(uint8_t *dst, uint32_t dstlen) {
      uint16_t rx_data_len = 0;
      memset(dst, 0xFF, dstlen); // sanitize the buffer
    
    
    
      /***********************FIRST READ*************************************/
      nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_RX(dst, 252);
    
      flash_spi_transfer_finished = 0;
      if (NRFX_SUCCESS != nrfx_spim_xfer(&radio_spi, &xfer_desc, 0)) {
        NRF_LOG_INFO("SPI READ FAILED!");
        return 0;
      }
    
      while (!radio_spi_transfer_finished)
        ;
      /*********************************************************************/
    
      nrf_delay_us(500);
      uint16_t total_data_length = bytes_to_u16(dst[0], dst[1]);
      if (total_data_length > 250) // need to read more data in case its more then 250 bytes?
      {
        uint16_t bytes_left = total_data_length - 250;
        nrf_delay_ms(1); // give some delay so that slave can easily prepare the next packet
      /***********************SECOND READ (OPTIONAL)*************************************/
      nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_RX(dst+252, total_data_length-252);
    
      flash_spi_transfer_finished = 0;
      if (NRFX_SUCCESS != nrfx_spim_xfer(&radio_spi, &xfer_desc, 0)) {
        NRF_LOG_INFO("SPI READ FAILED!");
        return 0;
      }
    
      while (!radio_spi_transfer_finished)
        ;
      /************************************************************************************/
        nrf_delay_us(500);
        rx_data_len = total_data_length;
      } else {
        rx_data_len = total_data_length;
      }
    
      NRF_LOG_INFO("received: %d, one: %X, last %X\n", rcv_cnt, rx_data_len, dst[0], dst[299]);
    
      return dstlen;
    }
    
    
    
    
    /***************************************  FUNCTION TO WRITE SPI DATA ******************************************/
    uint32_t radio_spi_write(uint8_t *data, uint32_t len) {
      uint32_t err_code;
      int i = 0;
      // check how many packets need to be sent if we send only 1 packet at a time with max size of 250 bytes
      uint8_t total_packets = 0; // total packets to send
      uint8_t packet_len = 0;
      if (len > 250) {
        total_packets = 2;
        packet_len = 250;
      } else {
        total_packets = 1;
        packet_len = len;
      }
    
      while (i < total_packets) {
        // split each packet and send
        uint8_t a = 0;
        uint8_t packet_to_send[255];
        if (i == 0) {
          // add the headers
          for (a = 0; a < packet_len; a++) {
            // keep space for headers in the first transaction
            packet_to_send[a + 2] = data[(i * 250) + a];
          }
        } else {
          for (a = 0; a < packet_len; a++) {
            // do not add any headers
            packet_to_send[a] = data[(i * 250) + a];
          }
        }
        i++;
        if (i != total_packets) {
          // add packet length in the first 2 bytes
          packet_to_send[0] = len >> 8;
          packet_to_send[1] = len;
        }
        // send the packet
        radio_spi_transfer_finished = false;
        if (i != total_packets) {
          // if its the first transaction, add 2 bytes count in the packet length
          nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(packet_to_send, packet_len + 2, NULL, 0);
    
          if (NRFX_SUCCESS != nrfx_spim_xfer(&radio_spi, &xfer_desc, 0)) {
            NRF_LOG_INFO("SPI WRITE FAILED!");
            return 1;
          }
        } else {
          nrfx_spim_xfer_desc_t xfer_desc = NRFX_SPIM_XFER_TRX(packet_to_send, packet_len, NULL, 0);
    
          if (NRFX_SUCCESS != nrfx_spim_xfer(&radio_spi, &xfer_desc, 0)) {
            NRF_LOG_INFO("SPI WRITE FAILED!");
            return 1;
          }
        }
    
        while (!radio_spi_transfer_finished) // wait for finish
          ;
        nrf_delay_ms(3);
    
        int d = 0;
        // calculate next data length
        if (i == total_packets) {
          // all data is sent
        } else if ((total_packets - i) == 1) {
          // only one packet left
          packet_len = len - 250;
        }
      }
    
      return NRF_SUCCESS;
    }
    
    //****************************************************************************************************//
    
    void radio_spi_init() {
      nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
      spi_config.frequency = NRF_SPIM_FREQ_4M;
      spi_config.ss_pin = SPIRADIO_CS;
      spi_config.miso_pin = SPIRADIO_MISO;
      spi_config.mosi_pin = SPIRADIO_MOSI;
      spi_config.sck_pin = SPIRADIO_SCK;
      spi_config.bit_order = NRF_SPI_BIT_ORDER_LSB_FIRST;
      spi_config.ss_active_high = false;
      spi_config.orc = 0x5A;
      APP_ERROR_CHECK(nrfx_spim_init(&radio_spi, &spi_config, radio_spi_handler, NULL));
    }
    
    
    
    
      //////////////////MAIN LOOP/////////////////
      memset(spi_buffer, 0, sizeof(spi_buffer));
      nrf_gpio_cfg_input(BUTTON_1, NRF_GPIO_PIN_PULLUP);   //for devboard testing
      while(1){
    
           if(!nrf_gpio_pin_read(BUTTON_1))
           {
                nrf_delay_ms(150);
                if(!nrf_gpio_pin_read(BUTTON_1))
                {
                   radio_spi_write(spi_test_payload, sizeof spi_test_payload); 
                }
           }
    
                    
    if(radio_is_ready_to_read() == 1) 
    		{
                        uint8_t rx_data1[320];
                        radio_spi_read(rx_data1, 320);
    		}
    
    
      }

    Looking forward to your reply.

Related