ARM Flash Memory
This post describes how to store data in the flash memory of the AT91SAM7S256 microprocessor. I wrote it because I could not find a straight-forward description on the net and also because I am bored and have nothing much else to write about today.
The Flash memory is mapped into the chip’s address space from address 0×00100000 to 0×0013FFFF. To read it, you can simply read bytes from that area of memory.
Writing to the flash is a little more complex of course. Firstly you need to set up the flash write cycle timer. This needs to be initialized with the number of CPU clock cycles required to cause a 1.5 microsecond delay. On my Olimex board with an 18.432MHz oscillator, that number works out to be 27.648 - I round it up to 28. The following line of code calculates the correct value based on the clock frequency (MCK) and programs that into the ARM memory controller.
mc->MC_FMR = AT91C_MC_FWS_1FWS | (1 + (((MCK * 15) / 10000000)) << 16);
Once that is done, we are ready to write. The chip writes one page at a time. The page size for this particular chip is 256 bytes. So that means a 256 byte section of Flash memory will be erased and completely overwritten.
Overwritten by what though? Well, you need to write your data to the section of memory where it is to be stored. You must keep your writes within the 256 byte page and you must only use 32 bit writes according to the official Atmel documentation.
Once you have written your data, it goes into an invisible RAM buffer and can then be transferred to the Flash memory by writing to the command register like so:
mc->MC_FCR = AT91C_MC_WRITE_KEY | AT91C_MC_FCMD_START_PROG | (page << 8 );
That will begin the write process. It will take some time (up to 6 milliseconds!) and you will not be able to read the data or write to any other Flash page until it is complete. You can detect when the write is complete by monitoring the FRDY bit in the status register.
The value AT91C_MC_WRITE_KEY is 0×5A000000. This is a magic number which is required for the chip to accept the flash write command (to prevent accidental overwriting I suppose).
As usual, I have prepared some example code which will compile and run on the Olimex SAM7-P256 board. Download it here:
To compile and run, type the following. You will need to have the toolchain and C library set up as described in my previous articles here and here.
tar jxvf ArmFlashTest.tar.bz2 cd FlashTest make ./startarm ./runram
As with my last example, the program is accessed via the serial port at 9600bps. Start your terminal program (I use GtkTerm) before you run the program. You will be prompted to type in a line of text. Once you press ENTER, your text will be stored in Flash. You may now run the program again and you should see your line retrieved from the Flash.
You could use this example code to store configuration data in your own ARM-based applications. This code is free to use for any purpose.
UPDATE: Dan Ashbrook kindly pointed out that my port assignments for the second serial port are incorrect in Board.h. I have now corrected the file, you can download it here: ArmFlashTest.tar.bz2
