FatFS, MinIni, Shell and FreeRTOS for the NXP K22FN512

I’m using the NXP Kinetis K22FN512 in many projects, either with the FRDM-K22F or on the tinyK22: with 120 MHz, 512 KByte FLASH and 128 KByte it has plenty of horsepower for many projects. The other positive thing is that it is supported by the NXP MCUXpresso IDE and SDK. I have now created an example which can be used as base for your own project, featuring FreeRTOS, FatFS, MinIni and a command line shell.

FRDM-K22F with SD Card

FRDM-K22F with SD Card

Outline

This article describes a example which can be used as base for your own project. It uses the Eclipse based MCUXpresso IDE V11.1 with the MCUXpresso SDK v2.7.0 with the following features:

  • FRDM-K22F board with NXP MK22FN512VLH12 running at 120 MHz
  • FatFS File system, Card Detection and adaptive SPI speed up to 50 MHz
  • RTC/Timestamping
  • FreeRTOS with reentrant file system support
  • MinIni integration
  • Command line shell
  • Integrated Segger SystemView
MCUXpresso IDE

MCUXpresso IDE

Sources

The project and all files are available on GitHub. The FatFS sources are located inside the McuLib:

FatFS Files

FatFS Files

The McuLib includes the FreeRTOS, the MinIni and all the other middleware including the command line shell. Configuration of the library is with the header files in the config folder.

Application files are located in the ‘source’ folder:

Application Files

Application Files

  • application: ‘blinky’ task and application initialization
  • fatfs_sdcard: callbacks for FatFS, including card detection
  • ffconf.h: configuration of FatFS
  • leds: GPIO driver for the RGB LEDs on the board
  • platform: driver and middleware configuration
  • Shell: command line shell and task
  • IncludeMcuLibConfig: configuration header file, see Different Ways of Software Configuration

Pins and Clocking

Pins are configured for the SPI bus to be used in the Pins tool:

SPI Pin Configuration

SPI Pin Configuration

For maximum performance, the MCU runs at 120 MHz:

Clock Configuration for 120 MHz System and Bus Clock

Clock Configuration for 120 MHz System and Bus Clock

See “Tutorial: Maximum Clock Frequency for Kinetis using MCUXpresso Clock Tools” for how to configure the clocks.

Shell

The application includes a command line shell which provides an easy access to the functionality. It uses the onboard USB-CDC connection through OpenSDA by default:

Command Line Shell

Command Line Shell

The same is available through SEGGER RTT:

SEGGER RTT Client

SEGGER RTT Client

RTT can be turned off in platform.h if not needed or not using a SEGGER J-Link.

MinIni

MinIni is a great open source project. Using it configuration settings (aka .INI files) can be used to configure the applicatio, using configuration sections and key-value pairs. The command line shell offers an easy way to create and modify .ini files:

  1. McuFatFS create config.ini
  2. McuMinINI write config.ini LED color green
  3. McuFatFS print config.ini
Creating ini file

Creating ini file

Below an example how the .ini files can be used to configure the application: depending on the ini file content a different RGB LED is used:

static void AppTask(void *pv) {
  McuLED_Handle_t led;
  uint8_t colorBuf[8];

  vTaskDelay(pdMS_TO_TICKS(1000));
  led = LEDS_LedGreen; /* default */
  if (ini_gets(
      (const TCHAR *)"LED", /* section */
      (const TCHAR *)"color", /* key */
      (const TCHAR *)"green",  /* default value */
      (TCHAR *)colorBuf, sizeof(colorBuf), /* key value from ini */
      (const TCHAR *)"config.ini" /* ini file */
      )
      > 0) /* success */
  {
    if (McuUtility_strcmp((char*)colorBuf, (char*)"red")==0) {
      led = LEDS_LedRed;
    } else if (McuUtility_strcmp((char*)colorBuf, (char*)"green")==0) {
      led = LEDS_LedGreen;
    } else if (McuUtility_strcmp((char*)colorBuf, (char*)"blue")==0) {
      led = LEDS_LedBlue;
    }
  }
  for(;;) {
    McuLED_Toggle(led);
    vTaskDelay(pdMS_TO_TICKS(100));
  }
}

SystemViewer

The project includes support for the SEGGER SystemView: to validate the application performance (requires a SEGGER J-Link debug connection).

SEGGER SystemViewer

SEGGER SystemViewer

It can be turned off with a setting in the IncludeMcuLibConfig:

#define configUSE_SEGGER_SYSTEM_VIEWER_HOOKS (1)

FatFS

FatFS has been integrated in a way I hope it is really easy to use: Shell task is checking the card detection pin and automatically detects card insertion and removal:

Card Detection

Card Detection

The FatFS is configured to use the RTC which can be both a HW RTC or a software RTC. To FreeRTOS timers are used: one for timeout functionality and one to update the software RTC:

FreeRTOS Timers

FreeRTOS Timers

A FreeRTOS Mutex is used to guarantee reentrant access to the file system:

FatFS Mutex

FatFS Mutex

The FatFS port uses adaptive speed: depending on the card capabilities a SPI clock of 12 MHz, 25 MHz or 50 MHz is used.

SPI Bus transactions

SPI Bus transactions

With a 12 MHz clocking the write speed is around 80-100 kByte/sec and reading is around 160-200 kByte/sec.

The hooks to detect card insertion and removal are realized in fatfs_sdcard.c. For the card detection pin a pull-down resistor needs to be turned on:

/*
 * Copyright (c) 2020, Erich Styger
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "platform.h"
#include "fatfs_sdcard.h"
#include "McuGPIO.h"

#if PL_CONFIG_USE_SD_CARD

#define CARD_DETECT_GPIO        GPIOB
#define CARD_DETECT_PORT        PORTB
#define CARD_DETECT_PIN         16U

static McuGPIO_Handle_t FatFS_CardDetectPin;

bool McuFatFS_IsDiskPresent(uint8_t drv) {
  return McuGPIO_IsHigh(FatFS_CardDetectPin); /* pin has internal pull-down. Pin is high if card is inserted */
}

bool McuFatFS_IsWriteProtected(uint8_t drv) {
  return false; /* there is no way to detect write detection on the micro SD card */
}

void FatFS_SdCardInit(void) {
  McuGPIO_Config_t config;

  McuGPIO_GetDefaultConfig(&config);
  config.isInput = true;
  config.hw.gpio = CARD_DETECT_GPIO;
  config.hw.port = CARD_DETECT_PORT;
  config.hw.pin = CARD_DETECT_PIN;
  FatFS_CardDetectPin = McuGPIO_InitGPIO(&config);
  McuGPIO_SetPullResistor(FatFS_CardDetectPin, McuGPIO_PULL_DOWN);
}

#endif /* PL_CONFIG_USE_SD_CARD */

Summary

I have now a great example with FatFS, MinIni, FreeRTOS and command line shell which is a starting point for any project which need a file system on a  SD card. I hope you will find it useful too. The project is maintained on GitHub and will be enhanced and improved as needed.

Happy FatFS’ing đŸ™‚

Links

10 thoughts on “FatFS, MinIni, Shell and FreeRTOS for the NXP K22FN512

    • Hi Brad,
      I did not enable optimization (-O0) for the moment, and I’m sure things could get smaller. But to give an idea:

      Memory region Used Size Region Size %age Used
      PROGRAM_FLASH: 95192 B 512 KB 18.16%
      SRAM_UPPER: 12768 B 64 KB 19.48%
      SRAM_LOWER: 24 KB 64 KB 37.50%

      I gave plenty of RAM to the FreeRTOS heap and task stacks (heap size 24 KByte), and of that heap only 33% (8 KB) is used at the moment.
      8 KByte in the SRAM_UPPER are right now for the Stdlib heap which I propably will eliminate anyway.

      Like

  1. Pingback: Tutorial: Adding FreeRTOS to where there is no FreeRTOS | MCU on Eclipse

  2. Pingback: McuLog: Logging Framework for small Embedded Microcontroller Systems | MCU on Eclipse

  3. Pingback: How to get Data off an Embedded System: FatFS with USB MSD Host and FreeRTOS Direct Task Notification | MCU on Eclipse

  4. Thanks for the blog Erich.

    I have been working on to integrate Minini with fatfs on baremetal. Everything seems working fine when reading the values and strings from the sections. But while writing value ini_putl & ini_puts, the unnecessary files inside the sd card has been creating with the size of 524787. I have not defined READ_ONLY in the header.
    What causing the issue ?

    Like

  5. Pingback: Using FatFS and MinINI with the NXP LPC55S16 EVK | MCU on Eclipse

  6. Pingback: Key-Value pairs in FLASH Memory: file-system-less minINI | MCU on Eclipse

What do you think?

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