SD Card

This sample demonstrates the use of an SD memory card with the chip using the SD library.

The sample initializes the memory card and performs a data write operation to the card. It then performs a data read and checks for consistency with the previously written data.

Requirements

The sample supports the following development kits:

Development Kits

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

For more requirements, please refer to Quick Start.

Wiring

For the SD Card daughterboard and wiring, please refer to WiFi and SD Nand Flash Multiplexed Interface in Model B Evaluation Board .

SD Card interface pins are shown in the table below:

SD Card Interface PINs

Name

PIN

Description

DAT3 / CS

P9_5

Data Line 3

CMD / DI

P9_3

Command Response Line

VSS1

GND

Supply Power Ground

VDD

VCC(3.3V)

Supply Power 3.3V

CLK

P9_4

Clock

VSS2

GND

Supply Power Ground

DAT0 / DO

P10_0

Data Line 0

DAT1

P9_7

Data Line 1

DAT2

P9_6

Data Line 2

Building and Downloading

This sample can be found in the SDK folder:

Project file: samples\sd\sdcard\proj\mdk

Project file: samples\sd\sdcard\proj\gcc

To build and run the sample, follow the steps listed below:

  1. Open sample project file.

  2. To build the target, follow the steps listed on the Generating App Image in Quick Start.

  3. After a successful compilation, the app bin app_MP_xxx.bin will be generated in the directory mdk\bin or gcc\bin.

  4. To download app bin into EVB board, follow the steps listed on the MP Tool Download in Quick Start.

  5. Press reset button on EVB board and it will start running.

Experimental Verification

  1. After resetting the EVB, observe the SD card initialization status in the Debug Analyzer. If the card is successfully recognized, the status Init: 0 is printed.

    Init: 0
    
  2. Write the prepared data (the first 30 blocks of data are 0xff, and the next 30 blocks of data are 0x00) to the SD card. If write success, the status Write: 0 is printed.

    Write: 0
    
  3. Read the data from the SD card. If read success, the status Read: 0 is printed along with the read data.

    Read: 0
    
    Block 0: 0x0000 -> 0xFF - 0xFF - 0xFF - 0xFF --- 0xFF - 0xFF - 0xFF - 0xFF
    ...
    Block 30: 0x0000 -> 0x00 - 0x00 - 0x00 - 0x00 --- 0x00 - 0x00 - 0x00 - 0x00
    ...
    
  4. Check if the read and write data are identical. If they are not, it will print the error data. For example, if the 100th data of the 1st block is an error: 0x33, it will print as follows:

    Block 0: 0xA0 -> 0x33 data error
    

Code Overview

This chapter will be introduced according to the following several parts:

  1. Source Code Directory.

  2. Peripheral initialization will be introduced in chapter Initialization.

  3. Functional implementation after initialization will be introduced in chapter Functional Implementation.

Source Code Directory

  • Project directory: sdk\samples\sd\sdcard\proj

  • Source code directory: sdk\samples\sd\sdcard\src

Source files are currently categorized into several groups as below.

└── Project: sdcard
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── lib                      includes all binary symbol files that user application is built on
            ├── sd.lib
            └── rtl87x2g_io.lib
        ├── peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_rcc.c
            ├── rtl_pinmux.c
            ├── io_dlps.c
            └── rtl_nvic.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            ├── app_task.c
            └── sd_test.c

Note

It is necessary to add sd.lib to the project. The SD library encapsulates the basic APIs.

Initialization

  1. Set the initialization parameters.

    1. Set the card type to SD Card.

    2. Set the data width to 4BIT.

    3. Set the clock output frequency to 50MHz.

    static const SdEmmcInitParm_t Parm =
    
     .CardType = CARDTYPE_SD,
     .DataWidth = DATAWIDTH_4BIT,
     .ClkOutFreq_kHz = 50 * 1000,
    ;
    ..
    

Functional Implementation

  1. Call Sd_Init to initialize the SD card.

  2. Execute the os_mem_alloc function to allocate memory for pBuf.

  3. Call Sd_Write function to write the prepared data (the first 30 blocks of data are 0xff, and the next 30 blocks of data are 0x00) to the SD card.

  4. Pre-fill pBuf with 0x77, then call Sd_Read function to read the data from the SD card into pBuf.

  5. Print the read data and check if the read and write data are identical. If they are not, it will print the error data.

  6. Execute the os_mem_free function to free the memory for pBuf.

    SdEmmcRes_t Res = Init(SD_Demo, &Parm);
    
    uint8_t *pBuf = os_mem_alloc(RAM_TYPE_EXT_DATA_SRAM, BUF_BYTES);
    memset(pBuf, 0xff, BUF_BYTES / 2);
    memset(pBuf + BUF_BYTES / 2, 0, BUF_BYTES / 2);
    Res = Write(SD_Demo, START_BLOCK, BLOCK_CNT, pBuf);
    
    memset(pBuf, 0x77, BUF_BYTES);
    Res = Read(SD_Demo, START_BLOCK, BLOCK_CNT, pBuf);
    
    /* Print all read data */
    for (size_t i = 0; i < BUF_BYTES; i += 8)
    {
        DBG_DIRECT("Block %d: 0x%04x -> 0x%02x - 0x%02x - 0x%02x - 0x%02x --- 0x%02x - 0x%02x - 0x%02x - 0x%02x",
                   i / 512, i % 512,
                   pBuf[i], pBuf[i + 1], pBuf[i + 2], pBuf[i + 3],
                   pBuf[i + 4], pBuf[i + 5], pBuf[i + 6], pBuf[i + 7]);
    }
    
    /* Compare whether the read data is correct from write data */
    for (uint32_t j = 0; j < BUF_BYTES; j++)
    {
        if (((j < BUF_BYTES / 2) && ((pBuf[j] != 0xff))) ||
            ((j >= BUF_BYTES / 2) && (j < BUF_BYTES) && (pBuf[j] != 0x00)))
        {
            DBG_DIRECT("Block %d: 0x%04x -> 0x%02x data error", j / 512, j % 512, pBuf[j]);
            if (pBuf[j] == 0x77) { break; }
        }
    }
    
    os_mem_free(pBuf);