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