├── README.md ├── flash.py └── Arduino sketch └── flash └── flash.ino /README.md: -------------------------------------------------------------------------------- 1 | # flash 2 | ## flash memory tool 3 | 4 | Tool for programming 8 bit flash memories with an Arduino Mega, for retrocomputing or whatever. Python 3 and pyserial are necessary for uploading data to the chip. 5 | 6 | ## Usage: 7 | 8 | The script allows reading and writing to the flash. The flash chip can also be erased with the same setup. 9 | This code is basically a small modification of my eprom project: 10 | https://github.com/robsoncouto/eprom 11 | 12 | ## Project 13 | A writeup on writing eproms with the Arduino Mega can be foun at http://dragaosemchama.com/2016/10/arduino-mega-eprom-programmer/ 14 | -------------------------------------------------------------------------------- /flash.py: -------------------------------------------------------------------------------- 1 | 2 | import serial,time #You need the pyserial library 3 | import struct 4 | 5 | ser = serial.Serial('/dev/ttyACM0', 230400, timeout=0) 6 | #time.sleep(10);#my arduino bugs if data is written to the port after opening it 7 | #filename='sonic.bin'#name of the rom, bin format 8 | #f=open(name,'rb'); 9 | #with open(filename,'rb') as f: 10 | romsize=1024 11 | 12 | while True: 13 | print("===========================================") 14 | print(" What do you want do do? ") 15 | print(" ") 16 | print(" 1-dump ") 17 | print(" 2-burn ") 18 | print(" 3-erase ") 19 | print(" 2016 ") 20 | print(" Robson C ") 21 | print("===========================================") 22 | option=int(input()) 23 | 24 | block=0 25 | print(option) 26 | if(option==1): 27 | name=input("What the name of the file?") 28 | size=int(input("What's the size of the file in KB?")) 29 | romsize=size*1024 30 | f = open(name, 'w') 31 | f.close() 32 | ser.flushInput() 33 | ser.write(b"\x55") 34 | ser.write(bytes("r","ASCII")) 35 | numBytes=0 36 | f = open(name, 'ab')#yes, that simple 37 | while (numBytesB",i>>8)) 60 | CHK=i>>8 61 | #CHK=ord(CHK) 62 | time.sleep(0.001) 63 | ser.write(struct.pack(">B",i&0xFF)) 64 | CHK^=i&0xFF 65 | time.sleep(0.001) 66 | data=f.read(128); 67 | print(data) 68 | #print("CHK:", CHK) 69 | for j in range(len(data)): 70 | CHK=CHK^data[j] 71 | time.sleep(0.001) 72 | print("Sector:",i) 73 | print("CHK:", CHK) 74 | #ser.write(data) 75 | response=~CHK 76 | while response!=CHK: 77 | ser.write(data) 78 | ser.write(struct.pack(">B",CHK&0xFF)) 79 | timeout=30 80 | while ser.inWaiting()==0: 81 | time.sleep(0.1) 82 | print("waiting for CHK response") 83 | response=ord(ser.read(1)) 84 | print("rsp", response) 85 | f.close() 86 | if(option==3): 87 | ser.flushInput() 88 | ser.write(b"\x55") 89 | ser.write(bytes("e","ASCII")) 90 | response=bytes("N","ASCII") 91 | while response!=bytes("Y","ASCII"): 92 | print("Waiting for response\n") 93 | while ser.inWaiting()==0: 94 | time.sleep(0.1) 95 | print("waiting for CHK response") 96 | response=ser.read(1) 97 | print("rsp", response) 98 | print("Chip erased\n") 99 | -------------------------------------------------------------------------------- /Arduino sketch/flash/flash.ino: -------------------------------------------------------------------------------- 1 | //FIXME 2 | const int programPin = 40; 3 | const int readPin = 4; 4 | const int enablePin = 2; 5 | 6 | 7 | const unsigned long romSize = 1024 * 1024; 8 | 9 | 10 | //The pinout from the eprom is different from the snes pinout 11 | int adrPins[20] = {22, //eprom A0 snes A0 12 | 23,//eprom A1 snes A1 13 | 24,//eprom A2 snes A2 14 | 25,//eprom A3 snes A3 15 | 26,//eprom A4 snes A4 16 | 27,//eprom A5 snes A5 17 | 28,//eprom A6 snes A6 18 | 29,//eprom A7 snes A7 19 | 30,//eprom A8 snes A8 20 | 31,//eprom A9 snes A9 21 | 32,//eprom A10 snes A10 38-a16 22 | 33,//eprom A11 snes A11 39-a17 23 | 34,//eprom A12 snes A12 40-a18 24 | 35,//eprom A13 snes A13 41-a19 25 | 36,//eprom A14 snes A14 26 | 37,//eprom A15 snes A15 27 | 39,//eprom A17 snes A16 * 28 | 41,//41 //eprom A18 snes A17 * 29 | 38//eprom A16 snes A18 * 30 | }; 31 | 32 | //39,//eprom A17 snes A19 * 33 | 34 | char dataPins[8] = {5, 6, 7, 8, 9, 10, 11, 12}; 35 | /* 36 | Frame Format 37 | program: 38 | |preamble|opt|addr0|addr1|addr2|numbbutes|bytes|checksum|end 39 | read: 40 | |preamble|opt|addr0|addr1|addr2|numbbutes|end 41 | 42 | 43 | */ 44 | byte inByte = 0; 45 | unsigned int secH = 0, secL = 0; 46 | 47 | void setup() { 48 | // put your setup code here, to run once: 49 | pinMode(3, OUTPUT); 50 | digitalWrite(3, LOW); 51 | 52 | pinMode(programPin, OUTPUT); 53 | pinMode(readPin, OUTPUT); 54 | pinMode(enablePin, OUTPUT); 55 | //FIXME 56 | for (int i = 0; i < 20; i++) { 57 | pinMode(adrPins[i], OUTPUT); 58 | } 59 | digitalWrite(programPin, HIGH); 60 | digitalWrite(readPin, HIGH); 61 | digitalWrite(enablePin, HIGH); 62 | Serial.begin(230400); 63 | delay(1000); 64 | readMode(); 65 | // setAddress(0); 66 | // programByte(0x78); 67 | // //writeSector(5); 68 | } 69 | int index = 0; 70 | void loop() { 71 | // put your main code here, to run repeatedly: 72 | if (Serial.available()) { 73 | inByte = Serial.read(); 74 | if (inByte == 0x55) { 75 | while (Serial.available() == 0); 76 | inByte = Serial.read(); 77 | switch (inByte) { 78 | case 'w': 79 | programMode(); 80 | while (Serial.available() < 2); 81 | secH = Serial.read(); 82 | secL = Serial.read(); 83 | writeSector(secH, secL); 84 | break; 85 | case 'r': 86 | readMode(); 87 | readROM(); 88 | break; 89 | case 'e': 90 | programMode(); 91 | eraseROM(); 92 | break; 93 | } 94 | } 95 | } 96 | } 97 | 98 | 99 | //low level functions, direct ccontact with hardware pins 100 | void programMode() { 101 | //data as output 102 | for (int i = 0; i < 8; i++) { 103 | pinMode(dataPins[i], OUTPUT); 104 | } 105 | digitalWrite(readPin, HIGH); 106 | digitalWrite(programPin, LOW); 107 | } 108 | void readMode() { 109 | //data as input 110 | for (int i = 0; i < 8; i++) { 111 | pinMode(dataPins[i], INPUT); 112 | } 113 | // for (int i = 0; i < 8; i++) { 114 | // digitalWrite(dataPins[i], HIGH); 115 | // } 116 | digitalWrite(programPin, HIGH); 117 | digitalWrite(readPin, LOW); 118 | 119 | } 120 | void setAddress(uint32_t Addr) { 121 | for (int i = 0; i < 8; i++) { 122 | digitalWrite(adrPins[i], Addr & (1 << i)); 123 | } 124 | Addr = Addr >> 8; 125 | for (int i = 0; i < 8; i++) { 126 | digitalWrite(adrPins[i + 8], Addr & (1 << i)); 127 | } 128 | Addr = Addr >> 8; 129 | for (int i = 0; i < 3; i++) { 130 | digitalWrite(adrPins[i + 16], Addr & (1 << i)); 131 | } 132 | } 133 | byte readByte(unsigned long adr) { 134 | byte data; 135 | setAddress(adr); 136 | digitalWrite(enablePin, LOW); 137 | delayMicroseconds(10); 138 | for (int i = 7; i >= 0; i--) { 139 | data = data << 1; 140 | data |= digitalRead(dataPins[i]) & 1; 141 | } 142 | digitalWrite(enablePin, HIGH); 143 | return data; 144 | } 145 | void setData(char Data) { 146 | for (int i = 0; i < 8; i++) { 147 | digitalWrite(dataPins[i], Data & (1 << i)); 148 | } 149 | } 150 | void programByte(byte Data) { 151 | //select address 152 | // 153 | //setAddress(adr); 154 | setData(Data); 155 | //Vpp pulse 156 | delayMicroseconds(4); 157 | digitalWrite(enablePin, LOW); 158 | delayMicroseconds(60); 159 | digitalWrite(enablePin, HIGH); 160 | } 161 | 162 | void writeSector(unsigned char sectorH, unsigned char sectorL) { 163 | byte dataBuffer[128]; 164 | unsigned long address = 0; 165 | byte CHK = sectorH, CHKreceived; 166 | CHK ^= sectorL; 167 | 168 | address = sectorH; 169 | address = (address << 8) | sectorL; 170 | address *= 128; 171 | 172 | for (int i = 0; i < 128; i++) { 173 | while (Serial.available() == 0); 174 | dataBuffer[i] = Serial.read(); 175 | CHK ^= dataBuffer[i]; 176 | } 177 | while (Serial.available() == 0); 178 | CHKreceived = Serial.read(); 179 | programMode(); 180 | //only program the bytes if the checksum is equal to the one received 181 | if (CHKreceived == CHK) { 182 | for (int i = 0; i < 128; i++) { 183 | setAddress(0x5555); 184 | programByte(0xAA); 185 | setAddress(0x2AAA); 186 | programByte(0x55); 187 | setAddress(0x5555); 188 | programByte(0xA0); 189 | 190 | setAddress(address++); 191 | programByte(dataBuffer[i]); 192 | } 193 | Serial.write(CHK); 194 | } 195 | readMode(); 196 | 197 | } 198 | int readROM() { 199 | unsigned long num = 1024 * 1024; 200 | unsigned long address; 201 | byte data, checksum = 0; 202 | address = 0; 203 | //read mode 204 | readMode(); 205 | //start frame 206 | digitalWrite(readPin, LOW); 207 | digitalWrite(programPin, HIGH); 208 | for (long i; i < 524288; i++) { //1048576 209 | data = readByte(address++); 210 | Serial.write(data); 211 | //checksum^=data; 212 | } 213 | digitalWrite(readPin, HIGH); 214 | 215 | //Serial.write(checksum); 216 | //Serial.write(0xAA); 217 | } 218 | int eraseROM() { 219 | setAddress(0x5555); 220 | programByte(0xAA); 221 | 222 | setAddress(0x2AAA); 223 | programByte(0x55); 224 | 225 | setAddress(0x5555); 226 | programByte(0x80); 227 | 228 | setAddress(0x5555); 229 | programByte(0xAA); 230 | 231 | setAddress(0x2AAA); 232 | programByte(0x55); 233 | 234 | setAddress(0x5555); 235 | programByte(0x10); 236 | readMode(); 237 | while(~(readByte(0xFF)&(1<<7))); 238 | if(readByte(0xFF)==0xFF){ 239 | Serial.write('Y'); 240 | } 241 | 242 | } 243 | 244 | 245 | 246 | --------------------------------------------------------------------------------