Thursday, 28 December 2017

i.mx6sx - M4 SD Card access on the UDOO NEO

In this post I demonstrate that it is possible to interface the M4 to a SD card shield (similar to using an Arduino SD card shield) in order to retrieve or save data locally (without relying on the A9). This work is the result of a larger data logger project, where the A9 remains in sleep mode to conserve power while the M4 performs data logging from numerous sensors.

In the video an SD card shield is interfaced to the UDOO NEO and accessed from the M4. The code initialises the SD card, mounts and reads the FAT32 partition. Subsequently we read bitmap files from the FAT32 partition and display the contents to the LCD display (320x240). Code is written using the FreeRTOS bsp and exeutes on the M4 while the A9 boots linux. Each bitmap file is 230400 bytes and when reading 720 byte blocks  throughput is around 230KB/sec. If we increase the block size to 23040 bytes then throughput is around 340KB/sec.

NEO Connectivty

I chose to use a WeMos data logger shield over a Arduino SD card shield mainly for the following reasons:

1. 3.3v compatible
2. An RTC (plus battery backup) is available on the shield, although the accuracy of the DS1307 compared to DS3231 is questionable.
3. Nice stackable design for inclusion of additional WeMos shields

The shield (just the Arduino equivalent) supports an SPI interface. The Phyical Layer of the SD Card Specification mentions that the primary hardware interface is the SD bus which is implemented through 4 data lines and one command line. On power up the native operating mode of the card is SD bus however it possible to switch the card to SPI bus which is considered a secondary operating mode. The main disadvantages of SPI mode versus SD mode are:

1. The loss of performance single data line versus 4 data lines .
2. Only a subset of the SD commands and functions are supported.
3. The maximum SPI clock speed is limited to 25Mhz regardless of the SD card Class.

Minimum connectivity from a host MCU for SPI mode requires 3 SPI pins plus a GPIO pin for CS.

From the NEO the shield can be connected to ECSPI 2 plus a arbitrary GPIO pin and 3.3v, see above (NEO Connectivity) image for wiring.

Power up and initialisation of the card along with commands and responses are well documented in the Phyical Layer of the SD Card Specification. After powering up the card it should be initialised by applying 74 clock cycles (eg. sending 10 bytes with 0xff as the payload). Followed by CMD0 as the first command to send the card to SPI mode, a positive R1 response will contain 0x01. Next step is to interrogate SD version support by sending CMD8 and lastly we can use ACMD41 to set or determine :

1. Card is initialised
2. Card capacity type (SDHC or SDXC)
3. Switch to 1.8V signal voltage

After initialising the card we can interrogate the card data for example:

1. Read the Card Identification (CID) Register, a 16 byte code that contains information that uniquely identifies the SD card, including the card serial number (PSN), manufacturer ID number (MID) and manufacture date (MDT).

2. Read the Card Specific Data (CSD) Register which defines the data format, error correction type, maximum data access time .. etc

Subsequently I built a simple library to read FAT32 partitions and their file contents as shown in the above screen shot.

In order to improve performance we would need to see if we can enable DMA for the SPI transfers however this represents a challenge as the DMA engine is initialised on the A9 therefore we would need to wait for Linux to boot before accessing the DMA engine.