Flash Management and JFFS2 File System Print

 

Linux provides management of the on-module NOR Flash, including the ability to partition the physical Flash onto separate logical partitions and mount a JFFS2 flash filesystem on a Flash partition.

The Flash management and JFFS2 filesystem require enabling appropriate kernel options in the kernel configuration and adding certain device nodes and Linux tools to the target file system. The rootfs project included in the Emcraft distribution at projects/rootfs provides a sample Linux configuration that has the Flash management and JFFS2 functionality fully enabled. The examples in the text below make use of the rootfs project.

Linux splits the external Flash onto several partitions. Even though the partitioning is purely logical in the software, the user view is that each Flash partition can be accessed as a separate "Flash disk" device, independent of the other Flash partitions. Each Flash partitioned can be accessed as a "raw" disk or, alternatively, a Flash file system can be mounted on a partition.

The Flash partitioning is defined in project/rootfs/rootfs.dts.STM32F4X9:

nor_flash {
status = "okay";

flash_uboot_env@0x0 {
label = "flash_uboot_env";
reg = <0x00000 0x20000>;
};
flash_linux_image@0x20000 {
label = "flash_linux_image";
reg = <0x20000 0xa00000>;
};
flash_jffs2@0xa20000 {
label = "flash_jffs2";
eg = <0xa20000 0x5e0000>;
};
};

The flash layout included in the distribution provides a reasonable Flash partitioning for the on-module Flash device, however, depending on your application needs, you might want to change the number and size of configured Flash partitions.

When Linux boots on the target, there will be the following messages in the kernel print-out indicating that the Flash driver is enabled and then describing the specific partitions created by the kernel:

Initializing STM32F4 mapper, copying code from c057c000 to 200001a8, size 560
Using SRAM as buffer with start 20000400 and size 400
physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000001 Chip ID 0x002101
Amd/Fujitsu Extended Query Table at 0x0040
Amd/Fujitsu Extended Query version 1.5.
number of CFI chips: 1
3 ofpart partitions found on MTD device physmap-flash.0
Creating 3 MTD partitions on "physmap-flash.0":
0x000000000000-0x000000020000 : "flash_uboot_env"
0x000000020000-0x000000a20000 : "flash_linux_image"
0x000000a20000-0x000001000000 : "flash_jffs2"

In the above example, the first partition is used to hold the U-Boot environment variables. The second partition is allocated to the bootable Linux image (uImage). Finally, the third partition is dedicated to the JFFS2 file system.

Let's start with creating a JFFS2 file system on the third partition. The following command erases the Flash partition and marks it up as a JFFS2 file system. JFFS2 provides transparent management of bad blocks and Flash wearing capabilities ensuring the robustness and longevity of the file system in Flash. Notice use of the -j flag as the indication to flash_eraseall that the partition must not only be erased but also marked up for JFFS2:

/ # flash_eraseall -j /dev/mtd2
Erasing 128 Kibyte @ 5e0000 - 100% complete.Cleanmarker written at 5c0000.
/ #

Now everything is ready to mount a JFFS2 file system on that partition. As expected, the initial file system is empty:

/ # mkdir /m
/ # mount -t jffs2 /dev/mtdblock2 /m
/ # ls -lt /m
/ #

Let's add some files to the JFFS2 file system and validate that they are correct. In the example below, we copy the busybox binary from the initramfs root file system to Flash and then run it from Flash:

/ # cp /bin/busybox /m
/ # /m/busybox echo Hello from JFFFS2
Hello from JFFFS2
/ #

Now, let's reboot the system and make sure that any updates we make in the JFFS2 are indeed persistent:

/ # reboot -f
Restarting system
...
init started: BusyBox v1.17.0 (2014-09-23 20:48:33 +0400)
/ # mkdir /m
/ # mount -t jffs2 /dev/mtdblock2 /m
/ # /m/busybox echo Hello from JFFS2 after reboot
Hello from JFFS2 after reboot
/ #

As a next step, let's update the Linux uImage in the second partition from a host directory mounted over NFS. This provides a simple demonstration of a possible software upgrade sequence using a Linux image pulled from the network.

First step is to prepare the partition for a new uImage by erasing the Flash:

/ # flash_eraseall /dev/mtd1
Erasing 128 Kibyte @ a00000 - 100% complete.
/ #

Let's mount the host directory over NFS and copy a prebuilt uImage to Flash. In this example, we install the Linux image for the rebuilt rootfs project:

/ # mount -o nolock 172.17.0.155:/work/psl/SF/linux-cortexm-2.0.0/projects/rootfs /mnt
/ # flashcp -v /mnt/rootfs.uImage /dev/mtd1
Erasing block: 44/44 (100%)
Writing kb: 5601/5601 (99%)
Verifying kb: 5601/5601 (99%)
/ #

Now, we are ready to reboot and validate the target is indeed running the newly installed Linux project:

U-Boot 2010.03-cortexm-2.0.0 (Mar 09 2016 - 12:37:27)

CPU : STM32F4 (Cortex-M4)
Freqs: SYSCLK=180MHz,HCLK=180MHz,PCLK1=45MHz,PCLK2=90MHz
Board: STM-SOM Rev 2.A, href="http://www.emcraft.com/">www.emcraft.com
DRAM: 32 MB
Flash: 16 MB
In: serial
Out: serial
Err: serial
Net: STM32_MAC
Hit any key to stop autoboot: 0
## Booting kernel from Legacy Image at c0007fb4 ...
Image Name: Linux-4.2.0-00026-g8bf998b-dirty
Image Type: ARM Linux Multi-File Image (uncompressed)
Data Size: 5735620 Bytes = 5.5 MB
Load Address: c0008000
Entry Point: c0008001
Contents:
Image 0: 5718576 Bytes = 5.5 MB
Image 1: 17032 Bytes = 16.6 kB
Verifying Checksum ... OK
## Flattened Device Tree from multi component Image at C0007FB4
Booting using the fdt at 0xc057c230
Loading Multi-File Image ... OK
OK
Loading Device Tree to c1ff8000, end c1fff287 ... OK

Starting kernel ...

Booting Linux on physical CPU 0x0
Linux version 4.2.0-00026-g8bf998b-dirty (psl @ocean.emcraft.com) (gcc version 4.4.1 (Sourcery G++ Lite 2010q1-189) ) #5 Tue May 31 20:17:17 +0400 2016
CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
...