Go Down

Topic: writing to flash memory (Read 51117 times) previous topic - next topic


Mar 30, 2007, 12:15 pm Last Edit: Mar 30, 2007, 12:22 pm by bigengineer Reason: 1
Can someone enlighten me about writing to flash memory? There is a link in the playground:
But with my limited C skills I can't really figure out what is going on.
Can I reserve a huge block of memory to store some data? Something like 3072 B to store 3 array's of bytes?
Can I read and write to it whenever I want?
Is there some restriction on speed?


The ATmega8 (and 168, and probably others of the family) has three different types of memory:  flash, EEPROM, and RAM.  Flash is where your program lives; it's 8kb on the ATmega8.  EEPROM is where your program can store stuff between power cycles (e.g. configuration information that can be changed).  The ATmega8 has 512 bytes of EEPROM.  RAM is, well, RAM, where your typical variables are stored; there's 1k of this on the ATmega8.

I point this out because some folks don't differentiate between flash and EEPROM and use the terms interchangeably (because they're similar physically) but the ATmega has both and uses them for two completely different things.

The ATmega8 flash can be written ~10,000 times.  EEPROM can be written ~100,000 times.  both are non-volatile - they will retain their values when power is lost.  You can write to RAM as many times as you want, but the contents are gone if power is lost.  All three types of memory can be read an infinite number of times.

The AVR is a Harvard architecture - this means program memory and data memory are separate, with separate address spaces.  The ATmega8 actually has 3 address spaces - one for flash, one for EEPROM, and one for RAM.  This is different from your "typical" microprocessor, like a Pentium, where there is only one address space and it is shared between data and program (this is called a von Neuman architecture).  You'll find this Harvard architecture frequently in microcontrollers, as it simplifies some aspects of the design, allowing the CPU to be simpler (therefore faster and cheaper).

So, you have flash memory addresses 0 - 8191, EEPROM memory addresses 0 - 511, and RAM addresses 0 - 1023.

To begin to answer your question, flash and EEPROM can be written be an executing program (else the bootloader wouldn't work and we would all be using ICP programmers).  This process is neither fast nor straightforward, since the data has to be transferred a byte at a time from a register (and probably from RAM to the register first), then out to flash (or EEPROM).  flash and EEPROM are both slower to write than RAM.

To really answer your question, I would only attempt to use flash to store data that is configured at compile time and never changes (e.g. constant strings for prompts, messages and so forth), and be aware you'll have to manually copy the data out of flash before you can use it (e.g. send it to Serial.print()).

What you are asking can be done, but you need to have some understanding of the web page you referenced to read from flash; writing to it gets more complicated (I've never tried).



Making your static data stay in flash is easy. You just use the PROGMEM modifier from <avr/pgmspace.h> and for string constants wrap them in a PSTR(). The trick is that you can't reference it directly anymore, you have to use the access functions from that header like pgm_read_byte().


Okay, no flash memory available it seems. I was hoping I could use the flash memory for slow data acquisition.


Mar 30, 2007, 07:39 pm Last Edit: Mar 30, 2007, 07:55 pm by jims Reason: 1
[[ discussion of how to proceed deleted in favor of the following ]]

The AVR library has support for writing flash pages.

The usage example pretty well covers it. Be aware that you have to write full pages which are 64 bytes on a mega8 and 128 on a mega168 (Use the SPM_PAGESIZE macro). And page number will be the address divided by SPM_PAGESIZE.

Another handy piece for this puzzle is to force your variables to be aligned on a page boundary so you don't have to mess around with it too much.

Code: [Select]
uint8_t myCollectedData[512] __attribute__ ((aligned (64)));


I don't know if I should use this. I can more or less follow what is happening. But, how do I know at what page to start? It won't be 0 I think?
This a little bit above my skills I am afraid.  :-[


Your pagenumber will be the address of the variable divided by SPM_PAGESIZE.
If you have a second Arduino you can use the bootcloner sketch to reflash your first arduino in the event of an embarassing miscalculation that overwrites your bootloader.

It would be safer to use the EEPROM. http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html I don't think anything in the base Arduino uses the EEPROM so you could use all 512 bytes however you see fit.  One trick, I think if I read the bootloader correctly the EEPROM is erased when you upload a sketch. Or maybe not, but be aware that it could happen.

Go Up