Yaffs for VxWorks

Submitted by Admin on 11 January, 2016 - 3:28pm

The source and the definitive version of this document can be found in our git repository, together with other Yaffs documents.

1 Background

The purpose of this document is to describe the Yaffs-for-VxWorks wrapper as well as provide sufficient information to port Yaffs to the VxWorks BSP. This document assumes a working knowledge of VxWorks.

This document does not describe the inner workings of Yaffs and a study of other Yaffs documents is recommended. Documents shown below in italics are available at http://www.yaffs.net/documents...

2 Licensing

Yaffs was originally released for Linux under the GNU Public License (GPL). Various embedded developers soon identified that Yaffs would be ideal for their applications, but were not able to use GPL based code in their systems. Aleph One Ltd has alternative licensing arrangements to support such applications.

Since VxWorks is proprietary code that is incompatible with GPL, alternative licensing arrangements must be sought to use Yaffs with VxWorks or most other embedded RTOSs.

3 What are Yaffs and Yaffs Direct Interface?

Yaffs stands for Yet Another Flash File System and was the first file system designed from the ground up for NAND flash storage.

In 2002 Aleph One set out to identify file system options for using NAND Flash as a file system. Various file systems available at the time were evaluated and all were found lacking in one way or another. The need for a suitable NAND storage file system was identified and Yaffs was designed to fill that need.

Although Yaffs was originally designed for NAND flash, it has been used successfully with NOR flash systems and even as a RAM file system. This allows high reliability file systems to be constructed using NOR flash, with a future migration path to NAND flash for higher density and performance.

Yaffs was originally designed for use with the Linux operating system, but was designed in a very modular way. The operating-system-specific code was kept separate from the main Yaffs file system code. This allows Yaffs to be ported quite cleanly to other operating systems through operating system personality modules. One such personality module is the Yaffs Direct Interface (YDI) which allows Yaffs to be simply integrated with embedded systems, with or without an RTOS. See http://www.yaffs.net/documents/yaffs-direct-interface

The current version is Yaffs2, which supports a wider range of NAND flash components including 2k/4k/8k or even 16k page devices and devices with multi-level cells (MLC), and produces equivalent or better performance. Yaffs2 include Yaffs1 compatibility code so Yaffs1 images still work and migration is quite simple. Yaffs1 or Yaffs2 mode of operation are simply selected by a run-time parameter.

As well as providing a NAND file system, YDI also provides a RAM emulation layer to allow Yaffs to operate as a RAM file system too. While the RAM emulation is perhaps not as efficient as a dedicated RAM file system, this does allow one well proven file system to use both RAM and flash.

Yaffs has been used for many products using various operating systems including Windows Embedded Compact (previously called Windows CE) and various RTOSs, including ThreadX, vXworks, pSOS to name just a few. Note that there is a native port of Yaffs to eCOS that does not use YDI. This is supported and distributed by eCocCentric.(http://www.ecoscentric.com/).

4 Why use Yaffs?

For an in depth understanding of the advantages of Yaffs, please read http://www.yaffs.net/documents/considerations-choosing-flash-file-system

For a brief overview: Yaffs is the first, and perhaps only, file system designed specifically for NAND flash. This means that Yaffs has been designed to work around the various limitations and quirks of NAND flash, as well as exploit the various features of NAND to achieve an effective file system.

Some features to consider:

  • Yaffs has been well proven and has been used to ship in large volumes in several products using many different operating systems, compilers and processors.
  • Yaffs is written in portable C and is endian neutral.
  • Yaffs provides bad block handling and ECC algorithms to handle deficiencies in NAND flash.
  • Yaffs is a log-structured file system which makes it very robust to corruptions caused by power failures etc.
  • Yaffs has highly optimised and predictable garbage collection strategies. This makes it high performance and very deterministic when compared with similar file systems.
  • Yaffs has a lower memory footprint than most other log-structured flash file systems.
  • Yaffs provides a wide range of POSIX-style file system support including directories, symbolic and hard links etc. through standard file system interface calls.
  • Yaffs is highly configurable to work with various flash geometries, various ECC options, caching options etc.
  • Yaffs Direct Interface is simple to integrate in a system – only a few interface functions are required.
  • Yaffs can be used with a wide range of memory technologies.

5 What is Yaffs -for-VxWorks?

Many organizations have used Yaffs on VxWorks with just Yaffs Direct Interface (YDI). So what benefit does Yaffs-for-VxWorks offer?

YDI provides a POSIX-like API, but with Yaffs specific names. For example: yaffs_open(), yaffs_read(), yaffs_close() etc.

While YDI provides a solution for many systems, and is very well proven, it has one major drawback. It is not a native file system. That means:

  • Existing code that calls open(), read(), write() etc cannot be immediately used with YDI. The code needs to be rewritten to call the YDI functions: yaffs_open(), yaffs_read()... This porting is costly and error prone.
  • Code written for YDI is then locked to Yaffs and makes portability/testability problems.
  • Tools such as the VxWorks console shell cannot be used to access Yaffs files via YDI.

Yaffs-for-VxWorks fixes these limitations..

Yaffs-for-VxWorks is a wrapper around YDI that plugs YDI in as a native file system (ie. Yaffs becomes a file system that is accessed no different from any of the other file systems on system. This makes it really easy to migrate existing VxWorks software, or develop new VxWorks software to get the benefits of Yaffs.

Yaffs-for-VxWorks follows the VxWorks operating system model used by other VxWorks file systems, so it is easy for VxWorks developers to integrate Yaffs and integrate it with their normal workflow.

As mentioned above, Yaffs-for-VxWorks is a wrapped version of YDI. That means all the testing and experience of using YDI since 2002 is incorporated into Yaffs-for-VxWorks.

Yaffs is already supported in u-boot, so if you're using u-boot as a boot loader then there is already seamless support for Yaffs file system access between the boot loader and VxWorks.

Some organizations have developed their own VxWorks wrappers for Yaffs, but using the Yaffs-for-VxWorks wrapper saves a lot of integration and testing effort.

Once the Yaffs-for-VxWorks file system code is loaded into the kernel, flash devices are added using yaffs_devAdd(). They are then available in the VxWorks file system for access just like any other files in the system.

Yaffs and VxWorks conceptual relationships

 

6 Yaffs-for-VxWorks code

Yaffs-for-VxWorks is supplied as a VxWorks Downloadable Kernel Module (DKM) project with full source code. This can then be modifies into a BSP layer or library and compiled directly into the kernel.

The code comprises Yaffs Direct Interface (YDI) plus two wrapper files:

  • yaffs_drv.c: This file does all the iosLib interfacing (ie. plugs Yaffs in as a VxWorks file system and plugs in the flash devices as file system devices. This file provides one externally visible function call: yaffs_devAdd() which allows Yaffs devices (ie. Flash drivers) to be plugged in.
  • yaffx_vx_glue.c: This file provides all the OS resources that Yaffs needs from VxWorks. For example, it initialises a semaphore and does any error code routing.

In addition, if the Yaffs filesystem driver is build as a DKM, a file called yaffs_dkm.c provides the dummy DKM start() function.

The code is provided as a DKM project. This includes the specification of the DEFINES needed to compile Yaffs under VxWorks. If the code is moved out of the DKM then it is important to make sure the correct DEFINES are set up.

7 Example Simulated Flash Driver

The Yaffs-for-VxWorks package provides an example Yaffs device that runs on a RAM simulator. This allows the file system to be tested in a simulation target without flash memory (eg the VxWorks simulator). This also provides an example for how to develop a flash driver and plug it in to Yaffs.

8 Example Real Time Process(RTP)

An example RTP is provided that performs some basic file system operations and demonstrates a working filesystem.

This RTP uses standard file system calls (open(), read(), write()...) demonstrating that the Yaffs-for-VxWorks layer is operating as a native file system.

9 Integrating a Flash Device

Integrating a flash device is a relatively straight-forward process.

The device is set up as a yaffs_device structure, which is then installed into Yaffs by calling the yaffs_devAdd() function.

The NAND simulator can serve as an example for how to do this. The following snippet outlines the requirements. For a better description of the params and drv sub-structures refer to http://www.yaffs.net/yaffs-tuning-and-configuration.

 

struct yaffs_dev *yramsim_CreateRamSim(...)
{
...
  dev = malloc(sizeof(*dev));
...
  /* First set everything to NULL. */
  memset(dev, 0, sizeof(*dev));
 
  /* 
   * There are three sections to the yaffs_dev structure
   * that needs to be initialised:
   * * The params sub-structure which are all the control
   * parameters.
   * * The drv sub-structure which holds the driver functions.
   * * The context which holds a private pointer (used to hold a
   * driver context).
   */
  p = &dev->param;
  p->name = strdup(name);
  p->start_block = start_block;
  p->end_block = end_block;
  p->total_bytes_per_chunk = DATA_SIZE;
  p->spare_bytes_per_chunk= SPARE_SIZE;
  p->chunks_per_block = PAGES_PER_BLOCK;
  p->n_reserved_blocks = 2;
  p->use_nand_ecc = 1;
  p->inband_tags = 0;
  p->is_yaffs2 = 1;
 
  d= &dev->drv;
  d->drv_initialise_fn = yramsim_initialise;
  d->drv_deinitialise_fn = yramsim_deinitialise;
  d->drv_read_chunk_fn = yramsim_rd_chunk;
  d->drv_write_chunk_fn = yramsim_wr_chunk;
  d->drv_erase_fn = yramsim_erase;
  d->drv_check_bad_fn = yramsim_check_block_bad;
  d->drv_mark_bad_fn = yramsim_mark_block_bad;
 
  dev->driver_context= (void *)sim;
 
  return dev;
}
 
 
void start(void)
{
  int result;
  struct yaffs_dev *dev;
 
  printf("Yaffs RAMSIM started\n");
 
  /* Create and add a RAM simulator device.
   * To add a different sort of device, set up the device
   * and call yaffs_devAdd.
   * 
   */
  dev = yramsim_CreateRamSim("/yramsim", 0, 400, 0, 399);
  printf("device is %p\n", dev);
 
  if (dev) {
  result = yaffs_devAdd(dev);
  printf("yaffs_devAdd() returned %d\n", result);
  printf("yaffs RAM simulator now available in file system as %s",
  dev->param.name);
 
}
}

 

10 Appendix: Running the examples on the VxWorks simulator

Once you have built the Yaffs_filesystem_driver and Yaffs_RAMSIM_device projects, you can start up Yaffs on the simulator as follows:

  1. Start the simulator.
  2. Load the Yaffs_filesystem_driver DKM by right clicking on the Yaffs_filesystem_driver project, then selecting Run/Debug Kernel Task...
  3. Load the Yaffs_RAMSIM_device DKM by right clicking on the Yaffs_filesystem_driver project, then selecting Run/Debug Kernel Task...

At this stage the VxWorks console should look something like:

 _________            _________

 \77777777\          /77777777/

  \77777777\        /77777777/

   \77777777\      /77777777/

    \77777777\    /77777777/

     \77777777\   \7777777/

      \77777777\   \77777/              VxWorks 7

       \77777777\   \777/

        \77777777\   \7/     Core Kernel version: 1.0.10.2

         \77777777\   -      Build date: Oct 13 2015 12:10:53

          \77777777\

           \7777777/         Copyright Wind River Systems, Inc.

            \77777/   -                 1984-2015

             \777/   /7\

              \7/   /777\

               -   -------


              Board: SIMLINUX board

     OS Memory Size: 511MB

   ED&R Policy Mode: Deployed

        Debug Agent: Started (always)

    Stop Mode Agent: Not started


Loading symbol table from charlesqcore:/home/charles/WindRiver/workspace/VIP_1/default/vxWorks.sym ...done

-> 

Yaffs file system DKM started

Yaffs flash devices can now be added by calling yaffs_devAdd()

Yaffs RAMSIM started

device is 0x8829e010

Adding Yaffs device 0x8829e010 (/yramsim)

yaffs_devAdd() returned 0

yaffs RAM simulator now available in file system as /yramsim

 

At this stage you should be able to see the yaffs file system is running:

-> ls "/yramsim"

/yramsim/lost+found 

value = 0 = 0x0

-> 

 

If you have built the yaffs_test project, then try running that. This should show something like:

 

Start running Yaffs test

…

dump directory from pwd

./lost+found inode 2 length 2048 mode 41B6 directory


fs size: 52297728 (51072k), free 51642368 (50432k), n files 4

write_check_test()

opening a

Open of a returned 3

write_stuff_to_file returned 100000

…

Finished running Yaffs test

 

Do a file listing  again will show the file system state after running the test:

 

-> llr "/yramsim"


Listing Directory /yramsim:

drwxrwxrw-  1 0       0                 2048 Nov 25 14:07 level1/

-rw-rw-rw-  1 0       0                50505 Nov 25 14:07 seek-trunc 

-rw-rw-rw-  1 0       0               123000 Nov 25 14:07 s 

drw-rw-rw-  1 0       0                 2048 Nov 25 14:06 lost+found/


Listing Directory /yramsim/level1:

drwxrwxrw-  1 0       0                 2048 Nov 25 14:07 level2/


Listing Directory /yramsim/level1/level2:

drwxrwxrw-  1 0       0                 2048 Nov 25 14:07 level3/


Listing Directory /yramsim/level1/level2/level3:

drwxrwxrw-  1 0       0                 2048 Nov 25 14:07 level4/


Listing Directory /yramsim/level1/level2/level3/level4:


Listing Directory /yramsim/lost+found:

value = 0 = 0x0