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.
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
Sources
The project and all files are available on GitHub. The FatFS sources are located inside the McuLib:
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: ‘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:
For maximum performance, the MCU runs at 120 MHz:
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:
The same is available through SEGGER RTT:
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:
- McuFatFS create config.ini
- McuMinINI write config.ini LED color green
- McuFatFS print config.ini
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).
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:
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:
A FreeRTOS Mutex is used to guarantee reentrant access to the file system:
The FatFS port uses adaptive speed: depending on the card capabilities a SPI clock of 12 MHz, 25 MHz or 50 MHz is used.
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
- Example on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/FRDM-K22F/FRDM-K22F_FatFS_SD_Card
- Mcu Library: https://github.com/ErichStyger/McuOnEclipseLibrary
- FatFS: http://elm-chan.org/fsw/ff/00index_e.html
- MinIni: FRDM with Arduino Ethernet Shield R3, Part 4: MinIni
- MCUXpresso IDE: MCUXpresso IDE V11.1.0
- MXUXpresso SDK: https://mcuxpresso.nxp.com
- FRDM-K22F Board: USB with the Freescale FRDM-K22F Board
- SD card for the FRDM-K22F: Added Micro SD Card Socket to FRDM-K22F
- tinyK22 Board: tinyK22 Boards arrived
- SEGGER SystemView: Segger SystemView: Realtime Analysis and Visualization for FreeRTOS
- Configuration: Different Ways of Software Configuration
How much SRAM and Flash resources are left over?
Thanks
LikeLike
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.
LikeLike
that’s very reasonable. Thanks.
LikeLike
Pingback: Tutorial: Adding FreeRTOS to where there is no FreeRTOS | MCU on Eclipse
Pingback: McuLog: Logging Framework for small Embedded Microcontroller Systems | MCU on Eclipse
Pingback: How to get Data off an Embedded System: FatFS with USB MSD Host and FreeRTOS Direct Task Notification | MCU on Eclipse
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 ?
LikeLike
Somehow don’t see this on my side. Could it be that you have runaway code with not enough stack space allocated? I assume you are using my project on GitHub?
LikeLiked by 1 person
Pingback: Using FatFS and MinINI with the NXP LPC55S16 EVK | MCU on Eclipse
Pingback: Key-Value pairs in FLASH Memory: file-system-less minINI | MCU on Eclipse