Let’s set up our Arduino IDE for use with the Arduino MEGA so that our code is all compiled and uploaded correctly. We need to select the Arduino MEGA as the board and the ATmega2560 as the processor and then the correct COM port.
The first thing that must be done is set-up the Arduino MEGA’s pins for operating the SST39SF040. We should create some definitions for each pin and then set them it either an input or output.
I only name the first of last of the address and data pins as there is no need to name each one. Next, the address pins need to be set as outputs on the Arduino so we can select an address, we can create a loop that runs from RA0 to RA18 which sets the pin to OUTPUT using pinMode() and drives it LOW using digitalWrite().
The same needs to be done for the data pins RD0 to RD7, however, we should have to separate functions, one for setting them to inputs, the other setting them to outputs as they are required for both reading and writing data.
Now we can just set-up the control pins and call the relevant functions in the setup() function. Overall, pretty standard stuff…
Input / Output Data on Address and Data pins.
We have now configured the pins for input and output so we can now begin to construct functions that allow us to convert the data/addresses so that can be valid across the pins of the flash chip.
We can see the setByte() function takes a byte as an input but the setAddress() function takes an unsigned long as an input. This is because the addresses are much longer than a byte(8-bit) or an int(16-bit) so a long(32-bit) must be used to accommodate for the 19-bit addresses and I made it unsigned just as the addresses are always positive values.
These functions allow the output of data but now we must make a different one for reading/input of data. This is achieved by reading each pin and then using bitSet() to set the corresponding bit of the byte.
Reading and Writing from the device
All of the pieces are in place to control the pins on the device so now we can make the functions to read, write and erase the flash chip based on what we looked at in part 1 of this project blog.
As discussed previously, we must drive OE# low and WE# high, we do not need to worry about CE# as its already tied to ground(low).
So in our function, we want to start by setting the digital pins to input and then WE# and OE# driven HIGH. We then set the address to the desired location and drive OE# LOW, I have added a very small delay to make sure the data on the flash chip is valid. The byte on DQ0 to DQ7 is then read and OE# is set back to HIGH. The function then returns the read byte, simple!
Writing and Erasing
We can now turn our attention to writing and erase, meaning we must start with a function to produce a write cycle so we can input the commands and data.
Again, as previously discussed in part 1, a write cycle involves the changing the state of WE# to LOW when the address and data are set.
This is done pretty easily, we start with OE# and WE# HIGH and then set our address and data and drive WE# LOW. I have added a small delay before driving #WE HIGH again to ensure the command was correctly read by the flash chip.
Now that we have the ability to produce the write cycles, we just need to build the functions that produce the command sequences for both programming and erasing the flash chip memory.
Here is the function that produces the command sequence for erasing the flash memory, it is fairly straightforward. First, the digital pins must be set to outputs to write the commands and then we use the previous function to produce the write cycles with the correct data and addresses detailed in the data-sheet. I put a delay at the end just to ensure the flash chip was ready before performing any more actions, its extreme overkill but might as well leave it there.
The program function is pretty much the same but with a 30us delay at the end, this is because the data-sheet details how there are some operations that happen after a byte is programmed and so we must wait for these to be completed. We do not make it a long delay as later when we want to program many bytes, the delay will add up meaning it will take ages to program the entire chip.
Serial Comms and Commands
We have now coded all the basic functionality of the Flash Programmer but we need a way to tell it what to do so we need to add some basic serial communications and command so we can make an application to send files over to the device. We will worry about the programming of entire files later, for now, let’s just get some basic commands up to test our code.
In our program loop we simply want to check for serial data and if there is some, we read the first byte and pass it into a function to decode the command.
The function consists of a switch-case which will execute different code depending on the input. So if the input is ‘E’ it will call the function to erase the chip, if the input is ‘R’ it will read and print the data at address 0x0000 or if the input is ‘W’ it will program 0x3E to 0x0000. I have used 0x0000 and 0x3E for demonstration purposes, these values could be anything we want within range.
And that’s that! Some simple serial comms to test our programmer using the Arduino serial monitor.
We can see that everything is working nicely from this screen-shot. When the data is first read it is FF(blank) and after sending the write command and then reading again it shows 3E meaning the program sequence is working. Then finally sending the erase command and reading again shows the data is once again FF. Brilliant!
In the next part, we will transfer our circuit from breadboard to a more permanent prototype and then create a host application to write or read more than one byte!
You can download my Arduino sketch from here.