Code:
/* Teensy++ 2 / Teensyduino
** EEPROM SST28SF040A Reader/Writer
** 4 Mbit (512 Kbit x 8)
** 512 Kylobytes total (8 sectors of 64 Kylobytes) */
#include <stdio.h>
#define DATA_DDR DDRC
#define DATA_PORT PORTC
#define DATA_PIN PINC
#define COL_ADDR_DDR DDRF
#define COL_ADDR_PORT PORTF
#define COL_ADDR_PIN PINF
#define ROW_ADDR_DDR DDRB
#define ROW_ADDR_PORT PORTB
#define ROW_ADDR_PIN PINB
#define SEC_ADDR_DDR DDRD
#define SEC_ADDR_PORT PORTD
#define SEC_ADDR_PIN PIND
#define CHIP_SIZE 0x80000 //bytes
const byte ledPin = 6;
const byte oePin = 8;
const byte cePin = 9;
const byte wePin = 18;
byte command;
enum {REBOOT = 0, READ, WRITE, ERASE};
void setup() {
Serial.begin(115200);
pinMode(oePin, OUTPUT);
pinMode(cePin, OUTPUT);
pinMode(wePin, OUTPUT);
// Address must be outputs
COL_ADDR_DDR = 0xFF;
ROW_ADDR_DDR = 0xFF;
SEC_ADDR_DDR = 0xFF;
digitalWrite(wePin, HIGH);
digitalWrite(cePin, HIGH);
digitalWrite(oePin, HIGH);
}
// Unprotect the chip to allow certain operations
void unprotect() {
digitalWrite(wePin, HIGH); digitalWrite(cePin, LOW);
digitalWrite(oePin, LOW); readFrom(0x1823); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x1820); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x1822); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x0418); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x041B); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x0419); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x041A); digitalWrite(oePin, HIGH);
}
// Protect the chip to prevent certain operations
void protect() {
digitalWrite(wePin, HIGH); digitalWrite(cePin, LOW);
digitalWrite(oePin, LOW); readFrom(0x1823); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x1820); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x1822); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x0418); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x041B); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x0419); digitalWrite(oePin, HIGH);
digitalWrite(oePin, LOW); readFrom(0x040A); digitalWrite(oePin, HIGH);
}
// Configure the address on correct pins
void setAddress(unsigned long address) {
COL_ADDR_PORT = address & 0xFF;
ROW_ADDR_PORT = (address >> 8) & 0xFF;
SEC_ADDR_PORT = address >> 16;
}
// Turn on the Teensy ++ 2 led
void ledOn(int ms) {
digitalWrite(ledPin, HIGH);
delay(ms);
}
// Turn off the Teensy ++ 2 led
void ledOff(int ms) {
digitalWrite(ledPin, LOW);
delay(ms);
}
// Erase the chip, the chip must be unprotected
void chipErase() {
DATA_DDR = 0xFF;
digitalWrite(cePin, LOW);
digitalWrite(oePin, HIGH);
digitalWrite(wePin, LOW);
DATA_PORT = 0x30;
digitalWrite(wePin, HIGH);
digitalWrite(cePin, HIGH);
digitalWrite(oePin, LOW);
digitalWrite(oePin, HIGH);
digitalWrite(cePin, LOW);
digitalWrite(wePin, LOW);
DATA_PORT = 0x30;
digitalWrite(cePin, HIGH);
digitalWrite(oePin, LOW);
digitalWrite(wePin, HIGH);
delayMicroseconds(1);
}
// Read a byte from the address
byte readFrom(unsigned long rAddress) {
byte data = 0;
DATA_DDR = 0x00; // Data must be input
digitalWrite(wePin, HIGH);
digitalWrite(cePin, LOW);
digitalWrite(oePin, LOW);
setAddress(rAddress);
data = DATA_PIN;
digitalWrite(wePin, LOW);
digitalWrite(cePin, HIGH);
digitalWrite(oePin, HIGH);
return data;
}
// Write a byte to the address
void writeTo(unsigned long wAddress, byte data) {
byte check = 0;
DATA_DDR = 0xFF; // Data must be output
digitalWrite(cePin, LOW);
digitalWrite(oePin, HIGH);
digitalWrite(wePin, LOW);
DATA_PORT = 0x10; // Command to write
digitalWrite(cePin, HIGH);
digitalWrite(oePin, LOW);
digitalWrite(wePin, HIGH);
setAddress(wAddress);
digitalWrite(cePin, LOW);
digitalWrite(oePin, HIGH);
digitalWrite(wePin, LOW);
DATA_PORT = data;
delayMicroseconds(1);
/* Data check - Can't write 2 times at the same address */
while (check != data) {
check = readFrom(wAddress);
}
}
// Do writes to an address range, the data is received from Serial
void doWrite(unsigned long int writeAddress, unsigned long int endAddress) {
digitalWrite(ledPin, HIGH);
if (endAddress >= CHIP_SIZE) {
Serial.print("ERROR: Cannot write beyond 0x7FFFF.");
} else {
for (writeAddress = 0; writeAddress < endAddress; writeAddress++) {
byte data = Serial.read();
writeTo(writeAddress, data);
Serial.write(">"); // feedback for write finish
}
}
digitalWrite(ledPin, LOW);
}
void loop() {
// While nothing is received, the led stay blinking
while (!Serial) {
ledOn(500); ledOff(500);
continue;
}
Serial.flush(); // Flush any previous data
command = Serial.read();
switch (command) {
case REBOOT:
_reboot_Teensyduino_(); // Builtin command
break;
case READ:
// Read the whole chip and print values in serial like an hexadecimal editor
char fAddr[5]; // formated address
char fData[2]; // formated data
Serial.println("_______________Data readed from SST28SF040A______________");
Serial.println(" [00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F]");
for (unsigned long int rAddr = 0; rAddr < CHIP_SIZE; rAddr += 0xF) {
sprintf(fAddr, "%05lX", rAddr); // pad formated address uint32_t with zeroes
Serial.print("[");
Serial.print(fAddr);
Serial.print("] "); // Space at end
for (byte count = 0; count <= 0xF; count++){
byte data = readFrom(rAddr);
sprintf(fData, "%02X", data);
if (count == 0){
Serial.print("[");
}
Serial.print(fData);
Serial.print(" ");
if (count == 0xF) {
Serial.println("]");
}
}
}
break;
case WRITE:
unprotect();
doWrite(0x0, 0x7FFFF); // Writes 0x80000 bytes coming from serial
protect();
break;
case ERASE:
unprotect();
chipErase();
protect();
}
}
And here's the python client code (Uses PySerial)