ADAM'S WEB PRESENCE

15 April 2007

ARM Flash Memory

Filed under: Nerd Notes — adam @ 10:45 pm

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:

ArmFlashTest.tar.bz2

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


5 April 2007

Adding a C library to the arm-gcc toolchain

Filed under: Nerd Notes — adam @ 9:04 pm

This is a sequel to my previous article Getting Started with the Olimex SAM7-P256. Flashing lights are all very well but I want to add a C library so I can use functions like printf().

There is a streamlined version of the standard C library available for embedded systems called newlib which you can download from the files section at http://www.gnuarm.com/. Here’s how you build it to fit in with the toolchain in my previous article:

First you need to have makeinfo. On Ubuntu, install it like this:

sudo apt-get install texinfo

Now we can build and install the library:

tar xzvf newlib-1.14.0.tar.gz

mkdir build-newlib

cd build-newlib

../newlib-1.14.0/configure --target=arm-elf --prefix=/usr/local/arm7

sudo make all install info

Documentation for newlib can be found at http://sourceware.org/newlib/.

Now we have a C library, how about writing Hello World! That was not as easy as it sounds, mainly because I wanted printf() to send its output to the serial port. It took me a lot of documentation-reading and hair-pulling to work out how to do that.

To redirect STDOUT, you need to override the syscalls.o module which is part of libc. Copy the syscalls.c and swi.h files from the newlib source into your project directory and modify the _write() function to send its data to the serial port.

I’ve got some example code to demonstrate this. You can download it by clicking the link here:

ArmHelloWorld.tar.bz2

I’ve tried to keep the code as simple and readable as possible. I’ve also included a couple of shell scripts to make it easier to download and run the code. Here is how you would compile and run it:

tar jxvf ArmHelloWorld.tar.bz2

cd HelloWorld

make

./startarm

Next you need to connect a serial cable and start up a serial terminal on your PC at 9600,n,8,1. Once that is running, launch the example code by typing this:

./runram

If all goes well, you should see “Hello World.” appear on your serial terminal.

If not, well then happy debugging !


UPDATE: Dan Ashbrook kindly pointed out that my port assignments for the 2nd serial port are incorrect in Board.h. I have now corrected the file, you can download it here: ArmHelloWorld.tar.bz2

UPDATE: I recently tried to do this on Ubuntu 8.04 and it didn’t work until I applied this patch to the newlib configure script.


Powered by WordPress