AM335x JFFS2 Support Guide

From Texas Instruments Wiki
Jump to: navigation, search
AM335x JFFS2 Support Guide
Linux PSP


What is JFFS2?

JFFS2 (Journaled Flash File System v2) is a file system designed for use on Flash devices such as those commonly found in embedded systems. Unlike some other file systems which may be stored on the Flash device and then copied into RAM during boot (i.e. ramdisk) JFFS2 actually resides on the Flash device and allows the user to read/write data to Flash. This is particularly useful in embedded devices that wish to save some persistent data between reboots. For more information on JFFS2 please see the JFFS2 wikipedia page.

Benefits of JFFS2

There are several reasons why JFFS2 is useful in an embedded system. Some of the more common are

  1. JFFS2 allows data to be written back to Flash for persistent storage
  2. JFFS2 is optimized for Flash memory which must be erased in block size segments
  3. JFFS2 provides wear leveling for longer Flash memory life
  4. JFFS2 supports compression
  5. JFFS2 file systems do not need to be copied from Flash to RAM to be used

AM335x JFFS2 support

On AM335x, JFFS2 support has been super-seeded by UBIFS.

Reasons for disabling JFFS2 support

  1. UBIFS file system is recommended for NAND File system over JFFS2 as it is seen as JFFS2 successor with significant improvements in scalability and NAND support.
  2. Compatibility of ECC layout across all components. RBL, U-boot SPL all uses BCH8 ECC scheme. However supporting BCH8 with JFFS2 is not possible because of shortage of OOB area.
    • Total OOB Bytes - 64 Bytes (for every 2048 bytes (512 * 4))
    • JFFS2 clean marker requires 8 bytes ==> 64 - 8 = 56 bytes
    • ECC requires 14 bytes for every 512 bytes of data. Total ECC bytes = 14 * 4 = 56 Bytes. ==> 56 - 56 = 0 byte
    • Manufactures bad block marking requires 2 bytes ==> 0 - 2 = -2 bytes
      This shortage (-2) is the main reason for switching to UBIFS

Enabling JFFS2 support

When using JFFS2 & Hamming in Linux, SPL and u-boot images can't be flashed from Linux as both these components needs to be flashed using BCH8 ECC scheme.

To support JFFS2 filesystem, kindly follow below steps. Steps involves

  1. Enabling JFFS2 in Linux kernel menuconfig.
  2. Switching back to Hamming ECC scheme which uses 1-bit error correction

Enabling of JFFS2 support in menuconfig

JFFS2 support is disabled in the default config file of am335x. To enableJFFS2 support, start the Linux Kernel Configuration tool:

host$ make menuconfig 

Edit the menuconfig as below by selecting Journalling Flash File System v2 support under File system -> Miscellaneous filesystems

  File systems  ---> 
         [*] Miscellaneous filesystems  ---> <*>
                 <*>   Journalling Flash File System v2 (JFFS2) support
                 (0)     JFFS2 debugging verbosity (0 = quiet, 2 = noisy) (NEW)
                 [*]     JFFS2 write-buffering support (NEW)
                 [ ]       Verify JFFS2 write-buffer reads (NEW)
                 [*]     JFFS2 summary support (EXPERIMENTAL)
                 [*]     JFFS2 XATTR support (EXPERIMENTAL)
                 [*]       JFFS2 POSIX Access Control Lists (NEW)
                 [*]       JFFS2 Security Labels (NEW)
                 [*]     Advanced compression options for JFFS2
                 [*]       JFFS2 ZLIB compression support (NEW)
                 [*}       JFFS2 LZO compression support (NEW)
                 [*]       JFFS2 RTIME compression support (NEW)
                 [*]       JFFS2 RUBIN compression support
                           JFFS2 default compression mode (priority)  ---> 

Switching linux to Hamming ECC scheme

Modify the ecc_opt passed through platform data in board_flash.c to support Hamming ECC scheme as below

diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
--- a/arch/arm/mach-omap2/board-flash.c<br>+++ b/arch/arm/mach-omap2/board-flash.c
@@ -148,7 +148,7 @@ __init board_nand_init(struct mtd_partition *nand_parts,
            board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;

            if (cpu_is_am335x()) {
-                board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW;
+                board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_HW;
                 board_nand_data.xfer_type = NAND_OMAP_PREFETCH_POLLED;

After above 2 steps, compile the Linux kernel.

 make CROSS_COMPILE=arm-arago-linux-gnueabi- ARCH=arm uImage

The final uImage binary can be flashed to NAND.

Flashing of components from u-boot

AM335x NAND flash Layout is described here. Kindly check the link for NAND partition and address on AM335x.

SPL & U-Boot

To flash SPL & U-Boot images to NAND, follow either of UART Boot mode or SD Boot

Linux Kernel & File system Image

Linux Kernel Image

Follow below steps to Flash Linux Kernel image Image to NAND

(i) Reset the DDR memory with 0xff.

u-boot> mw.b 0x82000000 0xff 0x500000  

(ii) TFTP the kernel uImage to DDR.

u-boot> tftp 82000000 <kernel_image>

(iii) switch to Hamming ECC scheme

u-boot> nandecc hw 0

(iv) Now flash the kernel image to NAND at the appropriate offset (refer to NAND layout section for the offsets)

u-boot> nand erase 0x00280000 0x00500000
u-boot> nand write 0x82000000 0x00280000 0x500000

Image_size should be aligned to page size of 2048 (0x800) bytes.

File system Image

Since JFFS2 is used only on flash devices, a standard Linux distribution does not have the tools to make a jffs2 file system. Refer MTD Utilities wiki page for instructions on how to compile MTD-utils . mkfs.jffs2 is the tool needed to build a JFFS2 file system.

With the mkfs.jffs2 utility built and in place, it is now time to make the jffs2 file system from the target directory. Change to the /home/user directory and enter the mkfs.jffs2 command as shown below. Probably the most important argument to the utility is the erase block size. For the NAND part on the AM335x EVM board the erase block size is 128k. Consult the flash part data manual to find the erase block size.

host$ cd /home/user
host$ mkfs.jffs2 -lqn –e 128 -r target_filesystem/ -o /tftpboot/rd-jffs2.bin

By building the file in the /tftpboot directory, the step of copying it over is eliminated. The file must now be written into flash at a specific location. In U-Boot, the flash file system will get flashed to the physical address 0x780000 and will be mounted by the kernel from /dev/mtdblock<PARTITION_ID>, PARTITION_ID starts from 0, refer flash layout. Use 'cat /proc/partitions' at Linux prompt for the list of partitions. Download the rd-jffs2.bin file. Write it to flash. Modify bootargs to support a JFFS2 file system as root on /dev/mtdblock<PARTITION_ID>. Save the environment variables.

Flashing File-system from U-Boot

(i) Clear the DDR memory & then load the file system image using TFTP (example - rootfs-base.jffs2) to DDR.

u-boot> mw.b 0x82000000 0xFF <filesystem_image_size>
u-boot> tftp 0x82000000 <filesystem_image>

Flash the file system image to NAND using the appropriate offsets by using Hamming ECC scheme

(ii) switch to Hamming ECC scheme

u-boot> nandecc hw 0

(iii) erase nand area

u-boot> nand erase clean 0x00780000 0x0F880000  <=== Erasing the whole partition before flashing the image

(iv) write data to nand

u-boot> nand write 0x82000000 0x00780000 <filesystem_image_size> <=== filesystem image size is upward aligned to nand page size


  • The image size should be upward aligned to NAND page size which is 2KiB (i.e. 0x800). For example, if the image size is 0x19B8004 the size to be passed to the NAND write command should be 0x19B8800.

Setting environment variables to boot JFFS2 file system
  • U-Boot environment variable bootargs has information on arguments to be passed to Linux kernel. The bootargs format for JFFS2 root file system is,
u-boot> setenv bootargs console=ttyO0,115200n8 root=/dev/mtdblock<PARTITION_ID> rw rootfstype=jffs2 mem=256M

The value of PARTITION_ID depends on MTD device which holds the rootfs. The below example assumes JFFS2 file system flashed on MTD partition 7 and respective device is enabled on the board,

 rootfs on NAND ==> PARTITION_ID should be 7 

Below examples set bootargs variable from u-boot prompt for different memory devices.

u-boot> setenv bootargs console=ttyO0,115200n8 root=/dev/mtdblock7 rw rootfstype=jffs2 mem=256M