This tutorial was extracted from Erich Styger blog http://mcuoneclipse.wordpress.com with his agreement.
One success factor of the Arduino platform is the broad availability so-called ‘shields’: hardware plugin-modules which extend the capability of platform. Shieldlist.org currently lists 288 different shields available! Clearly, Freescale wants to benefit from that ecosystem with the Freedom FRDM-KL25Z board which features Arduino compatible headers. Time to use the Freedom board with an Arduino shield .
Data Logger Shield Hardware
I ordered a the Adafruit Data Logger Shield as a kit: to solder such a kit is fun , and gives me the freedom what to put on the board. The schematics of the shield can be found here.
The board features an SD card with level shifter (required to work with 3.3V and 5V devices), two LED’s, a reset button, an I2C battery buffered realtime clock plus a prototype area. The minimal SD card pins (MISO, MOSI, DeviceSelect, BusCock) and I2C (SDA, SCL) bus are connected to the shield connector rows, while the two LEDs and the card write protect and card detect pins can be routed to any pins with a wire or any other kind of connection.
Data Logger Top View
In above picture the green wire is for WP (SD card Write Protection pin), the white wire is for the CD (SD Card Detect) pin. The yellow wires are for the red and green LED.
Freedom_FatFS Application
The application is Eclipse based CodeWarrior for MCU10.3 application. It uses the SD card with the open source FatFS file system.
The FAT_FileSystem and SD_Card component have been updated to work with Kinetis. So make sure you use the latest component from EmbeddedComponents for this project.
- GenericTimeDate: needed for date and time information, as the file system needs date/time attributes for files on the file system
- Wait: generic busy wait routines, needed by the SD card driver because initialization of the SD card driver needs to wait for a time as specified in the SD card standard.
- Timeout: As SD card operations can take a very long time (several hundreds of milliseconds), this timeout driver allows to wait for a given time.
- SPIMaster_LDD: implements the SPI bus driver using interrupts.
- FAT_FileSystem: Implements the FAT file system.
- SD_Card: Low level SD card driver implementing the memory device.
- TimerInt_LDD and TimerUnit_LDD: implement a 10 ms timer used for the Timeout component.
- Init_GPIO: Init components used for pull up resistors for the WP and CD signals (see this tutorial).
- LED and GPIO_LDD: Driver for the RGB LED on the Freedom board (see this tutorial). Note that the signal for the blue RGB LED is used for the SD card SPI clock signal by the Data Logger Shield.
- BitIO_LDD: Used for the green and red LED on the shield (see this tutorial).
The project and components can be easily changed for any other SD cards. In any case, here are tips and hints how the project is configured:
KL25Z with 48 MHz
In order to run the SPI bus with up to 12 MHz, the CPU core clock is configured to run at 48 MHz:
SPIMaster_LDD Configuration
The SPI component needs to be configured for the MISO, MOSI and CLK pins, *without* Chip select and two clock configurations, each with ‘MSB first’, ‘Low Clock polarity’ and ‘capture on leading edge’:
The Attribute Set 0 needs to point to Clock rate index 0, and the so the Attribute Set 1 to Clock rate index 1. The reason is that we need to SPI clock speeds: a maximum of 400 kHz for card initialization and up to 20 MHz for normal operation. What we can achieve here is 375 kHz and 12 MHz.
The two speed modes need to be set in the clock rate settings:
In the Timing Dialog the two SPI clock speeds need to be configured with ‘list of values’:
The two speed modes are referenced from the SD_Card component properties:
Timeout Component
As the SD card requires up to several hundreds of milliseconds delay, the Timeout component is used.
For this a 10 ms timer is configured with the TimerInt_LDD component. What easily gets missed is to call the AddTick()
method in Events.c from the 10 ms timer interrupt:
01 /*
02 ** ===================================================================
03 ** Event : TI1_OnInterrupt (module Events)
04 **
05 ** Component : TI1 [TimerInt_LDD]
06 ** Description :
07 ** Called if periodic event occur. Component and OnInterrupt
08 ** event must be enabled. See and
09 ** methods. This event is available only if a <Interrupt
10 ** service/event> is enabled.
11 ** Parameters :
12 ** NAME - DESCRIPTION
13 ** * UserDataPtr - Pointer to the user or
14 ** RTOS specific data. The pointer passed as
15 ** the parameter of Init method.
16 ** Returns : Nothing
17 ** ===================================================================
18 */
19 void TI1_OnInterrupt(LDD_TUserData *UserDataPtr)
20 {
21 TMOUT1_AddTick();
22 }
WP and CD Pins
Optionally the SD card holder can provide WP (Write Protect) and CD (Card Detect) signals. They are available in the SD_Card component settings:
If the signals do not have pull-ups or pull-down resistors on the board (as for my shield), they need to be configured in ‘pin-sharing’ mode and with pull-ups enabled (see this tutorial).
The WP signal is connected to the shield D8 line, and the CD signal is connected to D9.
LED’s
The projects used the RGB LED on the Freedom board plus the two LED’s on the Shield. The two shield LED’s are connected to the shield D7 and D6 lines.
Example Code
The example code is in ProcessorExpert.c:
01 static FATFS fs;
02 static FIL fp;
03
04 static void Test(void) {
05 UINT bw; /* number of bytes written */
06
07 if (FAT1_isDiskPresent()) { /* if no hardware CardDetect pin is assigned, it will always return TRUE */
08 LED_Rd_On(); /* turn red RGB LED on */
09 FAT1_mount(0, &fs); /* mount file system */
10 if (!FAT1_isWriteProtected()) { /* if no hardware WritePtotect pin is assigned, it will always return FALSE */
11 LED_Gr_On(); /* turn green RGB LED on */
12 if (FAT1_open(&fp, "./test.txt", FA_CREATE_ALWAYS|FA_WRITE)!=FR_OK) { /* open file, will always create it if not already on disk */
13 for(;;){} /* error! */
14 }
15 if (FAT1_write(&fp, "Hello World!", sizeof("Hello World!")-1, &bw)!=FR_OK) { /* write string to file */
16 for(;;){} /* error! */
17 }
18 }
19 (void)FAT1_close(&fp); /* close file */
20 FAT1_mount(0, NULL); /* unmount file system */
21 }
22 }
If a card is inserted, the Red RGB LED will be on and the file system will be mounted. If the card has not the write protection tab on, it will write a file ‘test.txt’ with an example text in it.
Summary
For now I only have this shield, and it worked very well with the Freedom board. The shield has an I2C Real-Time-Clock on it for which I did not wrote a driver yet. That would give me a battery backed up clock which would make it ideal for a data logger application. Again, still some work to do .
I need to check/measure the SD card speed, but for now it is reasonable for my tests. For sure I will need to extend my Shell Project with the SD card capabilities.
The project and sources is available from this link. Code size with gcc and even not optimized at all is less than 18 KByte, so very reasonable.