Arduino Data-Logger Shield with the FRDM-KL25Z Board

One success factor of the Arduino platform is the broad availability so-called ‘shields’: hardware plugin-modules which extend the capability of platform. 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 on Top of Freedom Board

Data Logger Shield on Top of Freedom Board

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

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.

Freedom_FatFS Processor Expert Components

Freedom_FatFS Processor Expert Components

  • 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:

48 MHz Core Clock

48 MHz Core Clock

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’:

SPI Configuration

SPI Configuration

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:

Clock Rate Settings

Clock Rate Settings

In the Timing Dialog the two SPI clock speeds need to be configured with ‘list of values’:

Timing Dialog

Timing Dialog

The two speed modes are referenced from the SD_Card component properties:

Slow and Fast Speed Modes

Slow and Fast Speed Modes

Timeout Component

As the SD card requires up to several hundreds of milliseconds delay, the Timeout component is used.

SD_Card Timeout Properties

SD_Card Timeout Properties

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:

** ===================================================================
**     Event       :  TI1_OnInterrupt (module Events)
**     Component   :  TI1 [TimerInt_LDD]
**     Description :
**         Called if periodic event occur. Component and OnInterrupt
**         event must be enabled. See  and
**         methods. This event is available only if a <Interrupt
**         service/event> is enabled.
**     Parameters  :
**         NAME            - DESCRIPTION
**       * UserDataPtr     - Pointer to the user or
**                           RTOS specific data. The pointer passed as
**                           the parameter of Init method.
**     Returns     : Nothing
** ===================================================================
void TI1_OnInterrupt(LDD_TUserData *UserDataPtr)

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:

CD and WP Pins

CD and WP Pins

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.


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.

LED Components in Component View

LED Components in Component View

Example Code

The example code is in ProcessorExpert.c:

static FATFS fs;
static FIL fp;

static void Test(void) {
  UINT bw; /* number of bytes written */

  if (FAT1_isDiskPresent()) { /* if no hardware CardDetect pin is assigned, it will always return TRUE */
    LED_Rd_On(); /* turn red RGB LED on */
    FAT1_mount(0, &fs); /* mount file system */
    if (!FAT1_isWriteProtected()) { /* if no hardware WritePtotect pin is assigned, it will always return FALSE */
      LED_Gr_On(); /* turn green RGB LED on */
      if (FAT1_open(&fp, "./test.txt", FA_CREATE_ALWAYS|FA_WRITE)!=FR_OK) { /* open file, will always create it if not already on disk */
        for(;;){} /* error! */
      if (FAT1_write(&fp, "Hello World!", sizeof("Hello World!")-1, &bw)!=FR_OK) { /* write string to file */
        for(;;){} /* error! */
    (void)FAT1_close(&fp); /* close file */
    FAT1_mount(0, NULL); /* unmount file system */

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.


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.

Happy Shielding 🙂

177 thoughts on “Arduino Data-Logger Shield with the FRDM-KL25Z Board

  1. Hello,

    I am trying to use your library with my application on MKE02Z64VLD4. My code gets stuck at ” while(!SD1_DataReceivedFlag){}”. However, until it initializes the card, the code runs with success. After the initialization, inside the check_fs function, first disk_read function that is commented as “load boot record” makes the CPU get stuck at ” while(!SD1_DataReceivedFlag){}”

    Could you please help?


    • Hello,

      I have found out that if I make SD1_SPI_WRITE_READ_BLOCK_ENABLED 0, thus disabling block write-read, then it works perfectly.


      • Thanks for posting what works for you. There is a setting ‘SPI Block Transfer’ in the SD_Card component which controls this.
        In order to have it working with block read/write, interrupts with buffers in the SPI component need to be enabled (SynchroMaster component, Interrupt service/event enabled with input and output buffer size of 512.
        Is this case?

        Liked by 1 person

      • Hello Erich,

        Thanks for the reply! 🙂

        My SynchroMaster component SM1 has its input and output interrupts enabled and supports a hardware input/output buffer of size 1 only. My SD_Card component has its “SPI Block Transfer” setting on “yes” and has a “Block size” property with a value of “512”.

        I believe the problem is at “Method: SM1_Interrupt (component SPIMaster_LDD)”

        I’ve noticed that “DeviceDataPrv->OutSentDataNum” reaches “DeviceDataPrv->OutDataNumReq” and then in the next iteration of the interrupt, disables the interrupt, loong before “DeviceDataPrv->InpRecvDataNum” reaches “DeviceDataPrv->InpDataNumReq” which means “InpRecvDataNum” cannot follow “OutSentDataNum”. That is what happens when I create a breakpoint and set its ignore count to something like 25 or 50 and make the CPU run. If I make the CPU run step by step, with the F6 key, then “InpRecvDataNum” follows “OutSentDataNum”. However, I did not try this until 512 as I am not that patient, only up to about 50 🙂


        • Hi Abdullah,
          I think “supports a hardware input/output buffer of size 1 only” is your problem. Yes, the hardware has only one byte, but the thing is that the AsynchroSerial component uses a ring buffer so supports much more. Try to set it to say 512 bytes. Otherwise see my examples on GitHub which are using a larger buffer size too.

          Liked by 1 person

      • I have checked your project on GitHub and found out that I have the same “Hardware Input/Output Buffer Size” properties.

        What I’ve found out to be is these two screenshots. Basically, if the interrupt routine is exited by a “Step Over(F6)” debug command and then re-entered, the status register is 224 (DEC) and works fine. However, if the interrupt routine is exited when the debugger is in “Run Mode” that is, for example, pressing “Run To Line (Ctrl + R)” in the first line of the interrupt routine, status register is 96.

        Status Register is 224:
        Status Register is 96:


      • Sorry, the status register is *sometimes* 96. And this leads to a mismatch between “InpRecvDataNum” and “OutSentDataNum”.


      • I am using MKE02Z64VLD4 with my custom board. I guess at this point it seems like I have to disable the “SPI block transfer” and live with the performance decrease..


  2. Hi Erich, nice work!

    I don’t know why, but my code is getting stuck inside the “FAT1_Init();”. There is no error, but when I call this function, it never gets out.

    I’m using MK20DX256VLL10 processor (I did the necessary changes I guess).



What do you think?

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.