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

Confusing how to integrate SPI master and slave drivers/HAL in my C code

Ok so I am trying to integrate SPI master and slave initialization code. I am very confused about legacy and non-legacy drivers and HAL. I am getting strange compilation and linking errors. Please help me out on this.

I am compiling following SPI related driver files in my IAR project:

  • modules\nrfx\drivers\src\nrfx_spi.c
  • modules\nrfx\drivers\src\nrfx_spis.c
  • modules\nrfx\drivers\src\nrfx_spim.c
  • integration\nrfx\legacy\nrf_drv_spi.c
  • integration\nrfx\legacy\nrf_drv_spis.c

sdk_config.h settings for SPI:

// <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
//==========================================================
#ifndef NRFX_SPIM_ENABLED
#define NRFX_SPIM_ENABLED 0
#endif
// <q> NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
 

#ifndef NRFX_SPIM0_ENABLED
#define NRFX_SPIM0_ENABLED 0
#endif

// <q> NRFX_SPIM1_ENABLED  - Enable SPIM1 instance
 

#ifndef NRFX_SPIM1_ENABLED
#define NRFX_SPIM1_ENABLED 0
#endif

// <q> NRFX_SPIM2_ENABLED  - Enable SPIM2 instance
 

#ifndef NRFX_SPIM2_ENABLED
#define NRFX_SPIM2_ENABLED 0
#endif


// <e> NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver
//==========================================================
#ifndef NRFX_SPIS_ENABLED
#define NRFX_SPIS_ENABLED 1
#endif
// <q> NRFX_SPIS0_ENABLED  - Enable SPIS0 instance
 

#ifndef NRFX_SPIS0_ENABLED
#define NRFX_SPIS0_ENABLED 1
#endif

// <q> NRFX_SPIS1_ENABLED  - Enable SPIS1 instance
 

#ifndef NRFX_SPIS1_ENABLED
#define NRFX_SPIS1_ENABLED 0
#endif

// <q> NRFX_SPIS2_ENABLED  - Enable SPIS2 instance
 

#ifndef NRFX_SPIS2_ENABLED
#define NRFX_SPIS2_ENABLED 0
#endif



// <e> NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver
//==========================================================
#ifndef NRFX_SPI_ENABLED
#define NRFX_SPI_ENABLED 1
#endif
// <q> NRFX_SPI0_ENABLED  - Enable SPI0 instance
 

#ifndef NRFX_SPI0_ENABLED
#define NRFX_SPI0_ENABLED 1
#endif

// <q> NRFX_SPI1_ENABLED  - Enable SPI1 instance
 

#ifndef NRFX_SPI1_ENABLED
#define NRFX_SPI1_ENABLED 0
#endif

// <q> NRFX_SPI2_ENABLED  - Enable SPI2 instance
 

#ifndef NRFX_SPI2_ENABLED
#define NRFX_SPI2_ENABLED 0
#endif




// <e> SPIS_ENABLED - nrf_drv_spis - SPIS peripheral driver - legacy layer
//==========================================================
#ifndef SPIS_ENABLED
#define SPIS_ENABLED 1
#endif


// <q> SPIS0_ENABLED  - Enable SPIS0 instance
 

#ifndef SPIS0_ENABLED
#define SPIS0_ENABLED 1
#endif

// <q> SPIS1_ENABLED  - Enable SPIS1 instance
 

#ifndef SPIS1_ENABLED
#define SPIS1_ENABLED 0
#endif

// <q> SPIS2_ENABLED  - Enable SPIS2 instance
 

#ifndef SPIS2_ENABLED
#define SPIS2_ENABLED 0
#endif



// <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
//==========================================================
#ifndef SPI_ENABLED
#define SPI_ENABLED 1
#endif


// <e> SPI0_ENABLED - Enable SPI0 instance
//==========================================================
#ifndef SPI0_ENABLED
#define SPI0_ENABLED 1
#endif

// <e> SPI1_ENABLED - Enable SPI1 instance
//==========================================================
#ifndef SPI1_ENABLED
#define SPI1_ENABLED 0
#endif


// <e> SPI2_ENABLED - Enable SPI2 instance
//==========================================================
#ifndef SPI2_ENABLED
#define SPI2_ENABLED 0
#endif

init.c

#include "common.h"
#include "nrf_drv_spi.h"
#include "nrf_drv_spis.h"

volatile bool bSpiMasterTxRxDone = false;
volatile bool bSpiSlaveTxRxDone = false;

nrf_drv_spi_t const hSpiMasterDev0 = NRF_DRV_SPI_INSTANCE(SPI_DEV_ID_0);
nrf_drv_spis_t const hSpiSlaveDev0 = NRF_DRV_SPIS_INSTANCE(SPI_DEV_ID_0);

/**
 * @brief SPI master event handler.
 * @param event
 */
static void spi_master_event_handler(nrf_drv_spi_evt_t const * p_event,
                                     void *                    p_context)
{
    bSpiMasterTxRxDone = true;
    NRF_LOG_INFO("Transfer completed.");
}

/**
 * @brief SPI Slave event handler.
 *
 * @param event
 */
static void spis_slave_event_handler(nrf_drv_spis_event_t event)
{
    if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
    {
        bSpiSlaveTxRxDone = true;
    }
}


/**@brief Function for initializing SPI controller in master or slave mode
 */
void spi_init(void const * pHSpiDev,
              SPI_MODE_TYPE const spi_mode)
{
    ret_code_t err_code;
    
    if( SPI_MODE_MASTER == spi_mode)
    {
      assert( pHSpiDev != NULL );
      nrf_drv_spi_config_t spi_master_config = NRF_DRV_SPI_DEFAULT_CONFIG;
      spi_master_config.ss_pin   = SPI_CS_PIN;
      spi_master_config.miso_pin = SPI_MISO_PIN;
      spi_master_config.mosi_pin = SPI_MOSI_PIN;
      spi_master_config.sck_pin  = SPI_SCK_PIN;
      spi_master_config.frequency = SPI_MASTER_BIT_RATE;
      spi_master_config.bit_order = SPI_MASTER_BIT_ORDER;
      spi_master_config.mode =  SPI_MASTER_MODE;
      spi_master_config.orc = 255;
      
      err_code = nrf_drv_spi_init((nrf_drv_spi_t const*)pHSpiDev, &spi_master_config, spi_master_event_handler, NULL);
      APP_ERROR_CHECK(err_code);
    }
    else if(SPI_MODE_SLAVE == spi_mode)
    {
      assert( pHSpiDev != NULL );
      nrf_drv_spis_config_t spi_slave_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
      spi_slave_config.miso_pin = SPI_MISO_PIN;
      spi_slave_config.mosi_pin = SPI_MOSI_PIN;
      spi_slave_config.sck_pin  = SPI_SCK_PIN;
      spi_slave_config.csn_pin   = SPI_CS_PIN;
      spi_slave_config.mode =  SPI_SLAVE_MODE;
      spi_slave_config.bit_order = SPI_SLAVE_BIT_ORDER;
      spi_slave_config.def = 255;      
      spi_slave_config.orc = 255;
      
      // How to specify SCK for SPI slave ?????
      
      err_code = nrf_drv_spis_init((nrf_drv_spis_t const*)pHSpiDev, &spi_slave_config, spis_slave_event_handler);
      APP_ERROR_CHECK(err_code);      
    }
    else 
    {
      // Default SPI mode is slave
    }
}

common.h

#ifndef COMMON_H
#define COMMON_H

/* SPI Modes */
typedef enum
{
  SPI_MODE_MASTER,
  SPI_MODE_SLAVE
}SPI_MODE_TYPE;

/* GPIO pin for SPI MOSI(12/P0.13) */
#define SPI_MOSI_PIN ((nrfx_gpiote_pin_t)13)

/* GPIO pin for SPI MISO(14/P0.14) */
#define SPI_MISO_PIN ((nrfx_gpiote_pin_t)14)

/* GPIO pin for SPI SCK(13/P0.12)*/
#define SPI_SCK_PIN ((nrfx_gpiote_pin_t)12)

/* GPIO pin for SPI CS(11/P0.15)*/
#define SPI_CS_PIN ((nrfx_gpiote_pin_t)15)

#define SPI_MASTER_BIT_RATE NRF_DRV_SPI_FREQ_125K
#define SPI_SLAVE_BIT_RATE ???????

#define SPI_MASTER_BIT_ORDER NRF_DRV_SPI_BIT_ORDER_MSB_FIRST
#define SPI_SLAVE_BIT_ORDER NRF_SPIS_BIT_ORDER_MSB_FIRST

#define SPI_MASTER_MODE NRF_DRV_SPI_MODE_0
#define SPI_SLAVE_MODE NRF_SPIS_MODE_0

#define SPI_DEV_ID_0 0

extern void spi_init(void const * pHSpiDev,
                     SPI_MODE_TYPE const spi_mode);

#endif /* COMMON_H */

main.c

#include "common.h"
#include "nrf_drv_spi.h"
#include "nrf_drv_spis.h"

extern nrf_drv_spi_t const hSpiMasterDev0;
extern nrf_drv_spis_t const hSpiSlaveDev0;

int main()
{
    // various init codes 
    // ...
    
    //..
    
    // spi init
    
    spi_init(&hSpiSlaveDev0, BMNL_SPI_MODE_SLAVE );
}

What I need:

  • One SPI controller on nrf52832 that I want o use in either master or mode (as I have just four hardwired GPIO pins connected to my another device on my custom board. ).  I will switch the mode of the same SPI controller device from slave to master and vice versa as needed(depends on which state my nrf52 is in).
  • Specify frequency(mbps,hz) for both master/slave configuration. I did find this setting for master, but for some reason I cannot locate this in initialization C structures for slave configuration.
  • Blocking/non-blocking modes in DMA/non-DMA configuration
  • I prefer not to use any legacy SPI driver/hal unless I will compromise on above requirements.

So here are my questions:

  1. Which SPI driver/HAL header (.h) files should I use in my C code and which C driver/HAL files should I compile & link with my project ? 
  2. What  is the different between SPI, SPIM and SPIS ? Which one should I use for master and which one for slave ? 
  3. Which of the following flags should I enable to use 0th SPI controller instance for master/slave ?
  4. How do I specify frequency configuration for SPI slave configuration ?
Parents
  • Thanks I will have a look.

    So what I did so far I am linking my project with only nrfx drivers and their headers, namely:

    • modules\nrfx\drivers\src\nrfx_spis.c 
    • modules\nrfx\drivers\src\nrfx_spim.c

    I changed my code to use only functions in the headers for above driver.

    From my sdk_config.h, I also removed many SPI legacy macros which are irrelevant.

    sdk_config.h:

    // <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
    //==========================================================
    #ifndef NRFX_SPIM_ENABLED
    #define NRFX_SPIM_ENABLED 1
    #endif
    // <q> NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
     
    
    #ifndef NRFX_SPIM0_ENABLED
    #define NRFX_SPIM0_ENABLED 1
    #endif
    
    // <e> NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver
    //==========================================================
    #ifndef NRFX_SPIS_ENABLED
    #define NRFX_SPIS_ENABLED 1
    #endif
    // <q> NRFX_SPIS0_ENABLED  - Enable SPIS0 instance
     
    
    #ifndef NRFX_SPIS0_ENABLED
    #define NRFX_SPIS0_ENABLED 1
    #endif
    
    
    /* COMMENTED OUT SPI macros for unused spi driver or legacy drivers
    
    // <e> NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver
    //==========================================================
    #ifndef NRFX_SPI_ENABLED
    #define NRFX_SPI_ENABLED 0
    #endif
    // <q> NRFX_SPI0_ENABLED  - Enable SPI0 instance
     
    
    #ifndef NRFX_SPI0_ENABLED
    #define NRFX_SPI0_ENABLED 0
    #endif
    
    
    // <e> SPIS_ENABLED - nrf_drv_spis - SPIS peripheral driver - legacy layer
    //==========================================================
    #ifndef SPIS_ENABLED
    #define SPIS_ENABLED 1
    #endif
    // <o> SPIS_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
    
    // <q> SPIS0_ENABLED  - Enable SPIS0 instance
     
    
    #ifndef SPIS0_ENABLED
    #define SPIS0_ENABLED 1
    #endif
    
    // <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
    //==========================================================
    #ifndef SPI_ENABLED
    #define SPI_ENABLED 0
    #endif
    // <o> SPI_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
    
    // <e> SPI0_ENABLED - Enable SPI0 instance
    //==========================================================
    #ifndef SPI0_ENABLED
    #define SPI0_ENABLED 1
    #endif
    
    */

    However, astonishingly I am still getting the same error. 

    Error[Li006]: duplicate definitions for "SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler"; in "D:\nRF\sdk\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\custom_project\pca10040\s132\iar\_build\nrfx_spim.o", and 
    "D:\nRF\sdk\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\custom_projectbmn\pca10040\s132\iar\_build\nrfx_spis.o" 

    I saw another related post: "SPIM3 initialization issue" , however SPI rleated macros still remain confusing.

    Not able to proceed forward. 

Reply
  • Thanks I will have a look.

    So what I did so far I am linking my project with only nrfx drivers and their headers, namely:

    • modules\nrfx\drivers\src\nrfx_spis.c 
    • modules\nrfx\drivers\src\nrfx_spim.c

    I changed my code to use only functions in the headers for above driver.

    From my sdk_config.h, I also removed many SPI legacy macros which are irrelevant.

    sdk_config.h:

    // <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
    //==========================================================
    #ifndef NRFX_SPIM_ENABLED
    #define NRFX_SPIM_ENABLED 1
    #endif
    // <q> NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
     
    
    #ifndef NRFX_SPIM0_ENABLED
    #define NRFX_SPIM0_ENABLED 1
    #endif
    
    // <e> NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver
    //==========================================================
    #ifndef NRFX_SPIS_ENABLED
    #define NRFX_SPIS_ENABLED 1
    #endif
    // <q> NRFX_SPIS0_ENABLED  - Enable SPIS0 instance
     
    
    #ifndef NRFX_SPIS0_ENABLED
    #define NRFX_SPIS0_ENABLED 1
    #endif
    
    
    /* COMMENTED OUT SPI macros for unused spi driver or legacy drivers
    
    // <e> NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver
    //==========================================================
    #ifndef NRFX_SPI_ENABLED
    #define NRFX_SPI_ENABLED 0
    #endif
    // <q> NRFX_SPI0_ENABLED  - Enable SPI0 instance
     
    
    #ifndef NRFX_SPI0_ENABLED
    #define NRFX_SPI0_ENABLED 0
    #endif
    
    
    // <e> SPIS_ENABLED - nrf_drv_spis - SPIS peripheral driver - legacy layer
    //==========================================================
    #ifndef SPIS_ENABLED
    #define SPIS_ENABLED 1
    #endif
    // <o> SPIS_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
    
    // <q> SPIS0_ENABLED  - Enable SPIS0 instance
     
    
    #ifndef SPIS0_ENABLED
    #define SPIS0_ENABLED 1
    #endif
    
    // <e> SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer
    //==========================================================
    #ifndef SPI_ENABLED
    #define SPI_ENABLED 0
    #endif
    // <o> SPI_DEFAULT_CONFIG_IRQ_PRIORITY  - Interrupt priority
    
    // <e> SPI0_ENABLED - Enable SPI0 instance
    //==========================================================
    #ifndef SPI0_ENABLED
    #define SPI0_ENABLED 1
    #endif
    
    */

    However, astonishingly I am still getting the same error. 

    Error[Li006]: duplicate definitions for "SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler"; in "D:\nRF\sdk\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\custom_project\pca10040\s132\iar\_build\nrfx_spim.o", and 
    "D:\nRF\sdk\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\custom_projectbmn\pca10040\s132\iar\_build\nrfx_spis.o" 

    I saw another related post: "SPIM3 initialization issue" , however SPI rleated macros still remain confusing.

    Not able to proceed forward. 

Children
  • Ok so I fixed the issue. Issue occurs if I associate same device id with both master and slave instances:

    #define SPI_DEV_ID_0 0
    
    
    nrfx_spim_t const hSpiMasterDev0 = NRFX_SPIM_INSTANCE(SPI_DEV_ID_0);
    nrfx_spis_t const hSpiSlaveDev0 = NRFX_SPIS_INSTANCE(SPI_DEV_ID_0);

    sdk_config.h:

    // <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
    //==========================================================
    #ifndef NRFX_SPIM_ENABLED
    #define NRFX_SPIM_ENABLED 1
    #endif
    // <q> NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
     
    
    #ifndef NRFX_SPIM0_ENABLED
    #define NRFX_SPIM0_ENABLED 1
    #endif
    
    // <q> NRFX_SPIM1_ENABLED  - Enable SPIM1 instance
     
    
    #ifndef NRFX_SPIM1_ENABLED
    #define NRFX_SPIM1_ENABLED 0
    #endif
    
    
    // <e> NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver
    //==========================================================
    #ifndef NRFX_SPIS_ENABLED
    #define NRFX_SPIS_ENABLED 1
    #endif
    // <q> NRFX_SPIS0_ENABLED - Enable SPIS0 instance
    
    #ifndef NRFX_SPIS0_ENABLED
    #define NRFX_SPIS0_ENABLED 1
    #endif
    
    // <q> NRFX_SPIS1_ENABLED - Enable SPIS1 instance
    
    #ifndef NRFX_SPIS1_ENABLED
    #define NRFX_SPIS1_ENABLED 0
    #endif

    However, if I change the device id for master and slave instances then problem goes away and it compiles & links successfully:

    #define SPI_DEV_ID_0 0
    #define SPI_DEV_ID_1 1
    
    nrfx_spim_t const hSpiMasterDev0 = NRFX_SPIM_INSTANCE(SPI_DEV_ID_0);
    nrfx_spis_t const hSpiSlaveDev0 = NRFX_SPIS_INSTANCE(SPI_DEV_ID_1);

    sdk_config.h:

    // <e> NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver
    //==========================================================
    #ifndef NRFX_SPIM_ENABLED
    #define NRFX_SPIM_ENABLED 1
    #endif
    // <q> NRFX_SPIM0_ENABLED  - Enable SPIM0 instance
     
    
    #ifndef NRFX_SPIM0_ENABLED
    #define NRFX_SPIM0_ENABLED 1
    #endif
    
    // <q> NRFX_SPIM1_ENABLED  - Enable SPIM1 instance
     
    
    #ifndef NRFX_SPIM1_ENABLED
    #define NRFX_SPIM1_ENABLED 0
    #endif
    
    
    // <e> NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver
    //==========================================================
    #ifndef NRFX_SPIS_ENABLED
    #define NRFX_SPIS_ENABLED 1
    #endif
    // <q> NRFX_SPIS0_ENABLED - Enable SPIS0 instance
    
    #ifndef NRFX_SPIS0_ENABLED
    #define NRFX_SPIS0_ENABLED 0
    #endif
    
    // <q> NRFX_SPIS1_ENABLED - Enable SPIS1 instance
    
    #ifndef NRFX_SPIS1_ENABLED
    #define NRFX_SPIS1_ENABLED 1
    #endif

Related