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 networking project included in the Emcraft distribution at projects/networking 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 networking 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 the following kernel platform file: linux/arch/arm/mach-stm32/flash.c. There are certain C data structures that define the number, offset and size of the configured Flash partitions, for instance:

static struct mtd_partition flash_partitions[] = {
{
.name = "flash_uboot_env",
.offset = 0,
.size = FLASH_IMAGE_OFFSET,
},
{
.name = "flash_linux_image",
.offset = FLASH_IMAGE_OFFSET,
.size = (FLASH_JFFS2_OFFSET - FLASH_IMAGE_OFFSET),
},
{
.name = "flash_jffs2",
.offset = FLASH_JFFS2_OFFSET,
},
};

flash.c 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:

stm32f4 platform flash device: 01000000 at 64000000
stm32f4-flash: Found 1 x16 devices at 0x0 in 16-bit bank
Amd/Fujitsu Extended Query Table at 0x0040
number of CFI chips: 1
RedBoot partition parsing not available
Using stm32f4 partition information
Creating 3 MTD partitions on "stm32f4-flash":
0x000000000000-0x000000020000 : "flash_uboot_env"
0x000000020000-0x000000300000 : "flash_linux_image"
0x000000300000-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 by also marked up for JFFS2:

~ # flash_eraseall -j /dev/mtd2
Erasing 128 Kibyte @ d00000 - 100% complete.Cleanmarker written at ce0000.
~ #

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:

~ # /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 @ 2e0000 - 100% complete.
~ #

Let's mount the host directory over NFS and copy a prebuilt uImage to the Flash. In this example, we install the Linux image for the hello project (available at projects/hello in the distribution):

~ # mount -o nolock,rsize=1024 172.17.0.1:/home/vlad/test /mnt
~ # cp /mnt/hello.uImage /dev/mtd1
~ #

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

~ # reboot -f
Restarting system.

U-Boot 2010.03-cortexm-1.14.2 (Sep 04 2015 - 20:31:28)

CPU  : STM32F4 (Cortex-M4)
Freqs: SYSCLK=180MHz,HCLK=180MHz,PCLK1=45MHz,PCLK2=90MHz
Board: STM-SOM Rev Rev 2.A, 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 c0007fc0 ...
Image Name:   Linux-2.6.33-arm1
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    544256 Bytes = 531.5 kB
Load Address: c0008000
Entry Point:  c0008001
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK

Starting kernel ...

Linux version 2.6.33-arm1 (vlad @ocean.emcraft.com) (gcc version 4.4.1 (Sourcery G++ Lite 2010q1-189) ) #2 Thu Sep 25 12:25:56 +0400 2014
CPU: ARMv7-M Processor [410fc241] revision 1 (ARMv7M)
CPU: NO data cache, NO instruction cache
Machine: STMicro STM32
Built 1 zonelists in Zone order, mobility grouping off.  Total pages: 8128
Kernel command line: stm32_platform=stm32f4x9-som console=ttyS0,115200 panic=10 ip=172.17.4.206:172.17.0.1:::stm32f4x9-som:eth0:off ethaddr=C0:B1:3C:88:88:85
PID hash table entries: 128 (order: -3, 512 bytes)
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 31912k/31912k available, 856k reserved, 0K highmem
Virtual kernel memory layout:
vector  : 0x00000000 - 0x00001000   (   4 kB)
fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
vmalloc : 0x00000000 - 0xffffffff   (4095 MB)
lowmem  : 0xc0000000 - 0xc2000000   (  32 MB)
modules : 0xc0000000 - 0xc2000000   (  32 MB)
.init : 0xc0008000 - 0xc0018000   (  64 kB)
.text : 0xc0018000 - 0xc0084000   ( 432 kB)
.data : 0xc0084000 - 0xc008ce00   (  36 kB)
Hierarchical RCU implementation.
NR_IRQS:90
Calibrating delay loop... 34.61 BogoMIPS (lpj=173056)
Mount-cache hash table entries: 512
Switching to clocksource cm3-systick
Serial: STM32 USART driver
stm32serial.0: ttyS0 at MMIO 0x40011000 (irq = 37) is a STM32 USART Port
console [ttyS0] enabled
ARMv7-M VFP Extension supported
Freeing init memory: 64K
Mounting /proc..apTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Shmem:                 0 kB
Slab:                244 kB
SReclaimable:         24 kB
SUnreclaim:          220 kB
KernelStack:          72 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       15988 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
Done
Hello, A2F-Linux!
Hello, A2F-Linux!
Hello, A2F-Linux!
Hello, A2F-Linux!

At this point, you will have to use the U-Boot command interface to install a different uImage to the Flash. Refer to Installing Linux images to Flash for detailed instructions on how to do that.