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 "device.hpp"
|
||||
#include "progressBar.hpp"
|
||||
#include "spiFlash.hpp"
|
||||
|
||||
#define REFRESH 0x01
|
||||
#define IDCODE 0x06
|
||||
|
|
@ -32,13 +33,19 @@
|
|||
|
||||
#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)
|
||||
{
|
||||
if (_filename != "") {
|
||||
if (_file_extension == "svf" || _file_extension == "bit")
|
||||
if (_file_extension == "svf")
|
||||
_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();
|
||||
}
|
||||
}
|
||||
|
|
@ -58,13 +65,57 @@ void Anlogic::program(unsigned int offset)
|
|||
{
|
||||
if (_mode == Device::NONE_MODE)
|
||||
return;
|
||||
if (_mode == Device::MEM_MODE) {
|
||||
if (_file_extension == "svf") {
|
||||
_svf.parse(_filename);
|
||||
return;
|
||||
|
||||
if (_file_extension == "svf") {
|
||||
_svf.parse(_filename);
|
||||
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);
|
||||
bit.parse();
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
_jtag->toggleClk(10000);
|
||||
|
||||
return;
|
||||
}
|
||||
if (_mode == Device::MEM_MODE) {
|
||||
|
||||
// Loading device with 'bypass' instruction.
|
||||
_jtag->shiftIR(BYPASS, IRLENGTH);
|
||||
|
|
@ -87,8 +138,6 @@ void Anlogic::program(unsigned int offset)
|
|||
_jtag->shiftIR(CFG_IN, IRLENGTH);
|
||||
_jtag->toggleClk(15);
|
||||
|
||||
uint8_t *data = bit.getData();
|
||||
int len = bit.getLength() / 8;
|
||||
_jtag->set_state(Jtag::SHIFT_DR);
|
||||
ProgressBar progress("Loading", len, 50);
|
||||
int pos = 0;
|
||||
|
|
@ -136,3 +185,93 @@ int Anlogic::idCode()
|
|||
((rx_data[2] << 16) & 0x00ff0000) |
|
||||
((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 "device.hpp"
|
||||
#include "jtag.hpp"
|
||||
#include "spiInterface.hpp"
|
||||
#include "svf_jtag.hpp"
|
||||
|
||||
class Anlogic: public Device {
|
||||
class Anlogic: public Device, SPIInterface {
|
||||
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();
|
||||
|
||||
void program(unsigned int offset = 0) override;
|
||||
int idCode() 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:
|
||||
SVF_jtag _svf;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue