PDA

View Full Version : Flash erase byte routine



longpole001
- 16th June 2014, 09:47
Hi guys ,

i am trying to do a erase byte routine for flash

The FLASH as i have learned is not the same as EEProm in that you cant just change bytes values as you may like to on the fly , changing byte to $FF requires your do a complete sector erase , depending on the chip and the size the sector erase can range from 4k bytes to 64k bytes at a time.

chip i am currently using has a sector erase of 64k bytes

I would like to have a routine that allows for a byte changes 1 to 256bytes at a time on the same sector/ page/ byte.

the current routine inputs give the 24bit start address , length of data of the bytes to be changed , and the data in the buffer

for easy naming i have broken the 24bit address in to 3 bytes named , sector/page/bytes for the 8mb chip i am working on sector size is 0-15, pages = 0-255,bytes = 0-255

method of approach i have is


1. erase temp swap sector 0
2. copy all data of sector/page/bytes to sector 0 EXCEPT the bytes that are to be changed
3. write the new bytes to correct location in sector 0
4. erase original sector
5. copy sector 0 to orginal sector

sounds simple , the only problem i have is item 2

whats a good approach

cheers

Sheldon

EarlyBird2
- 16th June 2014, 09:54
Hi Sheldon,

Have you got the data sheet so that I can do some reading?

longpole001
- 16th June 2014, 10:20
datasheet for M25P80 chip

http://www.farnell.com/datasheets/1737025.pdf

Link to working code
http://www.picbasic.co.uk/forum/showthread.php?t=19287

richard
- 16th June 2014, 10:36
should be doable just break job up to small lumps
say you have a 1k ram block spare

step 1 erase a temp sector (64k) on the flash
1. read a k of old sector data
2 . does this k need to updated?
if yes update this 1k block
write this block to temp sector
3 repeat step 2 63 more times (for each 1k block)
4 erase old sector (now copied to temp with updates)
5 copy temp sector back to old sector
end

just had a look at your data sheet
looks like 256 byte blocks may be more appropriate

and 100,000 write cycles , how often will you be doing this



still think raspberry pi a more fitting machine for this type of work

EarlyBird2
- 16th June 2014, 11:09
Reading the data sheet and your code example makes me think this statement is not true.



The FLASH as i have learned is not the same as EEProm in that you cant just change bytes values as you may like to on the fly , changing byte to $FF requires your do a complete sector erase , depending on the chip and the size the sector erase can range from 4k bytes to 64k bytes at a time.


and a write to any location is possible. But I will keep reading

HenrikOlsson
- 16th June 2014, 11:27
Hi,
Yes, they can be programmed one byte at the time at any arbitrary memory location. However, "programming" means changing (or not changing) a "1" to a "0". You can't change a "0" to a "1".
So, before you can program a location it needs to be erased ("reset" to $FF). Erasing is done either sector by sector or the entire chip (bulk).

/Henrik.

EarlyBird2
- 16th June 2014, 11:41
Hi,
Yes, they can be programmed one byte at the time at any arbitrary memory location. However, "programming" means changing (or not changing) a "1" to a "0". You can't change a "0" to a "1".
So, before you can program a location it needs to be erased ("reset" to $FF). Erasing is done either sector by sector or the entire chip (bulk).

/Henrik.

Yes I understand now. I was having difficulty finding the write command in the data sheet but as you explained the program command is used.

longpole001
- 16th June 2014, 11:46
yep have a look in the example of the code i have posted in the examples , but hendrik is correct the large bulk and sectors erase options suck for a byte change when the location has been written before

even with this routine its a time pain but Flash are large chips/cheep and if time is a worry then sram /eeproms are probably a option better suited , but there are time when only a few bytes changed option is very nice to have on flash chip

i am thinking maybe 2 x for, next loop based on the selected location for the change , eg , if selected page/byte is x then copy data to x-1 , and next loop x +1 , this is then done for lower address to lentght of data changed then set upper address

HenrikOlsson
- 16th June 2014, 12:27
Hi Sheldon,
Looking at the datasheet for your device it specifies a sector erase time of 3 seconds(!) and a bulk erase time of 20 seconds (!) - is that really correct?

The one I've been playing with is the SST25VF080B from Microchip, which is an 8Mbit SPI flash memory device with "only" 4k sectors. It specifies a sector erase time of 25ms and a chip erase time of 50ms (50ms vs 20s for a chip erase).

Using the SST25VF80 instead of the M25P80 should allow you to get the overall performance up due to the smaller sector size and cosiderably faster erase time - provided the 3second sector erase time is indeed correct. Then, of course, using bit banged SPI is really slow compared to using the MSSP module.

/Henrik.

longpole001
- 17th June 2014, 00:10
yes i have seen better chips and will change to them , the routines work for all the same size chip , ill how much i can get the SST25VF080B for ,
but ill also try W25Q80BV - have ordered 200 of these at 6c each + freight

these when they arrive they have a 4k erase space option , and have 25ms time to do it , plus other optionsthat come from the Q series of flash .

be it 4k or 64k , a routine to change say 1- 256k bytes in the same sector/page on the fly is really nice routine to have on hand on these chips and would be easy enought o change to the size that best suites your needs


http://www.adafruit.com/datasheets/W25Q80BV.pdf

EarlyBird2
- 17th June 2014, 06:41
be it 4k or 64k , a routine to change say 1- 256k bytes in the same sector/page on the fly is really nice routine to have on hand on these chips and would be easy enough to change to the size that best suites your needs


We need to start on the routine or have you started?

Your approach in #1 is to copy sectors to be changed to sector 0. The routine will read from the sector 0 into say byte variables these will then be changed if required and written to Flash. This will be repeated for the whole 4k.

Any thoughts?

longpole001
- 18th June 2014, 00:16
yep steve i was thing something like this

1. erase sector 0

2 write the changed bytes to sector 0 for page / byte /length data

3. using the address and number of byte to change length( assumes 1- 256 bytes contiguous) get the all OTHER pages/ bytes in orginal sector and write to sector 0

so need to find value of entered page address and read into the buffer (256kb) , then write
a. input page + 1 (data above the input page) for next loop 1 -
b. input page -1 ( data below the input page) for next loop 2
c. allow for input page location = 0 or 255 - so for next loop 1 only

this then copy of all pages EXCEPT that which need to change
If the input length was 255 then sector 0 has copy of the completed changed data

if length <255 bytes change then

then use the input length and byte start address value to read / write
a. read bytes start address + length + 1 - for next loop1 - ( read the bytes above that dont need to change)
b. read bytes start address + length - 1 - for next loop2 - ( read the bytes below that dont need to change)
c. allow for input bytes location + length of 0 or 255 - so for next loop 1 only

this then copy of all bytes except that which have been changed

now do a sector erase of the orginal sector

now read/ write each page back from sector 0 each page


not easy but as hedric said the smaller the sector erase size the less time it takes

Amoque
- 18th June 2014, 02:28
Sorry to interrupt... I'm just following along for the sake of understanding how this is managed.

Do I read you right? Using sector 0 as a scratchpad? Reading X sector to 0 WITH changes, then erasing X sector, then writing sector 0 to X? Finally, erasing sector 0, so its blank for the next go-round? Or did I miss something?

I think I'll read your post a few more times... see if I can't follow your thinking better. Thanks.

longpole001
- 18th June 2014, 06:21
yes that what i am thinking
sector 0 is erased
if the bytes to be changed are say bytes 5 - 10 for sector 15, page 1 then you

write changed data to sector 0/ page 1 / bytes 5-10
you copy bytes 0-4 of sector 15/page1 to sector 0/page1/ bytes 0-4 - for next loop 1
you copy bytes 11-255 of sector 15/page1 to sector 0/page1/ bytes 11-255 - for , next loop2
copy all other pages from sector 15 to sector 0 -

erase sector 15
copy sector 0 to 15 ( in

as you can see the smaller the sector erase the chip supports the better for small changes

longpole001
- 21st June 2014, 04:07
steve you want to have a go at it ?

EarlyBird2
- 21st June 2014, 06:07
steve you want to have a go at it ?

I could give it a go. How far have you got?

longpole001
- 21st June 2014, 14:28
Flash_Byte_Modify:
' assumes address , length ( upto 256bytes )
' assumes sector 0 is not protected
SDC_sector = 0
gosub Flash_Sec_Erase ' erase sector 0
SDC_address.byte2 = 0 ' use sector 0,instead of given sector , but use given page, byte length
gosub Flash_write ' Write the the changed data to sector 0

if SDC_page > 0 and SDC_page <255 then ' find the pages to copy
SDC_address.byte2 = 0
SDC_address.byte1 = SDC_page
if Data_Length < 255 then
SDC_address.byte0 = SDC_byte +1 -



well not far , this is the start

longpole001
- 21st June 2014, 23:48
bit more of an attempt , steve can you check the logic ,cleanup ,




Flash_Byte_Modify:
' assumes address , length ( upto 256bytes )
' assumes sector 0 is not protected
' assumes selectted sector is not protected

Flash_Addr_Copy.byte3 = Data_Length ' save the selected address & length
Flash_Addr_Copy.byte2 = SDC_Sector
Flash_Addr_Copy.byte1 = SDC_Page
Flash_Addr_Copy.byte0 = SDC_Byte

SDC_sector = 0
gosub Flash_Sec_Erase ' erase sector 0

SDC_sector = 0 ' use sector 0,instead of given sector , but use given page, byte length
gosub Flash_write ' Write the the changed data to sector 0

if Flash_Addr_Copy.byte1 = 0 then ' find the pages to copy - copy all pages/ bytes above 0 for given sector
for SDC_Page = 1 to 255 ' read all pages above 0 of selected sector
SDC_Sector = Flash_Addr_Copy.byte2 ' of read selected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Read ' read 255 bytes at a time
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Write ' write
next SDC_Page
endif

if Flash_Addr_Copy.byte1 = 255 then ' find the pages to copy - copy all pages/ bytes below given page/ byte of sector
for SDC_Page = 0 to 254 ' read all pages below 255 of selected sector
SDC_Sector = Flash_Addr_Copy.byte2 ' of read selected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Read ' read 255 bytes at a time
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Write ' write
next SDC_Page
endif

if Flash_Addr_Copy.byte1 >0 and Flash_Addr_Copy.byte1 < 254 then ' find the pages to copy - copy all pages/ bytes below given page/ byte of sector

for SDC_Page = 0 to Flash_Addr_Copy.byte1 - 1 ' read all pages from 0 to selected page -1
SDC_Sector = Flash_Addr_Copy.byte2 ' of read selected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Read ' read 255 bytes at a time
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Write ' write
next SDC_Page
endif

for SDC_Page = Flash_Addr_Copy.byte1 + 1 to 255 ' read all pages from selected page + 1 to 255
SDC_Sector = Flash_Addr_Copy.byte2 ' of read selected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Read ' read 255 bytes at a time
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_byte = 0 ' bytes 0 - 255
Data_Length = 255 ' all bytes
gosub Flash_Write ' write
next SDC_Page
endif
endif

if Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 < 255 then ' if the start byte + data length of the data changed is < 255 bytes ,
' then copy bytes below the selected changed data
SDC_Sector = Flash_Addr_Copy.byte2 ' read selected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = 0 ' start address bytes 0 to
Data_Length = Flash_Addr_Copy.byte0 - 1 ' selected byte - 1 ( length)
gosub Flash_Read ' read
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = 0 ' start address bytes 0 to
Data_Length = Flash_Addr_Copy.byte0 - 1 ' selected byte - 1 ( length)
gosub Flash_Write ' write

' then copy bytes above the selected changed data
SDC_Sector = Flash_Addr_Copy.byte2 ' read selected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 ' start address bytes above given address and length
Data_Length = 255 - SDC_byte ' data above changed bytes ( length = 255 bytes - given addrees + given length )
gosub Flash_Read ' read the data
SDC_Sector = 0 ' use sector 0
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 ' start address bytes above given address and length
Data_Length = 255 - SDC_byte ' data above changed bytes ( length = 255 bytes - given addrees + given length )
gosub Flash_Write ' write the data

endif

' Sector 0 should now have a complete copy of the data + changed data from the orginal selected sector

SDC_sector = Flash_Addr_Copy.byte2
gosub Flash_Sec_Erase ' erase orginal sector

for SDC_PAGE = 0 to 255 ' copy sector 0 pages to selected sector 0 ( 256bytes at a time)
SDC_Sector = 0 ' use sector 0
SDC_byte = 0
Data_Length = 255
gosub Flash_Read ' read the data
SDC_Sector = Flash_Addr_Copy.byte2 ' use selected sector
SDC_byte = 0
Data_Length = 255
next SDC_PAGE

SDC_sector = 0 ' clean up sector 0
gosub Flash_Sec_Erase ' erase orginal sector
return

EarlyBird2
- 22nd June 2014, 08:56
I will do! Just need a bit of time to absorb the logic.

longpole001
- 22nd June 2014, 09:09
forgot to write the data at the end




' Sector 0 should now have a complete copy of the data + changed data from the orginal selected sector

SDC_sector = Flash_Addr_Copy.byte2
gosub Flash_Sec_Erase ' erase orginal sector

for SDC_PAGE = 0 to 255 ' copy sector 0 pages to selected sector 0 ( 256bytes at a time)
SDC_Sector = 0 ' use sector 0
SDC_byte = 0
Data_Length = 255
gosub Flash_Read ' read the data
SDC_Sector = Flash_Addr_Copy.byte2 ' use selected sector
SDC_byte = 0
Data_Length = 255
gosub Flash_write ' write the data
next SDC_PAGE
SDC_sector = 0 ' clean up sector 0
gosub Flash_Sec_Erase
return

longpole001
- 24th June 2014, 04:36
well approach seems to work , here is a rundown , the real key is USE A FLASH CHIP THAT SUPPORTS SMALL SECTOR ERASE SIZE AND USE THAT SETTING

3 new routines - to be added to examples i left
hope it save others time in the future


Regards


Sheldon

1. Flash_byte_modfy - use - change 1- 255 bytes of a selected sector/page ,
uses sector 0 as scratchpad and places changed code to sector 0 ,
copies all other pages / bytes not changed of the selected sector to sector 0
then erases the origin sector and copy complete sector 0 to origin

how to use




'---------- FLASH_MODIFY_BYTE TEST - example

Data_Length = 10 ' changed data length
For SDC_index = 0 to Data_Length
SDC_buffer[SDC_index] = SDC_index ' fill the changed data into buffer with values
next SDC_index

SDC_Sector = 1 ' sector start address for where data is to be placed
SDC_Page = 3 ' page start address for where data is to be placed
SDC_Byte = 16 ' byte start addresss for where data is to be placed
gosub Flash_Byte_Modify






Flash_Byte_Modify:

' assumes address , length ( upto 256bytes )
' asusmes bytes changed are in the same sector and no boundry cross
' assumes sector 0 is not protected
' assumes selected sector is not protected

Flash_Addr_Copy.byte3 = Data_Length ' save the selected address & length
Flash_Addr_Copy.byte2 = SDC_Sector
Flash_Addr_Copy.byte1 = SDC_Page
Flash_Addr_Copy.byte0 = SDC_Byte

SDC_sector = 0
gosub Flash_Sec_Erase ' erase sector 0
SDC_sector = 0 ' use sector 0,instead of given sector , but use given page, byte length
gosub Flash_write ' Write the data to sector 0


if Flash_Addr_Copy.byte1 = 0 then ' find the pages to copy - copy all pages/ bytes above 0 for given sector
Flash_Page_Orgin =1 ' start page of orgin
Flash_Page_length = 255 ' how many pages
Flash_Sec_Orgin = Flash_Addr_Copy.byte2 ' sector
Flash_Sec_Dest = 0
Flash_Page_Dest = 1
gosub Flash_Page_Copy
endif

if Flash_Addr_Copy.byte1 = 255 then ' find the pages to copy - copy all pages/ bytes below given page/ byte of sector
Flash_Page_Orgin =0 ' start page of orgin
Flash_Page_length = 254 ' how many pages
Flash_Sec_Orgin = Flash_Addr_Copy.byte2 ' sector
Flash_Sec_Dest = 0
Flash_Page_Dest = 0
gosub Flash_Page_Copy
endif

if Flash_Addr_Copy.byte1 >0 and Flash_Addr_Copy.byte1 < 254 then ' find the pages to copy - copy all pages/ bytes below given page/ byte of sector
Flash_Page_Orgin =0 ' start page of orgin
Flash_Page_length = Flash_Addr_Copy.byte1 - 1 ' how many pages
Flash_Sec_Orgin = Flash_Addr_Copy.byte2 ' sector
Flash_Sec_Dest = 0 ' start at same page value as orgin
Flash_Page_Dest = 0
gosub Flash_Page_Copy

Flash_Page_Orgin = Flash_Addr_Copy.byte1 + 1 ' start page of orgin
Flash_Page_length = 255 - Flash_Page_Orgin ' panges to copy = 255 - start address +1
Flash_Sec_Orgin = Flash_Addr_Copy.byte2 ' sector
Flash_Sec_Dest = 0
Flash_Page_Dest = Flash_Addr_Copy.byte1 + 1
gosub Flash_Page_Copy
endif

if Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 < 255 then ' if the start byte + data length of the data changed is < 255 bytes ,
' then copy bytes below the selected changed data
SDC_Sector = Flash_Addr_Copy.byte2 ' read selected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = 0 ' start address bytes 0 to
Data_Length = Flash_Addr_Copy.byte0 - 1 ' selected byte - 1 ( length)
gosub Flash_Read ' read
SDC_Sector = 0 ' use sector 0 aselected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = 0 ' start address bytes 0 to
Data_Length = Flash_Addr_Copy.byte0 - 1 ' selected byte - 1 ( length)
gosub Flash_Write ' write

' then copy bytes above the selected changed data
SDC_Sector = Flash_Addr_Copy.byte2 ' read selected sector
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 ' start address bytes above given address and length
Data_Length = 255 - SDC_byte ' data above changed bytes ( length = 255 bytes - given addrees + given length )
gosub Flash_Read ' read the data
SDC_Sector = 0 ' use sector 0
SDC_PAGE = Flash_Addr_Copy.byte1 ' of selected page
SDC_byte = Flash_Addr_Copy.byte0 + Flash_Addr_Copy.byte3 ' start address bytes above given address and length
Data_Length = 255 - SDC_byte ' data above changed bytes ( length = 255 bytes - given addrees + given length )
gosub Flash_Write ' write the data

endif

' Sector 0 should now have a complete copy of the data + changed data from the orginal selected sector
Flash_Sec_Orgin = 0 ' copy sector 0
Flash_Sec_dest = Flash_Addr_Copy.byte2 ' erase destination and copy data from flash orgin
Flash_clear = 1 ' set flag erase orgin sector 0 after copy
gosub Flash_Sec_Copy ' copy the sector



return




2. Sector copy routine - - this routine copy the data from the origin sector to destination sector
- will erase destination sector prior to copy
- option flag " Flash_clear " when set will Erase orgin sector after copy
- assumes no copy protect on destination or origin
how to use


Flash_Sec_Orgin = 0 ' sector origin - sector to copy
Flash_Sec_dest = 1 ' sector destination - will be erased then copy data from sector origin
Flash_clear = 1 ' option flag to erase origin sector after copy
gosub Flash_Sec_Copy ' copy the sector




Flash_Sec_Copy:
' copys data from 1 sector to another
' erases destination sector - optional clean of orginal sector
' assumes Flash_Sect_Orgin,Flash_Sect_Dest Flash_clear
' Erases wont work on sectors that are write protected
' sector erase take 600ms per instruction
SDC_Sector = Flash_Sec_Dest ' clear destination sector
gosub Flash_Sec_Erase ' use SDC_sector info to erase destination sector
for SDC_PAGE = 0 to 255 ' copy sector 0 pages to selected sector 0 ( 256bytes at a time)
SDC_Sector = Flash_Sec_Orgin ' sector to copy
SDC_byte = 0
Data_Length = 255
gosub Flash_Read ' read the data to buffer
SDC_Sector = Flash_Sec_Dest ' sector to copy to
SDC_byte = 0 ' use sector details for destination
Data_Length = 255
gosub Flash_Write ' write the data
next SDC_PAGE
if Flash_clear = 1 then
SDC_sector = Flash_Sec_Orgin ' clean up orgin sector
gosub Flash_Sec_Erase
endif
return


3. Page copy routine - this routine will copy pages 0-255 of origin to destination
- no sector boundry cross supported
- assumes destination is all "1" - no erase is required
- sector is not protected
how to use



' example copy sector 0/ page 0 50 pages to sector 0 , start page 125 ( page size number of bytes depends on chip)
Flash_Page_Orgin = 0 ' start address page of origin
Flash_Page_length = 50 ' number of pages to copy
Flash_Sec_Orgin = 0 ' sector origin address
Flash_Sec_Dest = 0 ' Sector destination
Flash_Page_Dest = 125 ' Page destination
gosub Flash_Page_Copy





Flash_Page_Copy:
' copys data from pages 0 -255 from orgin or destination sector
' assumes destination sector pages are Erased
' assumes pages orgin and pages destination do not cross sector boundrys
' assumes Flash_Page_Orgin,Flash_Page_dest ,Flash_Page_length, Flash_Sec_orgin ,Flash_Sec_dest
' writes wont work on sectors that are write protected

for Flash_tmp2 = Flash_Page_Orgin to Flash_Page_length ' copy sector 0 pages to selected sector 0 ( 256bytes at a time)
SDC_Sector = Flash_Sec_Orgin ' sector to copy
SDC_PAGE = Flash_tmp2
SDC_byte = 0
Data_Length = 255
gosub Flash_Read ' read the data to buffer

SDC_Sector = Flash_Sec_Dest ' sector to copy to
SDC_PAGE = Flash_Page_Dest ' page to copy to
SDC_byte = 0
Data_Length = 255
gosub Flash_Write ' write the data
Flash_Page_Dest = Flash_Page_Dest + 1 ' increment destination page
next Flash_tmp2


return