SD card disk_initialization fails when the fatfs example is integrated in my FW project

Dear DevZone,

I am trying to integrate the fatfs example in my custom FW project, to be run on a custom board.

I first tried to upload only the fatfs example code on my custom board. I used a 2GB micro-SD card and I was able to successfully run the example (Nordic.txt file was correctly generated)

Then, I tried to integrate the example  in my custom FW project. To do this, I followed the usual steps, such as including all files and directories to the project, and configuring the SPI parameters as they are set in the fatfs example, such as SPI pins, SPI instances (in my custom code I am using 1 while in the fatfs example the 0 is used, but even changing to 0 it does not work).

The code correctly builds. However, when I try to run it in debug, what happens is that the disk initialization fails.

NRF_LOG_INFO("Initializing disk 0 (SDC)...");
for (uint32_t retries = 3; retries && disk_state; --retries)
{
disk_state = disk_initialize(0);
}
if (disk_state)
{
NRF_LOG_INFO("Disk initialization failed.");
return;
}

Going inside the disk_initialize function during debug, what I find is that usually neither 

/* Unsupported block size. */

/* SDC instance is busy. */


errors are reported (see the code snippet below)

static ret_code_t block_dev_sdc_init(nrf_block_dev_t const * p_blk_dev,
                                     nrf_block_dev_ev_handler ev_handler,
                                     void const * p_context)
{
    ASSERT(p_blk_dev);
    nrf_block_dev_sdc_t const * p_sdc_dev =
                                CONTAINER_OF(p_blk_dev, nrf_block_dev_sdc_t, block_dev);
    nrf_block_dev_sdc_work_t *  p_work = p_sdc_dev->p_work;

    if (p_sdc_dev->sdc_bdev_config.block_size != SDC_SECTOR_SIZE)
    {
        /* Unsupported block size. */
        return NRF_ERROR_NOT_SUPPORTED;
    }

    if (m_active_sdc_dev)
    {
        /* SDC instance is busy. */
        return NRF_ERROR_BUSY;
    }

    p_work->p_context  = p_context;
    p_work->ev_handler = ev_handler;
    m_active_sdc_dev   = p_sdc_dev;

    ret_code_t err_code = NRF_SUCCESS;

    err_code = app_sdc_init(&p_sdc_dev->sdc_bdev_config.sdc_config, sdc_handler);
    if (err_code == NRF_SUCCESS)
    {

What do you think can be the issue?

Note that in the board I share the SPI buses with other 2 slaves, but for the first tests I am not using them: I commented out the old SPI initialization function and I put the fatfs example call before everything related to other SPI devices in the main.

(In other words, I know that from https://devzone.nordicsemi.com/f/nordic-q-a/63517/interfacing-between-nrf52840-and-bme680-i2c-or-spi/258966#258966 the sharing of SPI buses between SD card and other slaves is not suggested, but: 1) for the time being this should not be the cause of the issue since I commented out everything related to other slaves , 2) in a second moment I will have to deal with this sharing since at this point the HW cannot be changed )

Thank you very much in advance,

best regards,

Gianluca

  • Hello Gianluca,

    disk_state = disk_initialize(0);
    }
    if (disk_state)
    {
    NRF_LOG_INFO("Disk initialization failed.");
    return;
    }

    Could you add the disk_state to your logged message, so that we may know exactly which error code was returned from the initialization?

    Regarding 'not sharing the SPI bus between devices', the SPI protocol is made to support multiple devices on the same bus, so long as the bus is used correctly (managed correctly by the application).
    There are however some considerations to take when having multiple devices on the same bus, such as how much time you will be accessing one of them (for instance, if you intend to write a large file and also frequently access another device the bus might be busy for the duration of the write, etc.), but in general it should be fine so long as this is given some though beforehand.

    Best regards,
    Karl

  • Dear Karl,

    thank you very much for your answer, during debug I get:

    disk_state = 0x01

    Let me know,

    best regards

    Gianluca

  • Hello Gianluca,

    Thank you for your patience with this.

    The disk_state 0x01 translates to "#define STA_NOINIT 0x01 /* Drive not initialized */" i.e that the disk is not initialized. Which line of disk_initialize do you get to before it returns to main, when you set breakpoints to check?
    Could you share with me your device configuration, and how you've changed this to match your sd-card? 

    As general advice (not applicable to the return code from the diskio.h functions, but to other SDK functions): since you are working with the nRF5 SDK you should also pass your error codes to an APP_ERROR_CHECK() and make sure to have DEBUG defined in your preprocessor defines like so:

    This will make your logger output a detailed error message whenever a non-NRF_SUCCESS error code is passed to an APP_ERROR_CHECK. 

    Best regards,
    Karl

  • Dear Karl,

    thanks for your answer and the useful advices.

     Which line of disk_initialize do you get to before it returns to main, when you set breakpoints to check?

    Here what happens inside the disk_initialize function.

    Three initialization attempt are done:

    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
    disk_state = disk_initialize(0);
    }
    if (disk_state)

    What happens inside is that it behaves differently in the first attempt with respect to second and third.

    In all the three attempt, the last message you get to before going back to main is:

     return m_drives[drv].state 

    and its value is always 1. This is located in the diskio_blkdev.c file (see below image)

    However, looking more in deep in the  block_dev_sdc_init function in the nrf_block_dev_sdc.c file, the results are different between the first attempt and the other two.

    In the first attempt, everything seems to go fine, neither the Unsupported block size and the SPI busy errors appear, the spi_init does not return error and the final err_code is 0:

    In the other two attempts, the NRF_ERROR_BUSY error is returned instead

    Could you share with me your device configuration?

    Here my device configuration:

    //NRF52840 GPIO PIN NET/FUNCTION
    //P0.26 SCL
    //P0.04 SDA
    //P0.20 SPI_MISO
    //P0.22 SPI_MOSI
    //P0.24 SPI_CLK
    //P0.17 SPI_SS1 (U6:AD7147)
    //P1.00 SPI_SS2 (U7:AD7147)
    //P0.08 SPI_SS2 (J7: microSD card)
    //P1.09 INT_CDC1 (U6:AD7147)
    //P0.13 INT_CDC2 (U7:AD7147)
    //P0.11 USR_BTN (U4: PUSHBUTTON)
    //P0.29 BAT_STATUS
    //P1.15 R0 (RGB LED)
    //P1.13 G0 (RGB LED)
    //P1.10 B0 (RGB LED)

    and how you've changed this to match your sd-card? 

    On the same custom board, the fatfs example works out. When I try to integrate it in my custom FW with the above configuration, it does not. So, I tried to comment out all the exceeding parts such as I2C initialization, as well as the spi initialization that was present before (for the initialization of the other SPI devices). I only updated the SPI pins as per above, adding the one related to the SD card CS pin

    Let me know, thank you very much,

    Best Regards,

    Gianluca

  • Hello,

    Karl is away this week. I am not sure what the problem is unfortunately, if you have access to a logic analyzer trace it could be interesting to compare working and failing, and see if that gives a clue. Also it could be interesting to look at interrupt priorities and whether that have any impact on this.

    Kenneth

Related