This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Flash infrastructure rework


Hi Folks

Ascom has recently required that Redboot run on a target board which
can be manufactured with two different FLASH devices which are pin
compatible and with two banks of flash in disjoint locations. We also
needed to support two jffs2 file systems simultaneously so allowing
fallback if one was corrupt. The client also wants one image to run on
both boards. The current flash infrastructure cannot support this. Due
to time pressures we have used Ian Campbells patches to get something
going quickly.

However in the background i took a step back and overhauled the whole
flash infrastructure in what i hope is a clean and consistent API with
all the features required:

        Multiple device drivers at the same time
        Multiple instantiations of the same driver
        Probing to detect what is actually on the board
        Support for boot block devices which have different size blocks
        Thread safe when used with the kernel
        Does not pollute the name space
        Optional backward compatible with old drivers
        Optional backward compatible with old API
        Able to support multiple JFFS2 filesystems
        Redboot to be able to access multiple devices
        Documentation!

Attached are the change. There are two .epk's. One is the new io/flash
code which uses v2 instead of current so you can have it in the
repository at the same time as the current code. The second is a flash
driver which uses the new API for the synthetic target. This installs
parallel the current synth flash driver which allows testing of legacy
and new drivers in the same system. There is also a patch to the rest
of eCos for redboot and jffs2.

Some screen shots....

RedBoot(tm) bootstrap and debug environment [ROM]
Non-certified release, version UNKNOWN - built 14:27:08, Jul 15 2004
 
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.
 
RAM: 0x02000000-0x02800000, [0x02006fd0-0x027e1000] available
FLASH: 0x40000000 - 0x400fffff 8 x 0x2000 blocks 15 x 0x10000 blocks 
FLASH: 0x40100000 - 0x401fffff 16 x 0x10000 blocks 

Here you can see two flash devices, the first one with boot blocks.
In this setup the first device is the new synthetic driver and the
second one is the legacy driver.

RedBoot> fis create -b 0x02000000 -l 0x10000 -f 0x40100000 junk
RedBoot> fis list
Name              FLASH addr  Mem addr    Length      Entry point
RedBoot           0x40000000  0x40000000  0x00020000  0x00000000
FIS directory     0x400EFFFF  0x400EFFFF  0x0000F000  0x00000000
RedBoot config    0x400FEFFF  0x400FEFFF  0x00001000  0x00000000
junk              0x40100000  0x40100000  0x00010000  0xFFFFFFFF
RedBoot> 

This creates an entry in the second flash device.

There are still some limitations. The FIS directory and RedBoot config
have to be in the lower device. Also they cannot yet make use of the
boot blocks, but that should be easy to add. 

The fileio1 test in the jffs2 package has been extended. If the flash
block io layer has been configured for two devices the second one is
also mounted:

<INFO>: mounting second JFFS2 filesystem on /mnt
<INFO>: reading directory /
<INFO>: entry              . [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry             .. [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            etc [mode 016f0001 ino 00000002 nlink 1 size 0]
<INFO>: entry            dev<FAIL>: stat() returned -1 No such entity
 
<INFO>: entry            mnt [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            var [mode 016f0001 ino 00000008 nlink 1 size 0]
<INFO>: entry            tmp [mode 016f0001 ino 00000007 nlink 1 size 0]
<INFO>: entry      jffs2.img [mode 004b0008 ino 00000009 nlink 1 size 2013]
<INFO>: reading directory /mnt
<INFO>: entry              . [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry             .. [mode 016f0001 ino 00000001 nlink 1 size 0]
<INFO>: entry            etc [mode 016f0001 ino 00000002 nlink 1 size 0]
<INFO>: entry            dev [mode 016f0001 ino 00000005 nlink 1 size 0]
<INFO>: entry            mnt [mode 016f0001 ino 00000006 nlink 1 size 0]
<INFO>: entry            var [mode 016f0001 ino 00000008 nlink 1 size 0]
<INFO>: entry            tmp [mode 016f0001 ino 00000007 nlink 1 size 0]
<INFO>: entry      jffs2.img [mode 004b0008 ino 00000009 nlink 1 size 2013]
<INFO>: umount /mnt
<INFO>: umount /

In this case the two filesystems are identical so its not the best of
tests. I also need to look into the /dev failure, but i don't think
that is related to the flashiodev code.

There is documentaion in SGML format which describes both the new
application and device API. Note that it might not be 100% correct. I
wrote the documentation first to get my ideas sorted out and then did
the implementation. There was some minor changes along the way which
might not of made it back into the documentation.

The new API is:

typedef int cyg_flash_printf(const char *fmt, ...);
__externC int cyg_flash_init( cyg_flash_printf *pf );
__externC int cyg_flash_get_info(cyg_uint32 devno, 
                                 cyg_flash_info_t * info);
__externC int cyg_flash_get_info_addr(cyg_flashaddr_t flash_base, 
                                      cyg_flash_info_t * info);
__externC int cyg_flash_verify_addr(const cyg_flashaddr_t address);
__externC bool cyg_flash_code_overlaps(const cyg_flashaddr_t start, 
                                       const cyg_flashaddr_t end);
__externC int cyg_flash_get_block_info(size_t *block_size, 
                                       cyg_uint32 *blocks);
__externC int cyg_flash_get_limits(cyg_flashaddr_t *start, 
                                   cyg_flashaddr_t *end);
__externC size_t cyg_flash_block_size(const cyg_flashaddr_t flash_base);
__externC int cyg_flash_read(cyg_flashaddr_t flash_base, 
                             const void *ram_base, 
                             const size_t len, 
                             cyg_flashaddr_t *err_address);
__externC int cyg_flash_erase(const cyg_flashaddr_t flash_base, 
                              const size_t len, 
                              cyg_flashaddr_t *err_address);
__externC int cyg_flash_program(const cyg_flashaddr_t flash_base, 
                                void *ram_base, 
                                const size_t len, 
                                cyg_flashaddr_t *err_address);
__externC int cyg_flash_lock(const cyg_flashaddr_t flash_base, 
                             const size_t len, 
                             cyg_flashaddr_t *err_address);
__externC int cyg_flash_unlock(const cyg_flashaddr_t flash_base, 
                               const size_t len, 
                               cyg_flashaddr_t *err_address);
__externC const char *cyg_flash_errmsg(const int err);
#ifdef CYGPKG_KERNEL
__externC int cyg_flash_mutex_lock(const cyg_flashaddr_t from, 
                                   const size_t len);
__externC int cyg_flash_mutex_unlock(const cyg_flashaddr_t from, 
#endif

and the device API is

// Structure of pointers to functions in the device driver
struct cyg_flash_dev_funs {
  int (*flash_init) (struct cyg_flash_dev *dev);
  size_t (*flash_query) (struct cyg_flash_dev *dev, void * data, 
                         const size_t len);
  int (*flash_erase_block) (struct cyg_flash_dev *dev, 
                            const cyg_flashaddr_t block_base);
  int (*flash_program) (struct cyg_flash_dev *dev, 
                        cyg_flashaddr_t base, 
                        const void* data, const size_t len);
  int (*flash_read) (struct cyg_flash_dev *dev, 
                     const cyg_flashaddr_t base, 
                     void* data, const size_t len);
  int (*flash_hwr_map_error) (struct cyg_flash_dev *dev, int err);
  int (*flash_block_lock) (struct cyg_flash_dev *dev, 
                           const cyg_flashaddr_t block_base);
  int (*flash_block_unlock) (struct cyg_flash_dev *dev, 
                             const cyg_flashaddr_t block_base);
};
 
// Structure each device places in the HAL table
struct cyg_flash_dev {
  struct cyg_flash_dev_funs   *funs;           // Function pointers
  cyg_flashaddr_t             start;           // First address
  cyg_flashaddr_t             end;             // Last address
  cyg_uint32                  num_block_infos; // Number of entries
  cyg_block_info_t            *block_info;     // Info about one block size
 
  void                        *priv;           // Devices private data
  void                        *config;         // Configuration info
 
// The following are only written to by the FLASH IO layer.
  cyg_flash_printf            *pf;             // Pointer to diagnostic printf
  bool                        init;            // Device has been initialised
#ifdef CYGPKG_KERNEL
  cyg_mutex_t                 mutex;           // Mutex for thread safeness
#endif
  struct cyg_flash_dev        *next;           // Pointer to next device
} CYG_HAL_TABLE_TYPE;

See the documentation for explanations of each function.

It needs some more device drivers. I plan to modify both the SST and
the Strata drivers to use the new API, but that work will not start
for another two weeks.

What i would like now is some feedback. Are there any missing
features? Does the APIs make sense. Reading the code do you see
obvious problems? 

Im on Holiday for the next two weeks so it would be nice to come back
to a few email of suggestions, improvements and bug fixes.

        Thanks
                Andrew

Attachment: flashv2.epk
Description: Binary data

Attachment: synthflashv2.epk
Description: Binary data

Attachment: flashv2.diff
Description: Text document

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]