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

NRF52 SD card example intermittent problem initialising

I am trying to get an SD card working with the NRF52832 chip, starting with the sd card example (SDK 14.2) using the fatfs module.

The SD card I am using is a Kingston 8GB class 4 card.

The nordic chip is in a Dynastream M8 module.

The problem is that when I first insert the card the example works fine.  Before initialisation the chip is using 4mA (due to other sensors on my board).  The card initialises fine, and I get this output from the example code:

[00135690] <info> app: Initializing disk 0 (SDC)...
[00174091] <info> app: Capacity: 7458 MB
[00174104] <info> app: Mounting volume...
[00201551] <info> app: 
 Listing directory: /
   <DIR>         320  [00211529] <info> app: Writing to file NORDIC.TXT...
[00220706] <info> app: 16 bytes written.
[00243467] <info> app: Unmounting volume...
[00243483] <info> app: Disk uninitialized.

However after this has run, the current usage goes up to 44mA and stays there.  Furthermore, if i try to run the example code again initialisation fails, and I get the following message (note the spurious capacity). 

[00135763] <info> app: Initializing disk 0 (SDC)...
[00141872] <info> app: Capacity: 121 MB
[00141885] <info> app: Mounting volume...
[00150526] <info> app: Mount failed.

I have tried unmounting the volume, and uninitialising the fatfs module, but it makes no difference.  

Here is the full example code (with unmount and uninitialise added):

#include "ff.h"
#include "diskio_blkdev.h"
#include "nrf_block_dev_sdc.h"

//#include "nrf_drv_clock.h"

#define FILE_NAME   "NORDIC.TXT"
#define TEST_STRING "SD card example."

#define SDC_SCK_PIN     15  ///< SDC serial clock (SCK) pin.
#define SDC_MOSI_PIN    13  ///< SDC serial data in (DI) pin.
#define SDC_MISO_PIN    14  ///< SDC serial data out (DO) pin.
#define SDC_CS_PIN      16  ///< SDC chip select (CS) pin.

/**
 * @brief  SDC block device definition
 * */
NRF_BLOCK_DEV_SDC_DEFINE(
        m_block_dev_sdc,
        NRF_BLOCK_DEV_SDC_CONFIG(
                SDC_SECTOR_SIZE,
                APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")
);

/**
 * @brief Function for demonstrating FAFTS usage.
 */
static void fatfs_example()
{
    static FATFS fs;
    static DIR dir;
    static FILINFO fno;
    static FIL file;

    uint32_t bytes_written;
    FRESULT ff_result;
    DSTATUS disk_state = STA_NOINIT;

    // Initialize FATFS disk I/O interface by providing the block device.
    static diskio_blkdev_t drives[] =
    {
            DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
    };

    diskio_blockdev_register(drives, ARRAY_SIZE(drives));
    //Check disk state:
    disk_state=disk_status(0);
    NRF_LOG_INFO("Disk status = %u",disk_state);


    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;
    }

    uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
    uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
    NRF_LOG_INFO("Capacity: %d MB", capacity);

    NRF_LOG_INFO("Mounting volume...");
    ff_result = f_mount(&fs, "", 1);
    if (ff_result)
    {
        NRF_LOG_INFO("Mount failed.");
        return;
    }

    NRF_LOG_INFO("\r\n Listing directory: /");
    ff_result = f_opendir(&dir, "/");
    if (ff_result)
    {
        NRF_LOG_INFO("Directory listing failed!");
        return;
    }

    do
    {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK)
        {
            NRF_LOG_INFO("Directory read failed.");
            return;
        }

        if (fno.fname[0])
        {
            if (fno.fattrib & AM_DIR)
            {
                NRF_LOG_RAW_INFO("   <DIR>   %s",(uint32_t)fno.fname);
            }
            else
            {
                NRF_LOG_RAW_INFO("%9lu  %s", fno.fsize, (uint32_t)fno.fname);
            }
        }
    }
    while (fno.fname[0]);
    NRF_LOG_RAW_INFO("");
    NRF_LOG_FLUSH();

    NRF_LOG_INFO("Writing to file " FILE_NAME "...");
    ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ".");
        return;
    }

    ff_result = f_write(&file, TEST_STRING, sizeof(TEST_STRING) - 1, (UINT *) &bytes_written);
    if (ff_result != FR_OK)
    {
        NRF_LOG_INFO("Write failed\r\n.");
    }
    else
    {
        NRF_LOG_INFO("%d bytes written.", bytes_written);
    }

    (void) f_close(&file);
    //unmount disk:
    NRF_LOG_INFO("Unmounting volume...");
    ff_result = f_mount(0, "", 0);
    if (ff_result)
    {
        NRF_LOG_INFO("unmount failed.");
        return;
    }
    //Uninitialise disc:
    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
        disk_state = disk_uninitialize(0);
    }
    if (disk_state)
    {
        NRF_LOG_INFO("Disk uninitialization failed.");
        return;
    }
        NRF_LOG_INFO("Disk uninitialized.");
    return;
}

If I power down the board, or remove and reinsert the card, the example will work again, but only the once, calling it multiple times it fails on the second time.

So in short I have two issues: The first and most important is high current usage after inisitalising the card despite it not reading or writing, and second is unable to reinitialise card if it has been previously initialised.  I appreciate that should not be necessary but I was thinking to get to a low power state uninitialising would be necessary.

It seems like if I were able to force the card to reset I would be able to get around it, or otherwise force the card into a sleep mode.  Is that possible?  Otherwise, any suggestions on how I can prevent this behaviour?

Related