Sharing SPI interface between SD card and other peripheral

Dear DevZone,

I am trying to share a SPI instance between an SD card and an other peripheral. I am working with nRF52840. 

I already opened a ticket back in time in devzone.nordicsemi.com/.../sd-card-disk_initialization-fails-when-the-fatfs-example-is-integrated-in-my-fw-project for initial configuration of the fatfs example.

Now, the fatfs example is correctly initializing the board if no other SPI periherals are initialized.

However, if I try to initialize my other peripheral before the fatfs example, the other peripheral correctly initializes, but the fatfs example goes in BREAKPOINT condition when trying to initialize the disk (disk_initialization) during spi setup.  Here the SPI initialization from the other peripheral. I deassert the CS pin after the other peripheral initialization

// spi_master_init: function that initializes the SPI master, its pins and the order in which it sends the bits on the bus
uint32_t spi_master_init(void)
{
	uint32_t err_code;
        nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
        spi_config.ss_pin   = NRF_DRV_SPI_PIN_NOT_USED;                             // unconnected, we are going to use a custom function to switch between SSx
        spi_config.miso_pin = SPI_MISO_PIN;
        spi_config.mosi_pin = SPI_MOSI_PIN;
        spi_config.sck_pin  = SPI_SCK_PIN;
	spi_config.bit_order = SPI_CONFIG_ORDER_MsbFirst;
	
        err_code = nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL);
        APP_ERROR_CHECK(err_code);
}

The same (but specular) happens if I try to run before the fatfs example and then initialize the other peripheral: the fatfs correctly initializes the SD card, but then the SPI initialization fails with a BREAKPOINT condition when it tryies to do a transfer. Here the two sequences of operations:

int main(void)
{
    status = INIT;
    ret_code_t err_code;
    uint32_t time_ticks;

    init_message_data();

    bsp_board_init(BSP_INIT_LEDS);


    gpio_init();


//    // initialization of SPI protocol
    err_code = spi_master_init();

//******************AD7147 initialization*********************************

    // this call initializes the converters
    CDCInit();                    

//*******************************************************************************************





    // some delay needed to allow the previous operations to be successfull
    nrf_delay_ms(1000);
//******************SD card initialization*********************************
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    // this call initializes the SD card
    fatfs_example();                  

//*******************************************************************************************

Here the breakpoint condition - NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x",:

        case NRF_FAULT_ID_SDK_ERROR:
        {
            error_info_t * p_info = (error_info_t *)info;
            NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x",
                          p_info->err_code,
                          nrf_strerror_get(p_info->err_code),
                          p_info->p_file_name,
                          p_info->line_num,
                          pc);
             NRF_LOG_ERROR("End of error report");
            break;
        }
        default:
            NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
            break;
    }
#endif

    NRF_BREAKPOINT_COND;

Which can be the issue? 

Thank you very much,

best regards

Gianluca

  • I found out that in the fatfs SPI initialization function there is this configuration:

    #define APP_SDCARD_CONFIG(MOSI_PIN, MISO_PIN, SCK_PIN, CS_PIN) {    \
                .mosi_pin = MOSI_PIN,                                   \
                .miso_pin = MISO_PIN,                                   \
                .sck_pin  = SCK_PIN,                                    \
                .cs_pin   = CS_PIN                                      \
            }
    

    Can this be the problem? In the sense that I set the CS to be a specific pin (while in the other case the CS pin was not set). Anyways, I would expect that the fatfs example work after this initialization

  • Hello Gianluca,

    Thank you for contacting DevZone at NordicSemi. Appreciate your patience. 

    When you are want to use a spi controller for two or more spi devices, then each device need to have its own chip-select (CS) pin, that will enable only one peripheral for communication. Rest of the lines (MOSI, MISO, CLK) are same pins.

    Yes, we can see that SDCard spi configuration has a definite CS pin (check #define at top of main), so I think your other device should also have a CS pin defined.

    Another test can be using a different spi-instance for both devices to make sure that nothing is wrong with code / procedure and both devices are working with their spi-istances. 

    BR, Naeem

  • Dear Naeem,

    thank you very much for your answer. 

    However, the standard SPI initialization (the one I use for the other device), handles two devices, not one. This is the reason why in that initialization I set the CS pin as not set (NRF_DRV_SPI_PIN_NOT_USED). Then, every time I need to communicate with those two devices, I manually set the CS pin.

    For the fatfs instead, I am not modifying the example code, which sets a specific CS pin. 

    Given that, I am wondering if this double initialization can create some kind of issues, but for the time being I tried to avoid modifying the fatfs example which seems to be very customized with respect to the SPI stuff.

    Given that, do you think there can be other possible modifications/solutions I can try?

    For what concerns this:

    Another test can be using a different spi-instance for both devices

    the devices share the same lines, so I think I cannot create two different instances, right?

    Thank you again,

    Best regards

    Gianluca

  • Dear Gianluca,

    Thank you for your patience.

    As you want to have two spi devices (SDCard and another peripheral): you can put both on the same spi controller by having different CS pins, or you can put one device on spi0 and other on spi1 (multiple spi instances) in which case we don't need to control through the CS pins.

    If you (and your hardware) have the flexibility, then it is preferred to use separate instance for SDCard as sharing another spi peripheral with the SDCard might not be very good idea.

    Nonetheless, as in your case, you have a SDCard and another peripheral that you are putting on the same spi-bus and using spi0 controller. 

    Also, as you are using FATFS sample, you have seen that this sample initializes spi internally and you don't have to do any initialization like you are doing for your other peripheral.

    What I mean is that: for the other peripheral, you have written spi_master_init() function but we have not written any such initialization function for the SDCard as we know that the FATFS must be handling internally.

    Saying that, the problem you are facing seems to be due to the fact that the instance is already initialized, and you are trying to reinitialize it. As per your code:

    err_code = spi_master_init();
    CDCInit();                    
    nrf_delay_ms(1000);
    
    APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    fatfs_example();                 

    If you are calling fatfs example first, then do something like this:

    fatfs_example();
    
    nrf_drv_spi_uninit(&spi);
    
    spi_transceiver_init();    
    
    while (1) 
        {   
            // ...
            APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, m_length, m_rx_buf, m_length));
            while (!spi_xfer_done)
            {
              __WFE();
            }
            // ...
            nrf_delay_ms(1000);
        }

    where, after fatfs example, we uninitialize the spi instance driver, and then re-initializ (in this spi_transceiver_init() function like spi_master_init() ) before using it.

    Best regards,

    Naeem

Related