Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Honored Contributor I
2,096 Views

Difference between alt_write_flash and alt_erase_flash_block/alt_write_flash_block

Hi, 

 

I have read the chapter on writing to Flash in chapter 6-19 of the Nios II Software Developer's Handbook. I understand the problem of overwriting data due to erasing and writing a whole block rather than just the desired address range. The way around this is to read the block into memory first, update the desired address in the block in memory, then write the whole block to the flash.  

 

If I understand the "Simple Flash Access" section correctly, it seems that the simple alt_write_flash function does both the erase and write at once, and will do multiple blocks at once. If you read the data first and overwrite this, it sounds like it would produce the desired results. I therefore don't understand the purpose of the alt_erase_flash_block and alt_write_flash_block functions in the "Fine Grained Flash Access" section. It seems that these do the erase and write parts separately, and will only do a single block at once. But if you want to write only a few bytes, you still need to read the whole block first, then update this before calling alt_erase_flash_block followed by alt_write_flash_block. Why not just call alt_write_flash at this point? What is the advantage of the separate erase_block/write_block functions over the simple write function? 

 

I have tried to search for more information on this but have come up blank. I hope someone can explain this. 

 

Thanks, 

Giles
0 Kudos
7 Replies
Highlighted
Honored Contributor I
81 Views

You would use the block level API's to construct your own functions for your own purpose. 

 

The "alt_write_flash" is simply a convenience function for a common operation. 

 

One easy reason why you might want to not use it would be if you cared about performance while writing large amounts of data (erase+write is faster than the read+memcmp+erase+write which alt_write_flash might do).
0 Kudos
Highlighted
Honored Contributor I
81 Views

Thanks for the reply. I had initially thought that the alt_write_flash function would do the read and compare as well. However, from table 6-7 in the manual it doesn't appear to do this. The table actually shows that the contents of a block outside the part that you are writing will be set to 0xFF and the original data will be lost. On page 161 it says: 

 

"alt_write_flash() might need to erase the contents of a block before it can write data to it. In this case, it makes no attempt to preserve the existing contents of the block. This action can lead to unexpected data corruption (erasure), if you are performing writes that do not fall on block boundaries." 

 

Which suggests that it is not reading and comparing the data before the erase. 

 

It then says "If you wish to preserve existing flash memory contents, use the fine-grained flash functions." and under the section on the fine grained functions, it says  

 

"Therefore, to alter a specific location in a block while leaving the surrounding contents unchanged, you must read out the entire contents of the block to a buffer, alter the value(s) in the buffer, erase the flash block, and finally write the whole block-sized buffer back to flash memory. The fine-grained flash access functions automate this process at the flash block level." 

 

But looking at the actual functions in the fine grained section (alt_erase_flash_block() and alt_write_flash_block()) I don't see how it automates the first two stages in that paragraph. It seems that they do the same thing as the simple functions (erase and write) except that the two stages are separated. 

 

I did think the fine grained methods referenced the flash by block number, but I don't even think that's true. For alt_write_flash you pass "offset" bytes from the start of the flash, and for alt_write_flash_block you must specify "block_offset" bytes from the start of the flash. If "offset" is on a block boundary, I can't see the difference between these two parameters. 

 

This isn't a problem - I can do the read myself and alter the buffer before I call erase and write, after working out the offset of the block I'm writing to, but I have to do this when using either the simple or fine grained functions. As I think you always have to do the erase before the write, I still don't see the difference between the two methods except that the first is a single function and the second is two functions (both of which must be called in order). I must be missing something, but from the documentation I'm not sure what it is.  

 

Is there any more documentation on this other than the chapter in the Software Developer's Handbook, or could you explain this a bit more please? 

 

Thanks a lot, 

Giles
0 Kudos
Highlighted
Honored Contributor I
81 Views

Actually, I think I now understand one difference. You only need to call alt_erase_flash_block() once to erase a block, but can then call alt_write_flash_block() multiple times to write to this block (as long as you don't overwrite the same addresses). If you had a function that writes (e.g.) a buffer of 50 bytes, and wanted to call this 5 times with consecutive addresses), you would only need to do the erase if the block changes. So if all the buffers were being written to the same block, you would only do the erase once. 

 

If you were doing this with the simple functions you would have to either write them all to a buffer in memory, then just write this buffer once with a single alt_write_flash() call, or do the whole read+modify+erase/write routine five times. 

 

I found this sentence confusing: "alt_write_flash_block() writes to a single block in the flash memory." as I thought this meant "writes a complete block". I think I understand now that you can just write a single byte without affecting the rest of the block, which you can't do with the simple functions. 

 

Is this correct?
0 Kudos
Highlighted
Honored Contributor I
81 Views

With NOR flash (which the above sounds like) it is also possible to rewrite an area provided that you are only trying to clear bits. 

So you can have a 'partial write' function that will do a read/erase/modify/write if any bits need to be set, and just a write if bits only need to be cleared. 

With a caches for a single full sized flash sector and a few 512 ones I got acceptable performance for a FAT16 filesystem. 

Although you really need a flash-friendly filesystem that treats both 0xff and 0x00 as 'unused' markers, and preferentially uses the 0xff entries.
0 Kudos
Highlighted
Honored Contributor I
81 Views

 

--- Quote Start ---  

 

Which suggests that it is not reading and comparing the data before the erase. 

 

--- Quote End ---  

 

Well, in the source code, it is reading and comparing. But on further inspection, it looks like it's not retaining the old data. 

It's just trying to figure out if the caller is trying to write the same data that is already there or not to determine if it needs to erase the block. 

 

 

--- Quote Start ---  

 

But looking at the actual functions in the fine grained section (alt_erase_flash_block() and alt_write_flash_block()) I don't see how it automates the first two stages in that paragraph.  

 

--- Quote End ---  

 

I think you are misreading it: it is not saying that those functions do that, it is saying that you have the capability to use those functions in order to write code to perform that task. 

 

 

--- Quote Start ---  

 

Is there any more documentation on this other than the chapter in the Software Developer's Handbook, or could you explain this a bit more please? 

 

--- Quote End ---  

 

 

Probably your best bet is the source code itself. The API you are looking at is an abstract layer which the individual flash HAL components implement. So there is version of functions for EPCS, and a version of functions for CFI, ... but they look roughly the same.
0 Kudos
Highlighted
Honored Contributor I
81 Views

Thanks for the replies dsl and ted. I think I do understand the difference now. I missed the fact that alt_write_flash_block could be used to write only part of a block without affecting the rest of the block. So, just to check, does this mean that if you erase and write the whole block (whether you read and modify the data first or not), there is no real difference between the two methods? I will check the source code, but that's my understanding at the moment. 

 

One final question (or couple of questions): The reference section of the manual states that these functions should be used "only when operating in single-threaded mode". Is this really true? I want to use them in a multi-threaded application, although I will make sure that all the writes to the flash are done from a single thread. Is it just that the functions aren't thread-safe, or should they really not be used in an application that uses multiple threads? If it just means that all the uses of these functions should be done from a single thread, can I still read from the flash by reading directly from the address (i.e. not using the alt_flash... functions) from another thread (with an appropriate mutex of course)? 

 

Thanks, 

Giles
0 Kudos
Highlighted
Honored Contributor I
81 Views

Hi, I hardly understand :  

The "simple flash access function" alt_write_flash( alt_flash_fd* fd, // file descriptor for flash int offset, // destination address offset const void* src_addr, // source address int length ) // length of data to be written to Flash, in Bytes(?)  

1) will read the block (8k B, 64 kB) in which "offset" is, 

2) copy this block to a buffer, which require some ram 

3) erase the block, 

4) modify the buffer with new data, 

5) write the whole buffer to the flash block. 

it automatically does it ? 

 

So, if the amount of data doesn't overlap the next block, there is NO Corruption, isn't there ?[/B] 

But if I want to write only 1 Byte, The alt_write_flash() will do read-copy-erase_block-modify-write. 

if the amount of data overlaps the next block, there IS Corruption ? 

 

the "fine-grained flash access" alt_write_flash_block() will only modify bytes without the "read-copy-erase_block-modify-write", it just writes and doesn't erase the whole block, doesn't it ? 

So, if the amount of data doesn't overlap the next block, there is NO Corruption, isn't there ? 

if the amount of data overlaps the next block, there IS Corruption ? 

 

I don't know what is the advantage of using the "Fine-Grained Flash Access". 

 

In the exemple of the "Chapter 6: Developing Programs Using the Hardware Abstraction Layer", alt_write_flash() write 0xAA to the next block,  

because before there was 0xFF (all bits is '1'), and the write function change only '1' to '0' if necessary. OK I understand. 

If this byte was not 0xFF, the result of write function will be unexpected, I think (It would be equal to {old_Byte AND new_byte}) 

 

I am very confused. 

 

EDIT :  

 

--- Quote Start ---  

You only need to call alt_erase_flash_block() once to erase a block, but can then call alt_write_flash_block() multiple times to write to this block (as long as you don't overwrite the same addresses). If you had a function that writes (e.g.) a buffer of 50 bytes, and wanted to call this 5 times with consecutive addresses), you would only need to do the erase if the block changes. So if all the buffers were being written to the same block, you would only do the erase once. 

--- Quote End ---  

 

 

To clarify, 

 

simple "alt_write_flash()" will write data to flash located at the address, but erase :( the rest of the block. 

 

fine-grained "alt_write_flash_block()" can only change bits '1' to '0' :( located at the address, and conserve the rest of the block. 

 

 

EDIT 2: 

Form document "Developping program using the HAL" :  

 

--- Quote Start ---  

Therefore, to alter a specific location in a block while leaving the surrounding contents 

unchanged, you must read out the entire contents of the block to a buffer, alter the 

value(s) in the buffer, erase the flash block, and finally write the whole block-sized 

buffer back to flash memory. the fine-grained flash access functions automate this 

process at the flash block level

--- Quote End ---  

 

 

That is the point that confuse the newbies. 

 

To resume, as said by an other, to alter a specific location in a block while leaving the surrounding contents 

unchanged, you can use the fine-grained flash access functions :  

to read out the entire contents of the block to a buffer : alt_read_flash_block()  

alter the value(s) in the buffer : buffer[42] = 123456 for example 

erase the flash block : alt_erase_flash_block() 

and finally write the whole block-sized buffer back to flash memory : alt_write_flash_block () 

 

With fine-grained flash access functions, DO NOT write to the next block. I experienced that ALL the flash get corrupted if I write more that one block.
0 Kudos