Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

unable to initialize to micro SD card using custom board

Chevalier_nRF52840_schema_v0.pdf

Hello all,

I have some troubles to initialize the micro SD card with my custom board.

I have used the nRF 52 DK to write a basic code and do some test. For micro card SD with the nRF 52 DK I have used this micro card SD reader

Here you can find the basic code. With my custom board the code can not do the initialization function. As the result disk_state = disk_initialize(0); is always true.

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "SEGGER_RTT.h"

#include "nrf.h"
#include "bsp.h"
#include "ff.h"
#include "diskio_blkdev.h"
#include "nrf_block_dev_sdc.h"
#include "app_sdcard.h"

#define SPI_INSTANCE  1 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */


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

#define SDC_SCK_PIN     42  ///< SDC serial clock (SCK) pin.
#define SDC_MOSI_PIN    36  ///< SDC serial data in (DI) pin.
#define SDC_MISO_PIN    45  ///< SDC serial data out (DO) pin.
#define SDC_CS_PIN      34  ///< SDC chip select (CS) pin. p1.02

/**
 * @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("PerfectStride", "SDC", "1.00")
);

/**
 * @brief Function for demonstrating FAFTS usage.
 */
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));

    SEGGER_RTT_printf(0,"Initializing disk 0 (SDC)...");
    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
        disk_state = disk_initialize(0);
    }
    if (disk_state)
    {
        SEGGER_RTT_printf(0,"Disk initialization failed.\n");
        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;
    SEGGER_RTT_printf(0,"Capacity: %d MB", capacity);

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

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

//    ff_result = f_unlink(FILE_NAME); //LC: delete nordic file if exist before starting
    do
    {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK)
        {
            SEGGER_RTT_printf(0,"Directory read failed.");
            return;
        }
        nrf_delay_ms(1000);
        if (fno.fname[0])
        {
            if (fno.fattrib & AM_DIR)
            {
                SEGGER_RTT_printf(0,"\n   <DIR>   %s",(uint32_t)fno.fname);
            }
            else
            {
                SEGGER_RTT_printf(0,"%9lu  %s", fno.fsize, (uint32_t)fno.fname);
            }
        }
    }
    while (fno.fname[0]);

    nrf_delay_ms(2000);
    SEGGER_RTT_printf(0,"\n \n");
    SEGGER_RTT_printf(0,"Writing to file %s ...   ", FILE_NAME);

    ff_result = f_open(&file, FILE_NAME, FA_READ | FA_WRITE | FA_OPEN_APPEND);
    if (ff_result != FR_OK)
    {
        SEGGER_RTT_printf(0,"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)
    {
        SEGGER_RTT_printf(0,"Write failed\r\n.");
    }
    else
    {
        SEGGER_RTT_printf(0,"%d bytes written.\n", bytes_written);
    }
SEGGER_RTT_printf(0,"before file close !");
    (void) f_close(&file);SEGGER_RTT_printf(0,"before out !");
    return;
}


void init_pins()
{
    SEGGER_RTT_printf(0, "\n \n-------- Fatfs CONFIG -------- \n");

    SEGGER_RTT_printf(0, "SDC_SCK_PIN   :\t %d \n", SDC_SCK_PIN);
    SEGGER_RTT_printf(0, "SDC_MOSI_PIN  :\t %d \n", SDC_MOSI_PIN);
    SEGGER_RTT_printf(0, "SDC_MISO_PIN  :\t %d \n", SDC_MISO_PIN);
    SEGGER_RTT_printf(0, "SDC_CS_PIN    :\t %d \n", SDC_CS_PIN);
    return;
}

void begin_message()
{
    SEGGER_RTT_printf(0, "\n\n\n \n\n\n -------------------------------------------------------- \n");
    SEGGER_RTT_printf(0, " Begin Perfect Stride program to read value from BMI160 sensor \n");
    SEGGER_RTT_printf(0, "\t linked with BMM150 sensor \n \n");
    return;
}



int main(void)
{
    begin_message();
    bsp_board_leds_init();

    init_pins();

    //LC ---- test
    fatfs_example();

    while (1)
    {
        bsp_board_led_invert(BSP_BOARD_LED_0);
        nrf_delay_ms(200);
    }
    //LC ---- end test
}

The file to configure the custom board is this one :

#include "boards.h"


#ifndef BOARD_CUSTOM_H
#define BOARD_CUSTOM_H

#ifdef __cplusplus
extern "C" {
#endif

#define LEDS_NUMBER    4

#define LED_1          NRF_GPIO_PIN_MAP(1,6)

#define LEDS_ACTIVE_STATE 0

#define LEDS_LIST { LED_1}

#define LEDS_INV_MASK  LEDS_MASK

#define BSP_LED_0      13
#define BSP_LED_1      14
#define BSP_LED_2      15
#define BSP_LED_3      16

#define BUTTONS_NUMBER 4

#define BUTTON_1       11
#define BUTTON_2       12
#define BUTTON_3       24
#define BUTTON_4       25
#define BUTTON_PULL    NRF_GPIO_PIN_PULLUP

#define BUTTONS_ACTIVE_STATE 0

#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4 }

#define BSP_BUTTON_0   BUTTON_1
#define BSP_BUTTON_1   BUTTON_2
#define BSP_BUTTON_2   BUTTON_3
#define BSP_BUTTON_3   BUTTON_4

// LEDs definitions
//#define LEDS_NUMBER    1

//#define LED_1          38

//#define LEDS_ACTIVE_STATE 0

//#define LEDS_LIST { LED_1}

//#define BSP_LED_0      LED_1

//#define LEDS_INV_MASK  0

//#define BUTTONS_LIST {  }

//#define BSP_BUTTON_0


#define RX_PIN_NUMBER  8
#define TX_PIN_NUMBER  6
#define CTS_PIN_NUMBER 7
#define RTS_PIN_NUMBER 5
#define HWFC           true

#define BSP_QSPI_SCK_PIN   19
#define BSP_QSPI_CSN_PIN   17
#define BSP_QSPI_IO0_PIN   20
#define BSP_QSPI_IO1_PIN   21
#define BSP_QSPI_IO2_PIN   22
#define BSP_QSPI_IO3_PIN   23


// serialization APPLICATION board - temp. setup for running serialized MEMU tests
#define SER_APP_RX_PIN              NRF_GPIO_PIN_MAP(1,13)    // UART RX pin number.
#define SER_APP_TX_PIN              NRF_GPIO_PIN_MAP(1,14)    // UART TX pin number.
#define SER_APP_CTS_PIN             NRF_GPIO_PIN_MAP(0,2)     // UART Clear To Send pin number.
#define SER_APP_RTS_PIN             NRF_GPIO_PIN_MAP(1,15)    // UART Request To Send pin number.

#define SER_APP_SPIM0_SCK_PIN       NRF_GPIO_PIN_MAP(0,27)     // SPI clock GPIO pin number.
#define SER_APP_SPIM0_MOSI_PIN      NRF_GPIO_PIN_MAP(0,2)      // SPI Master Out Slave In GPIO pin number
#define SER_APP_SPIM0_MISO_PIN      NRF_GPIO_PIN_MAP(0,26)     // SPI Master In Slave Out GPIO pin number
#define SER_APP_SPIM0_SS_PIN        NRF_GPIO_PIN_MAP(1,13)     // SPI Slave Select GPIO pin number
#define SER_APP_SPIM0_RDY_PIN       NRF_GPIO_PIN_MAP(1,15)     // SPI READY GPIO pin number
#define SER_APP_SPIM0_REQ_PIN       NRF_GPIO_PIN_MAP(1,14)     // SPI REQUEST GPIO pin number

// serialization CONNECTIVITY board
#define SER_CON_RX_PIN              NRF_GPIO_PIN_MAP(1,14)    // UART RX pin number.
#define SER_CON_TX_PIN              NRF_GPIO_PIN_MAP(1,13)    // UART TX pin number.
#define SER_CON_CTS_PIN             NRF_GPIO_PIN_MAP(1,15)    // UART Clear To Send pin number. Not used if HWFC is set to false.
#define SER_CON_RTS_PIN             NRF_GPIO_PIN_MAP(0,2)     // UART Request To Send pin number. Not used if HWFC is set to false.


#define SER_CON_SPIS_SCK_PIN        NRF_GPIO_PIN_MAP(0,27)    // SPI SCK signal.
#define SER_CON_SPIS_MOSI_PIN       NRF_GPIO_PIN_MAP(0,2)     // SPI MOSI signal.
#define SER_CON_SPIS_MISO_PIN       NRF_GPIO_PIN_MAP(0,26)    // SPI MISO signal.
#define SER_CON_SPIS_CSN_PIN        NRF_GPIO_PIN_MAP(1,13)    // SPI CSN signal.
#define SER_CON_SPIS_RDY_PIN        NRF_GPIO_PIN_MAP(1,15)    // SPI READY GPIO pin number.
#define SER_CON_SPIS_REQ_PIN        NRF_GPIO_PIN_MAP(1,14)    // SPI REQUEST GPIO pin number.

#define SER_CONN_CHIP_RESET_PIN     NRF_GPIO_PIN_MAP(1,1)    // Pin used to reset connectivity chip

// Arduino board mappings
#define ARDUINO_SCL_PIN             27    // SCL signal pin
#define ARDUINO_SDA_PIN             26    // SDA signal pin
#define ARDUINO_AREF_PIN            2     // Aref pin

#define ARDUINO_13_PIN              NRF_GPIO_PIN_MAP(1, 15)  // Digital pin 13
#define ARDUINO_12_PIN              NRF_GPIO_PIN_MAP(1, 14)  // Digital pin 12
#define ARDUINO_11_PIN              NRF_GPIO_PIN_MAP(1, 13)  // Digital pin 11
#define ARDUINO_10_PIN              NRF_GPIO_PIN_MAP(1, 12)  // Digital pin 10
#define ARDUINO_9_PIN               NRF_GPIO_PIN_MAP(1, 11)  // Digital pin 9
#define ARDUINO_8_PIN               NRF_GPIO_PIN_MAP(1, 10)  // Digital pin 8

#define ARDUINO_7_PIN               NRF_GPIO_PIN_MAP(1, 8) // Digital pin 7
#define ARDUINO_6_PIN               NRF_GPIO_PIN_MAP(1, 7) // Digital pin 6
#define ARDUINO_5_PIN               NRF_GPIO_PIN_MAP(1, 6) // Digital pin 5
#define ARDUINO_4_PIN               NRF_GPIO_PIN_MAP(1, 5) // Digital pin 4
#define ARDUINO_3_PIN               NRF_GPIO_PIN_MAP(1, 4) // Digital pin 3
#define ARDUINO_2_PIN               NRF_GPIO_PIN_MAP(1, 3) // Digital pin 2
#define ARDUINO_1_PIN               NRF_GPIO_PIN_MAP(1, 2) // Digital pin 1
#define ARDUINO_0_PIN               NRF_GPIO_PIN_MAP(1, 1) // Digital pin 0

#define ARDUINO_A0_PIN              3     // Analog channel 0
#define ARDUINO_A1_PIN              4     // Analog channel 1
#define ARDUINO_A2_PIN              28    // Analog channel 2
#define ARDUINO_A3_PIN              29    // Analog channel 3
#define ARDUINO_A4_PIN              30    // Analog channel 4
#define ARDUINO_A5_PIN              31    // Analog channel 5

// Low frequency clock source to be used by the SoftDevice
#define NRF_CLOCK_LFCLKSRC      {.source        = NRF_CLOCK_LF_SRC_XTAL,            \
                                 .rc_ctiv       = 0,                                \
                                 .rc_temp_ctiv  = 0,                                \
                                 .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM}

#ifdef __cplusplus
}
#endif

#endif // BOARD_CUSTOM_H

and in the make file I have add the path to the file custom_board.h and I have changed the CFLAG like this

CFLAGS += -DBOARD_CUSTOM
# CFLAGS += -DBOARD_PCA10056

Do you have an idea why I can not initialize the micro SD card ?

When looking at the schematic if you find something strange with the antenna or related with the BLE you may have spotted another error as I can not connect to the BLE (but I am able to detect it ! ).

Thank you very much for the help. As you can understand when looking at the custom board schematic, I have spend a lot of time and energy on this project and I start to feel low when running in so complicated problem.

Best regards,

Loïc

Parents
  • With my custom board the code can not do the initialization function

    What function returns what error? 

    We need a datasheet for your SD card.

     

  • Hi,

    Right, the micro SD card comes from Kingston and it is a micro SD card HC with a speed class rating of 4. Here a link to the datasheet.

    When using the custom board with the 104031-0811 reader from Molex the code return "Disk initialization failed." line 73 of the code pasted in the original message. Therefore, the error comes from the function disk_initialize(0) line 69.

    If I try to sum things up :

    I have two settings : one with the nRF52DK and this reader  which works - and a second setting with a custom board and the Molex reader which does not. In both configuration I run the same code, with the same pins for the SPI bus. 

    I hope you have an idea to help me,

    Thanks,

    Loïc  

  • Yes, it is where the problem is ie the app_sdc_init function. At the end of this function it will send 80 clocks without CS activated to switch into SPI mode

        // Send 80 clocks with CS inactive to switch into SPI mode.
        m_cb.cmd_buf[0] = 0xFF;
        err_code = nrf_drv_spi_transfer(&m_spi, m_cb.cmd_buf, 1,
                                                m_cb.rsp_buf, 10);
        APP_ERROR_CHECK(err_code);

    There is no problem at this point in the code. Few lines of code after, it waits for the transfer to finish and throw an error that the last result is bad NRF_BLOCK_DEV_RESULT_IO_ERROR (1). But I can not see what happened during the 80 clocks.

    I have tested the following things :

    - with nordic DK I have welded a SD card adaptor directly on SPI bus. I have tested without sd card reader if it is working and the answer is yes ! This is exactly the same circuit than the custom board. No SD card reader.

    SC adapter for micro SD card direct circuit for SPI bus using nordic DK

    - Using the custom board, I have downloaded a program that switch the pins (cs, clock, mosi, miso) to high and then enter an infinite loop which makes the debug led blinks. Using a voltmeter, I have checked that all pins deliver 3V when touching the pin on the sd card reader as shown check voltage ok

    To sum things up :

    The custom board is able to switch spi pins low to high (it is working). The code is working using the 'table' assembly (thank you Nordic). I don't have much ideas left to test.

    The custom board is a two layers boards, nRF52840 is on layer one and molex on layer two. Do you think the vias between two layers can create a capacitor ?

  • Hi Swip - I am also having similar issues and wanted to see if you were able to resolve it

  • no luck for the moment. What is your circuit ? Are you using your own custom board ?

  • You should see 80 clocks with CS=high followed by a CMD0 command sequence with CS=LOW. The CMD0 sequence is 0x40, 4 times 0x00, and then 0x95 on MOSI.

    Note that the SPI clock must not be faster than 400kHz, and there should be a pullup (internal or resistor) on MISO, as the sdcard will start up in open drain mode. Faster SPI clocks are only supported when the initialization sequence has finished.

  • The custom board is a two layers boards, nRF52840 is on layer one and molex on layer two. Do you think the vias between two layers can create a capacitor ?

    Via are inductors, not capacitors. We still need a scope of the SPI bus. 
    I suggest that you desolder the molex SD card holder and solder the SD card to the molex footprint pad via wires. If this works then there's something wrong with the molex. 

Reply
  • The custom board is a two layers boards, nRF52840 is on layer one and molex on layer two. Do you think the vias between two layers can create a capacitor ?

    Via are inductors, not capacitors. We still need a scope of the SPI bus. 
    I suggest that you desolder the molex SD card holder and solder the SD card to the molex footprint pad via wires. If this works then there's something wrong with the molex. 

Children
  • Hi,

    Finally got what was going wrong :) Turns out it was due to the power supply with the USB without using a battery. There was a level drop each 400 ns approximately which was messing up with the SPI bus for the SD reader.

    Thank you very much for your input and your help !

    Now I use the circuit from this figure in the post to power the custom board and flash the code. Is it good to do it like this ?

    I may have tried many things to solve my last problem and now I am getting error 33 when flash some basic code to the nRF52840 DK. I have notice that the green light is not perfectly solid. Do you think I may have fry my development kit ?

  • Hey swip sorry for the late reply, Are you still experiencing an issue when flashing your external board? You mentioned "getting error 33 when flash some basic code to the nRF52840 DK. I have notice that the green light is not perfectly solid. " Have you tried scoping VDD of the external board?

Related