[U-Boot] handling of bad blocks in nand

A short question to handling of bad blocks: My nand shows a few bad blocks (example 100000)
What is happen when I write / read from that block via nand write / read. Is content than ok (by mapping good blocks do that address)?
Other way around - if I have commands like
"get_kn=nand read.i 0x80000000 c0000 200000"
do I have to care for bad blocks in that range ? Di I have to make the part bigger to have some extra blocks, if one is skipped while write/read as it is bad?
Best regards Arno

On Wed, Jun 23, 2010 at 02:40:51PM +0200, Arno Steffen wrote:
A short question to handling of bad blocks: My nand shows a few bad blocks (example 100000)
What is happen when I write / read from that block via nand write / read. Is content than ok (by mapping good blocks do that address)?
Bad blocks are skipped, and all subsequent blocks are shifted out by one.
Other way around - if I have commands like
"get_kn=nand read.i 0x80000000 c0000 200000"
do I have to care for bad blocks in that range ? Di I have to make the part bigger to have some extra blocks, if one is skipped while write/read as it is bad?
The partition must be at least as large as the number of real data blocks you want to write, plus the number of bad blocks within that range.
-Scott

2010/6/23 Scott Wood scottwood@freescale.com:
On Wed, Jun 23, 2010 at 02:40:51PM +0200, Arno Steffen wrote:
A short question to handling of bad blocks: My nand shows a few bad blocks (example 100000)
What is happen when I write / read from that block via nand write / read. Is content than ok (by mapping good blocks do that address)?
Bad blocks are skipped, and all subsequent blocks are shifted out by one.
Other way around - if I have commands like
"get_kn=nand read.i 0x80000000 c0000 200000"
do I have to care for bad blocks in that range ? Di I have to make the part bigger to have some extra blocks, if one is skipped while write/read as it is bad?
The partition must be at least as large as the number of real data blocks you want to write, plus the number of bad blocks within that range.
-Scott
Thanks Scott, does it mean in other words - I don't have to care for the bad block, can write on the bad block address as it would be ok?
The only thing I have to care is, that I have leave enough space between the partitions. As for instance : I need 10 blocks for a certain filesystem, give it 12 ? So it could correct 2 bad blocks in this range.
Best regards Arno

Dear Arno Steffen,
In message AANLkTiktrnXK-erEMjHh9ALHMOhfJZMr09G57fidAsv1@mail.gmail.com you wrote:
The only thing I have to care is, that I have leave enough space between the partitions. As for instance : I need 10 blocks for a certain filesystem, give it 12 ? So it could correct 2 bad blocks in this range.
If you are dealing with NAND, and want any sort of reliability, you want to use UBI.
Best regards,
Wolfgang Denk

On 06/24/2010 01:28 AM, Arno Steffen wrote:
does it mean in other words - I don't have to care for the bad block, can write on the bad block address as it would be ok?
You can't write directly to that block, but it can be included in a range of blocks as long as the range is large enough to hold the data blocks plus the bad blocks.
The only thing I have to care is, that I have leave enough space between the partitions. As for instance : I need 10 blocks for a certain filesystem, give it 12 ? So it could correct 2 bad blocks in this range.
Right.
-Scott

2010/6/24 Scott Wood scottwood@freescale.com:
On 06/24/2010 01:28 AM, Arno Steffen wrote:
does it mean in other words - I don't have to care for the bad block, can write on the bad block address as it would be ok?
You can't write directly to that block, but it can be included in a range of blocks as long as the range is large enough to hold the data blocks plus the bad blocks.
Mhh. Think we misunderstood each other. Lets asume block with 0x10.0000 is bad.
I would guess from what you told me before that I could read/write to 0x10.0000. Of course this is than internally redirected, but from uboot point of view I hope to can do
nand write 0x8000.0000 0x10.0000 1000
The only thing I have to care is, that I have leave enough space between the partitions. As for instance : I need 10 blocks for a certain filesystem, give it 12 ? So it could correct 2 bad blocks in this range.
Right.
-Scott
@ Wolfgang: Ubi is probably better, but I can't start everything from beginning again. And this is a completly new topic for me.

On 06/25/2010 05:18 AM, Arno Steffen wrote:
2010/6/24 Scott Woodscottwood@freescale.com:
On 06/24/2010 01:28 AM, Arno Steffen wrote:
does it mean in other words - I don't have to care for the bad block, can write on the bad block address as it would be ok?
You can't write directly to that block, but it can be included in a range of blocks as long as the range is large enough to hold the data blocks plus the bad blocks.
Mhh. Think we misunderstood each other. Lets asume block with 0x10.0000 is bad.
I would guess from what you told me before that I could read/write to 0x10.0000. Of course this is than internally redirected, but from uboot point of view I hope to can do
nand write 0x8000.0000 0x10.0000 1000
It is "redirected" to the next good block after the one you're trying to write to. But it is not fully transparent. Suppose the block at 0x100000 is bad, and the next block at 0x120000 is good.
If you do the above command, it will skip the bad block and write to 0x120000. But if you then do "nand write 80000000 120000 1000", you will overwrite what you previously wrote.
-Scott

2010/6/25 Scott Wood scottwood@freescale.com:
On 06/25/2010 05:18 AM, Arno Steffen wrote:
2010/6/24 Scott Woodscottwood@freescale.com:
On 06/24/2010 01:28 AM, Arno Steffen wrote:
does it mean in other words - I don't have to care for the bad block, can write on the bad block address as it would be ok?
You can't write directly to that block, but it can be included in a range of blocks as long as the range is large enough to hold the data blocks plus the bad blocks.
Mhh. Think we misunderstood each other. Lets asume block with 0x10.0000 is bad.
I would guess from what you told me before that I could read/write to 0x10.0000. Of course this is than internally redirected, but from uboot point of view I hope to can do
nand write 0x8000.0000 0x10.0000 1000
It is "redirected" to the next good block after the one you're trying to write to. But it is not fully transparent. Suppose the block at 0x100000 is bad, and the next block at 0x120000 is good.
If you do the above command, it will skip the bad block and write to 0x120000. But if you then do "nand write 80000000 120000 1000", you will overwrite what you previously wrote.
-Scott
Ok, understood it now. Thanks a lot. -Arno

Sorry another question to that.
As for instance I want to have 10MB for root partion and keep 2 blocks extra as reserve for some bad blocks. I will erase the hole 10MB+2block, write 10MB. That's what I do in uboot.
But in Kernel I have some partition table like this:
{ .name = "root(1)", .offset = MTDPART_OFS_APPEND, .size = 82*(64*2048), /*10MB + 256k*/ .mask_flags = MTD_WRITEABLE /* force read-only */ },
There are right now the 2 extra blocks inside (but they haven't been written or formatted). That is wrong, isn't it? The kernel might now write beyond the 10MB.
I think I have to set size to 80*(62*2048) and append the 2 extra blocks to the offset in the next Partition to leave this 2 block free.
But I am not sure. So thanks for a quick look and an advice.

On Fri, Jul 9, 2010 at 5:12 AM, Arno Steffen arno.steffen@googlemail.com wrote:
Sorry another question to that.
As for instance I want to have 10MB for root partion and keep 2 blocks extra as reserve for some bad blocks. I will erase the hole 10MB+2block, write 10MB. That's what I do in uboot.
But in Kernel I have some partition table like this:
{ .name = "root(1)", .offset = MTDPART_OFS_APPEND, .size = 82*(64*2048), /*10MB + 256k*/ .mask_flags = MTD_WRITEABLE /* force read-only */ },
There are right now the 2 extra blocks inside (but they haven't been written or formatted). That is wrong, isn't it? The kernel might now write beyond the 10MB.
I think I have to set size to 80*(62*2048) and append the 2 extra blocks to the offset in the next Partition to leave this 2 block free.
But I am not sure. So thanks for a quick look and an advice.
I think you are are correct in specifying the total size of your partition.
If you are putting an MTD filesystem in that partition then the filesystem itself will take care of bad blocks that might occur in the partition during runtime. During the flash programming of this filesystem using nand write.jffs2 (or .e) will skip bad blocks that might occur in the partition.
If you are putting an image (kernel or initrd) into the partition then the 'nand read.e' and 'nand write.e' (as well as mtd-utils nandwrite) will handle bad blocks by skipping over them.
Either way, it is best to specify the partition by its total size.
Best Regards, Ben Gardiner
--- Nanometrics Inc. +1 (613) 592-6776 x239 http://www.nanometrics.ca

On Fri, Jul 09, 2010 at 08:56:40AM -0400, Ben Gardiner wrote:
If you are putting an MTD filesystem in that partition then the filesystem itself will take care of bad blocks that might occur in the partition during runtime. During the flash programming of this filesystem using nand write.jffs2 (or .e) will skip bad blocks that might occur in the partition.
If you are putting an image (kernel or initrd) into the partition then the 'nand read.e' and 'nand write.e' (as well as mtd-utils nandwrite) will handle bad blocks by skipping over them.
On any recent u-boot, the .jffs2/.e/.i suffixes are maintained for compatibility only -- bad block skipping is now the default behavior.
-Scott

On 2010-07-09, Scott Wood scottwood@freescale.com wrote:
On Fri, Jul 09, 2010 at 08:56:40AM -0400, Ben Gardiner wrote:
If you are putting an MTD filesystem in that partition then the filesystem itself will take care of bad blocks that might occur in the partition during runtime. During the flash programming of this filesystem using nand write.jffs2 (or .e) will skip bad blocks that might occur in the partition.
If you are putting an image (kernel or initrd) into the partition then the 'nand read.e' and 'nand write.e' (as well as mtd-utils nandwrite) will handle bad blocks by skipping over them.
On any recent u-boot, the .jffs2/.e/.i suffixes are maintained for compatibility only -- bad block skipping is now the default behavior.
I'm using 1.3.4 (that's what's supported by Atmel). While that's the current "released" version, it appears to be over two years old?
I've been reading nand flash docs and source code for a while now, and I must admit the more I read the more questions I have.
1) Is there any documentation for the "nand" commands?
There's nothing in the manual, and doc/README.nand appears to be incomplete, and self-contradictory. [There's no mention at all of .e or .i, and there are contradictory descriptions for .jffs2.]
2) Are the behaviors of ".jffs2", ".e", and ".i" the same? (It appears so from the source code.) If not how do they differ?
3) In the 1.3.4 source code, there are lots of instances where there are boolean flags with names like "jffs2". AFAICT those flags have nothing to do with the JFFS2 filesystem, but simply control whether or not bad flash blocks are skipped during read/write operations. Am I reading the code correctly?
4) If in a custom command, I want to read/write a large block of data to/from nand flash while skipping bad blocks what functions do I call? Right now I'm doing something like this:
nand_info[0].read(nand_info+0, offset, sizeof(buffer), &len, buffer)
nand_info[0].write(nand_info+0, offset, bytecount, &len, buffer)
but, I have a feeling that's not right (though it seems to work, I suspect it's not going to skip bad blocks).

On 2010-08-13, Grant Edwards grant.b.edwards@gmail.com wrote:
On 2010-07-09, Scott Wood scottwood@freescale.com wrote:
On Fri, Jul 09, 2010 at 08:56:40AM -0400, Ben Gardiner wrote:
If you are putting an MTD filesystem in that partition then the filesystem itself will take care of bad blocks that might occur in the partition during runtime. During the flash programming of this filesystem using nand write.jffs2 (or .e) will skip bad blocks that might occur in the partition.
If you are putting an image (kernel or initrd) into the partition then the 'nand read.e' and 'nand write.e' (as well as mtd-utils nandwrite) will handle bad blocks by skipping over them.
On any recent u-boot, the .jffs2/.e/.i suffixes are maintained for compatibility only -- bad block skipping is now the default behavior.
I'm using 1.3.4 (that's what's supported by Atmel). While that's the current "released" version, it appears to be over two years old?
Never mind. I see that the version naming scheme has changed and what I mistook for datestamped snapshots are actually released versions.
That said, 1.3.4 is the most recent version supported by Atmel. So my choices are try to port Atmels patches to a recent version or make do with the nand flash support in 1.3.4.

On Fri, Aug 13, 2010 at 09:22:21PM +0000, Grant Edwards wrote:
I'm using 1.3.4 (that's what's supported by Atmel). While that's the current "released" version, it appears to be over two years old?
I've been reading nand flash docs and source code for a while now, and I must admit the more I read the more questions I have.
Is there any documentation for the "nand" commands?
There's nothing in the manual, and doc/README.nand appears to be incomplete, and self-contradictory. [There's no mention at all of .e or .i, and there are contradictory descriptions for .jffs2.]
Are the behaviors of ".jffs2", ".e", and ".i" the same? (It appears so from the source code.) If not how do they differ?
At one point in the legacy NAND code, a distinction was made when reading between completely skipping bad blocks, and filling the buffer with zeroes in place of the bad blocks. It looks like ".jffs2" or ".e" would get you zeroes, and ".jffs2s" or ".i" would get you block skipping.
The zero-fill mode is no longer supported. In 1.3.4, assuming you're not using the legacy NAND code, you need to specify one of ".jffs2", ".e", or ".i" to get block skipping. It doesn't matter which one. In current u-boot these suffixes are accepted and ignored as legacy (bad blocks are always skipped), except for "jffs2s" which apparently never made an appearance outside the legacy code.
Yes, it's a bit of a mess.
- In the 1.3.4 source code, there are lots of instances where there are boolean flags with names like "jffs2". AFAICT those flags have nothing to do with the JFFS2 filesystem, but simply control whether or not bad flash blocks are skipped during read/write operations. Am I reading the code correctly?
The user interface .jffs2 suffix was to indicate bad block skipping, but opts->jffs2 (which is still around) refers to writing JFFS2 cleanmarkers after erasing a block.
If in a custom command, I want to read/write a large block of data to/from nand flash while skipping bad blocks what functions do I call? Right now I'm doing something like this:
nand_info[0].read(nand_info+0, offset, sizeof(buffer), &len, buffer)
nand_info[0].write(nand_info+0, offset, bytecount, &len, buffer)
but, I have a feeling that's not right (though it seems to work, I suspect it's not going to skip bad blocks).
You suspect correctly.
In current code there is nand_write_skip_bad() and nand_read_skip_bad() in drivers/mtd/nand/nand_util.c.
In 1.3.4 use nand_read_opts()/nand_write_opts(). Or convince Atmel to support something more recent. :-)
-Scott

On 2010-08-16, Scott Wood scottwood@freescale.com wrote:
On Fri, Aug 13, 2010 at 09:22:21PM +0000, Grant Edwards wrote:
At one point in the legacy NAND code, a distinction was made when reading between completely skipping bad blocks, and filling the buffer with zeroes in place of the bad blocks. It looks like ".jffs2" or ".e" would get you zeroes, and ".jffs2s" or ".i" would get you block skipping.
The zero-fill mode is no longer supported. In 1.3.4, assuming you're not using the legacy NAND code, you need to specify one of ".jffs2", ".e", or ".i" to get block skipping. It doesn't matter which one. In current u-boot these suffixes are accepted and ignored as legacy (bad blocks are always skipped), except for "jffs2s" which apparently never made an appearance outside the legacy code.
OK, that clears up quite a bit of my confusion.
Yes, it's a bit of a mess.
It does appear to be improving. :)
- In the 1.3.4 source code, there are lots of instances where there are boolean flags with names like "jffs2". AFAICT those flags have nothing to do with the JFFS2 filesystem, but simply control whether or not bad flash blocks are skipped during read/write operations. Am I reading the code correctly?
The user interface .jffs2 suffix was to indicate bad block skipping, but opts->jffs2 (which is still around) refers to writing JFFS2 cleanmarkers after erasing a block.
Thanks, that helps.
If in a custom command, I want to read/write a large block of data to/from nand flash while skipping bad blocks what functions do I call? Right now I'm doing something like this:
nand_info[0].read(nand_info+0, offset, sizeof(buffer), &len, buffer)
nand_info[0].write(nand_info+0, offset, bytecount, &len, buffer)
but, I have a feeling that's not right (though it seems to work, I suspect it's not going to skip bad blocks).
You suspect correctly.
In current code there is nand_write_skip_bad() and nand_read_skip_bad() in drivers/mtd/nand/nand_util.c.
Yup, I found those, and the read version is exactly what I need.
I've still got to figure out how to write.
The problem is that the data to be written is streaming. I don't know how much there is, and I don't want to allocate arbitrarily large buffers. So I want to write it one erase-block at a time as it arrives. AFAICT nand_write_skip_bad() can't be used in that situation. Since it provides no indication of how many blocks were skipped, I have no way of knowing where the next block should be written.
I guess that means I need to use the same lower-level API that is being used by nand_write_skip_bad().
In 1.3.4 use nand_read_opts()/nand_write_opts(). Or convince Atmel to support something more recent. :-)
It turns out that Atmel's patches have been merged into the main sources and 2010.6 works fine for the board in question. I don't know why the official Atmel web-page still instructs you to use 1.3.4+patches.
participants (5)
-
Arno Steffen
-
Ben Gardiner
-
Grant Edwards
-
Scott Wood
-
Wolfgang Denk