LittleFS Flash File System: Difference between revisions
No edit summary |
|||
(21 intermediate revisions by 2 users not shown) | |||
Line 18: | Line 18: | ||
The W25Q128FVSG uses 2.7V to 3.6V for operation. Here's a diagram for the the chip's pins and signals,<br> | The W25Q128FVSG uses 2.7V to 3.6V for operation. Here's a diagram for the the chip's pins and signals,<br> | ||
along with the Ebay "W25QXX" module" photo:<br> | along with the Ebay "W25QXX" module" photo:<br> | ||
[[File:W25Q128FV pinout.jpg|300px | [[File:W25Q128FV pinout.jpg|300px]][[File:W25QXX.jpg|300px]]<br> | ||
Since the NUCLEO-F103RB powers its STM32F103RB processor with 3.3V, this "W25QXX" module" | Since the NUCLEO-F103RB powers its STM32F103RB processor with 3.3V, this "W25QXX" module" | ||
Line 24: | Line 24: | ||
Let's look at the signal pins on the NUCLEO-F103RB:<br> | Let's look at the signal pins on the NUCLEO-F103RB:<br> | ||
[[File:NUCLEO-F103RB Connector Signals.jpg|600px | [[File:NUCLEO-F103RB Connector Signals.jpg|600px]]<br> | ||
On the NUCLEO board, the SPI1_SCK signal is being used to drive the board's Green LED.<br> | On the NUCLEO board, the SPI1_SCK signal is being used to drive the board's Green LED.<br> | ||
So, we will use SPI2 bus and its signal pins.<br> | So, we will use SPI2 bus and its signal pins.<br> | ||
To connect up the signals for power and the SPI BUS, here's the wiring diagram that was used:<br> | To connect up the signals for power and the SPI BUS, here's the wiring diagram that was used:<br> | ||
'''Winbond W25Q128FVSG SPI Flash Module wiring:''' | '''Winbond W25Q128FVSG SPI Flash Module wiring:''' | ||
'''Signal | '''W25QXX Windbond''' | ||
DI | '''Signal Pin Pin Color NUCLEO-F103RB Signal & Pin''' | ||
CLK | DI 1 5 Brown PB15 SPI2_MOSI CN10-26 | ||
GND | CLK 2 6 Red PB13 SPI2_SCK CN10-30 | ||
DO | GND 3 4 Orange GND CN10-20 | ||
CS | DO 4 2 Yellow PB14 SPI2_MISO CN10-28 | ||
VCC | CS 5 1 Green PB12 SPI2_NCS CN10-16 | ||
VCC 6 8 Blue +3V3 CN7-16 | |||
==The Software== | ==The Software== | ||
===The SPI and Serial Interface=== | ===The SPI and Serial Interface=== | ||
Let's start by getting enough in place to read the Manufacturer and Device ID from the Winbond part. | Let's start by getting enough in place to read the Manufacturer and Device ID from the Winbond part. | ||
Within the | Within the STM32CubeIDE configuration for your project: | ||
* Enable SPI2 as "Full-Duplex Master"., | * Enable SPI2 as "Full-Duplex Master"., | ||
* Hardware NSS Signal: "Disable" - We will use GPIO control for this signal. | * Hardware NSS Signal: "Disable" - We will use GPIO control for this signal. | ||
- Don't bother trying to use some form of SPI hardware control for this signal pin. | - Don't bother trying to use some form of SPI hardware control for this signal pin. | ||
* Frame Format - Motorola, 8-Bits, MSB First | * Frame Format - Motorola, 8-Bits, MSB First | ||
* Clock Prescaler 256, (140,625KBits/s - this can be changed later) | * Clock Prescaler 256, (140,625KBits/s - Using 72MHz SYSCLK - this can be changed later) | ||
* Clock Polarity - CPOL: Low (signal is normally low) | * Clock Polarity - CPOL: Low (signal is normally low) | ||
* Clock Phase - CPHA: 1 Edge (first rising edge) | * Clock Phase - CPHA: 1 Edge (first rising edge) | ||
* CRC Calculation: Disabled | * CRC Calculation: Disabled | ||
* NSS Signal Type: Software (GPIO | * NSS Signal Type: Software (GPIO control) | ||
* Select PB12 Pin, change signal to GPIO_Output, name it "SPI2_NCS" | * Select PB12 Pin, change signal to GPIO_Output, name it "SPI2_NCS" | ||
Click on Pinout & Configuration tab -> System Core -> GPIO -> PB12 - Set GPIO output to "High" | |||
We want the SPI2_NCS signal high - inactive initially. | |||
* Configure the HCLK for 72MHz (this is rather optional). | * Configure the HCLK for 72MHz (this is rather optional). | ||
(The Winbond part will function well beyond what this STM32 processor can clock over the SPI bus) | (The Winbond part will function well beyond what this STM32 processor can clock over the SPI bus) | ||
Line 60: | Line 63: | ||
===Serial Output, Serial Input, and printf() Support === | ===Serial Output, Serial Input, and printf() Support === | ||
See: https://merkles.com/wiki/index.php/Getting_Started_with_STM32#Create_a_New_STM32CubeIDE_1.10.1_Project_-_Hello-World | |||
===The Winbond 25Q128 (128M-Bit) Library=== | |||
// w25q128.c | Here's my example of a STM32 HAL interface to the Winbond W25Q128 part: | ||
// | [http://merkles.com/example_source_code/w25q128/w25q128.c w25q128.c] | ||
[http://merkles.com/example_source_code/w25q128/w25q128.h w25q128.h] | |||
==Debugging LittleFS== | |||
Capture and check the return code from all function calls. The original example didn't do this. | |||
* Check the return code for lfs_mount(). Make sure it retuns LFS_ERR_OK. | |||
- Although, the first time, it will return an error, and require an lfs_format() call. | |||
* Check the return code for lfs_file_open(). Make sure it retuns LFS_ERR_OK. | |||
* Although I didn't check the return code for lfs_file_rewind(), lfs_file_write(), and lfs_file_close(), | |||
it wouldn't hurt. | |||
* There are plenty of debug printf()s in the code already. Just need to enable them. | |||
Open up lfs_util.h, around line 50, you will want to define LFS_YES_TRACE, to enable printf() tracing: | |||
'''#define LFS_YES_TRACE''' | |||
// Logging functions | |||
#ifdef LFS_YES_TRACE}} | |||
* If your terminal wants CR/LF pairs, edit the printf() strings, adding "\r" to go with the "\n" line feed character. | |||
==To Do== | |||
Using the command line interface, test the SPI interface with the W25Q128. | |||
1) Begin with the JEDIC ID command. Display the part's ID: | |||
See: cl_w25_id() in w25q128.c | |||
>w25id | |||
Jedec ID: 0xEF 0x40 0x18 | |||
2) This part has a unique ID assigned to it. Display it: | |||
See: cl_w25_unique_id() in w25q128.c | |||
>w25uid | |||
Unique ID: D2 65 CC 22 67 24 37 28 <This ID is from one of my parts. Yours will be different.> | |||
At this point, you have both written to and read from the SPI FLASH device. | |||
If your ID is correct and you're not getting errors, chances are your SPI interface is functioning well. | |||
You can test erasing, reading, and writing to the FLASH device, and if you have an logic analyzer or | |||
digital scope, you can validate the resulting timing with the FLASH chip's data sheet. | |||
Reference Information | ==Reference / Additional Information== | ||
https://uimeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/ | https://uimeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/ | ||
https://github.com/ARMmbed/littlefs | https://github.com/ARMmbed/littlefs | ||
https://github.com/ARMmbed/littlefs/blob/master/README.md | https://github.com/ARMmbed/littlefs/blob/master/README.md |
Latest revision as of 14:15, 20 June 2024
LittleFS Flash File System
I recently learned about a compact embedded Flash File System known as SpiFFS.
While researching SpiFFS, I soon learned of another compact embedded Flash File System, LittleFS.
LittleFS appears to be even more compact and has additional security in that it creates and maintains a CRC for each file, and verifies the CRC each time the file is read.
- Compact
- Power-loss resilience
- Dynamic wear leveling
- Bounded RAM/ROM
- Maintains revision count and CRC (security features)
The Hardware
Let's put this file system onto an STM32 board and check it out.
I'll be using a NUCLEO-F103RB ($10.34), with a Winbond W25Q128FVSG SPI Flash module from Ebay. https://www.ebay.com/itm/264290947181 If the link doesn't work, just search Ebay for "W25Q128 Module". I bought two for $8.26 (free shipping). Download the PDF for the W25Q128FVSG: https://www.winbond.com/resource-files/w25q128fv%20rev.m%2005132016%20kms.pdf
The W25Q128FVSG uses 2.7V to 3.6V for operation. Here's a diagram for the the chip's pins and signals,
along with the Ebay "W25QXX" module" photo:
Since the NUCLEO-F103RB powers its STM32F103RB processor with 3.3V, this "W25QXX" module" is compatible with the NUCLEO-F103RB. (The STM32-F103RB is capable of running from 2.0V to 3.6V.)
Let's look at the signal pins on the NUCLEO-F103RB:
On the NUCLEO board, the SPI1_SCK signal is being used to drive the board's Green LED.
So, we will use SPI2 bus and its signal pins.
To connect up the signals for power and the SPI BUS, here's the wiring diagram that was used:
Winbond W25Q128FVSG SPI Flash Module wiring:
W25QXX Windbond Signal Pin Pin Color NUCLEO-F103RB Signal & Pin DI 1 5 Brown PB15 SPI2_MOSI CN10-26 CLK 2 6 Red PB13 SPI2_SCK CN10-30 GND 3 4 Orange GND CN10-20 DO 4 2 Yellow PB14 SPI2_MISO CN10-28 CS 5 1 Green PB12 SPI2_NCS CN10-16 VCC 6 8 Blue +3V3 CN7-16
The Software
The SPI and Serial Interface
Let's start by getting enough in place to read the Manufacturer and Device ID from the Winbond part. Within the STM32CubeIDE configuration for your project: * Enable SPI2 as "Full-Duplex Master"., * Hardware NSS Signal: "Disable" - We will use GPIO control for this signal. - Don't bother trying to use some form of SPI hardware control for this signal pin. * Frame Format - Motorola, 8-Bits, MSB First * Clock Prescaler 256, (140,625KBits/s - Using 72MHz SYSCLK - this can be changed later) * Clock Polarity - CPOL: Low (signal is normally low) * Clock Phase - CPHA: 1 Edge (first rising edge) * CRC Calculation: Disabled * NSS Signal Type: Software (GPIO control) * Select PB12 Pin, change signal to GPIO_Output, name it "SPI2_NCS" Click on Pinout & Configuration tab -> System Core -> GPIO -> PB12 - Set GPIO output to "High" We want the SPI2_NCS signal high - inactive initially. * Configure the HCLK for 72MHz (this is rather optional). (The Winbond part will function well beyond what this STM32 processor can clock over the SPI bus) Optional configuration and code that will ease debugging Select and configure USART2 (The USART2 signals are routed to the NEUCLEO's ST-LINK chip, creating a serial connection to your host computer over USB.) * Mode: Asychronous, Hardware Flow Control (RS232): Disable * Baud Rate: 115200, 8 bits, No Parity, 1 Stop Bit, Data Direction: Receive and Transmit
Serial Output, Serial Input, and printf() Support
See: https://merkles.com/wiki/index.php/Getting_Started_with_STM32#Create_a_New_STM32CubeIDE_1.10.1_Project_-_Hello-World
The Winbond 25Q128 (128M-Bit) Library
Here's my example of a STM32 HAL interface to the Winbond W25Q128 part: w25q128.c w25q128.h
Debugging LittleFS
Capture and check the return code from all function calls. The original example didn't do this.
* Check the return code for lfs_mount(). Make sure it retuns LFS_ERR_OK. - Although, the first time, it will return an error, and require an lfs_format() call. * Check the return code for lfs_file_open(). Make sure it retuns LFS_ERR_OK. * Although I didn't check the return code for lfs_file_rewind(), lfs_file_write(), and lfs_file_close(), it wouldn't hurt. * There are plenty of debug printf()s in the code already. Just need to enable them. Open up lfs_util.h, around line 50, you will want to define LFS_YES_TRACE, to enable printf() tracing: #define LFS_YES_TRACE // Logging functions #ifdef LFS_YES_TRACE}} * If your terminal wants CR/LF pairs, edit the printf() strings, adding "\r" to go with the "\n" line feed character.
To Do
Using the command line interface, test the SPI interface with the W25Q128. 1) Begin with the JEDIC ID command. Display the part's ID: See: cl_w25_id() in w25q128.c >w25id Jedec ID: 0xEF 0x40 0x18 2) This part has a unique ID assigned to it. Display it: See: cl_w25_unique_id() in w25q128.c >w25uid Unique ID: D2 65 CC 22 67 24 37 28 <This ID is from one of my parts. Yours will be different.> At this point, you have both written to and read from the SPI FLASH device. If your ID is correct and you're not getting errors, chances are your SPI interface is functioning well. You can test erasing, reading, and writing to the FLASH device, and if you have an logic analyzer or digital scope, you can validate the resulting timing with the FLASH chip's data sheet.
Reference / Additional Information
https://uimeter.com/2018-04-12-Try-LittleFS-on-STM32-and-SPI-Flash/ https://github.com/ARMmbed/littlefs https://github.com/ARMmbed/littlefs/blob/master/README.md