03_jm_flash_explorer.spin2 - I broke it
Hi all. I am experiencing challenges with a bit of code, hoping someone can provide a second or third set of eyes. I'm just a hack really, so excuse the crude code please
I am using JohnnyMac's 03_jm_flash_explorer.spin2 and have this bit of code write a block of data to the onboard flash on the P2 Edge. This code works correctly (see working.jpg):
pub writedc()|addr, t,n,x addr := $12_0000 t := getct() addr &= $FFFFFF00 repeat x from 0 to 1 ' force to page boundary flash.wr_page(addr+(x*256), @dc[x*256]) repeat while flash.busy() t := getct() - t - 40 term.fstr1(string("Write time: %.3fms\r\r"), t/US_001) term.str(string("Wrote flash at ",13)) term.hex(addr)
However, when i try to turn "writedc" into a callable method with parameters using the code below, the data is not written completely to the flash. It appears to load the first 5 items from @dc just fine, and the rest becomes corrupt. (see broken.jpg) In this example, i have rewritten writedc to accept three parameters (the starting memory location to write to, the number of pages, the location of the data). To write a new block of data, first clearsomething wipes the block (this works), then writesomthing (this is broken), then readsomething back out (works).
pub testseq() clearsomething(dcID) ' works as expected waitms(100) writesomething(dcID,dcRepeat,@dc) ' broken waitms(100) readsomething(dcID,dcBytes,dclen,dccount,dcAttr) ' works as expected pub writesomething(towrite,torepeat,todata)|t,n,x,addr addr := towrite t := getct() addr &= $FFFFFF00 repeat x from 0 to torepeat ' force to page boundary flash.wr_page(addr+(x*256), todata[x*256]) repeat while flash.busy() t := getct() - t - 40 term.fstr1(string("Write time: %.3fms\r\r"), t/US_001) term.str(string("Wrote flash at ",13)) term.hex(addr)
The entire code is attached below. (it is really a mess sorry...) I was hoping to replace all the bespoke write functions with a single method i could just pass parameters into. I managed to get this working for the erase (clear) and read (display in terminal) functions, but the write function has me pounding my head on the table. I did try this with other blocks of data, and it yields similar results (meaning that much of data is written correctly, and then becomes janky after the first several bytes.)
If you happen to run this yourself, from the main menu, use option "2" (undocumented) to run the testseq() method.
To use the working writedc() method instead, use "g" to clear the space, "u" to right the data, and "n" to read it back.
This is not a mission critical project, but I would appreciate any advice. I could continue to write a bespoke method for every block of data i need to write, but I would prefer a general purpose function, as there will be many data types ill need to eventually write to the flash. Thanks in advance to the community for your advice (and for JohnnyMac for supplying the original code - as per usual.)
Comments
Reading the quickbyte again: "The 16MB Flash array is organized into 65,536 programmable pages of 256 bytes each. Up to 256 bytes can be programmed at a time. Pages can be erased in blocks of 16 (4KB) or 256 (64KB). Flash blocks must be erased before they can be programmed." I should be able to wrap my head around what is happening now that I re-read that. Read the manual much?
Ah, yes, the curse of EEPROMs, Flash being the most extreme of them. SD cards have a busy life hiding all this.
Well found a work around i guess. Probably not the most efficient way to do this but its workable, and still enables me to use a single write method, so I will take it as a win, if anyone is keeping score. Moving the repeat loop from the write method and repeating the call multiple times for each 256 byte page works, but I am still buffered while the other way didn't work. This workaround still feels like a kludge and will require more typing but whatever, Im moving on.
You have big address gaps in you data addresses. Will all of your data fit in 4K? It it will, consider reorganizing your storage so that you can read a 4K page into a RAM buffer and operate on that. It will certainly be faster. When done, erase that 4K block and then write the RAM buffer to it.
White space can be your friend. I suggest you start by redefining your memory locations. Consider something like this
With the page read into RAM, you should be able to determine the array offset by subtracting TM_BASE from your named constant.
Thanks for the advice Jon. The C3 version of this game I am porting over to spin2 is much cleaner and better organized - I swear. I think at this point I am good to go here - thanks again for your demo code. After I integrate these methods into the old game (and update the rest of the code to spin2) I will be right back to where I was on the P1/C3 several years ago when I abandoned this project for the next shiny one. LOL. Good times.