added v2.0

This commit is contained in:
Michael Schröder
2023-01-11 11:13:09 +01:00
parent 2a5a64ca91
commit 971b323822
584 changed files with 159319 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
This firmware has to be uploaded to OLIMEXINO-32u4 in order to use it as an iCE40 programmer.
### Using Arduino IDE ###
This firmware can be uploaded via Arduino IDE. Just go to iceprog folder and load iceprog.ino.
We used SPIFlash 2.2.0 library for Winbond Flash Memory by Prajwal Bhattaram - Marzogh (the
project is now called "SPIMemory". The files we used are already inside the project, no need to
install it separately. But our advice is to the check the full project. It is availalbe here:
https://github.com/Marzogh/SPIMemory/tree/v2.2.0
### Using PlatformIO ###
Install PlatformIO, use this guide for details http://docs.platformio.org/en/stable/installation.html
Build & Upload:
platformio run
platformio run --target upload
Alternatively you can use SPI programmer to burn firmware into OLIMEXINO-32u4, e.g.:
avrdude -p atmega32u4 -P /dev/ttyUSB0 -c buspirate -b115200 -D -Uflash:w:[.pioenvs/leonardo/firmware.hex]:i

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,267 @@
/* Arduino SPIFlash Library v.2.2.0
* Copyright (C) 2015 by Prajwal Bhattaram
* Modified by Prajwal Bhattaram - 24/11/2015
*
* This file is part of the Arduino SPIFlash Library. This library is for
* Winbond NOR flash memory modules. In its current form it enables reading
* and writing individual data variables, structs and arrays from and to various locations;
* reading and writing pages; continuous read functions; sector, block and chip erase;
* suspending and resuming programming/erase and powering down for low power operation.
*
* This Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License v3.0
* along with the Arduino SPIFlash Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef SPIFLASH_H
#define SPIFLASH_H
#include <Arduino.h>
class SPIFlash {
public:
//----------------------------------------------Constructor-----------------------------------------------//
SPIFlash(uint8_t cs = 10, bool overflow = true);
//----------------------------------------Initial / Chip Functions----------------------------------------//
void begin();
uint16_t getManID();
uint32_t getJEDECID();
bool getAddress(uint16_t size, uint16_t &page_number, uint8_t &offset);
uint32_t getAddress(uint16_t size);
uint16_t getChipName();
uint16_t sizeofStr(String &inputStr);
uint32_t getCapacity();
uint32_t getMaxPage();
//-------------------------------------------Write / Read Bytes-------------------------------------------//
bool writeByte(uint32_t address, uint8_t data, bool errorCheck = true);
bool writeByte(uint16_t page_number, uint8_t offset, uint8_t data, bool errorCheck = true);
uint8_t readByte(uint16_t page_number, uint8_t offset, bool fastRead = false);
uint8_t readByte(uint32_t address, bool fastRead = false);
//----------------------------------------Write / Read Byte Arrays----------------------------------------//
bool writeByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
uint8_t readByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
//-------------------------------------------Write / Read Chars-------------------------------------------//
bool writeChar(uint32_t address, int8_t data, bool errorCheck = true);
bool writeChar(uint16_t page_number, uint8_t offset, int8_t data, bool errorCheck = true);
int8_t readChar(uint32_t address, bool fastRead = false);
int8_t readChar(uint16_t page_number, uint8_t offset, bool fastRead = false);
//----------------------------------------Write / Read Char Arrays----------------------------------------//
bool writeCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readCharArray(uint32_t address, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
uint8_t readCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
//------------------------------------------Write / Read Shorts------------------------------------------//
bool writeShort(uint32_t address, int16_t data, bool errorCheck = true);
bool writeShort(uint16_t page_number, uint8_t offset, int16_t data, bool errorCheck = true);
int16_t readShort(uint32_t address, bool fastRead = false);
int16_t readShort(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Words-------------------------------------------//
bool writeWord(uint32_t address, uint16_t data, bool errorCheck = true);
bool writeWord(uint16_t page_number, uint8_t offset, uint16_t data, bool errorCheck = true);
uint16_t readWord(uint32_t address, bool fastRead = false);
uint16_t readWord(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Longs-------------------------------------------//
bool writeLong(uint32_t address, int32_t data, bool errorCheck = true);
bool writeLong(uint16_t page_number, uint8_t offset, int32_t data, bool errorCheck = true);
int32_t readLong(uint32_t address, bool fastRead = false);
int32_t readLong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//--------------------------------------Write / Read Unsigned Longs---------------------------------------//
bool writeULong(uint32_t address, uint32_t data, bool errorCheck = true);
bool writeULong(uint16_t page_number, uint8_t offset, uint32_t data, bool errorCheck = true);
uint32_t readULong(uint32_t address, bool fastRead = false);
uint32_t readULong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Floats------------------------------------------//
bool writeFloat(uint32_t address, float data, bool errorCheck = true);
bool writeFloat(uint16_t page_number, uint8_t offset, float data, bool errorCheck = true);
float readFloat(uint32_t address, bool fastRead = false);
float readFloat(uint16_t page_number, uint8_t offset, bool fastRead = false);
//------------------------------------------Write / Read Strings------------------------------------------//
bool writeStr(uint32_t address, String &inputStr, bool errorCheck = true);
bool writeStr(uint16_t page_number, uint8_t offset, String &inputStr, bool errorCheck = true);
bool readStr(uint32_t address, String &outStr, bool fastRead = false);
bool readStr(uint16_t page_number, uint8_t offset, String &outStr, bool fastRead = false);
//-------------------------------------------Write / Read Pages-------------------------------------------//
bool writePage(uint16_t page_number, uint8_t *data_buffer, bool errorCheck = true);
bool readPage(uint16_t page_number, uint8_t *data_buffer, bool fastRead = false);
//------------------------------------------Write / Read Anything-----------------------------------------//
template <class T> bool writeAnything(uint32_t address, const T& value, bool errorCheck = true);
template <class T> bool writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck = true);
template <class T> bool readAnything(uint32_t address, T& value, bool fastRead = false);
template <class T> bool readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead = false);
//--------------------------------------------Erase functions---------------------------------------------//
bool eraseSector(uint32_t address);
bool eraseSector(uint16_t page_number, uint8_t offset);
bool eraseBlock32K(uint32_t address);
bool eraseBlock32K(uint16_t page_number, uint8_t offset);
bool eraseBlock64K(uint32_t address);
bool eraseBlock64K(uint16_t page_number, uint8_t offset);
bool eraseChip(void);
//---------------------------------------------Power functions--------------------------------------------//
bool suspendProg(void);
bool resumeProg(void);
bool powerDown(void);
bool powerUp(void);
//--------------------------------------------Private functions-------------------------------------------//
private:
void _troubleshoot(uint8_t error);
void _cmd(uint8_t cmd, bool _continue = true, uint8_t cs = 0);
void _endProcess(void);
void _errorCodeCheck(void);
void _beginRead(uint32_t address);
void _beginFastRead(uint32_t address);
bool _noSuspend(void);
bool _notBusy(uint32_t timeout = 10L);
bool _notPrevWritten(uint32_t address, uint8_t size = 1);
bool _addressCheck(uint32_t address);
bool _beginWrite(uint32_t address);
bool _writeNextByte(uint8_t c, bool _continue = true);
bool _writeEnable(void);
bool _writeDisable(void);
bool _getJedecId(uint8_t *b1, uint8_t *b2, uint8_t *b3);
bool _getManId(uint8_t *b1, uint8_t *b2);
bool _chipID(void);
uint8_t _readStat1(void);
uint8_t _readNextByte(bool _continue = true);
uint32_t _getAddress(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepRead(uint32_t address);
uint32_t _prepRead(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepWrite(uint32_t address);
uint32_t _prepWrite(uint16_t page_number, uint8_t offset = 0);
template <class T> bool _writeErrorCheck(uint32_t address, const T& value);
//-------------------------------------------Private variables------------------------------------------//
bool pageOverflow;
volatile uint8_t *cs_port;
uint8_t cs_mask, csPin, errorcode;
uint16_t name;
uint32_t capacity, maxPage;
uint32_t currentAddress = 1;
const uint8_t devType[10] = {0x5, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
const uint32_t memSize[10] = {64L * 1024L, 128L * 1024L, 256L * 1024L, 512L * 1024L, 1L * 1024L * 1024L,
2L * 1024L * 1024L, 4L * 1024L * 1024L, 8L * 1024L * 1024L, 16L * 1024L * 1024L};
const uint16_t chipName[10] = {05, 10, 20, 40, 80, 16, 32, 64, 128, 256};
};
//--------------------------------------------Templates-------------------------------------------//
// Writes any type of data to a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 4. errorCheck --> Turned on by default. Checks for writing errors
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. const T& value --> Variable with the data to be written
// 4. errorCheck --> Turned on by default. Checks for writing errors
// WARNING: You can only write to previously erased memory locations (see datasheet).
// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs)
// Variant A
template <class T> bool SPIFlash::writeAnything(uint32_t address, const T& value, bool errorCheck) {
if (!_prepWrite(address))
return false;
else {
const byte* p = (const byte*)(const void*)&value;
_beginWrite(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
_writeNextByte(*p++, false);
#endif
_writeNextByte(*p++);
}
_endProcess();
}
if (!errorCheck)
return true;
else
return _writeErrorCheck(address, value);
}
// Variant B
template <class T> bool SPIFlash::writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck) {
uint32_t address = _getAddress(page_number, offset);
return writeAnything(address, value, errorCheck);
}
// Reads any type of data from a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. T& value --> Variable to return data into
// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true
// Variant A
template <class T> bool SPIFlash::readAnything(uint32_t address, T& value, bool fastRead) {
if (!_prepRead(address))
return false;
byte* p = (byte*)(void*)&value;
if(!fastRead)
_beginRead(address);
else
_beginFastRead(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
*p++ = _readNextByte(false);
#endif
*p++ =_readNextByte();
}
_endProcess();
return true;
}
// Variant B
template <class T> bool SPIFlash::readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead)
{
uint32_t address = _getAddress(page_number, offset);
return readAnything(address, value, fastRead);
}
// Private template to check for errors in writing to flash memory
template <class T> bool SPIFlash::_writeErrorCheck(uint32_t address, const T& value) {
if (!_prepRead(address))
return false;
const byte* p = (const byte*)(const void*)&value;
_beginRead(address);
for(uint16_t i = 0; i < sizeof(value);i++)
{
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1) {
if (*p++ != _readNextByte(false))
return false;
else
return true;
}
else
if (*p++ != _readNextByte())
return false;
#elif defined (__AVR__)
if (*p++ != _readNextByte())
return false;
#endif
}
_endProcess();
return true;
}
#endif // _SPIFLASH_H_

View File

@@ -0,0 +1,399 @@
/*
* iceprog -- firmware scetch for Arduino based Lattice iCE programmers
*
* Chris B. <chris@protonic.co.uk> @ Olimex Ltd. <c> 2017
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Relevant Documents:
* -------------------
* http://www.latticesemi.com/~/media/Documents/UserManuals/EI/icestickusermanual.pdf
* http://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_32mb_3v_65nm.pdf
* http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
* https://www.olimex.com/Products/FPGA/iCE40/iCE40HX1K-EVB/
* https://github.com/Marzogh/SPIFlash
*/
#include <SPI.h>
// The demo uses SPIFlash v2.2.0, its files are included in the project folders the author is Prajwal Bhattaram - Marzogh
#include "SPIFlash.h"
#define LED 17
#define CDONE 3
#define RESET 2
#define UEXT_POWER 8
#define CS 13
//commands list
#define READ_ID 0x9F
#define PWR_UP 0xAB
#define PWR_DOWN 0xB9
#define WR_EN 0x06
#define BULK_ERASE 0xC7
#define SEC_ERASE 0xd8
#define PROG 0x02
#define READ 0x03
#define READ_ALL 0x83
#define CMD_ERROR 0xee
#define READY 0x44
#define EMPTY 0x45
#define FEND 0xc0
#define FESC 0xdb
#define TFEND 0xdc
#define TFESC 0xdd
#define cselect digitalWrite(CS,LOW)
#define deselect digitalWrite(CS,HIGH)
//Toggle iceprogduino with serial bridge by pressing the HWB button
#define HWB (PINE & B00000100)==0 // Check if the button has been pressed
#define HWB_INPUT DDRE &= B11111011 // Initialize the port
#define HWB_PULL_UP PORTE |= B00000100 // Initialize the port
boolean isProg;
uint8_t rxframe[512], txframe[512], fcs,rfcs;
uint8_t membuf[256];
uint8_t data_buffer[256];
uint16_t txp;
uint32_t maxPage;
bool escaped;
SPIFlash flash(CS);
void secerase(uint32_t sector);
void decodeFrame(void);
void writepage(int pagenr);
bool readSerialFrame(void);
void flash_bulk_erase(void);
void SendID(void);
void sendframe();
void startframe(uint8_t command);
void addbyte(uint8_t newbyte);
void readAllPages(void);
void readpage(uint16_t adr);
// FRAME: <FEND><CMD>{data if any}<FCS(sume of all bytes = 0xFF)><FEND>
// if FEND, FESC in data - <FEND>=<FESC><TFEND>; <FESC>=<FESC><TFESC>
void setup() {
// put your setup code here, to run once:
// Power Up UEXT
pinMode(CDONE,INPUT);
pinMode(RESET,OUTPUT);
pinMode(LED,OUTPUT);
digitalWrite(LED,0);
pinMode(CS,OUTPUT);
digitalWrite(CS,HIGH);
pinMode(UEXT_POWER, OUTPUT);
digitalWrite(UEXT_POWER, HIGH);
delay(1000);
digitalWrite(UEXT_POWER, LOW);
delay(500);
digitalWrite(RESET, HIGH);
Serial.begin(230400);
while (!Serial);
isProg=true;
HWB_INPUT; // Initialize HWB
HWB_PULL_UP;
Serial1.begin(115200);
digitalWrite(LED,!isProg); //Yellow LED is Prog
}
void loop(){
if (isProg) loopProg();
else loopBridge();
if (HWB) {
isProg = !isProg;
digitalWrite(LED,!isProg);
delay(1000);
}
}
void loopBridge(){
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte);
}
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte);
}
}
void loopProg() {
if (readSerialFrame())
{
decodeFrame();
if (rfcs==0xff)
{
digitalWrite(RESET, LOW);
switch (rxframe[0]){
case FEND:
break;
case READ_ID:
SendID();
break;
case BULK_ERASE:
flash_bulk_erase();
break;
case SEC_ERASE:
flash.powerUp();
secerase((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ:
flash.powerUp();
readpage((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ_ALL:
readAllPages();
break;
case PROG:
writepage((rxframe[1]<<8) | rxframe[2]);
break;
default:
break;
}//switch
digitalWrite(RESET, HIGH);
}
}
}
void secerase(uint32_t sector){
flash.eraseBlock64K(sector<<8);
startframe(READY);
sendframe();
}
void decodeFrame(void){
int x,y;
escaped = false;
y = 1;
rfcs = rxframe[1];
rxframe[0]=rxframe[1];
for (x=2;x<512;x++)
{
switch (rxframe[x]){
case FEND:
x = 513;
break;
case FESC:
escaped = true;
break;
case TFEND:
if (escaped)
{
rxframe[y++] = FEND;
rfcs+=FEND;
escaped = false;
}
else
{
rxframe[y++]=TFEND;
rfcs+=TFEND;
}
break;
case TFESC:
if (escaped)
{
rxframe[y++]=FESC;
rfcs+=FESC;
escaped = false;
}
else
{
rxframe[y++]=TFESC;
rfcs+=TFESC;
}
break;
default:
escaped = false;
rxframe[y++] = rxframe[x];
rfcs+=rxframe[x];
break;
}
}
}
void writepage(int pagenr){
int x;
flash.powerUp();
for (x=0; x<256;x++)
membuf[x]=rxframe[x+3];
flash.writePage(pagenr,membuf);
flash.readPage(pagenr,data_buffer);
flash.powerDown();
for (int a = 0; a < 256; a++)
if (data_buffer[a] != membuf[a])
return;
startframe(READY);
sendframe();
}
//Reads a frame from Serial
bool readSerialFrame(void)
{
Serial.setTimeout(50);
if (!Serial)
Serial.begin(230400);
// Serial.begin(1000000);
while (Serial.available()) {
Serial.readBytesUntil(FEND,rxframe,512);
//if (rxframe[0]!=FEND)
return true;
}
return false;
}
void flash_bulk_erase(void)
{
flash.powerUp();
flash.eraseChip();
flash.powerDown();
startframe(READY);
addbyte(BULK_ERASE);
sendframe();
}
void SendID(void)
{
flash.powerUp();
uint32_t JEDEC = flash.getJEDECID();
flash.powerDown();
startframe(READ_ID);
addbyte(JEDEC >> 16);
addbyte(JEDEC >> 8);
addbyte(JEDEC >> 0);
sendframe();
}
void sendframe(){
fcs = 0xff - fcs;
addbyte(fcs);
txframe[txp++] = FEND;
Serial.write(txframe,txp);
}
void startframe(uint8_t command){
txframe[0]=FEND;
txframe[1]=command;
txp = 2;
fcs = command;
}
void addbyte(uint8_t newbyte)
{
fcs+=newbyte;
if (newbyte == FEND)
{
txframe[txp++] = FESC;
txframe[txp++] = TFEND;
} else
if (newbyte == FESC)
{
txframe[txp++] = FESC;
txframe[txp++] = TFESC;
} else
txframe[txp++] = newbyte;
}
void readAllPages(void){
flash.powerUp();
maxPage=0x2000;
delay(10);
int p;
for (p=0;p<maxPage;p++)
readpage(p);
startframe(READY);
sendframe();
//
flash.powerDown();
}
void readpage(uint16_t adr){
bool sendempty = true;
//delay(5);
flash.readPage(adr,data_buffer);
for (int a = 0; a < 256; a++){
if (data_buffer[a] != 0xff){
startframe(READ);
addbyte(adr >> 8);
addbyte(adr >> 0);
for (int b = 0;b<256;b++)
addbyte(data_buffer[b]);
sendframe();
sendempty=false;
break;
}
}
if (sendempty){
startframe(EMPTY);
addbyte(adr >> 8);
addbyte(adr >> 0);
sendframe();
}
}

View File

@@ -0,0 +1,406 @@
/*
* iceprog -- firmware scetch for Arduino based Lattice iCE programmers
*
* Chris B. <chris@protonic.co.uk> @ Olimex Ltd. <c> 2017
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Relevant Documents:
* -------------------
* http://www.latticesemi.com/~/media/Documents/UserManuals/EI/icestickusermanual.pdf
* http://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_32mb_3v_65nm.pdf
* http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
* https://www.olimex.com/Products/FPGA/iCE40/iCE40HX1K-EVB/
* https://github.com/Marzogh/SPIFlash
*/
#include <SPI.h>
// The demo uses SPIFlash v2.2.0, its files are included in the project folders the author is Prajwal Bhattaram - Marzogh
#include "SPIFlash.h"
#define LED 17
#define CDONE 3
#define RESET 2
#define UEXT_POWER 8
#define CS 13
//commands list
#define READ_ID 0x9F
#define PWR_UP 0xAB
#define PWR_DOWN 0xB9
#define WR_EN 0x06
#define BULK_ERASE 0xC7
#define SEC_ERASE 0xd8
#define PROG 0x02
#define READ 0x03
#define READ_ALL 0x83
#define CMD_ERROR 0xee
#define READY 0x44
#define EMPTY 0x45
#define FEND 0xc0
#define FESC 0xdb
#define TFEND 0xdc
#define TFESC 0xdd
#define cselect digitalWrite(CS,LOW)
#define deselect digitalWrite(CS,HIGH)
//Toggle iceprogduino with serial bridge by pressing the HWB button
#define HWB (PINE & B00000100)==0 // Check if the button has been pressed
#define HWB_INPUT DDRE &= B11111011 // Initialize the port
#define LED_G 7 // The GREEN LED is on Pin 7
#define LED_Y 9 // The YELLOW LED is on Pin 9
boolean isProg;
uint8_t rxframe[512], txframe[512], fcs,rfcs;
uint8_t membuf[256];
uint8_t data_buffer[256];
uint16_t txp;
uint32_t maxPage;
bool escaped;
SPIFlash flash(CS);
void secerase(uint32_t sector);
void decodeFrame(void);
void writepage(int pagenr);
bool readSerialFrame(void);
void flash_bulk_erase(void);
void SendID(void);
void sendframe();
void startframe(uint8_t command);
void addbyte(uint8_t newbyte);
void readAllPages(void);
void readpage(uint16_t adr);
void loopProg(void);
void loopBridge(void);
// FRAME: <FEND><CMD>{data if any}<FCS(sume of all bytes = 0xFF)><FEND>
// if FEND, FESC in data - <FEND>=<FESC><TFEND>; <FESC>=<FESC><TFESC>
void setup() {
// put your setup code here, to run once:
// Power Up UEXT
pinMode(CDONE,INPUT);
pinMode(RESET,OUTPUT);
pinMode(LED,OUTPUT);
digitalWrite(LED,0);
pinMode(CS,OUTPUT);
digitalWrite(CS,HIGH);
pinMode(UEXT_POWER, OUTPUT);
digitalWrite(UEXT_POWER, HIGH);
delay(1000);
digitalWrite(UEXT_POWER, LOW);
delay(500);
digitalWrite(RESET, HIGH);
Serial.begin(230400);
while (!Serial);
isProg=true;
HWB_INPUT; // Initialize HWB
Serial1.begin(115200);
pinMode(LED_Y,OUTPUT);
digitalWrite(LED_Y,isProg); //Yellow LED is Prog
pinMode(LED_G,OUTPUT);
digitalWrite(LED_G,!isProg); //Green LED is Bridge
}
void loop(){
if (isProg) loopProg();
else loopBridge();
if (HWB) {
isProg = !isProg;
digitalWrite(LED_Y,isProg);
digitalWrite(LED_G,!isProg);
delay(1000);
}
}
void loopBridge(){
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte);
}
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte);
}
}
void loopProg() {
if (readSerialFrame())
{
decodeFrame();
if (rfcs==0xff)
{
digitalWrite(RESET, LOW);
switch (rxframe[0]){
case FEND:
break;
case READ_ID:
SendID();
break;
case BULK_ERASE:
flash_bulk_erase();
break;
case SEC_ERASE:
flash.powerUp();
secerase((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ:
flash.powerUp();
readpage((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ_ALL:
readAllPages();
break;
case PROG:
writepage((rxframe[1]<<8) | rxframe[2]);
break;
default:
break;
}//switch
digitalWrite(RESET, HIGH);
}
}
}
void secerase(uint32_t sector){
flash.eraseBlock64K(sector<<8);
startframe(READY);
sendframe();
}
void decodeFrame(void){
int x,y;
escaped = false;
y = 1;
rfcs = rxframe[1];
rxframe[0]=rxframe[1];
for (x=2;x<512;x++)
{
switch (rxframe[x]){
case FEND:
x = 513;
break;
case FESC:
escaped = true;
break;
case TFEND:
if (escaped)
{
rxframe[y++] = FEND;
rfcs+=FEND;
escaped = false;
}
else
{
rxframe[y++]=TFEND;
rfcs+=TFEND;
}
break;
case TFESC:
if (escaped)
{
rxframe[y++]=FESC;
rfcs+=FESC;
escaped = false;
}
else
{
rxframe[y++]=TFESC;
rfcs+=TFESC;
}
break;
default:
escaped = false;
rxframe[y++] = rxframe[x];
rfcs+=rxframe[x];
break;
}
}
}
void writepage(int pagenr){
int x;
flash.powerUp();
for (x=0; x<256;x++)
membuf[x]=rxframe[x+3];
flash.writePage(pagenr,membuf);
flash.readPage(pagenr,data_buffer);
flash.powerDown();
for (int a = 0; a < 256; a++)
if (data_buffer[a] != membuf[a])
return;
startframe(READY);
sendframe();
}
//Reads a frame from Serial
bool readSerialFrame(void)
{
Serial.setTimeout(50);
if (!Serial)
Serial.begin(230400);
// Serial.begin(1000000);
while (Serial.available()) {
Serial.readBytesUntil(FEND,rxframe,512);
//if (rxframe[0]!=FEND)
return true;
}
return false;
}
void flash_bulk_erase(void)
{
flash.powerUp();
flash.eraseChip();
flash.powerDown();
startframe(READY);
addbyte(BULK_ERASE);
sendframe();
}
void SendID(void)
{
flash.powerUp();
uint32_t JEDEC = flash.getJEDECID();
flash.powerDown();
startframe(READ_ID);
addbyte(JEDEC >> 16);
addbyte(JEDEC >> 8);
addbyte(JEDEC >> 0);
sendframe();
}
void sendframe(){
fcs = 0xff - fcs;
addbyte(fcs);
txframe[txp++] = FEND;
Serial.write(txframe,txp);
}
void startframe(uint8_t command){
txframe[0]=FEND;
txframe[1]=command;
txp = 2;
fcs = command;
}
void addbyte(uint8_t newbyte)
{
fcs+=newbyte;
if (newbyte == FEND)
{
txframe[txp++] = FESC;
txframe[txp++] = TFEND;
} else
if (newbyte == FESC)
{
txframe[txp++] = FESC;
txframe[txp++] = TFESC;
} else
txframe[txp++] = newbyte;
}
void readAllPages(void){
flash.powerUp();
maxPage=0x2000;
delay(10);
int p;
for (p=0;p<maxPage;p++)
readpage(p);
startframe(READY);
sendframe();
//
flash.powerDown();
}
void readpage(uint16_t adr){
bool sendempty = true;
//delay(5);
flash.readPage(adr,data_buffer);
for (int a = 0; a < 256; a++){
if (data_buffer[a] != 0xff){
startframe(READ);
addbyte(adr >> 8);
addbyte(adr >> 0);
for (int b = 0;b<256;b++)
addbyte(data_buffer[b]);
sendframe();
sendempty=false;
break;
}
}
if (sendempty){
startframe(EMPTY);
addbyte(adr >> 8);
addbyte(adr >> 0);
sendframe();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,267 @@
/* Arduino SPIFlash Library v.2.2.0
* Copyright (C) 2015 by Prajwal Bhattaram
* Modified by Prajwal Bhattaram - 24/11/2015
*
* This file is part of the Arduino SPIFlash Library. This library is for
* Winbond NOR flash memory modules. In its current form it enables reading
* and writing individual data variables, structs and arrays from and to various locations;
* reading and writing pages; continuous read functions; sector, block and chip erase;
* suspending and resuming programming/erase and powering down for low power operation.
*
* This Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License v3.0
* along with the Arduino SPIFlash Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef SPIFLASH_H
#define SPIFLASH_H
#include <Arduino.h>
class SPIFlash {
public:
//----------------------------------------------Constructor-----------------------------------------------//
SPIFlash(uint8_t cs = 10, bool overflow = true);
//----------------------------------------Initial / Chip Functions----------------------------------------//
void begin();
uint16_t getManID();
uint32_t getJEDECID();
bool getAddress(uint16_t size, uint16_t &page_number, uint8_t &offset);
uint32_t getAddress(uint16_t size);
uint16_t getChipName();
uint16_t sizeofStr(String &inputStr);
uint32_t getCapacity();
uint32_t getMaxPage();
//-------------------------------------------Write / Read Bytes-------------------------------------------//
bool writeByte(uint32_t address, uint8_t data, bool errorCheck = true);
bool writeByte(uint16_t page_number, uint8_t offset, uint8_t data, bool errorCheck = true);
uint8_t readByte(uint16_t page_number, uint8_t offset, bool fastRead = false);
uint8_t readByte(uint32_t address, bool fastRead = false);
//----------------------------------------Write / Read Byte Arrays----------------------------------------//
bool writeByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
uint8_t readByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
//-------------------------------------------Write / Read Chars-------------------------------------------//
bool writeChar(uint32_t address, int8_t data, bool errorCheck = true);
bool writeChar(uint16_t page_number, uint8_t offset, int8_t data, bool errorCheck = true);
int8_t readChar(uint32_t address, bool fastRead = false);
int8_t readChar(uint16_t page_number, uint8_t offset, bool fastRead = false);
//----------------------------------------Write / Read Char Arrays----------------------------------------//
bool writeCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readCharArray(uint32_t address, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
uint8_t readCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
//------------------------------------------Write / Read Shorts------------------------------------------//
bool writeShort(uint32_t address, int16_t data, bool errorCheck = true);
bool writeShort(uint16_t page_number, uint8_t offset, int16_t data, bool errorCheck = true);
int16_t readShort(uint32_t address, bool fastRead = false);
int16_t readShort(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Words-------------------------------------------//
bool writeWord(uint32_t address, uint16_t data, bool errorCheck = true);
bool writeWord(uint16_t page_number, uint8_t offset, uint16_t data, bool errorCheck = true);
uint16_t readWord(uint32_t address, bool fastRead = false);
uint16_t readWord(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Longs-------------------------------------------//
bool writeLong(uint32_t address, int32_t data, bool errorCheck = true);
bool writeLong(uint16_t page_number, uint8_t offset, int32_t data, bool errorCheck = true);
int32_t readLong(uint32_t address, bool fastRead = false);
int32_t readLong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//--------------------------------------Write / Read Unsigned Longs---------------------------------------//
bool writeULong(uint32_t address, uint32_t data, bool errorCheck = true);
bool writeULong(uint16_t page_number, uint8_t offset, uint32_t data, bool errorCheck = true);
uint32_t readULong(uint32_t address, bool fastRead = false);
uint32_t readULong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Floats------------------------------------------//
bool writeFloat(uint32_t address, float data, bool errorCheck = true);
bool writeFloat(uint16_t page_number, uint8_t offset, float data, bool errorCheck = true);
float readFloat(uint32_t address, bool fastRead = false);
float readFloat(uint16_t page_number, uint8_t offset, bool fastRead = false);
//------------------------------------------Write / Read Strings------------------------------------------//
bool writeStr(uint32_t address, String &inputStr, bool errorCheck = true);
bool writeStr(uint16_t page_number, uint8_t offset, String &inputStr, bool errorCheck = true);
bool readStr(uint32_t address, String &outStr, bool fastRead = false);
bool readStr(uint16_t page_number, uint8_t offset, String &outStr, bool fastRead = false);
//-------------------------------------------Write / Read Pages-------------------------------------------//
bool writePage(uint16_t page_number, uint8_t *data_buffer, bool errorCheck = true);
bool readPage(uint16_t page_number, uint8_t *data_buffer, bool fastRead = false);
//------------------------------------------Write / Read Anything-----------------------------------------//
template <class T> bool writeAnything(uint32_t address, const T& value, bool errorCheck = true);
template <class T> bool writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck = true);
template <class T> bool readAnything(uint32_t address, T& value, bool fastRead = false);
template <class T> bool readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead = false);
//--------------------------------------------Erase functions---------------------------------------------//
bool eraseSector(uint32_t address);
bool eraseSector(uint16_t page_number, uint8_t offset);
bool eraseBlock32K(uint32_t address);
bool eraseBlock32K(uint16_t page_number, uint8_t offset);
bool eraseBlock64K(uint32_t address);
bool eraseBlock64K(uint16_t page_number, uint8_t offset);
bool eraseChip(void);
//---------------------------------------------Power functions--------------------------------------------//
bool suspendProg(void);
bool resumeProg(void);
bool powerDown(void);
bool powerUp(void);
//--------------------------------------------Private functions-------------------------------------------//
private:
void _troubleshoot(uint8_t error);
void _cmd(uint8_t cmd, bool _continue = true, uint8_t cs = 0);
void _endProcess(void);
void _errorCodeCheck(void);
void _beginRead(uint32_t address);
void _beginFastRead(uint32_t address);
bool _noSuspend(void);
bool _notBusy(uint32_t timeout = 10L);
bool _notPrevWritten(uint32_t address, uint8_t size = 1);
bool _addressCheck(uint32_t address);
bool _beginWrite(uint32_t address);
bool _writeNextByte(uint8_t c, bool _continue = true);
bool _writeEnable(void);
bool _writeDisable(void);
bool _getJedecId(uint8_t *b1, uint8_t *b2, uint8_t *b3);
bool _getManId(uint8_t *b1, uint8_t *b2);
bool _chipID(void);
uint8_t _readStat1(void);
uint8_t _readNextByte(bool _continue = true);
uint32_t _getAddress(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepRead(uint32_t address);
uint32_t _prepRead(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepWrite(uint32_t address);
uint32_t _prepWrite(uint16_t page_number, uint8_t offset = 0);
template <class T> bool _writeErrorCheck(uint32_t address, const T& value);
//-------------------------------------------Private variables------------------------------------------//
bool pageOverflow;
volatile uint8_t *cs_port;
uint8_t cs_mask, csPin, errorcode;
uint16_t name;
uint32_t capacity, maxPage;
uint32_t currentAddress = 1;
const uint8_t devType[10] = {0x5, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
const uint32_t memSize[10] = {64L * 1024L, 128L * 1024L, 256L * 1024L, 512L * 1024L, 1L * 1024L * 1024L,
2L * 1024L * 1024L, 4L * 1024L * 1024L, 8L * 1024L * 1024L, 16L * 1024L * 1024L};
const uint16_t chipName[10] = {05, 10, 20, 40, 80, 16, 32, 64, 128, 256};
};
//--------------------------------------------Templates-------------------------------------------//
// Writes any type of data to a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 4. errorCheck --> Turned on by default. Checks for writing errors
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. const T& value --> Variable with the data to be written
// 4. errorCheck --> Turned on by default. Checks for writing errors
// WARNING: You can only write to previously erased memory locations (see datasheet).
// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs)
// Variant A
template <class T> bool SPIFlash::writeAnything(uint32_t address, const T& value, bool errorCheck) {
if (!_prepWrite(address))
return false;
else {
const byte* p = (const byte*)(const void*)&value;
_beginWrite(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
_writeNextByte(*p++, false);
#endif
_writeNextByte(*p++);
}
_endProcess();
}
if (!errorCheck)
return true;
else
return _writeErrorCheck(address, value);
}
// Variant B
template <class T> bool SPIFlash::writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck) {
uint32_t address = _getAddress(page_number, offset);
return writeAnything(address, value, errorCheck);
}
// Reads any type of data from a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. T& value --> Variable to return data into
// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true
// Variant A
template <class T> bool SPIFlash::readAnything(uint32_t address, T& value, bool fastRead) {
if (!_prepRead(address))
return false;
byte* p = (byte*)(void*)&value;
if(!fastRead)
_beginRead(address);
else
_beginFastRead(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
*p++ = _readNextByte(false);
#endif
*p++ =_readNextByte();
}
_endProcess();
return true;
}
// Variant B
template <class T> bool SPIFlash::readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead)
{
uint32_t address = _getAddress(page_number, offset);
return readAnything(address, value, fastRead);
}
// Private template to check for errors in writing to flash memory
template <class T> bool SPIFlash::_writeErrorCheck(uint32_t address, const T& value) {
if (!_prepRead(address))
return false;
const byte* p = (const byte*)(const void*)&value;
_beginRead(address);
for(uint16_t i = 0; i < sizeof(value);i++)
{
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1) {
if (*p++ != _readNextByte(false))
return false;
else
return true;
}
else
if (*p++ != _readNextByte())
return false;
#elif defined (__AVR__)
if (*p++ != _readNextByte())
return false;
#endif
}
_endProcess();
return true;
}
#endif // _SPIFLASH_H_

View File

@@ -0,0 +1,403 @@
/*
* iceprog -- firmware scetch for Arduino based Lattice iCE programmers
*
* Chris B. <chris@protonic.co.uk> @ Olimex Ltd. <c> 2017
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Relevant Documents:
* -------------------
* http://www.latticesemi.com/~/media/Documents/UserManuals/EI/icestickusermanual.pdf
* http://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_32mb_3v_65nm.pdf
* http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
* https://www.olimex.com/Products/FPGA/iCE40/iCE40HX1K-EVB/
* https://github.com/Marzogh/SPIFlash
*/
#include <SPI.h>
// The demo uses SPIFlash v2.2.0, its files are included in the project folders the author is Prajwal Bhattaram - Marzogh
#include "SPIFlash.h"
#define LED 17
#define CDONE 3
#define RESET 2
#define UEXT_POWER 8
#define CS 13
//commands list
#define READ_ID 0x9F
#define PWR_UP 0xAB
#define PWR_DOWN 0xB9
#define WR_EN 0x06
#define BULK_ERASE 0xC7
#define SEC_ERASE 0xd8
#define PROG 0x02
#define READ 0x03
#define READ_ALL 0x83
#define CMD_ERROR 0xee
#define READY 0x44
#define EMPTY 0x45
#define FEND 0xc0
#define FESC 0xdb
#define TFEND 0xdc
#define TFESC 0xdd
#define cselect digitalWrite(CS,LOW)
#define deselect digitalWrite(CS,HIGH)
//Toggle iceprogduino with serial bridge by pressing the HWB button
#define HWB (PINE & B00000100)==0 // Check if the button has been pressed
#define HWB_INPUT DDRE &= B11111011 // Initialize the port
#define LED_G 7 // The GREEN LED is on Pin 7
#define LED_Y 9 // The YELLOW LED is on Pin 9
boolean isProg;
uint8_t rxframe[512], txframe[512], fcs,rfcs;
uint8_t membuf[256];
uint8_t data_buffer[256];
uint16_t txp;
uint32_t maxPage;
bool escaped;
SPIFlash flash(CS);
void secerase(uint32_t sector);
void decodeFrame(void);
void writepage(int pagenr);
bool readSerialFrame(void);
void flash_bulk_erase(void);
void SendID(void);
void sendframe();
void startframe(uint8_t command);
void addbyte(uint8_t newbyte);
void readAllPages(void);
void readpage(uint16_t adr);
// FRAME: <FEND><CMD>{data if any}<FCS(sume of all bytes = 0xFF)><FEND>
// if FEND, FESC in data - <FEND>=<FESC><TFEND>; <FESC>=<FESC><TFESC>
void setup() {
// put your setup code here, to run once:
// Power Up UEXT
pinMode(CDONE,INPUT);
pinMode(RESET,OUTPUT);
pinMode(LED,OUTPUT);
digitalWrite(LED,0);
pinMode(CS,OUTPUT);
digitalWrite(CS,HIGH);
pinMode(UEXT_POWER, OUTPUT);
digitalWrite(UEXT_POWER, HIGH);
delay(1000);
digitalWrite(UEXT_POWER, LOW);
delay(500);
digitalWrite(RESET, HIGH);
Serial.begin(230400);
while (!Serial);
isProg=true;
HWB_INPUT; // Initialize HWB
Serial1.begin(115200);
pinMode(LED_Y,OUTPUT);
digitalWrite(LED_Y,isProg); //Yellow LED is Prog
pinMode(LED_G,OUTPUT);
digitalWrite(LED_G,!isProg); //Green LED is Bridge
}
void loop(){
if (isProg) loopProg();
else loopBridge();
if (HWB) {
isProg = !isProg;
digitalWrite(LED_Y,isProg);
digitalWrite(LED_G,!isProg);
delay(1000);
}
}
void loopBridge(){
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte);
}
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte);
}
}
void loopProg() {
if (readSerialFrame())
{
decodeFrame();
if (rfcs==0xff)
{
digitalWrite(RESET, LOW);
switch (rxframe[0]){
case FEND:
break;
case READ_ID:
SendID();
break;
case BULK_ERASE:
flash_bulk_erase();
break;
case SEC_ERASE:
flash.powerUp();
secerase((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ:
flash.powerUp();
readpage((rxframe[1]<<8) | rxframe[2]);
flash.powerDown();
break;
case READ_ALL:
readAllPages();
break;
case PROG:
writepage((rxframe[1]<<8) | rxframe[2]);
break;
default:
break;
}//switch
digitalWrite(RESET, HIGH);
}
}
}
void secerase(uint32_t sector){
flash.eraseBlock64K(sector<<8);
startframe(READY);
sendframe();
}
void decodeFrame(void){
int x,y;
escaped = false;
y = 1;
rfcs = rxframe[1];
rxframe[0]=rxframe[1];
for (x=2;x<512;x++)
{
switch (rxframe[x]){
case FEND:
x = 513;
break;
case FESC:
escaped = true;
break;
case TFEND:
if (escaped)
{
rxframe[y++] = FEND;
rfcs+=FEND;
escaped = false;
}
else
{
rxframe[y++]=TFEND;
rfcs+=TFEND;
}
break;
case TFESC:
if (escaped)
{
rxframe[y++]=FESC;
rfcs+=FESC;
escaped = false;
}
else
{
rxframe[y++]=TFESC;
rfcs+=TFESC;
}
break;
default:
escaped = false;
rxframe[y++] = rxframe[x];
rfcs+=rxframe[x];
break;
}
}
}
void writepage(int pagenr){
int x;
flash.powerUp();
for (x=0; x<256;x++)
membuf[x]=rxframe[x+3];
flash.writePage(pagenr,membuf);
flash.readPage(pagenr,data_buffer);
flash.powerDown();
for (int a = 0; a < 256; a++)
if (data_buffer[a] != membuf[a])
return;
startframe(READY);
sendframe();
}
//Reads a frame from Serial
bool readSerialFrame(void)
{
Serial.setTimeout(50);
if (!Serial)
Serial.begin(230400);
// Serial.begin(1000000);
while (Serial.available()) {
Serial.readBytesUntil(FEND,rxframe,512);
//if (rxframe[0]!=FEND)
return true;
}
return false;
}
void flash_bulk_erase(void)
{
flash.powerUp();
flash.eraseChip();
flash.powerDown();
startframe(READY);
addbyte(BULK_ERASE);
sendframe();
}
void SendID(void)
{
flash.powerUp();
uint32_t JEDEC = flash.getJEDECID();
flash.powerDown();
startframe(READ_ID);
addbyte(JEDEC >> 16);
addbyte(JEDEC >> 8);
addbyte(JEDEC >> 0);
sendframe();
}
void sendframe(){
fcs = 0xff - fcs;
addbyte(fcs);
txframe[txp++] = FEND;
Serial.write(txframe,txp);
}
void startframe(uint8_t command){
txframe[0]=FEND;
txframe[1]=command;
txp = 2;
fcs = command;
}
void addbyte(uint8_t newbyte)
{
fcs+=newbyte;
if (newbyte == FEND)
{
txframe[txp++] = FESC;
txframe[txp++] = TFEND;
} else
if (newbyte == FESC)
{
txframe[txp++] = FESC;
txframe[txp++] = TFESC;
} else
txframe[txp++] = newbyte;
}
void readAllPages(void){
flash.powerUp();
maxPage=0x2000;
delay(10);
int p;
for (p=0;p<maxPage;p++)
readpage(p);
startframe(READY);
sendframe();
//
flash.powerDown();
}
void readpage(uint16_t adr){
bool sendempty = true;
//delay(5);
flash.readPage(adr,data_buffer);
for (int a = 0; a < 256; a++){
if (data_buffer[a] != 0xff){
startframe(READ);
addbyte(adr >> 8);
addbyte(adr >> 0);
for (int b = 0;b<256;b++)
addbyte(data_buffer[b]);
sendframe();
sendempty=false;
break;
}
}
if (sendempty){
startframe(EMPTY);
addbyte(adr >> 8);
addbyte(adr >> 0);
sendframe();
}
}

View File

@@ -0,0 +1,14 @@
; PlatformIO Project Configuration File
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html
[platformio]
env_default = leonardo
[env:leonardo]
platform = atmelavr
framework = arduino
board = leonardo
board_build.mcu = atmega32u4
board_build.f_cpu = 16000000L

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,267 @@
/* Arduino SPIFlash Library v.2.2.0
* Copyright (C) 2015 by Prajwal Bhattaram
* Modified by Prajwal Bhattaram - 24/11/2015
*
* This file is part of the Arduino SPIFlash Library. This library is for
* Winbond NOR flash memory modules. In its current form it enables reading
* and writing individual data variables, structs and arrays from and to various locations;
* reading and writing pages; continuous read functions; sector, block and chip erase;
* suspending and resuming programming/erase and powering down for low power operation.
*
* This Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License v3.0
* along with the Arduino SPIFlash Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef SPIFLASH_H
#define SPIFLASH_H
#include <Arduino.h>
class SPIFlash {
public:
//----------------------------------------------Constructor-----------------------------------------------//
SPIFlash(uint8_t cs = 10, bool overflow = true);
//----------------------------------------Initial / Chip Functions----------------------------------------//
void begin();
uint16_t getManID();
uint32_t getJEDECID();
bool getAddress(uint16_t size, uint16_t &page_number, uint8_t &offset);
uint32_t getAddress(uint16_t size);
uint16_t getChipName();
uint16_t sizeofStr(String &inputStr);
uint32_t getCapacity();
uint32_t getMaxPage();
//-------------------------------------------Write / Read Bytes-------------------------------------------//
bool writeByte(uint32_t address, uint8_t data, bool errorCheck = true);
bool writeByte(uint16_t page_number, uint8_t offset, uint8_t data, bool errorCheck = true);
uint8_t readByte(uint16_t page_number, uint8_t offset, bool fastRead = false);
uint8_t readByte(uint32_t address, bool fastRead = false);
//----------------------------------------Write / Read Byte Arrays----------------------------------------//
bool writeByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readByteArray(uint32_t address, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
uint8_t readByteArray(uint16_t page_number, uint8_t offset, uint8_t *data_buffer, uint16_t bufferSize, bool fastRead = false);
//-------------------------------------------Write / Read Chars-------------------------------------------//
bool writeChar(uint32_t address, int8_t data, bool errorCheck = true);
bool writeChar(uint16_t page_number, uint8_t offset, int8_t data, bool errorCheck = true);
int8_t readChar(uint32_t address, bool fastRead = false);
int8_t readChar(uint16_t page_number, uint8_t offset, bool fastRead = false);
//----------------------------------------Write / Read Char Arrays----------------------------------------//
bool writeCharArray(uint32_t address, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
bool writeCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t bufferSize, bool errorCheck = true);
uint8_t readCharArray(uint32_t address, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
uint8_t readCharArray(uint16_t page_number, uint8_t offset, char *data_buffer, uint16_t buffer_size, bool fastRead = false);
//------------------------------------------Write / Read Shorts------------------------------------------//
bool writeShort(uint32_t address, int16_t data, bool errorCheck = true);
bool writeShort(uint16_t page_number, uint8_t offset, int16_t data, bool errorCheck = true);
int16_t readShort(uint32_t address, bool fastRead = false);
int16_t readShort(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Words-------------------------------------------//
bool writeWord(uint32_t address, uint16_t data, bool errorCheck = true);
bool writeWord(uint16_t page_number, uint8_t offset, uint16_t data, bool errorCheck = true);
uint16_t readWord(uint32_t address, bool fastRead = false);
uint16_t readWord(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Longs-------------------------------------------//
bool writeLong(uint32_t address, int32_t data, bool errorCheck = true);
bool writeLong(uint16_t page_number, uint8_t offset, int32_t data, bool errorCheck = true);
int32_t readLong(uint32_t address, bool fastRead = false);
int32_t readLong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//--------------------------------------Write / Read Unsigned Longs---------------------------------------//
bool writeULong(uint32_t address, uint32_t data, bool errorCheck = true);
bool writeULong(uint16_t page_number, uint8_t offset, uint32_t data, bool errorCheck = true);
uint32_t readULong(uint32_t address, bool fastRead = false);
uint32_t readULong(uint16_t page_number, uint8_t offset, bool fastRead = false);
//-------------------------------------------Write / Read Floats------------------------------------------//
bool writeFloat(uint32_t address, float data, bool errorCheck = true);
bool writeFloat(uint16_t page_number, uint8_t offset, float data, bool errorCheck = true);
float readFloat(uint32_t address, bool fastRead = false);
float readFloat(uint16_t page_number, uint8_t offset, bool fastRead = false);
//------------------------------------------Write / Read Strings------------------------------------------//
bool writeStr(uint32_t address, String &inputStr, bool errorCheck = true);
bool writeStr(uint16_t page_number, uint8_t offset, String &inputStr, bool errorCheck = true);
bool readStr(uint32_t address, String &outStr, bool fastRead = false);
bool readStr(uint16_t page_number, uint8_t offset, String &outStr, bool fastRead = false);
//-------------------------------------------Write / Read Pages-------------------------------------------//
bool writePage(uint16_t page_number, uint8_t *data_buffer, bool errorCheck = true);
bool readPage(uint16_t page_number, uint8_t *data_buffer, bool fastRead = false);
//------------------------------------------Write / Read Anything-----------------------------------------//
template <class T> bool writeAnything(uint32_t address, const T& value, bool errorCheck = true);
template <class T> bool writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck = true);
template <class T> bool readAnything(uint32_t address, T& value, bool fastRead = false);
template <class T> bool readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead = false);
//--------------------------------------------Erase functions---------------------------------------------//
bool eraseSector(uint32_t address);
bool eraseSector(uint16_t page_number, uint8_t offset);
bool eraseBlock32K(uint32_t address);
bool eraseBlock32K(uint16_t page_number, uint8_t offset);
bool eraseBlock64K(uint32_t address);
bool eraseBlock64K(uint16_t page_number, uint8_t offset);
bool eraseChip(void);
//---------------------------------------------Power functions--------------------------------------------//
bool suspendProg(void);
bool resumeProg(void);
bool powerDown(void);
bool powerUp(void);
//--------------------------------------------Private functions-------------------------------------------//
private:
void _troubleshoot(uint8_t error);
void _cmd(uint8_t cmd, bool _continue = true, uint8_t cs = 0);
void _endProcess(void);
void _errorCodeCheck(void);
void _beginRead(uint32_t address);
void _beginFastRead(uint32_t address);
bool _noSuspend(void);
bool _notBusy(uint32_t timeout = 10L);
bool _notPrevWritten(uint32_t address, uint8_t size = 1);
bool _addressCheck(uint32_t address);
bool _beginWrite(uint32_t address);
bool _writeNextByte(uint8_t c, bool _continue = true);
bool _writeEnable(void);
bool _writeDisable(void);
bool _getJedecId(uint8_t *b1, uint8_t *b2, uint8_t *b3);
bool _getManId(uint8_t *b1, uint8_t *b2);
bool _chipID(void);
uint8_t _readStat1(void);
uint8_t _readNextByte(bool _continue = true);
uint32_t _getAddress(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepRead(uint32_t address);
uint32_t _prepRead(uint16_t page_number, uint8_t offset = 0);
uint32_t _prepWrite(uint32_t address);
uint32_t _prepWrite(uint16_t page_number, uint8_t offset = 0);
template <class T> bool _writeErrorCheck(uint32_t address, const T& value);
//-------------------------------------------Private variables------------------------------------------//
bool pageOverflow;
volatile uint8_t *cs_port;
uint8_t cs_mask, csPin, errorcode;
uint16_t name;
uint32_t capacity, maxPage;
uint32_t currentAddress = 1;
const uint8_t devType[10] = {0x5, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
const uint32_t memSize[10] = {64L * 1024L, 128L * 1024L, 256L * 1024L, 512L * 1024L, 1L * 1024L * 1024L,
2L * 1024L * 1024L, 4L * 1024L * 1024L, 8L * 1024L * 1024L, 16L * 1024L * 1024L};
const uint16_t chipName[10] = {05, 10, 20, 40, 80, 16, 32, 64, 128, 256};
};
//--------------------------------------------Templates-------------------------------------------//
// Writes any type of data to a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 4. errorCheck --> Turned on by default. Checks for writing errors
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. const T& value --> Variable with the data to be written
// 4. errorCheck --> Turned on by default. Checks for writing errors
// WARNING: You can only write to previously erased memory locations (see datasheet).
// Use the eraseSector()/eraseBlock32K/eraseBlock64K commands to first clear memory (write 0xFFs)
// Variant A
template <class T> bool SPIFlash::writeAnything(uint32_t address, const T& value, bool errorCheck) {
if (!_prepWrite(address))
return false;
else {
const byte* p = (const byte*)(const void*)&value;
_beginWrite(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
_writeNextByte(*p++, false);
#endif
_writeNextByte(*p++);
}
_endProcess();
}
if (!errorCheck)
return true;
else
return _writeErrorCheck(address, value);
}
// Variant B
template <class T> bool SPIFlash::writeAnything(uint16_t page_number, uint8_t offset, const T& value, bool errorCheck) {
uint32_t address = _getAddress(page_number, offset);
return writeAnything(address, value, errorCheck);
}
// Reads any type of data from a specific location in the flash memory.
// Has two variants:
// A. Takes two arguments -
// 1. address --> Any address from 0 to maxAddress
// 2. T& value --> Variable to return data into
// 2. fastRead --> defaults to false - executes _beginFastRead() if set to true
// B. Takes three arguments -
// 1. page --> Any page number from 0 to maxPage
// 2. offset --> Any offset within the page - from 0 to 255
// 3. T& value --> Variable to return data into
// 3. fastRead --> defaults to false - executes _beginFastRead() if set to true
// Variant A
template <class T> bool SPIFlash::readAnything(uint32_t address, T& value, bool fastRead) {
if (!_prepRead(address))
return false;
byte* p = (byte*)(void*)&value;
if(!fastRead)
_beginRead(address);
else
_beginFastRead(address);
for (uint16_t i = 0; i < sizeof(value); i++) {
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1)
*p++ = _readNextByte(false);
#endif
*p++ =_readNextByte();
}
_endProcess();
return true;
}
// Variant B
template <class T> bool SPIFlash::readAnything(uint16_t page_number, uint8_t offset, T& value, bool fastRead)
{
uint32_t address = _getAddress(page_number, offset);
return readAnything(address, value, fastRead);
}
// Private template to check for errors in writing to flash memory
template <class T> bool SPIFlash::_writeErrorCheck(uint32_t address, const T& value) {
if (!_prepRead(address))
return false;
const byte* p = (const byte*)(const void*)&value;
_beginRead(address);
for(uint16_t i = 0; i < sizeof(value);i++)
{
#if defined (__arm__) && defined (__SAM3X8E__)
if (i == sizeof(value)-1) {
if (*p++ != _readNextByte(false))
return false;
else
return true;
}
else
if (*p++ != _readNextByte())
return false;
#elif defined (__AVR__)
if (*p++ != _readNextByte())
return false;
#endif
}
_endProcess();
return true;
}
#endif // _SPIFLASH_H_

View File

@@ -0,0 +1 @@
../iceprog.ino