nand2/tools/olimexino-32u4 firmware/iceprog-nano/iceprog-nano.ino

400 lines
7.6 KiB
Arduino
Raw Permalink Normal View History

2023-01-11 10:13:09 +00:00
/*
* 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();
}
}