Using SD Card in Linux Print


This application note explains how to use SD Card with the STM32F7 in Linux. All software tests documented below were performed on the STmicro STM32F7 Discovery board.

The STM32F7 SD Card device driver is linux/drivers/mmc/host/mmci.c. To enable the SD Card support in the kernel, you must enable the CONFIG_MMC_ARMMMCI build time option in the kernel configuration. To do so, start the kernel configuration GUI (make kmenuconfig from the project directory) and proceed to enable the following item: Device Drivers -> MMC/SD/SDIO card support. Then enter the MMC/SD/SDIO card support menu and enable the following options:

Then, return to the top level menu, enter the System Type -> STM32 I/O interfaces menu, and check the Enable STM32 SD Card interface and Use DMA for the SD Card Interface options:

The most typical use of SD Card in embedded applications is a removable storage device (disk) that can be easily taken from the embedded target to a PC or notebook. In such contexts, SD Card installed to the embedded target is typically already formatted with an MS-DOS file system. The Linux kernel must be specially configured to allow mounting the MS-DOS file system. To perform the configuration, start the kernel configuration interface, proceed to File systems -> DOS/FAT/NT Filesystems and enable the following kernel options:

The two additional kernel configuration options that, depending on your application needs, may be needed to mount an MS-DOS file system on SD Card are illustrated below:

and:

In the target file system, there must be appropriate device nodes to access the SD Card using standard Linux tools and utilities. Add the following lines to your <project>.initramfs file to create the device nodes for the SD Card:

nod /dev/mmcblk0 0600 0 0 b 179 0
nod /dev/mmcblk0p1 0666 0 0 b 179 1
nod /dev/mmcblk0p2 0666 0 0 b 179 2
nod /dev/mmcblk0p3 0666 0 0 b 179 3
nod /dev/mmcblk0p4 0666 0 0 b 179 4

On the target, you will require the mount utility in order to mount an MS-DOS file system on the SD Card. In uClinux, mount is available as part of the multi-call busybox utility. Typically, mount will already be enabled in your busybox configuration, but in case it is not, run the busybox configuration GUI (make bmenuconfig from the project directory), proceed to Linux System Utilities and enable the following item:

You will also need to add a symlink for mount to the target file system. This is done by adding the following line to the <project>.initramfs file (if the line is not already there):

slink /bin/mount busybox 777 0 0

Having updated your project configuration as described above, build the bootable Linux image (<project>.uImage) by running make from the project directory.

Install the newly built uImage file to the Flash on the target as described in Installing Linux Images to Flash or load it to RAM via Ethernet as described in Loading Linux Images via Ethernet and TFTP.

Insert a pre-formatted card with an MS-DOS file system to the SD Card slot on the Discovery board. When you boot the uImage on the STM32F7, there should be messages similar to the ones shown below. In the below example, Linux has detected an SD Card with a single partition on it:

......
mmci-pl18x mmci-pl18x: mmc0: MMCI rev 4 cfg 10 at 0x0000000040012c00 irq 49,-1
...
mmc0: host does not support reading read-only switch. assuming write-enable.
mmc0: new SDHC card at address b368
...
mmcblk0: mmc0:b368 USD 7.45 GiB
mmcblk0: p1
...
init started: BusyBox v1.17.0 (2015-06-18 16:10:32 +0400)
~ #

At this point you are ready to mount the MS-DOS file system on the SD Card. This is done as follows:

~ # mount /dev/mmcblk0p1 /mnt

Check that the file system has indeed been mounted (refer to the last line in the below output):

~ # mount
rootfs on / type rootfs (rw)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
none on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
/dev/mmcblk0p1 on /mnt type vfat
(rw,relatime,fmask=0022,dmask=0022,codepage=cp437,
iocharset=iso8859-1,shortname=mixed,errors=remount-ro)

Now you can write something to the SD Card. In the below example, we store the current date and time to a log file, although in real-life applications you will probably want to do something more meaningful:

~ # date > /mnt/log.file

Verify the written content by reading the log file back:

~ # cat /mnt/log.file
Mon Jun 8 12:27:02 UTC 2015
~ #

Write throughput to an 8GB Kingston SDHC card class 10 is measured to be the following:

~ # dd if=/dev/zero of=/mnt/10m bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10.0MB) copied, 2.515461 seconds, 4.0MB/s
~ #

Read throughput using the same SDHC card is as follows:

~ # umount /mnt
~ # mount /dev/ mmcblk0 /mnt
~ # dd if=/mnt/10m of=/dev/null bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10.0MB) copied, 2.180360 seconds, 4.6MB/s
~ #

Ok, you have validated that we can write data to the SD Card. Now you remove the card the from the embedded target. Unmount the file system and then extract the card from the SD Card slot:

~ # umount /mnt
~ #

mmc0: card aaaa removed

At this point, you can take the card to your PC or notebook and process data stored in the MS-DOS filesystem. As a final step in this application note, validate hot insertion of SD Card on the target. Insert the card back into the SD Card slot on the baseboard with Linux up and running on the STM32F7. Messages similar to the ones shown below should appear on the Linux console:

mmc0: new SD card at address aaaa
mmcblk0: mmc0:aaaa SU02G 1.84 GiB
mmcblk0:
p1

Mount the MS-DOS file system and verify the content of the previously created log file:

~ # mount /dev/mmcblk0p1 /mnt
~ # ls -lt /mnt
-rwxr-xr-x 1 root root 29 Jun 8 12:27 log.file
~ # cat /mnt/log.file
Mon Jun 8 12:27:02 UTC 2015
~ #