Writing internal flash with dfu-util to set EEPROM defaults

I am trying to find a dfu-util command to write to the EEPROM memory area such that I can seed my device with some default configuration flags. I’ve read up on the “100 bytes” of emulated EEPROM, and have been digging into spark code and see that its actually implemented as a 1k area with some sort of paging that I don’t understand fully, but I thought I figured out enough to at least accomplish what I was trying to do, but hit a snag.

I wrote a sketch that sets all 100 EEPROM bytes to some specific value, and then used the following command to download the emulated EEPROM flash bytes:

dfu-util -d 1d50:607f -a 0 -s 0x08004000:1024 -U eeprom.dat

And when I hexdump the file, I see the following

0000000 00 00 ff ff 0a 00 00 00 0b 00 01 00 0c 00 02 00
0000010 0d 00 03 00 0e 00 04 00 0f 00 05 00 10 00 06 00
0000020 11 00 07 00 12 00 08 00 13 00 09 00 41 00 0a 00
0000030 0a 00 00 00 0b 00 01 00 0c 00 02 00 0d 00 03 00
(truncated for brevity - has all the data my sketch wrote to EEPROM)
00001f0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
*
0000400

So after the first 32 bits I see a repeating 32 bits where 16 bits are used for the stored value (even though the API only lets you write 8 bits), and then the 16 bit ‘virtual address’.

What I then did is use a hex editor to change some of the data bytes, and then I was hoping to dfu-util write the file back to the core at the same EEPROM memory location, and then have my sketch dump all 100 virtual EEPROM bytes, hoping to see the value I put in with the hex editor. This would prove that I can seed specific EEPROM values to my device before shipping to the customer. But here is the error I get when trying to write the EEPROM 1k bytes:

dfu-util -d 1d50:607f -a 0 -s 0x08004000 -D updated_eeprom.dat
dfu-util 0.7

Copyright 2005-2008 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2012 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

Filter on vendor = 0x1d50 product = 0x607f
Opening DFU capable USB device… ID 1d50:607f
Run-time device DFU version 011a
Found DFU: [1d50:607f] devnum=0, cfg=1, intf=0, alt=0, name="@Internal Flash /0x08000000/20001Ka,108001Kg"
Claiming USB DFU Interface…
Setting Alternate Setting #0
Determining device status: state = dfuERROR, status = 10
dfuERROR, clearing status
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 1024
No valid DFU suffix signature
Warning: File has no DFU suffix
DfuSe interface name: "Internal Flash "
Downloading to address = 0x08004000, size = 1024
Error: Last page at 0x080043ff is not writeable

“Error: Last page at 0x080043ff is not writeable” makes me think some sort of write protection is in place, and when I read about the ‘unprotect’ and ‘force’ options of dfu-util, I got a little nervious about bricking the core, so I thought I would ask here first :smile:

Of course I could just write a ‘seed’ sketch for my device that uses code to set the EEPROM, but then I would have to flash my device with the seed firmware, run it once, re-flash with the real product firmware. I would like to bypass that first firmware if possible and just write the EEPROM with dfu-util during product production.

Any thoughts on how I can get dfu-util to let me write these bytes?

For reference, this is where you can see the memory mapping: http://docs.spark.io/hardware/#memory-mapping-external-flash-memory-map

For using DFU-util to write to the EEPROM, you probably need a simple .txt file with all the values in hex format.

Not sure what’s the best way to generate the file so i shall ping @bko. :wink:

For the uploading to the core,

the command will be: dfu-util -d 1d50:607f -a 1 -s 0xADDRESS:leave -D your_file.der

1.) Change the 0xADDRESS to the starting address you want to write to.

2.) the command leave should make the core restart after the uploading is done

3.) I’m not sure if this command works but you can try:

dfu-util -d 1d50:607f -a 1 -s 0xADDRESS:1024 -D your_file.der

So instead of leave, try 1024 to see to specify you want to write to 1KB of flash. (You need to test this, i have no idea if it works :D)

So I think @kennethlimcp is showing how to write the external FLASH on Spark, but I think @machadolab wants to write the internal FLASH in the EEPROM emulated area, hence the -a 0 to dfu-util. The firmware is at 0x8005000, so don’t write too far.

I have written the external flash from dfu-util and it works fine but I have not tried the internal flash other than downloading the core firmware bin file which everybody does when doing a local build, but I am sure it works too. The makefile does not do anything special with dfu-util, it just uses the standard download arguments that @machadolab is using.

I do know that I had to write an even number of bytes from dfu-util to external flash–an odd number never worked. Also the file format is binary not ASCII hex so you are going to have to edit that with a programming editor, not a text editor.

Maybe @satishgn could comment on unswizzling the addresses of the bytes. My understanding is that he implemented a standard wear-leveling algorithm.

Opps. :smiley:

I would prefer to write to the external FLASH though. :wink:

Yes, I found that memory map, and then in the code, I also found:

#define EEPROM_START_ADDRESS    ((uint32_t)0x08004000)

The file I get from the core when using:

dfu-util -d 1d50:607f -a 0 -s 0x08004000:1024 -U eeprom.dat

Is a binary file, so I assumed I needed to upload a binary file. The error sure doesn’t sound file a file format issue, but if someone can tell me how to convert a binary file into the proper hex format, I can try that. I also renamed my new_eeprom.dat to new_eeprom.bin just in case dfu-util cares about the file extension to detect format, but I still get the same result:

"Error: Last page at 0x080043ff is not writeable"

@bko, Yes, used a binary editor to edit the binary file that came from the dfu-util upload (upload from spark to host computer). I am indeed wanting to write to the internal flash, as I want to write a file and then in my code, have the EEPROM.read() methods see this data. I explored external flash, and may go this route, but I only need to store a few bytes, so the ease of the EEPROM.read() API was appealing, and seems to fill the exact use case I need.

File I am uploading is indeed 1024 bytes:

thunder:~ machado$ ls -al new_eeprom.bin
-rw-------  1 machado  staff  1024 Aug 31 14:25 new_eeprom.bin

So I am not in danger of interfering with the firmware at 0x08005000.

OK great! It sounds like you maybe with the help of @satishgn need to figure out how to unswizzle the wear-leveling. I think you are going to need a fairly smart program on the host side if you want to change this often.

If you just want a static image downloaded, then I would just create it on the core, read it out to a bin file and then use that to program other cores.

You should probably use -s 0x08004000:leave which means write only as many bytes as are in the file.

@bko,

Thats how I got my binary in the first place :slight_smile: I wrote to EEPROM from within a spark sketch with some test values, then read it out via:

dfu-util -d 1d50:607f -a 0 -s 0x08004000:1024 -U eeprom.bin

Edited, the eeprom.bin file with a hex editor, and am now just trying to write it back:

dfu-util -v -d 1d50:607f -a 0 -s 0x08004000 -D eeprom.bin

And getting:

"Error: Last page at 0x080043ff is not writeable"

My understanding is that add “:leave” to the address simply tells the core to exit DFU mode after the interaction. Regardless, just tried that too, same error.

Even if I skip the hex editor step, and just try and write back the same file I downloaded without modification, still get the same not writable error. It REALLY seems like there needs to be some dfu-util switch activated to force the write, but I don’t want to do that until someone can confirm this is correct and I won’t wipe out the bootloader data that is in the same DfuSe location.

Looked up the dfu-util source and here is the code that prints the error I am getting:

Assuming its finding the segment, it looks like the segment doesnt have the DFUSE_WRITEABLE flag.

May I suggest you use my eeprom library flashee - I think this will make life a lot simpler, since it avoids having to reverse engineer the wear leveling.

If you require just read-only access, then writing the data via dfu-util and then accessing that via the Devices::userFlash() is the simplest way.

If you need read/write access, then create the read/write device X pages from the start, where X is large enough to accommodate the configuration data you write with dfu-util. E.g.

    FlashDevice& user = Devices::userFlash(); // here you can read the config data. 
    FlashDevice* device = Devices::createAddressErase(user.pageSize()*10, user.length()); // use the remaining space for read/write

You can then write to the user region with dfu-util to populate the first 10 pages.
You could then copy from the read-only area to the read-write area, if you wanted the config data to be mutable.

Like the built-in eeprom library, this library supports eeprom emulation in flash, allowing inplace rewrites over the whole of the external flash memory.

I hope that helps!

Hi @mdma

Does Flashee work with the internal flash in the SMT32 ARM? I thought it was for external flash. @machadolab wants to write to internal flash, for whatever reason.

1 Like

Flashee is just external flash. If using internal is a must-have, then this won’t work…and I’d love to know why you can’t use external flash if that’s the case!

I was trying to avoid adding extra code to an already large project, but I may go the flashee route after all.

Actually came across it a couple hours ago and posted a question there. It wasnt clear how I can still solve the core problem - being able to use dfu-util to ‘seed’ data into flash so that I dont first have to write a ‘setup’ firmware that initializes the flash with all the values my main firmware needs. I’d like to simply run one dfu-util command before uploading my firmware that setups the flash with all the values my firmware will need.

mdma - I am assuming I can just upload a copy of the whole “NOT USED” flash area. Does it need to be the full 384 * 4096 bytes, or can I just upload a smaller subset if I only have a few values set?

The wear-leveling approach used in Internal Flash based EEPROM lib is neatly explained in this document from ST : http://www.st.com/st-web-ui/static/active/en/resource/technical/document/application_note/CD00165693.pdf

2 Likes