Hi, I am trying to do the SPI communication between a SPI master and two SPI slaves. I am using NRF52840 Dev Kit as SPI master and 2 ESP32-S3 as SPI slaves. I am using SDK version 17.1 for NRF. I am sending and receiving a 32 bytes of data. My work flow is to send a 32 Bytes of data from Master to Slave then Slave will respond on that . So as per the SPI I need to send two commands from Master to read the data from Slave. In first command '0x11', Slave will prepare the data on its side, then Master will send a dummy command '0x13' to read that data. Currently for debugging I have added a dummy data to transmit and receive. Total data which I may need to transmit or receive could be 2 Kbytes.
For template I have used the SPI example from the SDK peripheral example
I have used the following pins for SPI master on NRF side
#define ESP1_IO_PIN 36
#define ESP_32_S3_1_PWR 6 // MUX Select PIN
#define ESP_ESP_32_S3_1_TRIG 15
#define ESP_32_S3_1_SS 12 // P0.12
#define ESP1_SPI_MISO_PIN 11 // P0.11
#define ESP1_SPI_MOSI_PIN 41 // P1.09
#define ESP1_SPI_SCK_PIN 40 // P1.08
#define ESP1_EN_PIN 33 // P1.08
#define ESP2_IO_PIN 43
#define ESP_32_S3_2_PWR 46
#define ESP_32_S3_2_SS 45
#define ESP2_SPI_MISO_PIN 13
#define ESP2_SPI_MOSI_PIN 17
#define ESP2_SPI_SCK_PIN 16
#define ESP2_EN_PIN 44 // P1.08
#define ESP_32_S3_1_SPI_INSTANCE 1
#define ESP_32_S3_2_SPI_INSTANCE 2
I have added the main.c code here
/** * Copyright (c) 2015 - 2021, Nordic Semiconductor ASA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include "nrf_drv_spi.h" #include "app_util_platform.h" #include "nrf_gpio.h" #include "nrf_delay.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 DATA_CHECKSUM 255 // This value is calculated depending upon the value recevied by master. uint8_t dataChecksum = 0; void createChecksumforData(); #define ESP1_IO_PIN 36 #define ESP_32_S3_1_PWR 6 // MUX Select PIN #define ESP_ESP_32_S3_1_TRIG 15 #define ESP_32_S3_1_SS 12 // P0.12 #define ESP1_SPI_MISO_PIN 11 // P0.11 #define ESP1_SPI_MOSI_PIN 41 // P1.09 #define ESP1_SPI_SCK_PIN 40 // P1.08 #define ESP1_EN_PIN 33 // P1.08 #define ESP2_IO_PIN 43 #define ESP_32_S3_2_PWR 46 // Chip select pin for SPI 2 interface #define ESP_32_S3_2_SS 45 #define ESP2_SPI_MISO_PIN 13 #define ESP2_SPI_MOSI_PIN 17 #define ESP2_SPI_SCK_PIN 16 #define ESP2_EN_PIN 44 // P1.08 #define ESP_32_S3_1_SPI_INSTANCE 1 #define ESP_32_S3_2_SPI_INSTANCE 2 static const nrf_drv_spi_t esp_1_spi = NRF_DRV_SPI_INSTANCE(ESP_32_S3_1_SPI_INSTANCE); /**< SPI instance. */ static const nrf_drv_spi_t esp_2_spi = NRF_DRV_SPI_INSTANCE(ESP_32_S3_2_SPI_INSTANCE); /**< SPI instance. */ static volatile bool spi_xfer_done; /**< Flag used to indicate that SPI instance completed the transfer. */ //uint8_t #define BUFFER_SIZE 32 uint8_t imageChecksum = 0; static uint8_t m_tx1_buf[BUFFER_SIZE] ={0}; static uint8_t m_rx1_buf[BUFFER_SIZE]; /**< RX buffer. */ static const uint8_t m_length1 = sizeof(m_tx1_buf); /**< Transfer length. */ static uint8_t m_tx2_buf[BUFFER_SIZE] ={0}; static uint8_t m_rx2_buf[BUFFER_SIZE]; /**< RX buffer. */ static const uint8_t m_length2 = sizeof(m_tx2_buf); /**< Transfer length. */ /** * @brief SPI user event handler. * @param event */ void spi_event_handler(nrf_drv_spi_evt_t const * p_event, void * p_context) { spi_xfer_done = true; NRF_LOG_INFO("Transfer completed."); // if (m_rx_buf[0] != 0) // Check received data in SPI Rx buffer { //NRF_LOG_INFO(" Received:"); //NRF_LOG_HEXDUMP_INFO(m_rx_buf, sizeof(m_rx_buf)); } } bool toggle = 1; int main(void) { nrf_gpio_cfg_output(ESP_32_S3_2_PWR); nrf_gpio_pin_clear(ESP_32_S3_2_PWR); nrf_gpio_cfg_output(ESP_32_S3_1_PWR); nrf_gpio_pin_clear(ESP_32_S3_1_PWR); APP_ERROR_CHECK(NRF_LOG_INIT(NULL)); NRF_LOG_DEFAULT_BACKENDS_INIT(); nrf_gpio_cfg_output(ESP_32_S3_2_PWR); nrf_gpio_pin_set(ESP_32_S3_2_PWR); nrf_gpio_cfg_output(ESP_32_S3_1_PWR); nrf_gpio_pin_set(ESP_32_S3_1_PWR); nrf_delay_ms(5000); nrf_drv_spi_config_t spi_esp1_config = NRF_DRV_SPI_DEFAULT_CONFIG; nrf_drv_spi_config_t spi_esp2_config = NRF_DRV_SPI_DEFAULT_CONFIG; spi_esp1_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;//SPI_SS_PIN;// spi_esp1_config.miso_pin = ESP1_SPI_MISO_PIN; // SPI_MISO_PIN spi_esp1_config.mosi_pin = ESP1_SPI_MOSI_PIN; // SPI_MOSI_PIN; spi_esp1_config.sck_pin = ESP1_SPI_SCK_PIN; // SPI_SCK_PIN; spi_esp1_config.mode = NRF_DRV_SPI_MODE_0; spi_esp1_config.frequency = NRF_DRV_SPI_FREQ_4M; spi_esp2_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED;//SPI_SS_PIN;// spi_esp2_config.miso_pin = ESP2_SPI_MISO_PIN; // SPI_MISO_PIN spi_esp2_config.mosi_pin = ESP2_SPI_MOSI_PIN; // SPI_MOSI_PIN; spi_esp2_config.sck_pin = ESP2_SPI_SCK_PIN; // SPI_SCK_PIN; spi_esp2_config.mode = NRF_DRV_SPI_MODE_0; spi_esp2_config.frequency = NRF_DRV_SPI_FREQ_4M; APP_ERROR_CHECK(nrf_drv_spi_init(&esp_1_spi, &spi_esp1_config, NULL, NULL)); APP_ERROR_CHECK(nrf_drv_spi_init(&esp_2_spi, &spi_esp2_config, NULL, NULL)); NRF_P0->PIN_CNF[ESP2_SPI_SCK_PIN] |= (NRF_GPIO_PIN_H0H1 << GPIO_PIN_CNF_DRIVE_Pos); NRF_P1->PIN_CNF[8] |= (NRF_GPIO_PIN_H0H1 << GPIO_PIN_CNF_DRIVE_Pos); nrf_gpio_cfg_output(ESP_32_S3_1_SS); nrf_gpio_pin_set(ESP_32_S3_1_SS); nrf_gpio_cfg_output(ESP_32_S3_2_SS); nrf_gpio_pin_set(ESP_32_S3_2_SS); NRF_LOG_INFO("SPI example started."); int sent_once = 0; while (1) { // Reset rx buffer and transfer done flag memset(m_rx1_buf, 0, sizeof(m_rx1_buf)); memset(m_rx2_buf, 0, sizeof(m_rx2_buf)); if(toggle == 1){ m_tx1_buf[0] = 0x11; m_tx1_buf[1] = 0xfa; m_tx1_buf[2] = 0xfb; for(uint8_t i =3;i<BUFFER_SIZE;i++){ m_tx1_buf[i] = i; } m_tx2_buf[0] = 0x12; m_tx2_buf[1] = 0xfa; m_tx2_buf[2] = 0xfb; for(uint8_t i =3;i<BUFFER_SIZE;i++){ m_tx2_buf[i] = i; } printf("Command sent- %xd \n",m_tx1_buf[0]); nrf_gpio_pin_clear(ESP_32_S3_1_SS); APP_ERROR_CHECK(nrf_drv_spi_transfer(&esp_1_spi, m_tx1_buf,BUFFER_SIZE, NULL, 0)); nrf_gpio_pin_set(ESP_32_S3_1_SS); } else{ m_tx1_buf[0] = 0x13; for(uint8_t i =1;i<BUFFER_SIZE;i++){ m_tx1_buf[i] = 0; } m_tx2_buf[0] = 0x13; for(uint8_t i =1;i<BUFFER_SIZE;i++){ m_tx2_buf[i] = 0; } nrf_gpio_pin_clear(ESP_32_S3_1_SS); APP_ERROR_CHECK(nrf_drv_spi_transfer(&esp_1_spi, m_tx1_buf, 1, NULL, 0)); APP_ERROR_CHECK(nrf_drv_spi_transfer(&esp_1_spi, NULL, 0, m_rx1_buf, BUFFER_SIZE)); //APP_ERROR_CHECK(nrf_drv_spi_transfer(&esp_1_spi, m_tx1_buf, 1, m_rx1_buf, BUFFER_SIZE)); nrf_gpio_pin_set(ESP_32_S3_1_SS); printf("Command sent- %xd \n",m_tx1_buf[0]); createChecksumforImage(); } toggle = ! toggle; nrf_delay_ms(40); } } void createChecksumforImage() { for (uint32_t i = 0; i < 32; i++) { imageChecksum = imageChecksum ^ m_rx1_buf[i]; printf("Rx buff - %d\n",m_rx1_buf[i]); } printf("Calculated checksum - %d \n",imageChecksum); if((imageChecksum == DATA_CHECKSUM) || (imageChecksum == 0)){ printf("correct checksum \n "); } else{ printf("checksum wrong \n "); while(1); } }
I have uploaded the SPI master code for NRF
spi_master_code_nrf_side_tested221222.zip
Here, I have uploaded the code for ESP32-S3
Issues
- While communicating with NRF with ESP32-S3 I have to put delay in NRF side code.
- Otherwise it will receive some garbage for some bytes or zero
- I have tested with providing different delays like 30 ms, 40 ms , 50 ms, but I am able to get exact data without any loss or garbage on 50 ms delay or more than any value of 50 ms only.
- I have calculated the checksum for whole 32 Bytes of data to check if data get corrupted
- I want to remove that delay to get max speed for transmission.
In case of setting the delay to 10 ms
In case of setting delay to 30 ms
In case of setting the delay to 50 ms
Please give me suggestion for how to resolve this issue for removing the delay from the code.