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

Correct way of using SPI instance through source files

Hello,

I have a question regarding the correct way/good practice of programming with the use of SPI. I am using SDK 15.0.0.

I've written some code in a source file peripheral.c to control a peripheral (e.g. initiliazations, writing/reading registers). To do this it makes use of SPI. My main.c creates the SPI instance, defines the pinout, and calls de initialization.

main.c:

#define SPI_INSTANCE        0       /**< SPI instance index */
#define SPI_SCK_PIN         3       /**< SPI_SCK_PIN - pin number */
#define SPI_MOSI_PIN        4       /**< SPI_SCK_PIN - pin number */
#define SPI_MISO_PIN        28      /**< SPI_SCK_PIN - pin number */
#define SPI_SS_PIN          29      /**< SPI_SCK_PIN - pin number */

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);     /**< SPI instance */

static volatile bool spi_xfer_done;                                     /**< Flag used to indicate that SPI instance completed the transfer */
static uint8_t m_tx_buf[2] = {};                                        /**< TX buffer */
static uint8_t m_rx_buf[sizeof(m_tx_buf) + 1];                          /**< RX buffer */
static const int8_t m_length = sizeof(m_tx_buf);                        /**< Transfer length */

void spi_config(void)
{
    //Configures SPI instance
}
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
                       void *                    p_context)
{
    //Event handler code
}

peripheral.c:

static void register_read(int register_to_access, int rx_length)
{
  uint8_t command;

  command = command_byte_set(register_to_access, read);

  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, tx_length, m_rx_buf, rx_length));
}

//lots of other code

Due to the SPI instance being declared as static I cannot access it in peripheral.c. I assume that the SPI instance should stay static though.

Should I move the declaration and initialization of the SPI instance and event handler over to peripheral.c, or should and can I make the instance available to peripheral.c somehow?

Thank you in advance

Parents
  • Hi Kevin, 

    I usually pass a pointer to the instance in a peripheral_init() function and then use that within the peripheral.c file. 

    Best regards

    Bjørn

  • Hi,

    I have exactly the same situation described by KevinL above, but even if I tried what you said it does not seem to work....

    Would you mind providing a snippet of code showing the peripheral_init() method? Your help would be really appreciated, because I think I am missing something....

    Thanks a lot!


    Lorenzo

  • Hi,

    I have actually done it even differently from what bjorn suggested, although I still use the pointer. I felt my solution would be  safer, but I don't think there is much of a difference. Anyway, I can now call the init() if I so  desire at a later point without running the risk of changing the SPIM instance pointer.

    I have done it in the following way:

    main.c:

    static const nrfx_spim_t spim_peripheral = NRFX_SPIM_INSTANCE(SPIM_INSTANCE);          /**< SPIM instance */
    const nrfx_spim_t *p_spim_instance = &spim_peripheral;
    static volatile bool spi_xfer_done;                                             /**< Flag used to indicate that SPI instance completed the transfer */
    
    main()
    {
        max3421e_init(&spi_xfer_done);
    }

    peripheral.h:

    extern const nrfx_spim_t *p_spim_instance;
    

    peripheral.c:

    static volatile bool *p_spi_xfer_done;                                           /**< Pointer to SPI_xfer_done flag */
    
    void peripheral_init(volatile bool *spi_xfer_done)
    {
      p_spi_xfer_done = spi_xfer_done;
        
        //whatever you need to initialize
    }

    Note that I do pass a pointer the the xfer_done flag still. You could probably do that in the same way I assign the pointer to the SPIM instance. Or if you wish so you can pass the pointer to the SPIM instance to the init() function and use it the same way as the xfer_done flag.

Reply
  • Hi,

    I have actually done it even differently from what bjorn suggested, although I still use the pointer. I felt my solution would be  safer, but I don't think there is much of a difference. Anyway, I can now call the init() if I so  desire at a later point without running the risk of changing the SPIM instance pointer.

    I have done it in the following way:

    main.c:

    static const nrfx_spim_t spim_peripheral = NRFX_SPIM_INSTANCE(SPIM_INSTANCE);          /**< SPIM instance */
    const nrfx_spim_t *p_spim_instance = &spim_peripheral;
    static volatile bool spi_xfer_done;                                             /**< Flag used to indicate that SPI instance completed the transfer */
    
    main()
    {
        max3421e_init(&spi_xfer_done);
    }

    peripheral.h:

    extern const nrfx_spim_t *p_spim_instance;
    

    peripheral.c:

    static volatile bool *p_spi_xfer_done;                                           /**< Pointer to SPI_xfer_done flag */
    
    void peripheral_init(volatile bool *spi_xfer_done)
    {
      p_spi_xfer_done = spi_xfer_done;
        
        //whatever you need to initialize
    }

    Note that I do pass a pointer the the xfer_done flag still. You could probably do that in the same way I assign the pointer to the SPIM instance. Or if you wish so you can pass the pointer to the SPIM instance to the init() function and use it the same way as the xfer_done flag.

Children
No Data
Related