OpenCores
URL https://opencores.org/ocsvn/s6soc/s6soc/trunk

Subversion Repositories s6soc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /s6soc/trunk/sw/host
    from Rev 8 to Rev 11
    Reverse comparison

Rev 8 → Rev 11

/ttybus.h
0,0 → 1,124
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ttybus.h
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: This is the C++ program on the command side that will interact
// with a serial port (through DEPP) on an FPGA, to command the
// WISHBONE on that same FPGA to ... whatever we wish to command it to do.
//
// This code does not run on an FPGA, is not a test bench, neither is it
// a simulator. It is a portion of a command program for commanding an
// FPGA from an attached host computer.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#ifndef TTYBUS_H
#define TTYBUS_H
 
#include "llcomms.h"
#include "devbus.h"
 
#define RDBUFLN 2048
 
class TTYBUS : public DEVBUS {
public:
unsigned long m_total_nread;
private:
LLCOMMSI *m_dev;
static const unsigned MAXRDLEN, MAXWRLEN;
 
bool m_interrupt_flag, m_decode_err, m_addr_set, m_bus_err;
unsigned int m_lastaddr;
 
int m_buflen, m_rdfirst, m_rdlast;
char *m_buf, *m_rdbuf;
 
bool m_wrloaded;
int m_rdaddr, m_wraddr;
BUSW m_readtbl[1024], m_writetbl[512];
 
void init(void) {
m_interrupt_flag = false;
m_buflen = 0; m_buf = NULL;
m_addr_set = false;
bufalloc(64);
m_bus_err = false;
m_decode_err = false;
m_wrloaded = false;
 
m_rdfirst = m_rdlast = 0;
m_rdbuf = new char[RDBUFLN];
 
m_rdaddr = m_wraddr = 0;
}
 
char charenc(const int sixbitval) const;
unsigned chardec(const char b) const;
void encode(const int fbits, const BUSW v, char *buf) const;
unsigned decodestr(const char *buf) const;
int decodehex(const char hx) const;
void bufalloc(int len);
BUSW readword(void); // Reads a word value from the bus
void readv(const BUSW a, const int inc, const int len, BUSW *buf);
void writev(const BUSW a, const int p, const int len, const BUSW *buf);
 
int lclread(char *buf, int len);
int lclreadcode(char *buf, int len);
char *encode_address(const BUSW a);
char *readcmd(const int inc, const int len, char *buf);
public:
TTYBUS(LLCOMMSI *comms) : m_dev(comms) { init(); }
virtual ~TTYBUS(void) {
m_dev->close();
if (m_buf) delete[] m_buf; m_buf = NULL;
delete m_rdbuf; m_rdbuf = NULL;
delete m_dev;
}
 
void kill(void) { m_dev->close(); }
void close(void) { m_dev->close(); }
void writeio(const BUSW a, const BUSW v);
BUSW readio(const BUSW a);
void readi(const BUSW a, const int len, BUSW *buf);
void readz(const BUSW a, const int len, BUSW *buf);
void writei(const BUSW a, const int len, const BUSW *buf);
void writez(const BUSW a, const int len, const BUSW *buf);
bool poll(void) { return m_interrupt_flag; };
void usleep(unsigned msec); // Sleep until interrupt
void wait(void); // Sleep until interrupt
bool bus_err(void) const { return m_bus_err; };
void reset_err(void) { m_bus_err = false; }
void clear(void) { m_interrupt_flag = false; }
};
 
#endif
/flashdrvr.h
2,16 → 2,16
//
// Filename: flashdrvr.h
//
// Project: XuLA2-LX25 System on a Chip
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: Flash driver. Encapsulate writing to the flash device.
//
// Creator: Dan Gisselquist
// Gisselquist Tecnology, LLC
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2016, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
23,6 → 23,11
// 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
/deppi.cpp
0,0 → 1,273
////////////////////////////////////////////////////////////////////////////////
//
// Filename: deppi.cpp
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: Creates a DEPP interface pseudo-character device, similar to
// what you might get from a serial port or other character device,
// from the DEPP interface to a CMOD S6 board.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
// From Digilent's Adept Library
#include "dpcdecl.h"
#include "dmgr.h"
#include "depp.h"
 
// From my own library
#include "llcomms.h"
#include "deppi.h"
 
DEPPI::DEPPI(char *szSel) {
if (!DmgrOpen(&m_dev, szSel)) {
fprintf(stderr, "Open failed!\n");
exit(EXIT_FAILURE);
}
 
if (!DeppEnable(m_dev)) {
fprintf(stderr, "Could not enable DEPP interface\n");
exit(EXIT_FAILURE);
}
 
m_int = false, m_err = false;
 
// fprintf(stdout, "Flushing **************\n");
flush_read();
// fprintf(stdout, "Flushed! **************\n");
}
 
DEPPI::~DEPPI(void) {
close();
}
 
void DEPPI::close(void) {
if (m_dev)
DmgrClose(m_dev);
m_dev = 0;
}
 
void DEPPI::depperr(void) {
ERC erc = DmgrGetLastError();
if(erc != ercNoErc) {
char scode[cchErcMax], msg[cchErcMsgMax];
DmgrSzFromErc(erc, scode, msg);
fprintf(stderr, "ErrCode : %s\n", scode);
fprintf(stderr, "ErrMessage: %s\n", msg);
close();
exit(EXIT_FAILURE);
}
}
 
void DEPPI::write(char *buf, int len) {
bool good = true;
 
if (false) {
// Debug code--write one at a time
fputs("WR: ", stdout);
for(int i=0; i<len; i++) {
good = good && DeppPutReg(m_dev, 0, (unsigned char)buf[i], false);
fputc(buf[i], stdout);
} fputc('\n', stdout);
} else
good = DeppPutRegRepeat(m_dev, 0, (unsigned char *)buf, len, false);
if (!good)
depperr();
}
 
int DEPPI::read(char *buf, int len) {
return read(buf, len, 4);
}
 
int DEPPI::read(char *buf, int len, int timeout_ms) {
int left = len, nr=0;
struct timespec now, later;
 
clock_gettime(CLOCK_MONOTONIC, &now);
 
// printf("USBI::read(%d) (FIFO is %d-%d)\n", len, m_rend, m_rbeg);
nr = pop_fifo(buf, left);
left -= nr;
while(left > 0) {
raw_read(left, timeout_ms);
nr = pop_fifo(&buf[len-left], left);
left -= nr;
 
// printf("\tWHILE (nr = %d, LEFT = %d, len=%d)\n", nr, left, len);
if (nr == 0)
break;
#define TIMEOUT
#ifdef TIMEOUT
if (timeout_ms == 0)
break;
else if (timeout_ms > 0) {
clock_gettime(CLOCK_MONOTONIC, &later);
 
long num_ns = later.tv_nsec - now.tv_nsec, num_ms;
if (num_ns < 0) {
num_ns += 1000000000;
later.tv_sec--;
} num_ms = num_ns / 1000000;
if (later.tv_sec > now.tv_sec)
num_ms += (later.tv_sec - now.tv_sec)*1000;
 
if (num_ms > timeout_ms)
break;
}
#endif
}
 
// printf("READ %d characters (%d req, %d left)\n", len-left, len, left);
return len-left;
}
 
void DEPPI::raw_read(const int clen, int timeout_ms) {
int empty = RCV_BUFMASK - ((m_rbeg - m_rend)&(RCV_BUFMASK));
int len = clen;
bool good = true;
 
if (len > empty)
len = empty;
if (len > 0) {
// Fill the tail of our buffer
int ln = len;
if (ln > PKTLEN)
ln = PKTLEN;
 
// fprintf(stdout, "RAW-READ(%d)\n", ln);
if (false) {
// Debug code--read one word at a time
for(int i=0; i<ln; i++) {
good = good && DeppGetReg(m_dev, 0, (unsigned char *)&m_rxbuf[i], false);
usleep(1);
}
} else
good = good && DeppGetRegRepeat(m_dev, 0, (unsigned char *)m_rxbuf, ln, false);
// fprintf(stdout, "Pushing to FIFO\n");
push_fifo(m_rxbuf, ln);
len -= ln;
}
 
if (!good)
depperr();
}
 
void DEPPI::flush_read(void) {
while(poll(4)) {
m_rbeg = m_rend = 0;
}
}
 
void DEPPI::push_fifo(char *buf, int len) {
char last = 0;
char *sptr = buf;
 
// fprintf(stdout, "PUSH(%d)\n", len);
 
if (m_rbeg != m_rend)
last = m_rbuf[(m_rbeg-1)&RCV_BUFMASK];
for(int i=0; i<len; i++) {
char v = *sptr++;
if (((v & 0x80)||((unsigned char)v < 0x10))&&(v == last)) {
// Skipp any stuff bytes
// fprintf(stderr, "SKIPPING-1: %02x\n", v & 0x0ff);
} else if ((unsigned char)v == 0x0ff) {
// Skipp any not-yet-ready bytes
// fprintf(stdout, "SKIPPING-2: %02x\n", 0x0ff);
} else {
m_rbuf[m_rbeg] = v;
// fprintf(stdout, "PUSHING: %02x %c\n", v&0x0ff,
// isprint(v)?v:'.');
m_rbeg = (m_rbeg+1)&(RCV_BUFMASK);
} last = v;
}
}
 
int DEPPI::pop_fifo(char *buf, int len) {
int avail = (m_rbeg - m_rend)&(RCV_BUFMASK);
int left = len;
int nr = 0;
 
// printf("Attempting to pop %d items from FIFO (%d - %d)\n",
// len, m_rend, m_rbeg);
while((avail > 0)&&(left > 0)) {
int ln = RCV_BUFLEN-m_rend;
if (ln > left)
ln = left;
if (ln > avail)
ln = avail;
memcpy(&buf[len-left], &m_rbuf[m_rend], ln);
left -= ln;
avail -= ln;
m_rend = (m_rend + ln)&(RCV_BUFMASK);
nr += ln;
 
}
 
return nr;
}
 
bool DEPPI::poll(unsigned ms) {
int avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
bool r = true;
 
// printf("POLL\n");
if ((avail < 2)&&((avail<1)||(m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10))) {
// printf("POLL -- CALLS RAW READ\n");
raw_read(4,ms);
avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
 
if (avail != 0) {
// Read 'til there's nothing more to be read
char v = (m_rbuf[(m_rbeg-1)&(RCV_BUFMASK)]);
while(((v&0x80)==0)&&((unsigned)v>=0x10)&&(avail < RCV_BUFMASK-32)) {
raw_read(26,ms);
if (avail == ((m_rbeg-m_rend)&(RCV_BUFMASK)))
break; // We didn't read anything more
avail = (m_rbeg-m_rend)&(RCV_BUFMASK);
// printf("POLL/LOOP -- %d available\n", avail);
}
if (avail < 1)
r = false;
else if ((avail==1)&&((m_rbuf[m_rend]&0x80)||(m_rbuf[m_rend]<0x10)))
r = false;
} else r = false;
}
// printf("POLL -- is %s\n", (r)?"true":"false");
 
return r;
}
/zipload.cpp
0,0 → 1,516
////////////////////////////////////////////////////////////////////////////////
//
// Filename: zipload.cpp
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: To load the flash--both a the two configurations and the
// a program for the ZipCPU into (flash) memory.
//
// Steps:
// 1. Reboot the CMod into the alternate/debug/command mode
// 2. Load flash memory
// 3. Reload (reboot) the CMod configuration into ZipCPU mode
// 4. Program should start on its own.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "devbus.h"
#include "llcomms.h"
#include "deppi.h"
#include "regdefs.h"
#include "flashdrvr.h"
 
bool iself(const char *fname) {
FILE *fp;
bool ret = true;
 
if ((!fname)||(!fname[0]))
return false;
 
fp = fopen(fname, "rb");
 
if (!fp) return false;
if (0x7f != fgetc(fp)) ret = false;
if ('E' != fgetc(fp)) ret = false;
if ('L' != fgetc(fp)) ret = false;
if ('F' != fgetc(fp)) ret = false;
fclose(fp);
return ret;
}
 
long fgetwords(FILE *fp) {
// Return the number of words in the current file, and return the
// file as though it had never been adjusted
long fpos, flen;
fpos = ftell(fp);
if (0 != fseek(fp, 0l, SEEK_END)) {
fprintf(stderr, "ERR: Could not determine file size\n");
perror("O/S Err:");
exit(-2);
} flen = ftell(fp);
if (0 != fseek(fp, fpos, SEEK_SET)) {
fprintf(stderr, "ERR: Could not seek on file\n");
perror("O/S Err:");
exit(-2);
} flen /= sizeof(FPGA::BUSW);
return flen;
}
 
FPGA *m_fpga;
class SECTION {
public:
unsigned m_start, m_len;
FPGA::BUSW m_data[1];
};
 
SECTION **singlesection(int nwords) {
fprintf(stderr, "NWORDS = %d\n", nwords);
size_t sz = (2*(sizeof(SECTION)+sizeof(SECTION *))
+(nwords-1)*(sizeof(FPGA::BUSW)));
char *d = (char *)malloc(sz);
SECTION **r = (SECTION **)d;
memset(r, 0, sz);
r[0] = (SECTION *)(&d[2*sizeof(SECTION *)]);
r[0]->m_len = nwords;
r[1] = (SECTION *)(&r[0]->m_data[r[0]->m_len]);
r[0]->m_start = 0;
r[1]->m_start = 0;
r[1]->m_len = 0;
 
return r;
}
 
SECTION **rawsection(const char *fname) {
SECTION **secpp, *secp;
unsigned num_words;
FILE *fp;
int nr;
 
fp = fopen(fname, "r");
if (fp == NULL) {
fprintf(stderr, "Could not open: %s\n", fname);
exit(-1);
}
 
if ((num_words=fgetwords(fp)) > FLASHWORDS-(RESET_ADDRESS-SPIFLASH)) {
fprintf(stderr, "File overruns flash memory\n");
exit(-1);
}
secpp = singlesection(num_words);
secp = secpp[0];
secp->m_start = RAMBASE;
secp->m_len = num_words;
nr= fread(secp->m_data, sizeof(FPGA::BUSW), num_words, fp);
if (nr != (int)num_words) {
fprintf(stderr, "Could not read entire file\n");
perror("O/S Err:");
exit(-2);
} assert(secpp[1]->m_len == 0);
 
return secpp;
}
 
unsigned byteswap(unsigned n) {
unsigned r;
 
r = (n&0x0ff); n>>= 8;
r = (r<<8) | (n&0x0ff); n>>= 8;
r = (r<<8) | (n&0x0ff); n>>= 8;
r = (r<<8) | (n&0x0ff); n>>= 8;
 
return r;
}
 
// #define CHEAP_AND_EASY
#ifdef CHEAP_AND_EASY
#else
#include <libelf.h>
#include <gelf.h>
 
void elfread(const char *fname, unsigned &entry, SECTION **&sections) {
Elf *e;
int fd, i;
size_t n;
char *id;
Elf_Kind ek;
GElf_Ehdr ehdr;
GElf_Phdr phdr;
const bool dbg = false;
 
if (elf_version(EV_CURRENT) == EV_NONE) {
fprintf(stderr, "ELF library initialization err, %s\n", elf_errmsg(-1));
perror("O/S Err:");
exit(EXIT_FAILURE);
} if ((fd = open(fname, O_RDONLY, 0)) < 0) {
fprintf(stderr, "Could not open %s\n", fname);
perror("O/S Err:");
exit(EXIT_FAILURE);
} if ((e = elf_begin(fd, ELF_C_READ, NULL))==NULL) {
fprintf(stderr, "Could not run elf_begin, %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
}
 
ek = elf_kind(e);
if (ek == ELF_K_ELF) {
; // This is the kind of file we should expect
} else if (ek == ELF_K_AR) {
fprintf(stderr, "Cannot run an archive!\n");
exit(EXIT_FAILURE);
} else if (ek == ELF_K_NONE) {
;
} else {
fprintf(stderr, "Unexpected ELF file kind!\n");
exit(EXIT_FAILURE);
}
 
if (gelf_getehdr(e, &ehdr) == NULL) {
fprintf(stderr, "getehdr() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
} if ((i=gelf_getclass(e)) == ELFCLASSNONE) {
fprintf(stderr, "getclass() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
} if ((id = elf_getident(e, NULL)) == NULL) {
fprintf(stderr, "getident() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
} if (i != ELFCLASS32) {
fprintf(stderr, "This is a 64-bit ELF file, ZipCPU ELF files are all 32-bit\n");
exit(EXIT_FAILURE);
}
 
if (dbg) {
printf(" %-20s 0x%jx\n", "e_type", (uintmax_t)ehdr.e_type);
printf(" %-20s 0x%jx\n", "e_machine", (uintmax_t)ehdr.e_machine);
printf(" %-20s 0x%jx\n", "e_version", (uintmax_t)ehdr.e_version);
printf(" %-20s 0x%jx\n", "e_entry", (uintmax_t)ehdr.e_entry);
printf(" %-20s 0x%jx\n", "e_phoff", (uintmax_t)ehdr.e_phoff);
printf(" %-20s 0x%jx\n", "e_shoff", (uintmax_t)ehdr.e_shoff);
printf(" %-20s 0x%jx\n", "e_flags", (uintmax_t)ehdr.e_flags);
printf(" %-20s 0x%jx\n", "e_ehsize", (uintmax_t)ehdr.e_ehsize);
printf(" %-20s 0x%jx\n", "e_phentsize", (uintmax_t)ehdr.e_phentsize);
printf(" %-20s 0x%jx\n", "e_shentsize", (uintmax_t)ehdr.e_shentsize);
printf("\n");
}
 
 
// Check whether or not this is an ELF file for the ZipCPU ...
if (ehdr.e_machine != 0x0dadd) {
fprintf(stderr, "This is not a ZipCPU ELF file\n");
exit(EXIT_FAILURE);
}
 
// Get our entry address
entry = ehdr.e_entry;
 
 
// Now, let's go look at the program header
if (elf_getphdrnum(e, &n) != 0) {
fprintf(stderr, "elf_getphdrnum() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
}
 
unsigned total_octets = 0, current_offset=0, current_section=0;
for(i=0; i<(int)n; i++) {
total_octets += sizeof(SECTION *)+sizeof(SECTION);
 
if (gelf_getphdr(e, i, &phdr) != &phdr) {
fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
}
 
if (dbg) {
printf(" %-20s 0x%x\n", "p_type", phdr.p_type);
printf(" %-20s 0x%jx\n", "p_offset", phdr.p_offset);
printf(" %-20s 0x%jx\n", "p_vaddr", phdr.p_vaddr);
printf(" %-20s 0x%jx\n", "p_paddr", phdr.p_paddr);
printf(" %-20s 0x%jx\n", "p_filesz", phdr.p_filesz);
printf(" %-20s 0x%jx\n", "p_memsz", phdr.p_memsz);
printf(" %-20s 0x%x [", "p_flags", phdr.p_flags);
 
if (phdr.p_flags & PF_X) printf(" Execute");
if (phdr.p_flags & PF_R) printf(" Read");
if (phdr.p_flags & PF_W) printf(" Write");
printf("]\n");
printf(" %-20s 0x%jx\n", "p_align", phdr.p_align);
}
 
total_octets += phdr.p_memsz;
}
 
char *d = (char *)malloc(total_octets + sizeof(SECTION)+sizeof(SECTION *));
memset(d, 0, total_octets);
 
SECTION **r = sections = (SECTION **)d;
current_offset = (n+1)*sizeof(SECTION *);
current_section = 0;
 
for(i=0; i<(int)n; i++) {
r[i] = (SECTION *)(&d[current_offset]);
 
if (gelf_getphdr(e, i, &phdr) != &phdr) {
fprintf(stderr, "getphdr() failed: %s\n", elf_errmsg(-1));
exit(EXIT_FAILURE);
}
 
if (dbg) {
printf(" %-20s 0x%jx\n", "p_offset", phdr.p_offset);
printf(" %-20s 0x%jx\n", "p_vaddr", phdr.p_vaddr);
printf(" %-20s 0x%jx\n", "p_paddr", phdr.p_paddr);
printf(" %-20s 0x%jx\n", "p_filesz", phdr.p_filesz);
printf(" %-20s 0x%jx\n", "p_memsz", phdr.p_memsz);
printf(" %-20s 0x%x [", "p_flags", phdr.p_flags);
 
if (phdr.p_flags & PF_X) printf(" Execute");
if (phdr.p_flags & PF_R) printf(" Read");
if (phdr.p_flags & PF_W) printf(" Write");
printf("]\n");
 
printf(" %-20s 0x%jx\n", "p_align", phdr.p_align);
}
 
current_section++;
 
r[i]->m_start = phdr.p_vaddr;
r[i]->m_len = phdr.p_filesz/ sizeof(FPGA::BUSW);
 
current_offset += phdr.p_memsz + sizeof(SECTION);
 
// Now, let's read in our section ...
if (lseek(fd, phdr.p_offset, SEEK_SET) < 0) {
fprintf(stderr, "Could not seek to file position %08lx\n", phdr.p_offset);
perror("O/S Err:");
exit(EXIT_FAILURE);
} if (phdr.p_filesz > phdr.p_memsz)
phdr.p_filesz = 0;
if (read(fd, r[i]->m_data, phdr.p_filesz) != (int)phdr.p_filesz) {
fprintf(stderr, "Didnt read entire section\n");
perror("O/S Err:");
exit(EXIT_FAILURE);
}
 
// Next, we need to byte swap it from big to little endian
for(unsigned j=0; j<r[i]->m_len; j++)
r[i]->m_data[j] = byteswap(r[i]->m_data[j]);
 
if (dbg) for(unsigned j=0; j<r[i]->m_len; j++)
fprintf(stderr, "ADR[%04x] = %08x\n", r[i]->m_start+j,
r[i]->m_data[j]);
}
 
r[i] = (SECTION *)(&d[current_offset]);
r[current_section]->m_start = 0;
r[current_section]->m_len = 0;
 
elf_end(e);
close(fd);
}
#endif
 
void usage(void) {
printf("USAGE: ziprun [-h] [<bit-file> [<alt-bit-file>]] <zip-program-file>\n");
printf("\n"
"\t-h\tDisplay this usage statement\n");
}
 
int main(int argc, char **argv) {
int skp=0;
bool permit_raw_files = false;
unsigned entry = RAMBASE;
FLASHDRVR *flash = NULL;
const char *bitfile = NULL, *altbitfile = NULL;
 
if (argc < 2) {
usage();
exit(EXIT_SUCCESS);
}
 
skp=1;
for(int argn=0; argn<argc-skp; argn++) {
if (argv[argn+skp][0] == '-') {
switch(argv[argn+skp][1]) {
case 'h':
usage();
exit(EXIT_SUCCESS);
case 'r':
permit_raw_files = true;
break;
} skp++; argn--;
} else { // Check for bit files
int sl = strlen(argv[argn+skp]);
if ((sl>4)&&(strcmp(&argv[argn+skp][sl-4],".bit")==0)) {
if (bitfile == NULL)
bitfile = argv[argn+skp];
else if (altbitfile == NULL)
altbitfile = argv[argn+skp];
else {
fprintf(stderr, "Err: Too many bit files listed\n");
exit(EXIT_FAILURE);
} skp++; argn--;
} else
argv[argn] = argv[argn+skp];
}
} argc -= skp;
 
 
if ((bitfile)&&(access(bitfile,R_OK)!=0)) {
fprintf(stderr, "Cannot open bitfile, %s\n", bitfile);
exit(EXIT_FAILURE);
} if ((altbitfile)&&(access(altbitfile,R_OK)!=0)) {
fprintf(stderr, "Cannot open alternate bitfile, %s\n",
altbitfile);
exit(EXIT_FAILURE);
} if(((!bitfile)&&(argc<=0)) || ((argc>0)&&(access(argv[0],R_OK)!=0))) {
// If there's no code file, or the code file cannot be opened
if (argc>0)
fprintf(stderr, "Cannot open executable, %s\n", argv[0]);
else
usage();
exit(EXIT_FAILURE);
}
 
const char *codef = (argc>0)?argv[0]:NULL;
DEVBUS::BUSW *fbuf = new DEVBUS::BUSW[FLASHWORDS];
 
// Set the flash buffer to all ones
memset(fbuf, -1, FLASHWORDS*sizeof(fbuf[0]));
 
{
char szSel[64];
strcpy(szSel, "SN:210282768825");
m_fpga = new FPGA(new DEPPI(szSel));
}
 
flash = new FLASHDRVR(m_fpga);
 
// First, see if we need to load a bit file
if (bitfile) {
int len;
FILE *fp = fopen(bitfile, "rb");
 
fseek(fp, 0x5dl, SEEK_SET);
len = fread(&fbuf[CONFIG_ADDRESS-SPIFLASH],
sizeof(fbuf[0]),
FLASHWORDS-(CONFIG_ADDRESS-SPIFLASH), fp);
assert(len + CONFIG_ADDRESS < ALTCONFIG_ADDRESS);
fclose(fp);
 
for(int i=0; i<4; i++) {
// printf("0x%08x\n", fbuf[i]);
assert(fbuf[i] == 0x0ffffffff);
} // printf("0x%08x\n", fbuf[4]);
assert(fbuf[4] == 0x0665599aa);
 
printf("Loading: %s\n", bitfile);
if (!flash->write(CONFIG_ADDRESS, len, &fbuf[CONFIG_ADDRESS-SPIFLASH], true)) {
fprintf(stderr, "Could not write primary bitfile\n");
exit(EXIT_FAILURE);
}
} if (altbitfile) {
int len;
FILE *fp = fopen(altbitfile, "rb");
 
// The alternate configuration follows the first configuration
len = fread(&fbuf[ALTCONFIG_ADDRESS-SPIFLASH],
sizeof(fbuf[0]),
FLASHWORDS-(ALTCONFIG_ADDRESS-SPIFLASH), fp);
assert(len + ALTCONFIG_ADDRESS < RESET_ADDRESS);
fclose(fp);
printf("Loading: %s\n", altbitfile);
 
if (!flash->write(ALTCONFIG_ADDRESS, len, &fbuf[ALTCONFIG_ADDRESS-SPIFLASH], true)) {
fprintf(stderr, "Could not write alternate bitfile\n");
exit(EXIT_FAILURE);
}
}
 
if (codef) try {
SECTION **secpp = NULL, *secp;
 
if(iself(codef)) {
// zip-readelf will help with both of these ...
elfread(codef, entry, secpp);
assert(entry == RESET_ADDRESS);
} else if (permit_raw_files) {
secpp = rawsection(codef);
entry = RESET_ADDRESS;
} else {
fprintf(stderr, "ERR: %s is not in ELF format\n", codef);
exit(EXIT_FAILURE);
}
 
printf("Loading: %s\n", codef);
// assert(secpp[1]->m_len = 0);
for(int i=0; secpp[i]->m_len; i++) {
bool valid = false;
secp= secpp[i];
if ((secp->m_start >= RESET_ADDRESS)
&&(secp->m_start+secp->m_len
<= SPIFLASH+FLASHWORDS))
valid = true;
if (!valid) {
fprintf(stderr, "No such memory on board: 0x%08x - %08x\n",
secp->m_start, secp->m_start+secp->m_len);
exit(EXIT_FAILURE);
}
}
 
for(int i=0; secpp[i]->m_len; i++) {
secp = secpp[i];
if (!flash->write(secp->m_start, secp->m_len, secp->m_data, true)) {
fprintf(stderr, "ERR: Could not write program to flash\n");
exit(EXIT_FAILURE);
}
}
m_fpga->readio(R_VERSION); // Check for bus errors
 
// Now ... how shall we start this CPU?
printf("The CPU should be fully loaded, you may now start\n");
printf("it. To start the CPU, either toggle power or type\n");
printf("%% wbregs fpgagen1 0 \n");
printf("%% wbregs fpgagen2 0x0300 \n");
printf("%% wbregs fpgacmd 14 \n");
} catch(BUSERR a) {
fprintf(stderr, "XULA-BUS error: %08x\n", a.addr);
exit(-2);
}
 
delete m_fpga;
 
return EXIT_SUCCESS;
}
 
/deppi.h
0,0 → 1,83
////////////////////////////////////////////////////////////////////////////////
//
// Filename: deppi.h
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: This package attempts to convet a DEPP over USB based
// communication system into something similar to a serial port
// based communication system. Some differences include the fact that,
// if the DEPP port isn't polled, nothing comes out of the port. Hence,
// on connecting (or polling for the first time) ... there might be a
// bunch of stuff to (initially) ignore.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef DEPPI_H
#define DEPPI_H
 
#include "dpcdecl.h"
#include "dmgr.h"
// #include "devbus.h"
 
//
#define PKTLEN 32
#define RCV_BUFLEN 512
#define RCV_BUFMASK (RCV_BUFLEN-1)
 
#include "llcomms.h"
 
class DEPPI : public LLCOMMSI { // DEPP Interface
private:
HIF m_dev;
bool m_int, m_err;
char m_rbuf[RCV_BUFLEN];
char m_txbuf[2*PKTLEN], m_rxbuf[2*PKTLEN];
int m_rbeg, m_rend;
 
virtual int pop_fifo(char *buf, int len);
virtual void push_fifo(char *buf, int len);
virtual void raw_read(int len, int timeout_ms);
virtual void flush_read(void);
void depperr(void);
 
public:
DEPPI(char *szSel);
~DEPPI(void);
 
virtual void close(void);
virtual int read(char *buf, int len);
virtual int read(char *buf, int len, int timeout_ms);
virtual void write(char *buf, int len);
virtual bool poll(unsigned ms);
};
 
#endif // DEPPI_H
 
/llcomms.cpp
0,0 → 1,150
////////////////////////////////////////////////////////////////////////////////
//
// Filename: llcomms.cpp
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: This defines a C++ interface on the command side that can
// interact with an FPGA, both sending and receiving characters.
// Any bus interaction will call routines from this lower level
// library to accomplish the actual connection to and
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <poll.h>
#include <ctype.h>
 
#include "llcomms.h"
 
LLCOMMSI::LLCOMMSI(void) {
m_fdw = -1;
m_fdr = -1;
m_total_nread = 0l;
m_total_nwrit = 0l;
}
 
void LLCOMMSI::write(char *buf, int len) {
int nw;
nw = ::write(m_fdw, buf, len);
m_total_nwrit += nw;
assert(nw == len);
}
 
int LLCOMMSI::read(char *buf, int len) {
int nr;
nr = ::read(m_fdr, buf, len);
m_total_nread += nr;
return nr;
}
 
void LLCOMMSI::close(void) {
if(m_fdw>=0) ::close(m_fdw);
if((m_fdr>=0)&&(m_fdr != m_fdw)) ::close(m_fdr);
m_fdw = m_fdr = -1;
}
 
bool LLCOMMSI::poll(unsigned ms) {
struct pollfd fds;
 
fds.fd = m_fdr;
fds.events = POLLIN;
::poll(&fds, 1, ms);
 
if (fds.revents & POLLIN) {
return true;
} else return false;
}
 
TTYCOMMS::TTYCOMMS(const char *dev) {
m_fdr = ::open(dev, O_RDWR | O_NONBLOCK);
if (m_fdr < 0) {
printf("\n Error : Could not open %s\n", dev);
perror("O/S Err:");
exit(-1);
}
 
if (isatty(m_fdr)) {
struct termios tb;
tcgetattr(m_fdr, &tb);
cfmakeraw(&tb);
// tb.c_iflag &= (~(IXON|IXOFF));
tb.c_cflag &= (~(CRTSCTS));
tcsetattr(m_fdr, TCSANOW, &tb);
tcflow(m_fdr, TCOON);
}
 
m_fdw = m_fdr;
}
 
NETCOMMS::NETCOMMS(const char *host, const int port) {
struct sockaddr_in serv_addr;
struct hostent *hp;
 
if ((m_fdr = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n");
exit(-1);
}
 
memset(&serv_addr, '0', sizeof(serv_addr));
 
hp = gethostbyname(host);
if (hp == NULL) {
printf("Could not get host entity for %s\n", host);
perror("O/S Err:");
exit(-1);
}
bcopy(hp->h_addr, &serv_addr.sin_addr.s_addr, hp->h_length);
 
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
 
if (connect(m_fdr,(struct sockaddr *)&serv_addr, sizeof(serv_addr))< 0){
perror("Connect Failed Err");
exit(-1);
}
 
m_fdw = m_fdr;
}
 
/llcomms.h
0,0 → 1,70
////////////////////////////////////////////////////////////////////////////////
//
// Filename: llcomms.h
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: This defines a C++ interface on the command side that can
// interact with an FPGA, both sending and receiving characters.
// Any bus interaction will call routines from this lower level
// library to accomplish the actual connection to and
// transmission to/from the board.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#ifndef LLCOMMS_H
#define LLCOMMS_H
 
class LLCOMMSI {
protected:
int m_fdw, m_fdr;
LLCOMMSI(void);
public:
unsigned long m_total_nread, m_total_nwrit;
 
virtual ~LLCOMMSI(void) { close(); }
virtual void kill(void) { this->close(); };
virtual void close(void);
virtual void write(char *buf, int len);
virtual int read(char *buf, int len);
virtual bool poll(unsigned ms);
};
 
class TTYCOMMS : public LLCOMMSI {
public:
TTYCOMMS(const char *dev);
};
 
class NETCOMMS : public LLCOMMSI {
public:
NETCOMMS(const char *dev, const int port);
};
 
#endif
/regdefs.h
102,34 → 102,35
// RAM memory space
#define RAMBASE 0x00002000
#define MEMWORDS (1<<12)
#define RAMLEN MEMWORDS
 
// Flash memory space
#define SPIFLASH 0x00040000
#define FLASHWORDS (1<<18)
// SDRAM memory space
#define SDRAMBASE 0x00400000
#define SDRAMWORDS (1<<24)
#define SPIFLASH 0x00400000
#define FLASHWORDS (1<<22)
#define CONFIG_ADDRESS 0x00400000 // Main Xilinx configuration (ZipCPU)
#define ALTCONFIG_ADDRESS 0x440000 // Alternate Xilinx configuration (Debug)
#define RESET_ADDRESS 0x00480000 // ZipCPU Reset address
 
// Interrupt control constants
// #define GIE 0x80000000 // Enable all interrupts
// #define SCOPEN 0x80080008 // Enable WBSCOPE interrupts
// #define ISPIF_EN 0x80040004 // Enable SPI Flash interrupts
// #define ISPIF_DIS 0x00040000 // Disable SPI Flash interrupts
// #define ISPIF_CLR 0x00000004 // Clear pending SPI Flash interrupt
#define GIE 0x80000000 // Enable all interrupts
#define SCOPEN 0x80040004 // Enable WBSCOPE interrupts
#define ISPIF_EN 0x90001000 // Enable SPI Flash interrupts
#define ISPIF_DIS 0x10000000 // Disable SPI Flash interrupts
#define ISPIF_CLR 0x10001000 // Clear pending SPI Flash interrupt
 
// Flash control constants
#define ERASEFLAG 0x80000000
#define DISABLEWP 0x10000000
 
#define SZPAGE 64
#define PGLEN 64
#define NPAGES 32
// Sectors are defined as 64 kB (16 kW)
#define SZPAGE 64 // 256 bytes
#define PGLEN 64 // 256 bytes
#define NPAGES 256 // 64 kB sectors / 256 bytes is ...
#define SECTORSZ (NPAGES * SZPAGE)
#define NSECTORS 256
#define SECTOROF(A) ((A) & (-1<<10))
#define NSECTORS (FLASHWORDS/SECTORSZ) // 256 sectors
#define SECTOROF(A) ((A) & (-1<<14)) // 64 kB ea
#define PAGEOF(A) ((A) & (-1<<6))
 
#define RAMLEN MEMWORDS
 
// Scop definition/sequences
#define SCOPE_NO_RESET 0x80000000
#define SCOPE_TRIGGER (0x08000000|SCOPE_NO_RESET)
152,5 → 153,7
// #include "deppbus.h"
 
// typedef DEPPBUS FPGA;
#include "ttybus.h"
typedef TTYBUS FPGA;
 
#endif
/wbregs.cpp
48,11 → 48,25
#include <signal.h>
#include <assert.h>
 
#include "deppbus.h"
#include "devbus.h"
 
#ifdef SIMPLE_DEPPBUS
# include "deppbus.h"
#else
# include "llcomms.h"
# include "deppi.h"
# include "ttybus.h"
 
#endif
 
// #include "port.h"
#include "regdefs.h"
 
typedef DEPPBUS FPGA;
#ifdef SIMPLE_DEPPBUS
# define FPGAOPEN(SN) new DEPPBUS(SN);
#else
# define FPGAOPEN(SN) new FPGA(new DEPPI(SN))
#endif
 
FPGA *m_fpga;
void closeup(int v) {
75,10 → 89,6
argv[argn] = argv[argn+skp];
} argc -= skp;
 
char szSel[64];
strcpy(szSel, "SN:210282768825");
m_fpga = new DEPPBUS(szSel);
 
signal(SIGSTOP, closeup);
signal(SIGHUP, closeup);
 
94,6 → 104,10
if (nm == NULL)
nm = "no name";
 
char szSel[64];
strcpy(szSel, "SN:210282768825");
m_fpga = FPGAOPEN(szSel);
 
if (argc < 2) {
FPGA::BUSW v;
try {
/readflash.cpp
0,0 → 1,126
////////////////////////////////////////////////////////////////////////////////
//
// Filename: readflash.cpp
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: Read/Empty the entire contents of the flash memory to a file.
// The flash is unchanged by this process.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <assert.h>
 
#include "devbus.h"
#include "llcomms.h"
#include "deppi.h"
#include "ttybus.h"
#include "regdefs.h"
 
#define FPGAOPEN(SN) new FPGA(new DEPPI(SN))
 
FPGA *m_fpga;
void closeup(int v) {
m_fpga->kill();
exit(0);
}
 
// #define DUMPMEM RAMBASE
// #define DUMPWORDS MEMWORDS
 
#define DUMPMEM SPIFLASH
#define DUMPWORDS FLASHWORDS // 1MB Flash
 
int main(int argc, char **argv) {
FILE *fp;
const int BUFLN = DUMPWORDS;
FPGA::BUSW *buf = new FPGA::BUSW[BUFLN];
 
char szSel[64];
strcpy(szSel, "SN:210282768825");
m_fpga = FPGAOPEN(szSel);
 
fprintf(stderr, "Before starting, nread = %ld\n",
m_fpga->m_total_nread);
 
// Start with testing the version:
printf("VERSION: %08x\n", m_fpga->readio(R_VERSION));
 
// SPI flash testing
// Enable the faster (vector) reads
bool vector_read = true;
unsigned sz;
 
if (vector_read) {
try {
for(int i=0; i<BUFLN; i+= 2048) {
printf("i = %02x / %04x, addr = i + %04x = %08x\n", i, BUFLN, DUMPMEM, i+DUMPMEM);
m_fpga->readi(DUMPMEM+i, 2048, &buf[i]);
}} catch(BUSERR a) {
printf("%08x : BUS-ERR\n", a.addr);
}
} else {
for(int i=0; i<BUFLN; i++) {
buf[i] = m_fpga->readio(DUMPMEM+i);
// if (0 == (i&0x0ff))
printf("i = %02x / %04x, addr = i + %04x = %08x\n", i, BUFLN, DUMPMEM, i+DUMPMEM);
}
}
printf("\nREAD-COMPLETE\n");
 
// Now, let's find the end
sz = BUFLN-1;
while((sz>0)&&(buf[sz] == 0xffffffff))
sz--;
sz+=1;
printf("The size of the buffer is 0x%06x or %d words\n", sz, sz);
 
fp = fopen("qspiflash.bin","w");
fwrite(buf, sizeof(buf[0]), sz, fp);
fclose(fp);
 
printf("The read was accomplished in %ld bytes over the UART\n",
m_fpga->m_total_nread);
 
if (m_fpga->poll())
printf("FPGA was interrupted\n");
delete m_fpga;
}
 
 
/ttybus.cpp
0,0 → 1,631
////////////////////////////////////////////////////////////////////////////////
//
// Filename: ttybus.cpp
//
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: This is the C++ program on the command side that will interact
// with a serial port (through DEPP) on an FPGA, to command the
// WISHBONE on that same FPGA to ... whatever we wish to command it to do.
//
// This code does not run on an FPGA, is not a test bench, neither is it
// a simulator. It is a portion of a command program for commanding an
// FPGA from an attached host computer.
//
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): 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 program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <assert.h>
#include <strings.h>
#include <poll.h>
#include <ctype.h>
 
#include "ttybus.h"
 
#define TTYC_IDLE '0'
#define TTYC_BUSY '1'
#define TTYC_WRITE '2'
#define TTYC_RESET '3'
#define TTYC_INT '4'
#define TTYC_ERR '5'
 
const unsigned TTYBUS::MAXRDLEN = 1024;
const unsigned TTYBUS::MAXWRLEN = 32;
 
#define DBGPRINTF null
// #define DBGPRINTF printf
// #define DBGPRINTF filedump
 
void null(...) {}
#include <stdarg.h>
// #include <varargs.h>
/*
void filedump(const char *fmt, ...) {
static FILE *dbgfp = NULL;
va_list args;
 
if (!dbgfp)
dbgfp = fopen("debug.txt", "w");
va_start(args, fmt);
vfprintf(dbgfp, fmt, args);
va_end(args);
fflush(dbgfp);
}
*/
 
char TTYBUS::charenc(const int sixbitval) const {
if (sixbitval < 10)
return '0' + sixbitval;
else if (sixbitval < 10+26)
return 'A' - 10 + sixbitval;
else if (sixbitval < 10+26+26)
return 'a' - 10 - 26 + sixbitval;
else if (sixbitval == 0x3e)
return '@';
else if (sixbitval == 0x3f)
return '%';
 
fprintf(stderr, "INTERNAL ERR: SIXBITVAL isn\'t!!!! sixbitval = %08x\n", sixbitval);
assert((sixbitval & (~0x03f))==0);
return 0;
}
 
unsigned TTYBUS::chardec(const char b) const {
if ((b >= '0')&&(b <= '9'))
return b-'0';
else if ((b >= 'A')&&(b <= 'Z'))
return b-'A'+10;
else if ((b >= 'a')&&(b <= 'z'))
return b-'a'+36;
else if (b == '@')
return 0x03e;
else if (b == '%')
return 0x03f;
else
return 0x0100; // ERR -- invalid code
}
 
int TTYBUS::lclreadcode(char *buf, int len) {
char *sp, *dp;
int nr, ret;
 
nr = m_dev->read(buf, len);
m_total_nread += nr;
ret = nr; sp = buf; dp = buf;
for(int i=0; i<nr; i++) {
if (chardec(*sp)&(~0x3f)) {
ret--; // Skip this value, not a valid codeword
sp++;
} else {
*sp++ = *dp++;
}
} return ret;
}
 
void TTYBUS::bufalloc(int len) {
if ((m_buf)&&(m_buflen >= len))
return;
if (m_buf)
delete[] m_buf;
m_buflen = (len&(-0x3f))+0x40;
m_buf = new char[m_buflen];
}
 
void TTYBUS::encode(const int hb, const BUSW val, char *buf) const {
buf[0] = charenc( (hb<<2)|((val>>30)&0x03) );
buf[1] = charenc( (val>>24)&0x3f);
buf[2] = charenc( (val>>18)&0x3f);
buf[3] = charenc( (val>>12)&0x3f);
buf[4] = charenc( (val>> 6)&0x3f);
buf[5] = charenc( (val )&0x3f);
}
 
unsigned TTYBUS::decodestr(const char *buf) const {
unsigned r;
 
r = chardec(buf[0]) & 0x03;
r = (r<<6) | (chardec(buf[1]) & 0x03f);
r = (r<<6) | (chardec(buf[2]) & 0x03f);
r = (r<<6) | (chardec(buf[3]) & 0x03f);
r = (r<<6) | (chardec(buf[4]) & 0x03f);
r = (r<<6) | (chardec(buf[5]) & 0x03f);
 
return r;
}
 
int TTYBUS::decodehex(const char hx) const {
if ((hx >= '0')&&(hx <= '9'))
return hx-'0';
else if ((hx >= 'A')&&(hx <= 'Z'))
return hx-'A'+10;
else if ((hx >= 'a')&&(hx <= 'z'))
return hx-'a'+10;
else
return 0;
}
 
void TTYBUS::writeio(const BUSW a, const BUSW v) {
 
writev(a, 0, 1, &v);
m_lastaddr = a; m_addr_set = true;
}
 
void TTYBUS::writev(const BUSW a, const int p, const int len, const BUSW *buf) {
char *ptr;
 
// Allocate a buffer of six bytes per word, one for addr, plus
// six more
bufalloc((len+2)*6);
 
DBGPRINTF("WRITEV(%08x,%d,#%d,0x%08x ...)\n", a, p, len, buf[0]);
// Encode the address
ptr = encode_address(a);
m_lastaddr = a; m_addr_set = true;
 
for(int i=0; i<len; i++) {
BUSW val = buf[i];
 
int caddr = 0;
// Let's try compression
for(int i=1; i<256; i++) {
unsigned tstaddr;
tstaddr = (m_wraddr - i) & 0x0ff;
if ((!m_wrloaded)&&(tstaddr > (unsigned)m_wraddr))
break;
if (m_writetbl[tstaddr] == val) {
caddr = ( m_wraddr- tstaddr ) & 0x0ff;
break;
}
}
 
if (caddr != 0)
DBGPRINTF("WR[%08x] = %08x (= TBL[%4x] <= %4x)\n", m_lastaddr, val, caddr, m_wraddr);
else
DBGPRINTF("WR[%08x] = %08x\n", m_lastaddr, val);
 
if (caddr != 0) {
*ptr++ = charenc( (((caddr>>6)&0x03)<<1) + (p?1:0) + 0x010);
*ptr++ = charenc( caddr &0x3f );
} else {
// For testing, let's start just doing this the hard way
*ptr++ = charenc( (((val>>30)&0x03)<<1) + (p?1:0) + 0x018);
*ptr++ = charenc( (val>>24)&0x3f);
*ptr++ = charenc( (val>>18)&0x3f);
*ptr++ = charenc( (val>>12)&0x3f);
*ptr++ = charenc( (val>> 6)&0x3f);
*ptr++ = charenc( (val )&0x3f);
 
m_writetbl[m_wraddr++] = val;
m_wraddr &= 0x0ff;
if (m_wraddr == 0) {
m_wrloaded = true;
}
}
 
if (p == 1) m_lastaddr++;
}
// *ptr++ = charenc(0x2e);
*ptr++ = '\n'; *ptr = '\0';
m_dev->write(m_buf, ptr-m_buf);
 
DBGPRINTF(">> %s\n", m_buf);
DBGPRINTF("WR: LAST ADDRESS LEFT AT %08x\n", m_lastaddr);
}
 
void TTYBUS::writez(const BUSW a, const int len, const BUSW *buf) {
int ln = len;
const TTYBUS::BUSW *bptr = buf;
TTYBUS::BUSW addr = a;
 
while((unsigned)ln > MAXWRLEN) {
writev(addr, 0, MAXWRLEN, bptr);
bptr += MAXWRLEN;
ln -= MAXWRLEN;
// addr += MAXWRLEN;
} if ((unsigned)ln > 0)
writev(addr, 0, ln, bptr);
}
 
void TTYBUS::writei(const BUSW a, const int len, const BUSW *buf) {
int ln = len;
const TTYBUS::BUSW *bptr = buf;
TTYBUS::BUSW addr = a;
 
while((unsigned)ln > MAXWRLEN) {
writev(addr, 1, MAXWRLEN, bptr);
bptr += MAXWRLEN;
ln -= MAXWRLEN;
addr += MAXWRLEN;
} if ((unsigned)ln > 0)
writev(addr, 1, ln, bptr);
}
 
TTYBUS::BUSW TTYBUS::readio(const TTYBUS::BUSW a) {
BUSW v;
 
// I/O reads are now the same as vector reads, but with a vector length
// of one.
DBGPRINTF("READIO(0x%08x)\n", a);
try {
readv(a, 0, 1, &v);
} catch(BUSERR b) {
throw BUSERR(a);
}
 
if (m_lastaddr != a) {
DBGPRINTF("LAST-ADDR MIS-MATCH: (RCVD) %08x != %08x (XPECTED)\n", m_lastaddr, a);
m_addr_set = false;
 
exit(-3);
}
 
return v;
}
 
char *TTYBUS::encode_address(const TTYBUS::BUSW a) {
TTYBUS::BUSW addr = a;
char *ptr = m_buf;
 
// #warning DEBUG_APPROACH
// encode(0, addr, ptr);
// return ptr+6;
 
if ((m_addr_set)&&(a == m_lastaddr))
return ptr;
if (m_addr_set) {
// Encode a difference address
int diffaddr = addr - m_lastaddr;
ptr = m_buf;
if ((diffaddr >= -32)&&(diffaddr < 32)) {
*ptr++ = charenc(0x09);
*ptr++ = charenc(diffaddr & 0x03f);
} else if ((diffaddr >= -2048)&&(diffaddr < 2048)) {
*ptr++ = charenc(0x0b);
*ptr++ = charenc((diffaddr>>6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
} else if ((diffaddr >= -(1<<17))&&(diffaddr < (1<<17))) {
*ptr++ = charenc(0x0d);
*ptr++ = charenc((diffaddr>>12) & 0x03f);
*ptr++ = charenc((diffaddr>> 6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
} else if ((diffaddr >= -(1<<23))&&(diffaddr < (1<<23))) {
*ptr++ = charenc(0x0d);
*ptr++ = charenc((diffaddr>>18) & 0x03f);
*ptr++ = charenc((diffaddr>>12) & 0x03f);
*ptr++ = charenc((diffaddr>> 6) & 0x03f);
*ptr++ = charenc( diffaddr & 0x03f);
}
*ptr = '\0';
DBGPRINTF("DIF-ADDR: (%ld) \'%s\'\n", ptr-m_buf, m_buf);
}
 
{
// Encode an absolute (low memory) address
// Prefer absolute address encoding over differential encoding,
// when both encodings encode the same address, and when both
// encode the address in the same number of words
if ((addr <= 0x03f)&&((ptr == m_buf)||(ptr >= &m_buf[2]))) {
ptr = m_buf;
*ptr++ = charenc(0x08);
*ptr++ = charenc(addr);
} else if((addr <= 0x0fff)&&((ptr == m_buf)||(ptr >= &m_buf[3]))) {
DBGPRINTF("Setting ADDR.3 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0a);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if((addr <= 0x03ffff)&&((ptr == m_buf)||(ptr >= &m_buf[4]))) {
DBGPRINTF("Setting ADDR.4 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0c);
*ptr++ = charenc((addr>>12) & 0x03f);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if((addr <= 0x0ffffff)&&((ptr == m_buf)||(ptr >= &m_buf[5]))) {
DBGPRINTF("Setting ADDR.5 to %08x\n", addr);
ptr = m_buf;
*ptr++ = charenc(0x0e);
*ptr++ = charenc((addr>>18) & 0x03f);
*ptr++ = charenc((addr>>12) & 0x03f);
*ptr++ = charenc((addr>> 6) & 0x03f);
*ptr++ = charenc( addr & 0x03f);
} else if (ptr == m_buf) { // Send our address prior to any read
// ptr = m_buf;
encode(0, addr, ptr);
ptr+=6;
}
}
 
*ptr = '\0';
DBGPRINTF("ADDR-CMD: (%ld) \'%s\'\n", ptr-m_buf, m_buf);
m_rdaddr = 0;
 
return ptr;
}
 
char *TTYBUS::readcmd(const int inc, const int len, char *buf) {
char *ptr = buf;
 
DBGPRINTF("READCMD: LEN = %d\n", len);
assert(len < 520);
assert(len > 0);
 
if ((len < 8)||((len == 8)&&(inc))) {
*ptr++ = charenc(0x20 + (((len-1)&0x07)<<1) + (inc?1:0));
} else {
*ptr++ = charenc(0x30 + (((len-8)>>5)&0x0e) + (inc?1:0));
*ptr++ = charenc( (len-8) & 0x03f);
}
 
return ptr;
}
 
void TTYBUS::readv(const TTYBUS::BUSW a, const int inc, const int len, TTYBUS::BUSW *buf) {
const int READAHEAD = MAXRDLEN/2, READBLOCK=MAXRDLEN/2;
int cmdrd = 0, nread = 0;
// TTYBUS::BUSW addr = a;
char *ptr = m_buf;
 
if (len <= 0)
return;
DBGPRINTF("READV(%08x,%d,#%4d)\n", a, inc, len);
 
ptr = encode_address(a);
try {
while(cmdrd < len) {
// ptr = m_buf;
do {
int nrd = len-cmdrd;
if (nrd > READBLOCK)
nrd = READBLOCK;
if (cmdrd-nread + nrd>READAHEAD+READBLOCK)
nrd = READAHEAD+READBLOCK-(cmdrd-nread);
ptr = readcmd(inc, nrd, ptr);
cmdrd += nrd;
} while((cmdrd-nread < READAHEAD+READBLOCK)&&(cmdrd< len));
 
*ptr++ = '\n'; *ptr = '\0';
m_dev->write(m_buf, (ptr-m_buf));
 
while(nread<(cmdrd-READAHEAD)) {
buf[nread++] = readword();
} ptr = m_buf;
} while(nread<len) {
buf[nread++] = readword();
}
} catch(BUSERR b) {
throw BUSERR(a+((inc)?nread:0));
}
if ((unsigned)m_lastaddr != (a+((inc)?(len):0))) {
DBGPRINTF("TTYBUS::READV(a=%08x,inc=%d,len=%4x,x) ERR: (Last) %08x != %08x + %08x (Expected)\n", a, inc, len, m_lastaddr, a, (inc)?(len):0);
printf("TTYBUS::READV(a=%08x,inc=%d,len=%4x,x) ERR: (Last) %08x != %08x + %08x (Expected)\n", a, inc, len, m_lastaddr, a, (inc)?(len):0);
sleep(1);
assert((int)m_lastaddr == (a+(inc)?(len):0));
exit(-3);
}
}
 
void TTYBUS::readi(const TTYBUS::BUSW a, const int len, TTYBUS::BUSW *buf) {
readv(a, 1, len, buf);
}
 
void TTYBUS::readz(const TTYBUS::BUSW a, const int len, TTYBUS::BUSW *buf) {
readv(a, 0, len, buf);
}
 
TTYBUS::BUSW TTYBUS::readword(void) {
TTYBUS::BUSW val = 0;
int nr;
unsigned sixbits;
 
DBGPRINTF("READ-WORD()\n");
 
bool found_start = false;
do {
// Blocking read (for now)
do {
nr = lclreadcode(&m_buf[0], 1);
} while (nr < 1);
 
sixbits = chardec(m_buf[0]);
 
if (sixbits&(~0x03f)) {
// Ignore new lines, unprintables, and characters
// not a part of our code
;
} else if (sixbits < 6) {
switch(sixbits) {
case 0: break; // Idle -- ignore
case 1: break; // Idle, but the bus is busy
case 2: break; // Write acknowledgement, ignore it here
case 3:
m_bus_err = true;
throw BUSERR(0);
break;
case 4:
m_interrupt_flag = true;
break;
case 5:
m_bus_err = true;
throw BUSERR(0);
break;
}
} else if (0x08 == (sixbits & 0x3c)) { // Set 32-bit address
do {
nr += lclreadcode(&m_buf[nr], 6-nr);
} while (nr < 6);
 
val = chardec(m_buf[0]) & 0x03;
val = (val<<6) | (chardec(m_buf[1]) & 0x03f);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
val = (val<<6) | (chardec(m_buf[5]) & 0x03f);
 
m_addr_set = true;
m_lastaddr = val;
 
DBGPRINTF("RCVD ADDR: 0x%08x\n", val);
} else if (0x0c == (sixbits & 0x03c)) { // Set 32-bit address,compressed
int nw = (sixbits & 0x03) + 2;
do {
nr += lclreadcode(&m_buf[nr], nw-nr);
} while (nr < nw);
 
if (nw == 2) {
val = chardec(m_buf[1]);
} else if (nw == 3) {
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
} else if (nw == 4) {
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
} else { // if (nw == 5)
val = chardec(m_buf[1]);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
}
 
m_addr_set = true;
m_lastaddr = val;
DBGPRINTF("RCVD ADDR: 0x%08x (%d bytes)\n", val, nw+1);
} else
found_start = true;
} while(!found_start);
 
int rdaddr;
 
DBGPRINTF("READ-WORD() -- sixbits = %02x\n", sixbits);
if (0x06 == (sixbits & 0x03e)) { // Tbl read, last value
rdaddr = (m_rdaddr-1)&0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
DBGPRINTF("READ-WORD() -- repeat last value, %08x\n", val);
} else if (0x10 == (sixbits & 0x030)) { // Tbl read, up to 521 into past
int idx;
do {
nr += lclreadcode(&m_buf[nr], 2-nr);
} while (nr < 2);
 
idx = (chardec(m_buf[0])>>1) & 0x07;
idx = ((idx<<6) | (chardec(m_buf[1]) & 0x03f)) + 2 + 8;
rdaddr = (m_rdaddr-idx)&0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
DBGPRINTF("READ-WORD() -- long table value[%3d], %08x\n", idx, val);
} else if (0x20 == (sixbits & 0x030)) { // Tbl read, 2-9 into past
rdaddr = (m_rdaddr - (((sixbits>>1)&0x07)+2)) & 0x03ff;
val = m_readtbl[rdaddr];
m_lastaddr += (sixbits&1);
DBGPRINTF("READ-WORD() -- short table value[%3d], %08x\n", rdaddr, val);
} else if (0x38 == (sixbits & 0x038)) { // Raw read
DBGPRINTF("READ-WORD() -- RAW-READ, nr = %d\n", nr);
do {
nr += lclreadcode(&m_buf[nr], 6-nr);
} while (nr < 6);
 
val = (chardec(m_buf[0])>>1) & 0x03;
val = (val<<6) | (chardec(m_buf[1]) & 0x03f);
val = (val<<6) | (chardec(m_buf[2]) & 0x03f);
val = (val<<6) | (chardec(m_buf[3]) & 0x03f);
val = (val<<6) | (chardec(m_buf[4]) & 0x03f);
val = (val<<6) | (chardec(m_buf[5]) & 0x03f);
 
m_readtbl[m_rdaddr++] = val; m_rdaddr &= 0x03ff;
m_lastaddr += (sixbits&1);
DBGPRINTF("READ-WORD() -- RAW-READ %02x:%02x:%02x:%02x:%02x:%02x -- %08x\n",
m_buf[0], m_buf[1], m_buf[2], m_buf[3],
m_buf[4], m_buf[5], val);
} else
DBGPRINTF("READ-WORD() -- Unknown character, %02x\n", sixbits);
 
return val;
}
 
void TTYBUS::usleep(unsigned ms) {
if (m_dev->poll(ms)) {
int nr;
nr = m_dev->read(m_buf, 16);
if (nr == 0) {
// Connection closed, let it drop
DBGPRINTF("Connection closed!!\n");
m_dev->close();
exit(-1);
} for(int i=0; i<nr; i++) {
if (m_buf[i] == TTYC_INT) {
m_interrupt_flag = true;
DBGPRINTF("!!!!!!!!!!!!!!!!! ----- INTERRUPT!\n");
} else if (m_buf[i] == TTYC_IDLE) {
DBGPRINTF("Interface is now idle\n");
} else if (m_buf[i] == TTYC_WRITE) {
} else if (m_buf[i] == TTYC_RESET) {
DBGPRINTF("Bus was RESET!\n");
} else if (m_buf[i] == TTYC_ERR) {
DBGPRINTF("Bus error\n");
} else if (m_buf[i] == TTYC_BUSY) {
DBGPRINTF("Interface is ... busy ??\n");
}
// else if (m_buf[nr] == 'Q')
// else if (m_buf[nr] == 'W')
// else if (m_buf[nr] == '\n')
}
}
}
 
void TTYBUS::wait(void) {
if (m_interrupt_flag)
DBGPRINTF("INTERRUPTED PRIOR TO WAIT()\n");
do {
usleep(200);
} while(!m_interrupt_flag);
}
 
// TTYBUS: 3503421 ~= 3.3 MB, stopwatch = 1:18.5 seconds, vs 53.8 secs
// If you issue two 512 word reads at once, time drops to 41.6 secs.
// PORTBUS: 6408320 ~= 6.1 MB, ... 26% improvement, 53 seconds real time
 
/flashdrvr.cpp
40,7 → 40,7
#include <signal.h>
#include <assert.h>
 
#include "port.h"
#include "devbus.h"
#include "regdefs.h"
#include "flashdrvr.h"
 
133,9 → 133,10
// command immediately. As soon as the write completes the read will
// begin sending commands back. This allows us to recover the lost
// time between the interrupt and the next command being received.
if ((!HIGH_SPEED)||(!verify_write)) {
flwait();
} if (verify_write) {
flwait();
// if ((!HIGH_SPEED)||(!verify_write)) { }
if (verify_write) {
// printf("Attempting to verify page\n");
// NOW VERIFY THE PAGE
m_fpga->readi(addr, len, buf);
for(unsigned i=0; i<len; i++) {
145,7 → 146,7
i, buf[i], data[i], i+addr);
return false;
}
}
} // printf("\nVerify success\n");
} return true;
}
 
194,21 → 195,26
continue; // This sector already matches
 
// Just erase anyway
if ((need_erase)&&(!erase_sector(s, verify))) {
printf("SECTOR ERASE FAILED!\n");
return false;
} else if (!need_erase)
if (!need_erase)
printf("NO ERASE NEEDED\n");
else {
printf("ERASING SECTOR %08x\n", s);
newv = (s<addr) ? addr : s;
if (!erase_sector(s, verify)) {
printf("SECTOR ERASE FAILED!\n");
return false;
} newv = (s<addr) ? addr : s;
}
for(unsigned p=newv; (p<s+SECTORSZ)&&(p<addr+len); p=PAGEOF(p+PGLEN))
if (!write_page(p, (p+PGLEN<addr+len)
?((PAGEOF(p)!=PAGEOF(p+PGLEN-1))?(PAGEOF(p+PGLEN-1)-p):PGLEN)
:(addr+len-p), &data[p-addr]), verify) {
for(unsigned p=newv; (p<s+SECTORSZ)&&(p<addr+len); p=PAGEOF(p+PGLEN)) {
unsigned start = p, len = addr+len-start;
 
// BUT! if we cross page boundaries, we need to clip
// our results to the page boundary
if (PAGEOF(start+len-1)!=PAGEOF(start))
len = PAGEOF(start+PGLEN)-start;
if (!write_page(start, len, &data[p-addr], verify)) {
printf("WRITE-PAGE FAILED!\n");
return false;
}
}
}
 
/Makefile
1,11 → 1,12
all:
PROGRAMS := wbregs
PROGRAMS := wbregs readflash zipload
all: $(PROGRAMS)
 
CXX := g++
OBJDIR := obj-pc
BUSSRCS:= deppbus.cpp regdefs.cpp
SOURCES:= wbregs.cpp # flashload.cpp/ziprun.cpp
# BUSSRCS:= deppbus.cpp regdefs.cpp
BUSSRCS:= deppi.cpp regdefs.cpp llcomms.cpp ttybus.cpp
SOURCES:= wbregs.cpp readflash.cpp zipload.cpp flashdrvr.cpp # flashload.cpp/ziprun.cpp
ADEPT := ../../../refs/digilent.adept.sdk_2.3.1
HEADERS:= deppbus.h devbus.h flashdrvr.h regdefs.h twoc.h
OBJECTS:= $(addprefix $(OBJDIR)/,$(subst .cpp,.o,$(SOURCES)))
24,9 → 25,15
wbregs: $(OBJDIR)/wbregs.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
 
readflash: $(OBJDIR)/readflash.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -o $@
 
zipload: $(OBJDIR)/zipload.o $(OBJDIR)/flashdrvr.o $(BUSOBJS)
$(CXX) $(CFLAGS) $^ $(LIBS) -lelf -o $@
 
define build-depends
@echo "Building dependency file(s)"
@$(CXX) $(CFLAGS) -MM $(SOURCES) > $(OBJDIR)/xdepends.txt
@$(CXX) $(CFLAGS) -MM $(SOURCES) $(BUSSRCS) > $(OBJDIR)/xdepends.txt
@sed -e 's/^.*.o: /$(OBJDIR)\/&/' < $(OBJDIR)/xdepends.txt > $(OBJDIR)/depends.txt
@rm $(OBJDIR)/xdepends.txt
endef
/devbus.h
2,7 → 2,7
//
// Filename: devbus.h
//
// Project: XuLA2 board
// Project: CMod S6 System on a Chip, ZipCPU demonstration project
//
// Purpose: The purpose of this file is to document an interface which
// any device with a bus, whether it be implemented over a UART,
22,7 → 22,7
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
34,6 → 34,11
// 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 along
// with this program. (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.) If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License: GPL, v3, as defined and found on www.gnu.org,
// http://www.gnu.org/licenses/gpl.html
//

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.