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

14
tools/AsciiToBin.py Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/python3
import sys
if (len(sys.argv)!=2):
print('usage: {:s} <filename>'.format(sys.argv[0]));
sys.exit(0)
fbin=open(sys.argv[1].replace('.hack','.bin'),'w+b')
fhack=open(sys.argv[1],'r')
lines=fhack.readlines()
for line in lines:
binary=int(line.strip(),2)
byte=bytearray([(binary>>8),binary&0xff])
fbin.write(byte)

BIN
tools/Assembler/assembler.pyc Executable file

Binary file not shown.

BIN
tools/Assembler/code.pyc Normal file

Binary file not shown.

BIN
tools/Assembler/parser.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

55
tools/Readme.md Normal file
View File

@@ -0,0 +1,55 @@
# tools
This folder contains the toolchain for Hack/Jack development.
## vim
vim configuration file to highlight syntax of jack/hack-files, when editing with vim. Copy the content of the subfolders into the appropriate vim configuration directory situated in your home directory `~/.vim`.
```
$ cp vim/syntax/* ~/.vim/syntax/
$ cp vim/ftdetect/* ~/.vim/ftdetect/
```
## Assembler
Assembler translates Hack-Assembly-files to Machnine-code. Outputs the machine code to filename.hack.
`usage: ./Assembler/assembler.pyc [filename.asm]`
## JackCompiler
Compiles Jack classes (single file or all *.jack files in directory) to virtualmachine code.
`usage: ./JackCompiler/JackCompiler.pyc [filename.jack] or [dir]`
## VMTranslator
Translates vm code (single file or all files with ending *.vm in directory)to Assembler.
`usage: ./VMTranslator/VMTranslator.pyc [filename.vm] or [dir]`
## AsciiToBin.py
Translates .hack files to binary files that can be uploaded with iecprogduino.
`usage: ./AsciiToBin.py [filename.hack]`
## iceprogduino
iceprogduino is the programmer to upload bitstream files to iCE40 boards of olimex over olimexino-32u4 (arduino like board).
For this you first have to upload firmware to olimexino-32u4.
iceprogduino is supportes from apio (fpgawars)
connect:
1. ice40-HX1/8K-EVB to olimexino-32u4 (over UEXT)
2. olimexino-32u4 (with installed firmware) to PC over USB.
## olimexino-32u4-firmware
Firmware to run olimexino-32u4 as programmer/UART bridge.
#

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,17 @@
CC = gcc
CFLAG = -c -Wall
EXECUTE = iceprogduino
NAME = iceprogduino
all: $(EXECUTE)
$(EXECUTE): $(NAME).o
$(CC) $(NAME).o -o $(EXECUTE)
clean:
rm -rf *.o $(EXECUTE)
install:
cp $(EXECUTE) /usr/local/bin/$(EXECUTE)

BIN
tools/iceprogduino/iceprogduino Executable file

Binary file not shown.

View File

@@ -0,0 +1,824 @@
/*
* iceprogduino -- simple programming tool for FTDI-based Lattice iCE programmers
* and Olinuxino based programmers for iCE40HX1K-EVB
*
* Copyright (C) 2015 Clifford Wolf <clifford@clifford.at>
* Olimexino Nano edition by Chris B. <chris@protonic.co.uk> @ Olimex Ltd. <c> 2016
*
* 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
* https://www.olimex.com/ iCE40HX1K-EVB
*/
//#define Olinuxino
//#define FTDI
#define Nano
#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 READY 0x44
#define READ_ALL 0x83
#define EMPTY 0x45
#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void serial_read(int x);
#define FEND 0xc0
#define FESC 0xdb
#define TFEND 0xdc
#define TFESC 0xdd
bool newframe;
bool timeout;
bool escaped;
#include <termios.h>
#define SerialPort "/dev/ttyACM0"
int fd;
uint8_t rxframe[512], txframe[512], fcs, tfcs;
uint16_t txp,rxp;
uint8_t membuf[0x200000];
uint8_t pages[0x2000];
bool verbose = false;
int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
fprintf(stderr,"error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 0; // no read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
fprintf(stderr,"error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
fprintf(stderr,"error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 0;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
fprintf(stderr,"error %d setting term attributes", errno);
}
void startframe(uint8_t command){
txframe[0]=FEND;
txframe[1]=command;
tfcs = command;
txp = 2;
}
void addbyte(uint8_t newbyte){
tfcs+=newbyte;
switch(newbyte){
case FEND:
txframe[txp++] = FESC;
txframe[txp++] = TFEND;
break;
case FESC:
txframe[txp++] = FESC;
txframe[txp++] = TFESC;
break;
default:
txframe[txp++] = newbyte;
break;
}
}
void sendframe(){
tfcs=0xff-tfcs;
addbyte(tfcs);
txframe[txp++] = FEND;
#ifdef frdebug
printf("%02X-L:%04X/%02X\n",txframe[txp-1],txp,tfcs);
#endif
if (fd>=0)
write(fd,txframe,txp);
}
void error()
{
exit(1);
}
bool waitframe(uint8_t cmd)
{
rxp = 0;
newframe = false;
fcs = 0;
uint32_t addr;
for (uint32_t to=0;to<5000;to++)
{
serial_read(0);
usleep(50);
if (newframe){
// int rxpp = rxp;
rxp = 0;
newframe = false;
usleep(10);
if ((rxframe[0]==READ_ID) && (cmd == READ_ID)){
if (rxframe[1]==0xef) fprintf(stderr, "Winbond Serial Flash ");
else fprintf(stderr, "Manufacturer ID: 0x%02X",rxframe[1]);
if ((rxframe[2]==0x40) && (rxframe[3]==0x15)) fprintf(stderr, "- W25Q16BV\n");
else fprintf(stderr, " / Device ID: 0x%02X%02X\n",rxframe[2],rxframe[3]);
return true;
}
if (rxframe[0]==READ)
{
addr = (rxframe[1]<<16) | (rxframe[2]<<8);
pages[addr>>8]=0;
for (int x=3; x < 259;x++)
{
membuf[addr++]=rxframe[x];
}
}
if (rxframe[0]==READY) if (cmd==READY) return true; else to = 0;
if (rxframe[0]==EMPTY) pages[(rxframe[1]<<8) | rxframe[2]]=0;
if ((rxframe[0]==READ)||(rxframe[0]==EMPTY)) if (cmd==READ) return true; else to = 0;
rxframe[0]=0;
fcs = 0;
}
}
return false;
}
void flash_read_id()
{
startframe(READ_ID);
sendframe();
waitframe(READ_ID);
return;
fprintf(stderr, "\n");
}
void flash_bulk_erase()
{
fprintf(stderr, "\nbulk erase..");
startframe(BULK_ERASE);
sendframe();
waitframe(BULK_ERASE);
fprintf(stderr, "\rbulk erased\n");
}
void flash_64kB_sector_erase(int addr)
{
fprintf(stderr, "erase 64kB sector at 0x%06X..", addr);
startframe(SEC_ERASE);
addbyte(addr>>16);
addbyte(addr>>8);
sendframe();
waitframe(READY);
fprintf(stderr, "erased\n");
}
void flash_read_all(void){
fprintf(stderr, "read 0x%06X +0x%06X..\n", 0, 0x200000);
memset(&membuf,0xff,sizeof(membuf));
memset(&pages,0xff,sizeof(pages));
startframe(READ_ALL);
sendframe();
if (!waitframe(READY))
{
error();
}
fprintf(stderr, "Requesting missmatched frames...");
bool notready=false;
while (1){
notready = false;
int s = 0;
for(int x = 0; x < 0x2000;x++)
{
if (pages[x]>0){
if (s++ > 25)
{
fprintf(stderr, "ERROR Reading..\n");
notready = false;
break;
}
notready=true;
fprintf(stderr, ".");
startframe(READ);
addbyte(x >> 8);
addbyte(x >> 0);
sendframe();
waitframe(READ);
}
}
if (!notready) break;
}
fprintf(stderr, "\n");
uint32_t i;
if (verbose)
for (i = 0; i < 1024; i++)
fprintf(stderr, "%02x%c", membuf[i], i == 0 || i % 32 == 31 ? '\n' : ' ');
}
void help(const char *progname)
{
fprintf(stderr, "\n");
fprintf(stderr, "iceprog -- simple programming tool for Olinuxino Nano-based Lattice iCE programmers\n");
fprintf(stderr, "\n");
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [options] <filename>\n", progname);
fprintf(stderr, "\n");
fprintf(stderr, " -e\n");
fprintf(stderr, " bulk erase entire flash only\n");
fprintf(stderr, "\n");
fprintf(stderr, " -w\n");
fprintf(stderr, " write only, do not verify\n\n");
fprintf(stderr, " -f\n");
fprintf(stderr, " write all data, including 0xFF's pages\n\n");
fprintf(stderr, " -I<serialport>\n");
fprintf(stderr, " port to connect Arduino (default /dev/ttyACM0)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -r\n");
fprintf(stderr, " read entire flash (2MB) and write to file\n");
fprintf(stderr, "\n");
fprintf(stderr, " -c\n");
fprintf(stderr, " do not write flash, only verify (check)\n");
fprintf(stderr, "\n");
fprintf(stderr, " -b\n");
fprintf(stderr, " bulk erase entire flash before writing\n");
fprintf(stderr, "\n");
fprintf(stderr, " -n\n");
fprintf(stderr, " do not erase flash before writing\n");
fprintf(stderr, "\n");
fprintf(stderr, " -o <offset in bytes> start address for write [default: 0]\n");
fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n");
fprintf(stderr, " or 'M' for size in megabytes)\n");
fprintf(stderr, " this feature works not with all options.\n");
fprintf(stderr, " tested with -b, -v\n");
fprintf(stderr, " -t\n");
fprintf(stderr, " just read the flash ID sequence\n");
fprintf(stderr, "\n");
fprintf(stderr, " -v\n");
fprintf(stderr, " verbose output\n");
fprintf(stderr, "\n");
exit(1);
}
void serial_read(int x)
{
while (1)
{
if (rxp>512)
{
newframe = 0;
rxp = 0;
escaped = false;
fcs = 0;
break;
}
usleep(5);
uint8_t buf[1];
int n;
if (fd < 0)
{
printf(".");
break;
}
else
{
n=read(fd, buf, 1);
if (n==1){
switch(buf[0]){
case FEND:
if (fcs==0xff)
{
newframe = 1;
return;
}
newframe = 0;
rxp = 0;
escaped = false;
fcs = 0;
break;
case FESC:
escaped = true;
break;
case TFESC:
if (escaped)
{
rxframe[rxp++]=FESC;
fcs+=FESC;
escaped = false;
}
else
{
rxframe[rxp++]=TFESC;
fcs += TFESC;
}
break;
case TFEND:
if (escaped)
{
rxframe[rxp++]=FEND;
fcs += FEND;
escaped=false;
}
else
{
rxframe[rxp++]=TFEND;
fcs += TFEND;
}
break;
default:
escaped=false;
rxframe[rxp++]=buf[0];
fcs+=buf[0];
break;
}
}
else break;
}
}
}
int main(int argc, char **argv)
{
int addr;
int max_read_size = 0x200000;
bool read_mode = false;
bool check_mode = false;
bool bulk_erase = false;
bool dont_erase = false;
bool prog_sram = false;
bool test_mode = false;
bool noverify = true; // verify performs by arduino board
bool ff_mode = false;
bool bulk_erase_only = false;
const char *filename = NULL;
const char *devstr = NULL;
int rw_offset = 0;
int opt;
char *endptr;
char *portname = SerialPort;
while ((opt = getopt(argc, argv, "I:o:rcbntvwfeh")) != -1)
{
switch (opt)
{
case 'd':
devstr = optarg;
break;
case 'I':
portname = optarg;
break;
case 'r':
read_mode = true;
noverify=false;
break;
case 'e':
bulk_erase_only = true;
break;
case 'f':
ff_mode = true;
break;
case 'R':
read_mode = true;
max_read_size = 256 * 1024;
break;
case 'c':
check_mode = true;
noverify=false;
break;
case 'b':
bulk_erase = true;
break;
case 'n':
dont_erase = true;
break;
case 'S':
prog_sram = true;
break;
case 't':
test_mode = true;
printf("\nTest mode\n");
break;
case 'v':
verbose = true;
break;
case 'w':
noverify = true;
break;
case 'o': /* set address offset */
rw_offset = strtol(optarg, &endptr, 0);
if (*endptr == '\0')
/* ok */;
else if (!strcmp(endptr, "k"))
rw_offset *= 1024;
else if (!strcmp(endptr, "M"))
rw_offset *= 1024 * 1024;
else {
fprintf(stderr, "'%s' is not a valid offset\n", optarg);
return EXIT_FAILURE;
}
break;
default:
help(argv[0]);
}
}
if (read_mode + check_mode + prog_sram + test_mode > 1)
help(argv[0]);
if (bulk_erase && dont_erase)
help(argv[0]);
if (optind+1 != argc && !test_mode && !bulk_erase_only)
help(argv[0]);
filename = argv[optind];
//bulk_erase = true; // comment this line if you do not want to bulk erase by default
/* open serial port */
fd = open(portname, O_RDWR | O_NOCTTY);
// fd = open(portname, O_RDWR | O_ASYNC | O_NDELAY);
if (fd < 0)
{
fprintf(stderr,"error %d opening %s: %s\n", errno, portname, strerror (errno));
return -1;
}
set_interface_attribs (fd, B57600, 0); // set speed to 57600 bps, 8n1 (no parity)
set_blocking (fd, 0); // set no blocking
fprintf(stderr,"Serial: %s: %s\n", portname, strerror (errno));
rxp = 0;
if (test_mode)
{
flash_read_id();
}
else if (prog_sram)
{
fprintf(stderr, "\nprogramming SRAM is not supported!\n");
}
else
{
// ---------------------------------------------------------
// Program
// ---------------------------------------------------------
if (!read_mode && !check_mode && !bulk_erase_only)
{
FILE *f = (strcmp(filename, "-") == 0) ? stdin :
fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "Error: Can't open '%s' for reading: %s\n", filename, strerror(errno));
error();
}
if (!dont_erase)
{
if (bulk_erase)
{
flash_bulk_erase();
sleep(1);
flash_read_id();
usleep(10000);
}
else
{
struct stat st_buf;
if (stat(filename, &st_buf)) {
fprintf(stderr, "Error: Can't stat '%s': %s\n", filename, strerror(errno));
error();
}
fprintf(stderr, "file size: %d\n", (int)st_buf.st_size);
/* 64 k */
int begin_addr = rw_offset & ~0xffff;
int end_addr = (rw_offset + st_buf.st_size + 0xffff) & ~0xffff;
for (addr = begin_addr; addr < end_addr; addr += 0x10000) {
flash_64kB_sector_erase(addr);
}
}
}
fprintf(stderr, "\nprogramming..\n");
int ccc;
flash_read_id();
/* page is 256 */
for (int rc, addr = 0; true; addr += rc) {
uint8_t buffer[256];
int page_size = 256 - (rw_offset + addr) % 256;
rc = fread(buffer, 1, page_size, f);
int offset_addr = addr + rw_offset;
if (rc <= 0) break;
if (verbose)
fprintf(stderr, "prog 0x%06X +0x%03X..\n", offset_addr, rc);
else
fprintf(stderr, "\rprog 0x%06X +0x%03X..", offset_addr, rc);
for (ccc=0;ccc<rc;ccc++){
if ((buffer[ccc] != 0xFF) || (ff_mode))
{
int x;
while(1){
startframe(PROG);
addbyte(offset_addr>>16);
addbyte(offset_addr>>8);
for (x=0;x<rc;x++)
addbyte(buffer[x]);
sendframe();
//if (verbose)
fprintf(stderr, ".");
//usleep(1000);
if (waitframe(READY)) break;
}
break;
}
}
}
fprintf(stderr, "\n");
if (f != stdin)
fclose(f);
}
if (!noverify && !bulk_erase_only)
{
// ---------------------------------------------------------
// Read/Verify
// ---------------------------------------------------------
if (read_mode)
{
FILE *f = (strcmp(filename, "-") == 0) ? stdout :
fopen(filename, "w");
if (f == NULL) {
fprintf(stderr, "Error: Can't open '%s' for writing: %s\n", filename, strerror(errno));
error();
}
fprintf(stderr, "\nreading..\n");
flash_read_id();
flash_read_all();
printf("\nWriting data to file %s\n",filename);
fwrite(membuf, 0x200000, 1, f);
if (f != stdout)
fclose(f);
}
else
{
FILE *f = (strcmp(filename, "-") == 0) ? stdin :
fopen(filename, "r");
if (f == NULL) {
fprintf(stderr, "Error: Can't open '%s' for reading: %s\n", filename, strerror(errno));
error();
}
fprintf(stderr, "\nreading..\n");
flash_read_id();
flash_read_all();
uint8_t buffer_file[0x200000];
int rc = fread(buffer_file, 1, 0x200000, f);
if (memcmp(buffer_file, membuf, rc))
{
fprintf(stderr, "Found difference between flash and file!\n");
error();
}
fprintf(stderr, "\nVERIFY OK\n");
if (f != stdin)
fclose(f);
}
}
if (bulk_erase_only)
{
flash_bulk_erase();
fprintf(stderr, "Flash erased!\n");
}
// ---------------------------------------------------------
// Reset
// ---------------------------------------------------------
}
// ---------------------------------------------------------
// Exit
// ---------------------------------------------------------
fprintf(stderr, "Bye.\n");
close(fd);
return 0;
}

Binary file not shown.

43
tools/jack.vim Normal file
View File

@@ -0,0 +1,43 @@
" Vim syntax file
setlocal iskeyword+=:
" Language: Jack
" Maintainer: Michael Schroeder
if exists("b:current_syntax")
finish
endif
setlocal iskeyword+=-
setlocal iskeyword+=?
setlocal iskeyword+=!
set tabstop=4
let b:current_syntax = "jack"
syn keyword jackTodo class method constructor function
syn region jackComment start="\/\*" end="\*\/"
syn region jackComment start="\/\/" end="\n"
syn keyword jackConstant null
syn keyword jackBoolean true false
syn region jackString start=+"+ end=+"+ skip=+\\\\\|\\"+ contains=jackSpecial,@Spell
syn match jackNumber "\<0\>"
syn match jackNumber "\<[1-9][0-9]*\>"
syn keyword jackType void int boolean String char Array
syn keyword jackConditional if else
syn keyword jackRepeat while
syn keyword jackKeyword var field static
syn keyword jackFunction return let do
highlight link jackTodo Todo
highlight link jackComment Comment
highlight link jackConstant Constant
highlight link jackBoolean Boolean
highlight link jackString String
highlight link jackNumber Number
highlight link jackType Type
highlight link jackConditional Conditional
highlight link jackRepeat Repeat
highlight link jackKeyword Keyword
highlight link jackFunction Function

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

23
tools/removeCode.sh Executable file
View File

@@ -0,0 +1,23 @@
#!/bin/sh
for filename in ../*/*.v
do
sed -i '1,/Put your code here:/!d' ${filename}
echo "\nendmodule" >> ${filename}
done
sed -i '1,/endmodule/!d' ../01_Boolean_Logic/Nand.v
sed -i '1,/endmodule/!d' ../03_Sequential_Logic/DFF.v
sed -i '1,/endmodule/!d' ../03_Sequential_Logic/RAM256.v
sed -i '1,/endmodule/!d' ../05_Computer_Architecture/ROM.v
sed -i '1,/endmodule/!d' ../06_IO_Devices/InOut.v
sed -i '/[\t]/d' ../07_Operating_System/*.jack
sed -i '/[\t]/d' ../04_Machine_Language/*.asm
for filename in ../06_IO_Devices/*/*.asm
do
sed -i '1,/Put your code here:/!d' ${filename}
done
sed -i '/REMOVE CODE/d' ../07_Operating_System/12_Tetris/Main.jack
#rm -r ../tools/Assembler/src
#rm -r ../tools/VMTranslator/src
#rm -r ../tools/JackCompiler/src

View File

@@ -0,0 +1 @@
autocmd BufNewFile,BufRead *.asm set filetype=hack_asm

View File

@@ -0,0 +1 @@
autocmd BufNewFile,BufRead *.vm set filetype=hack_vm

View File

@@ -0,0 +1 @@
autocmd BufNewFile,BufRead *.hdl set filetype=hdl

View File

@@ -0,0 +1 @@
autocmd BufNewFile,BufRead *.jack set filetype=jack

2
tools/vim/syntax/c.vim Normal file
View File

@@ -0,0 +1,2 @@
syn match cType "pair "
syn match cType "number "

View File

@@ -0,0 +1,32 @@
" Vim syntax file
" Language: Hack Assembly
" Maintainer: Severyn Kozak
" Latest Revision: 15 November 2014
if version < 600
syntax clear
endif
setl iskeyword+=.,$,:
syn keyword hackAsmDestination A M D AM MD AD AMD null
syn keyword hackAsmJump JGT JEQ JGE JLT JNE JLE JMP
syn match hackAsmComment "\/\/.*$"
syn match hackAsmLabel "(\k\+)"
syn match hackAsmMathOp "[+-]"
syn match hackAsmBitwiseOp "[&|]"
syn match hackAsmAInstruction "@\k\+"
syn match hackAsmCInstruction "[=;]"
syn match hackAsmConstant "-1\|0\|1"
hi link hackAsmDestination Identifier
hi link hackAsmJump Function
hi link hackAsmConstant Constant
hi link hackAsmComment Comment
hi link hackAsmLabel Label
hi link hackAsmMathOp Operator
hi link hackAsmBitwiseOp Operator
hi link hackAsmAInstruction PreProc
hi link hackAsmCInstruction Operator

View File

@@ -0,0 +1,29 @@
" Vim syntax file
" Language: Hack Virtual Machine
" Maintainer: Severyn Kozak
" Latest Revision: 02 December 2014
if version < 600
syntax clear
endif
setl iskeyword+=.,:
setl iskeyword+=-
syn keyword hackVmMathLogicOp add sub neg eq gt lt or not
syn keyword hackVmMemoryOp push pop
syn keyword hackVmMemorySegments argument local static constant this that
\ pointer temp
syn keyword hackVmProgramFlowOp label goto if-goto
syn keyword hackVmFunctionCallOp function call return
syn match hackVmComment "\/\/.*$"
syn match hackVmNumber "\v(\w)@<!\d+"
hi link hackVmComment Comment
hi link hackVmMathLogicOp Operator
hi link hackVmMemoryOp Statement
hi link hackVmMemorySegments Identifier
hi link hackVmProgramFlowOp Conditional
hi link hackVmFunctionCallOp Function
hi link hackVmNumber Number

49
tools/vim/syntax/hdl.vim Normal file
View File

@@ -0,0 +1,49 @@
" Vim syntax file
" Language: HDL
" Maintainer: Severyn Kozak
" Latest Revision: 11 November 2014
if version < 600
syntax clear
endif
" The `.hdl` extension is reserved for the `vhdl` filetype, and, by the time
" this plugin is sourced, Vim has already loaded the `vhdl` ftplugin files,
" which contain some undesired settings. The fullproof way to ignore them is to
" prevent Vim from ever setting the `vhdl` filetype, which can only be done by
" having the user specify the following:
"
" au BufNewFile,BufRead *.hdl setfiletype hdl
"
" in their vimrc, which is messy. Best to let the plugin do the work just by
" explicitly overriding the settings that we don't want, like the following.
setl indentexpr=
setl formatoptions+=or
let b:current_syntax = "hdl"
let did_load_filetypes = 1
syn match _hdl_comment_inline "\/\/.*"
syn match _hdl_delimiter "[,;:.]"
syn match _hdl_assignment "="
syn match _hdl_number "\v(\w)@<!\d+"
syn match _hdl_surrounding "[[\](){}]"
syn match _hdl_pin_name "\a[a-zA-Z0-9]*\ze=" contains=ALL
syn region _hdl_comment_block start="/\*" end="*/"
syn keyword _hdl_builtin_chip Add16 ALU And And16 ARegister Bit DFF DMux
\ DMux4Way DMux8Way DRegister Mux4Way16 Mux8Way16 FullAdder HalfAdder Inc16
\ Keyboard Mux Mux16 Or Or16 Or8Way PC RAM RAM16K RAM4K RAM512 RAM64 ROM32K
\ Screen Xor RAM8 Register RegisterWithGUI Nand Not Not16
syn keyword _hdl_section CHIP PARTS IN OUT
syn keyword _hdl_constant true false
hi link _hdl_comment_block Comment
hi link _hdl_comment_inline Comment
hi link _hdl_builtin_chip Constant
hi link _hdl_section Label
hi link _hdl_delimiter Comment
hi link _hdl_surrounding Delimiter
hi link _hdl_number Number
hi link _hdl_constant Constant
hi link _hdl_assignment Operator
hi link _hdl_pin_name Identifier

33
tools/vim/syntax/jack.vim Normal file
View File

@@ -0,0 +1,33 @@
" Vim syntax file
" Language: Jack
" Maintainer: Severyn Kozak
" Latest Revision: 01 January 2015
if version < 600
syntax clear
endif
syn keyword jackDeclaration var static field class
syn keyword jackStatement let if else while do return
syn keyword jackVarType int char boolean void
syn keyword jackFuncType constructor function method
syn keyword jackConstant true false null this
syn match jackOp "[-+*/&|<>=~]"
syn match jackString '"[^"\n]*"'
syn match jackNumber "\d\+"
syn match jackDelimiter "[.,;]"
syn match jackSurroundingElement "[{}()\[\]]"
syn match jackCommentInline "\/\/.*"
syn region jackCommentBlock start="/\*" end="*/"
hi link jackOp Operator
hi link jackSurroundingElement Delimiter
hi link jackVarType Type
hi link jackFuncType Function
hi link jackDeclaration Statement
hi link jackStatement Statement
hi link jackConstant Constant
hi link jackNumber Number
hi link jackCommentInline Comment
hi link jackCommentBlock Comment
hi link jackDelimiter Comment

View File

@@ -0,0 +1,49 @@
"Vim syntax file
"Language: nand2tetris Hardware Description Language
"Maintainer: Christopher Noussis
"Latest Revision: 14 January 2015
"TODO: Fix syntax names to work with accepted style convention
"syn keyword [languageName][SyntaxElementName]
if exists("b:current_syntax")
finish
endif
"Comments.
syn match hdlComment "\/\/.*$"
syn region hdlComment start='\/\*' end='\*\/'
syn region hdlComment start='\/\*\*' end='\*\/'
"The all-caps basic language keywords.
syn keyword basicKeywords CHIP PARTS IN OUT BUILTIN CLOCKED
"Builtin chips.
syn keyword builtInChips Nand Not And Or Xor Mux DMux
syn keyword builtInChips Not16 And16 Or16 Mux16
syn keyword builtInChips Or8Way Mux4Way16 Mux8Way16 DMux4Way DMux8Way
syn keyword builtInChips HalfAdder FullAdder Add16 ALU Inc16
syn keyword builtInChips DFF Bit Register ARegister DRegister
syn keyword builtInChips RAM8 RAM64 RAM512 RAM4K RAM16K
syn keyword builtInChips PC ROM32K Screen Keyboard
"External
syn keyword extPin in out nextgroup=busNumber
syn match busNumber '\[\d*\]' "TODO: Make it so the braces are not matched.
syn region hdlInterface start='{' end='}' fold transparent
"Internal
syn region hdlImplementation start=':' end='}' fold transparent
syn region partInterface start='(' end=')' contains=connection, extPin
"syn match connection '\w\+(\[\d+\])\*=\w\+(\[\d+\])\*'
syn match connection '\w\+=\@=' contained
syn match connection '=\@<=\w\+' contained
let b:current_syntax = 'chip'
"Syntax Highlighting
hi def link hdlComment Comment
hi def link basicKeywords Statement
hi def link builtInChips Special
hi def link extPin Type
hi def link busNumber Constant
hi def link connection Identifier