[ECOS] Re: NAND flash driver considerations: RFC

Rutger Hofman rutger@cs.vu.nl
Fri Sep 26 17:41:00 GMT 2008


Andrew Lunn wrote:
>>> I don't see there being any problem mixing up NOR and NAND drivers in
>>> packages/dev/flash/ The CDL rules will prevent somebody from trying to
> 
> There are many different ways at looking at the packages. The CDL
> language imposes a hierarchy as well which has nothing to do with the
> directory hierarchy. We could have packages/io/flash_nand/current for
> the common code. This is not unknown. Eg we have packages/net/tcpip
> and packages/net/bsd_tcpip. The first one is no longer supported and
> the second one is what everybody uses.
> 
> I don't really see that mixing up the packages is obfuscating them. We
> already have two different classes of flash drivers in
> packages/dev/flash. We have chip drivers and we have target board
> drivers. When the flash_v2 branch gets merged in we will have another
> two classes added. 
> 
> What is important here is the CDL. The new packages need to have
> 
>     parent        CYGPKG_IO_FLASH_NAND
>     active_if     CYGPKG_IO_FLASH_NAND 
> 
> so that they are correctly placed into the CDL tree and only active
> when appropriate.

OK, I refactored my test setup to reflect what you suggest. So now we 
have packages:

io/flash_nand/
   + common/
   + controller/
   + chip/

devs/flash/bfin/
   + nfc/
   + ez_kit_bf548/nand/
  (+ ez_kit_bf548/nor/ for the NOR flash also on this board)

devs/flash/st-micro/nand0xG/

and I refactored the .cdl's, the #defines, the includes etc etc. The 
.cdl-s have the parentage you suggested.

Is this OK?

>> The code for the *basic* API is something like this.
>>
>> Example: program (within) one page:
>>
>> cyg_nand_page_program(cyg_nand_t *nand,
>>                       const void *data, size_t len,
>>                       size_t col, size_t row,
>>                       const void *spare, size_t spare_len)
>>
>> must implement the ONFI command sequence for page program. So, it is  
>> essentially implemented as follows:
>>
>>    nand->cmd(nand, 0x80);
>>    nand->addr(nand, col, row);
>>    nand->program_data(nand, data, len);
>>    nand->goto_addr(nand, spare_offset, row);
>>    nand->program_data(nand, spare, spare_len);
>>    nand->cmd(nand, 0x10);
>>    nand->await_status(nand, 6);
>>
>> where the indirect calls are implemented by the specific controller.
>>
>> A minimal set of other calls would be:
>>    cyg_nand_page_read()
>>    cyg_nand_block_erase()
>>    cyg_nand_bad_block_...()
>>    cyg_nand_chip_select(nand, chip_number)
>>    cyg_nand_init()
> 
> Given this API, what does the device filenames /dev/nand0/1 have to do
> with anything. How do i get from a file descriptor returned with
> open() to a cyg_nand_t * nand structure?

That is not the idea. There must be a NAND filesystem that is layered on 
top of flash_nand devices. That file system has an open() implementation 
(like yaffs_open()).

 > Do file descriptors and /dev/
> files make any sense? The NOR devices don't do this?

NOR flash is memory-mapped, it uses the memory mapping to locate
devices. NAND flash is not memory-mapped, so I had to come up with some
other mechanism to locate devices. The target cdl must tell the devices 
their names, and the implementation must locate the driver data 
structures from that.

My proposal was to use cyg_io_lookup() to locate the controller and chip 
devices by name. Well, as I wrote in my RFC, this is obviously broken 
because NAND controller and chip devices must not be accessed through 
the file system. But we still need a mechanism to look them up and then 
tie them together.

Then, the File System must retrieve its NAND controller (+ associated 
chip(s)) from the name it is passed at cdl or mount time. I thought 
cyg_io_lookup() can be used again to get the nand_t pointer. (Or ad lib 
replace NAND controller here with "Abstract NAND Device".)

Would you care to suggest a better scheme for lookup for chip, 
controller, FS? Or would you already be satisfied if the names are not 
like /dev/nand0 but like '#nand0' or whatever non-filesystem-capable string?

[...]
>> of pages. What if we want to hide the fact that there are  
>> pages/blocks/luns/chips? Then we must address the bytes in this abstract  
>> NAND, but 32bit addresses will be insufficient.
> 
> Not necessarily bytes, but by blocks. We could define a block as being
> 512 bytes, and use a u32 to indicate which block to access. That would
> allow access to i think 2TB. For an embedded system that is quite a
> lot. Is 512 sensible? I have no idea.

Blocks are the unit of erase. Pages are the unit of read/program (with 
ECC in the page's spare area). Blocks usually consist of a good number 
of pages (think 64). Pages can be 256, 512, 1K, 2K, 4K bytes (with 
larger to come, I'd guess).

Even at the chip level, NAND allows addressing of individual x8 or x16 
words (bytes or shorts). This saves on IO between CPU and NAND 
peripherals -- it allows random access (within a page). I wouldn't 
suggest to throw that faculty away. So, my proposal is to have two 
32-bit indices, column (= x8/x16 word within page) and row = 
page+block+lun. This resembles the ONFI chip specification, where 
addressing is done in tuples too (some integral number of bytes for the 
column, some integral number of bytes for the row). It also makes 
evident that some things are different with NAND flash; e.g. it is 
impossible to program/read more than 1 page at a time (although there is 
an interface to do pipelining and interleaving (which I have skipped) of 
pages).

Brainstorm: it might be possible to generalize my previous suggestion of 
'uniform chips', and let the Abstract Nand Device export one contiguous 
NAND 'chip'; it must translate between the abstract blocks and pages and 
the blocks and pages of individual chips. The block size (unit of erase) 
of the Abstract Chip must be the maximum of the block size of the chips. 
The page size (unit of ECC) must be handled carefully to translate ECC 
addresses within the spare area to match potentially different page sizes.

> YAFFS is interesting, but from a licensing point of view, it is
> bad. It is pure GPL. We can never include it into the eCos tree.  We
> should also be looking at support for JFFS2, which we can and do
> import into eCos. People who are using Redboot as a Linux bootloader
> will want the NAND implementation to the compatible with what linux
> does so that they can boot there Linux kernel out of a NAND filesystem
> with JFFS2. Taking this further, UBI and UBIFS is of interest for the
> Linux world, however it has the same licensing problems as YAFFS.

YAFFS is also Linuxware. It has been in the kernel for a long time. I 
understand that the licensing of incorporating YAFFS into their RedBoot 
may bite (i.e. cost) people. Just for curiosity: does anyone know what a 
commercial license of YAFFS would cost?

JFFS2 uses mtd. Should we then make a thin mtd portability layer on top 
of cyg_nand? Or should we hack JFFS2 to speak native cyg_nand (and again 
loose JFFS2 compatibility)? I seem to read that JFFS2 has been frozen, 
and JFFS3 is now UBI/UBIFS.

If we make a thin mtd portability layer on top of cyg_nand, I have to 
read up on mtd, or at least those parts of mtd that are actually used by 
JFFS2. I skimmed through mtd when I started this. mtd's interface is *huge*.

Rutger

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



More information about the Ecos-discuss mailing list