anlogic: add SPI flash support
This commit is contained in:
parent
bfd7e9b6ed
commit
3349e65079
161
src/anlogic.cpp
161
src/anlogic.cpp
|
|
@ -21,6 +21,7 @@
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "progressBar.hpp"
|
#include "progressBar.hpp"
|
||||||
|
#include "spiFlash.hpp"
|
||||||
|
|
||||||
#define REFRESH 0x01
|
#define REFRESH 0x01
|
||||||
#define IDCODE 0x06
|
#define IDCODE 0x06
|
||||||
|
|
@ -32,13 +33,19 @@
|
||||||
|
|
||||||
#define IRLENGTH 8
|
#define IRLENGTH 8
|
||||||
|
|
||||||
Anlogic::Anlogic(Jtag *jtag, const std::string &filename, bool verbose):
|
Anlogic::Anlogic(Jtag *jtag, const std::string &filename,
|
||||||
|
bool flash_wr, bool sram_wr, bool verbose):
|
||||||
Device(jtag, filename, verbose), _svf(_jtag, _verbose)
|
Device(jtag, filename, verbose), _svf(_jtag, _verbose)
|
||||||
{
|
{
|
||||||
if (_filename != "") {
|
if (_filename != "") {
|
||||||
if (_file_extension == "svf" || _file_extension == "bit")
|
if (_file_extension == "svf")
|
||||||
_mode = Device::MEM_MODE;
|
_mode = Device::MEM_MODE;
|
||||||
else
|
else if (_file_extension == "bit") {
|
||||||
|
if (sram_wr)
|
||||||
|
_mode = Device::MEM_MODE;
|
||||||
|
else
|
||||||
|
_mode = Device::SPI_MODE;
|
||||||
|
} else
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,13 +65,57 @@ void Anlogic::program(unsigned int offset)
|
||||||
{
|
{
|
||||||
if (_mode == Device::NONE_MODE)
|
if (_mode == Device::NONE_MODE)
|
||||||
return;
|
return;
|
||||||
if (_mode == Device::MEM_MODE) {
|
|
||||||
if (_file_extension == "svf") {
|
if (_file_extension == "svf") {
|
||||||
_svf.parse(_filename);
|
_svf.parse(_filename);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnlogicBitParser bit(_filename, (_mode == Device::MEM_MODE), _verbose);
|
||||||
|
bit.parse();
|
||||||
|
uint8_t *data = bit.getData();
|
||||||
|
int len = bit.getLength() / 8;
|
||||||
|
|
||||||
|
if (_mode == Device::SPI_MODE) {
|
||||||
|
SPIFlash flash(this, _verbose);
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
|
//Verify Device id.
|
||||||
|
//SIR 8 TDI (06) ;
|
||||||
|
//SDR 32 TDI (00000000) TDO (0a014c35) MASK (ffffffff) ;
|
||||||
|
//Boundary Scan Chain Contents
|
||||||
|
//Position 1: BG256
|
||||||
|
//Loading device with 'refresh' instruction.
|
||||||
|
_jtag->shiftIR(REFRESH, IRLENGTH);
|
||||||
|
//Loading device with 'bypass' & 'spi_program' instruction.
|
||||||
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
|
_jtag->shiftIR(SPI_PROGRAM, IRLENGTH);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
_jtag->toggleClk(50000);
|
||||||
|
|
||||||
|
flash.reset();
|
||||||
|
flash.read_id();
|
||||||
|
flash.read_status_reg();
|
||||||
|
|
||||||
|
flash.erase_and_prog(offset, data, len);
|
||||||
|
|
||||||
|
//Loading device with 'bypass' instruction.
|
||||||
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
|
////Loading device with 'refresh' instruction.
|
||||||
|
_jtag->shiftIR(REFRESH, IRLENGTH);
|
||||||
|
_jtag->toggleClk(20);
|
||||||
|
////Loading device with 'bypass' instruction.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
|
_jtag->toggleClk(20);
|
||||||
}
|
}
|
||||||
AnlogicBitParser bit(_filename, _verbose);
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
bit.parse();
|
_jtag->toggleClk(10000);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_mode == Device::MEM_MODE) {
|
||||||
|
|
||||||
// Loading device with 'bypass' instruction.
|
// Loading device with 'bypass' instruction.
|
||||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||||
|
|
@ -87,8 +138,6 @@ void Anlogic::program(unsigned int offset)
|
||||||
_jtag->shiftIR(CFG_IN, IRLENGTH);
|
_jtag->shiftIR(CFG_IN, IRLENGTH);
|
||||||
_jtag->toggleClk(15);
|
_jtag->toggleClk(15);
|
||||||
|
|
||||||
uint8_t *data = bit.getData();
|
|
||||||
int len = bit.getLength() / 8;
|
|
||||||
_jtag->set_state(Jtag::SHIFT_DR);
|
_jtag->set_state(Jtag::SHIFT_DR);
|
||||||
ProgressBar progress("Loading", len, 50);
|
ProgressBar progress("Loading", len, 50);
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
@ -136,3 +185,93 @@ int Anlogic::idCode()
|
||||||
((rx_data[2] << 16) & 0x00ff0000) |
|
((rx_data[2] << 16) & 0x00ff0000) |
|
||||||
((rx_data[3] << 24) & 0xff000000));
|
((rx_data[3] << 24) & 0xff000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* SPI wrapper
|
||||||
|
* For read operation a delay of one bit is added
|
||||||
|
* So add one bit more and move everything by one
|
||||||
|
* In write only operations to care about this delay
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Anlogic::spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
|
{
|
||||||
|
int xfer_len = len + 1;
|
||||||
|
if (rx)
|
||||||
|
xfer_len++;
|
||||||
|
uint8_t jtx[xfer_len];
|
||||||
|
uint8_t jrx[xfer_len];
|
||||||
|
|
||||||
|
jtx[0] = AnlogicBitParser::reverseByte(cmd);
|
||||||
|
if (tx != NULL) {
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
jtx[i+1] = AnlogicBitParser::reverseByte(tx[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write anlogic command before sending packet */
|
||||||
|
uint8_t op = 0x60;
|
||||||
|
_jtag->shiftDR(&op, NULL, 8);
|
||||||
|
|
||||||
|
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*xfer_len);
|
||||||
|
if (rx != NULL) {
|
||||||
|
for (int i=0; i < len; i++)
|
||||||
|
rx[i] = AnlogicBitParser::reverseByte(jrx[i+1]>>1)
|
||||||
|
| (jrx[i+2]&0x01);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int Anlogic::spi_put(uint8_t *tx, uint8_t *rx, uint32_t len)
|
||||||
|
{
|
||||||
|
int xfer_len = len;
|
||||||
|
if (rx)
|
||||||
|
xfer_len++;
|
||||||
|
uint8_t jtx[xfer_len];
|
||||||
|
uint8_t jrx[xfer_len];
|
||||||
|
|
||||||
|
if (tx != NULL) {
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
jtx[i] = AnlogicBitParser::reverseByte(tx[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write anlogic command before sending packet */
|
||||||
|
uint8_t op = 0x60;
|
||||||
|
_jtag->shiftDR(&op, NULL, 8);
|
||||||
|
|
||||||
|
_jtag->shiftDR(jtx, (rx == NULL)? NULL: jrx, 8*xfer_len);
|
||||||
|
if (rx != NULL) {
|
||||||
|
for (int i=0; i < len; i++)
|
||||||
|
rx[i] = AnlogicBitParser::reverseByte(jrx[i]>>1) |
|
||||||
|
(jrx[i+1]&0x01);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int Anlogic::spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
|
uint32_t timeout, bool verbose)
|
||||||
|
{
|
||||||
|
uint8_t rx[3];
|
||||||
|
uint8_t tx[3];
|
||||||
|
tx[0] = AnlogicBitParser::reverseByte(cmd);
|
||||||
|
uint8_t op = 0x60;
|
||||||
|
uint8_t tmp;
|
||||||
|
uint32_t count = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
_jtag->shiftDR(&op, NULL, 8);
|
||||||
|
_jtag->shiftDR(tx, rx, 8 * 3);
|
||||||
|
tmp = (AnlogicBitParser::reverseByte(rx[1]>>1)) | (0x01 & rx[2]);
|
||||||
|
count ++;
|
||||||
|
if (count == timeout) {
|
||||||
|
printf("timeout: %x %x %x\n", tmp, rx[0], rx[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (verbose) {
|
||||||
|
printf("%x %x %x %u\n", tmp, mask, cond, count);
|
||||||
|
}
|
||||||
|
} while ((tmp & mask) != cond);
|
||||||
|
|
||||||
|
if (count == timeout) {
|
||||||
|
printf("%02x\n", tmp);
|
||||||
|
std::cout << "wait: Error" << std::endl;
|
||||||
|
return -ETIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,25 @@
|
||||||
#include "bitparser.hpp"
|
#include "bitparser.hpp"
|
||||||
#include "device.hpp"
|
#include "device.hpp"
|
||||||
#include "jtag.hpp"
|
#include "jtag.hpp"
|
||||||
|
#include "spiInterface.hpp"
|
||||||
#include "svf_jtag.hpp"
|
#include "svf_jtag.hpp"
|
||||||
|
|
||||||
class Anlogic: public Device {
|
class Anlogic: public Device, SPIInterface {
|
||||||
public:
|
public:
|
||||||
Anlogic(Jtag *jtag, const std::string &filename, bool verbose);
|
Anlogic(Jtag *jtag, const std::string &filename,
|
||||||
|
bool flash_wr, bool sram_wr, bool verbose);
|
||||||
~Anlogic();
|
~Anlogic();
|
||||||
|
|
||||||
void program(unsigned int offset = 0) override;
|
void program(unsigned int offset = 0) override;
|
||||||
int idCode() override;
|
int idCode() override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
|
/* spi interface */
|
||||||
|
int spi_put(uint8_t cmd, uint8_t *tx, uint8_t *rx,
|
||||||
|
uint32_t len) override;
|
||||||
|
int spi_put(uint8_t *tx, uint8_t *rx, uint32_t len) override;
|
||||||
|
int spi_wait(uint8_t cmd, uint8_t mask, uint8_t cond,
|
||||||
|
uint32_t timeout, bool verbose=false) override;
|
||||||
private:
|
private:
|
||||||
SVF_jtag _svf;
|
SVF_jtag _svf;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue