Using USB Flash with the USB High Speed Interface on the LPC4357 Print

 

This application note explains how to use a USB Flash device with the USB High Speed (HS) interface of the Embedded Artists LPC4357 Dev Kit running uCLinux.


Hardware Platform

The hardware platform is the Embedded Artists LPC4357 Dev Kit. This demo assumes that a mini-USB cable is plugged into the USB0 interface connector J32 on the baseboard and that a pre-formatted USB Flash disk with an FAT32 partition is plugged into the USB 2.0 A Female connector of the above USB cable.


Installing the Demo

The procedure described here explains how to install the bootable Linux image (usbflash.uImage) to the target.

Here is how you can build and install the bootable Linux image from the project sources (usbflash.tgz), having installed them on top of the Emcraft Systems uClinux distribution.

Note: The Linux image and the sample project have been built and validated in context of the Emcraft Systems Release 1.14.0. If you are using a different release, some porting changes may be needed.


Logging Data onto USB Flash

When you boot the Linux image to the target, there will be the following messages on the system console indicating that the USB High-Speed controller and USB mass storage device driver have been initialized:

...
Starting kernel ...
...
usbcore: registered new interface driver smsc95xx
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
lpc43xx-ehci lpc43xx-ehci: LPC43XX EHCI
lpc43xx-ehci lpc43xx-ehci: new USB bus registered, assigned bus number 1
lpc43xx-ehci lpc43xx-ehci: irq 8, io mem 0x40006000
lpc43xx-ehci lpc43xx-ehci: USB 0.0 started, EHCI 1.00
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: LPC43XX EHCI
usb usb1: Manufacturer: Linux 2.6.33-arm1 ehci_hcd
usb usb1: SerialNumber: LPC43XX
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
...
Freeing init memory: 348K
init started: BusyBox v1.17.0 (2015-05-20 15:20:04 +0400)
....

The following messages indicate the USB Flash has been detected and configured:

usb 1-1: new high speed USB device using lpc43xx-ehci and address 2
usb 1-1: New USB device found, idVendor=0781, idProduct=5572
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Cruzer Switch
usb 1-1: Manufacturer: SanDisk
usb 1-1: SerialNumber: 4C530000
240703121445
scsi0 : usb-storage 1-1:1.0 ~ # PHY: 00:01 - Link is Up - 100/Full
scsi 0:0:0:0: Direct-Access SanDisk Cruzer Switch 1.27 PQ: 0 ANSI: 6
sd 0:0:0:0: [sda] 15633408 512-byte logical blocks: (8.00 GB/7.45 GiB)
sd 0:0:0:0: [sda] Write Protect is off
sd 0:0:0:0: [sda] Assuming drive cache: write through
sd 0:0:0:0: [sda] Assuming drive cache: write through
sda:
sda1
sd 0:0:0:0: [sda] Assuming drive cache: write through
sd 0:0:0:0: [sda] Attached SCSI removable disk

At this point, the USB Flash is accessible as a disk. The following command is used to examine the disk, which is detected as a 8 GBytes disk partitioned to have a single empty FAT32 partition:

~ # fdisk -l /dev/sda

Disk /dev/sda: 8004 MB, 8004304896 bytes
35 heads, 21 sectors/track, 21269 cylinders
Units = cylinders of 735 * 512 = 376320 bytes

Device Boot Start End Blocks Id System
/dev/sda1 1 21270 7816688 b Win95 FAT32
~ #

Let's mount the FAT32 file system. As expected, it is empty at this point:

~ # mount /dev/sda1 /mnt
~ # ls -lt /mnt
~ #

Let's "harvest" some data and store what is collected into a file on the USB Flash disk. In this demo, we emulate a data stream by taking a snapshot of the system time each second:

~ # while true; do date >> /mnt/data.log; sleep 1; done

Having let the "data harvesting" run for a few seconds, let's interrupt it (by pressing ^-C) and take a look at what data we have collected:

^C
~ # cat /mnt/data.log
Thu Jan 1 00:01:18 UTC 1970
Thu Jan 1 00:01:19 UTC 1970
Thu Jan 1 00:01:20 UTC 1970
Thu Jan 1 00:01:21 UTC 1970
Thu Jan 1 00:01:22 UTC 1970
Thu Jan 1 00:01:23 UTC 1970
Thu Jan 1 00:01:24 UTC 1970
Thu Jan 1 00:01:25 UTC 1970

Now, let's unmount the USB Flash and unplug the device from the USB connector:

~ # umount /mnt/
~ # usb 1-1: USB disconnect, address 2

At this point, the USB Flash device can be taken to a PC for further data processing. Just plug in the USB Flash into a USB port on your PC and the PC software will be able to mount the device as a FAT32 file system.

Note that the format of Windows and Unix text files differs slightly. In Windows, lines end with both the line feed and carriage return ASCII characters, but Unix uses only a line feed. As a consequence, some Windows applications will not show the line breaks in Unix-format files. Assuming that data is stored in a text file (vs a binary file) and Windows is a data processing host, Linux data harvesting applications should take care of the difference by adding a carriage return character to data logs.

Note further that you can hot plug your USB Flash device on the running system at any time:

~ # usb 1-1: new high speed USB device using lpc43xx-ehci and address 3
usb 1-1: New USB device found, idVendor=0781, idProduct=5572
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Cruzer Switch
usb 1-1: Manufacturer: SanDisk
usb 1-1: SerialNumber: 4C530000240703121445
scsi1 : usb-storage 1-1:1.0
scsi 1:0:0:0: Direct-Access SanDisk Cruzer Switch 1.27 PQ: 0 ANSI: 6
sd 1:0:0:0: [sda] 15633408 512-byte logical blocks: (8.00 GB/7.45 GiB)
sd 1:0:0:0: [sda] Write Protect is off
sd 1:0:0:0: [sda] Assuming drive cache: write through
sd 1:0:0:0: [sda] Assuming drive cache: write through
sda:
sda1
sd 1:0:0:0: [sda] Assuming drive cache: write through
sd 1:0:0:0: [sda] Attached SCSI removable disk
~ # mount /dev/sda1 /mnt
~ # ls -lt /mnt
-rwxr-xr-x 1 root root 232 Jan 1 1980 data.log
~ #


Read / Write Performance

Write throughput to the above USB Flash is measured to be as follows:

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

Read throughput using the same USB Flash device is as follows:

~ # umount /mnt
~ # mount /dev/sda1 /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, 3.894266 seconds, 2.6MB/s
~ #


Data Synchronization Considerations

It is important to understand that VFAT supports write-back in Linux, which means that file changes do not go to the physical media straight away and instead are cached in memory and go to the Flash at a later time. This helps to reduce amount to I/O to the physical Flash, resulting in a better performance overall.

The write-back creates a certain issue for embedded devices however. If the power to the device is shut down unexpectedly, or the USB Flash is unplugged without a proper unmount or sync, some of latest file changes may be lost.

As it is typical with Linux, the issue can be handled in many ways. Data synchronization can be ensured on a per-file, per-subtree, per-filesystem or system-wide basis. Synchronization can be transparent for the user or may require issuing an explicit API call or a shell command.

The most obvious solution is to mount the file system in synchronous mode (note the -o sync parameter in the call below):

~ # mount -o sync /dev/sda1 /mnt
~ # 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/sda1 on /mnt type vfat
(rw,sync,relatime,fmask=0022,dmask=0022,codepage=cp437,iocharset=iso8859-1,
shortname=mixed,errors=remount-ro)
~ #

When the file system is mounted for synchronous operation, Linux guarantees that data is written to the physical media before any write() returns to a calling application. The tradeoff is that written data is no longer cached in memory, which reduces the write performance substantially.