This is the mail archive of the
mailing list for the eCos project.
Re: NAND technical review
(resend, having fallen foul of sourceware's spamtrap)
Jonathan Larmour wrote:
> > Good ONFI support should be the highest priority as that's the way
> > everything is likely to go, although we do need the others too.
Agreed. As the Samsung K9 is nearly ONFI already, adapting my driver is
likely to be very quick; all other things being equal, I would just do this
as and when there was a demand (and suitable hardware on my desk).
> > Personally I would expect use as an interrupt line as the main role of
> > the ready line.
IMLE the overhead of sleeping and context switching is quite significant. In
the drivers I've written to date, where there is a possiblity to use the
ready line as an interrupt source I have provided this as an option in CDL.
>> >> Theoretically, multiple chips could be
>> >> hooked up in parallel to give something that looks like a 16 or 32-bit
>> >> "wide" chip, but I have never encountered this in the NAND world [...]
> > Have you found on-chip (SoC's) NAND controllers permit such a
> > configuration? If not, I would assume that it's not an expected hardware
> > configuration.
Not on the small number of controllers I have looked at in detail.
> > What problems would you see, if any, using your layer with the same
> > controller and two completely different chips, of different geometry?
> > Can you still have a common codebase with other (different) platforms?
I don't see any issue: controllers don't IME care about the chip geometry,
they just take care of the electrical side, and some calculate ECC in
passing. For that matter I don't see an issue with a single controller on
one board driving two chips of different geometries at once.
> > Is anyone aware of NAND chips with different sized blocks? Analogous to
> > bootblocks with NOR (I haven't, but others will undoubtedly have seen
> > more parts than I). Although it's possible that even if they're not
> > around or common now, they may be in future.
I don't think there's a way to express such a chip in the ONFI chip
interrogation logic, and such a chip would I think comprehensively break the
Linux MTD layer into the bargain.
> > Unfortunately from what I
> > can tell neither layer would be able to support that directly, although
> > I think it may be possible for the eCosCentric layer to allow the driver
> > to pretend there is a different NAND chip. Do you think so too?
Two chip drivers exposing different geometries but with essentially the same
underlying access functions would probably do the trick. There would have to
be careful address translation or partitioning between the two, and a single
mutex protecting both devices in the chip driver layer, but I think it'd be
>> >> 2. Application interface -----------------------------------------------
>> >> The basic operations required are reading a page, programming a page and
>> >> erasing a block, and both layers provide these.
> > However I believe Rutger's supports partial page writes (use of
> > 'column'), whereas I don't believe eCosCentric's does.
As covered in the other subthread, is this actually useful, and how to sort
out the ECC?
>> >> Rutger's layer has an extra hook in
>> >> place where an application may explicitly request the use of cached reading
>> >> and writing where the device supports this.
> > That seems like a useful potential optimisation, exploiting underlying
> > capabilities. Any reason you didn't implement this?
> > I could also believe that NAND controllers can also optimise by doing
> > multiple block reads, where this hint would also prove useful.
Not particularly. Looking at cache-assisted read and program operations for
multi-page operations is sitting on my TODO list, languishing :-). I would
note in passing that YAFFS doesn't make use of these, preferring only to
read and write single pages fully synchronously; this might be a worthwhile
enhancement in dealing with larger files, though YAFFS's own internal NAND
interface is strictly page-oriented at the moment and so this would require
a bit of brain surgery - something best done in conjunction with Charles
Manning, I think.
> > Does your implementation _require_ a BBT in its current implementation?
> > For simpler NAND usage, it may be overkill e.g. an application where the
> > number of rewrites is very small, so the factory bad markers may be
> > considered sufficient.
I suppose it would be possible to provide a CDL option to switch the
persistent BBT off if you really wanted to. Caution is required, though:
after you have ever written to the chip, it can be impossible to distinguish
a genuine factory-bad marker from application data in the OOB area that
happens to resemble it. This can be worked around with very careful
management of what the application puts into the OOB or by tweaking the OOB
layout to simply avoid ever writing to the relevant byte(s).
>> >> (a) Partitions
> > [snip]
>> >> R's interface does not have such a facility. It appears that, in the
>> >> event
>> >> that the flash is shared between two or more logical regions, it's up to
>> >> higher-level code to be configured with the correct block ranges to use.
> > In yours, the block ranges must be configured in CDL. Is there much
> > difference? I can see an advantage in writing platform-independent test
> > programs. But in applications within products possibly less so.
I provide CDL for manual config, but have included a partition layout
initialisation hook. If there was an on-chip partition table, all that's
needed would be some code to go into that hook to interrogate it and
translate to my layer's in-memory layout. This is admittedly not well
documented, but hinted at by "Planning a port"
and should be readily apparent on examining code for existing chip drivers.
> > Especially since the flash geometry, including size, can be
> > programmatically queried.
Flash geometry can only be programmatically queried up to a point in
non-ONFI chips. Look at the k9_devinit function in k9fxx08x08.inl: while the
ReadID response of Samsung chips encodes the page, block and spare area
sizes, it doesn't tell you about the chip block count or overall size - you
have to know based on the device identifier byte. Linux, for example, has a
big table of these in drivers/mtd/nand/nand_ids.c.
> > If there was to be a single firmware supporting multiple board
> > revisions/configurations (as can definitely happen), which could include
> > different sizes of NAND, I think R's implementation would be able to
> > adapt better than E's, as the high-level program can divide up the sizes
> > based on what it sees.
I see no reason why E's wouldn't adapt just as well, given suitably written
driver(s) and init hooks.
>> >> (b) Dynamic memory allocation
>> >> R's layer mandates the provision of malloc and free, or compatible
>> >> functions. These must be provided to the cyg_nand_init() call.
> > That's unfortunate - that limits its use in smaller boot loaders - a key
> > application.
>> >> E's doesn't; instead it declares a small number of static buffers.
> > I assume everything is keyed off CYGNUM_NAND_PAGEBUFFER, and there are
> > no other variables. Again I'm thinking of the scenario of single
> > firmware - different board revs. Can you confirm?
Chip drivers are expected to require in CDL that CYGNUM_NAND_PAGEBUFFER be
large enough, and to set up a static byte array for their Bad Block Table.
Efficiently supporting two differently-sized chips on a single board - I
mean only allocating enough static space for the largest known BBT - would
not be difficult.
> > OTOH your implementation doesn't supports program verifies in the higher
> > level anyway (I note your code comment about it being unnecessary as the
> > device should report a successful program - your faith in correct
> > hardware behaviour is considerable :-) ).
Verifying after programming is also on my todo list :-)
>> >> If multiple chips of different types are present in a build, E's model
>> >> potentially duplicates code (though this could be worked around; also, an
>> >> ONFI driver ought to be written).
> > Worked around in a way likely to increase single-device footprint
> > though. Shame about the lack of OFNI driver, although I guess the parts
> > still aren't widely used which can't help. The Samsung K9 is close at
> > least.
As I said, when one lands on my desk I'll gladly get writing :-)
> > In fact, because of the requirement for the
> > drivers to call CYG_NAND_FUNS, it doesn't seem difficult at all to be
> > backwardly compatible. Am I right? Nevertheless, it would be unfortunate
> > to have an API which already needs its low level driver interface
> > updating to a rev 2.
Adding hardware ECC support and making the driver interface
backwards-compatible turned out to break layering, so I chose to change the
It's a relatively straightforward change in that I have broken up page read
and program operations into three: initialise, to read/write a stride of
data (length chosen by the NAND layer to mesh with whatever ECC length is
provided by the controller), and finalise. The flow inside my NAND layer for
programming a page becomes:
* Call chip driver to initialise the write (we expect it to send the command
* For each ECC-sized stride of data:
** If hardware ECC, call the ECC driver to tell it we're about to start a stride
** Call chip driver to write a stride of data
** If hardware ECC, call the ECC driver to get the ECC for the stride now
completed and stash it away
* If software ECC, compute it for the page
* Finalise the spare layout using the ECC wherever it came from
* Call chip driver to finalise the write, passing the final spare layout (we
expect it to write the spare area and send the program-confirm command).
I am not yet finished this work, but will update all my existing drivers
when it is done. In a way, the drawn-out nature of this process has provided
extra time for my state of the art to evolve ;-)
> > Incidentally I note Rutger has a "Samsung" ECC implementation, whereas
> > you support Samsung K9 chips, but use the normal ECC algorithm. Did
> > Samsung change their practice?
The "Samsung" ECC implementation has nothing to do with the underlying chip;
it's just an algorithm whose details they published, I think in conjunction
with some of the higher-level NAND-based products they ship which feature an
FTL (USB sticks, SD cards, etc). There is in general no requirement to use
any particular ECC algorithm with any particular chip; all the spec sheets
tend to say is "use ECC".
If I have understood the code correctly, Rutger provides two ECC algorithms:
* nand_ecc.c implements the "standard" Linux MTD algorithm (indeed the code
is lifted, with acknowledgement). This is an algorithm created by Toshiba,
with a 256 byte data block and 22 bit ECC and the layer uses it by default
where no other algorithm is provided.
* io_nand_ecc_samsung.c provides a Samsung algorithm of the same parameters,
used by the BlackFin board driver.
My layer only provides the Linux MTD algorithm at the moment (also by
lifting the code with acknowledgement).
In passing I note that the 22 bits for 256 bytes algorithm is a bit wasteful
of space as it's relative simple to add an extra pair of row-parity bits and
have 24 bits of ECC for 512 bytes of data. If you were happy that the chip
wouldn't suffer too many single-bit dropouts at once, and you decided you
didn't want to worry about subpage support you could go for 26/1024 or
28/2048. Would you believe it, writing 24/512 (and perhaps 26/1024 and
28/2048) algorithms is also on my todo list ...
> > Your documentation does appear very thorough and well-structured
> > (although the Samsung and EA LPC2468 docs really should be broken out
> > into their own packages). Rutger's does also seem fine though so I don't
> > think there's a strong difference either way.
The Samsung K9 is in its own (single-chapter) docs package as of a few weeks
ago, and the board-specific bits for the EA LPC2468 have been moved into
> > [synth target]
> > Bad block injection sounds like an extremely useful feature. I infer
> > from the latter that we're now talking about many hours of testing?
We are. We have run our YAFFS severe stress testing with bad block injection
for over a week at a time.
>> >> * Expansion of the device interface to better allow efficient hardware
>> >> ECC support (in progress)
> > Rough ETA? All I'm interested in knowing is whether the device interface
> > changes for this are likely to be concluded within the timeframe of this
> > discussion.
It's part and parcel of the customer port that I'm currently working on, so
"real soon now" - top of my priority list apart from this discussion ;-)
With a following wind I would hope to be able to finish it up, synch my
changes with the anoncvs side and push out maybe a week or so after I'm back
>> >> * Partition addressing: make addressing relative to the start of the
>> >> partition, once and for all
> > That's quite a major API change, which seems problematic to me.
This is why it has to be worked out sooner rather than later, and is
currently very close to the top of my todo list ;-). Bart in particular has
been encouraging me to make this change for a while.
>> >> * Part-page read support (would provide a big speed-up to parts of YAFFS2
>> >> inbandTags mode as needed by small-page devices like that on the
>> >> STM3210E)
> > Do you foresee this happening within any particular timeframe? Do you
> > expect the changes to be backwardly compatible?
No timescale as yet as it's relatively far down my todo list. I think
support would require an addition to the device interface to support reading
from a column address, not a break - so existing drivers would continue
working. But I need to think about this a bit more when I get there, as it
may require work on the YAFFS side, and it tickles the sleeping dragon that
is support for ECC on part-pages.
Embedded Software Engineer, eCosCentric Limited.
Barnwell House, Barnwell Drive, Cambridge CB5 8UU, UK.
Registered in England no. 4422071. www.ecoscentric.com