ice40: add CRAM support

This commit is contained in:
Gwenhael Goavec-Merou 2022-01-18 08:08:48 +01:00
parent 6597dcf374
commit 60ba2b1ccc
2 changed files with 63 additions and 0 deletions

View File

@ -20,6 +20,7 @@
Ice40::Ice40(FtdiSpi* spi, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type,
uint16_t rst_pin, uint16_t done_pin,
bool verify, int8_t verbose):
Device(NULL, filename, file_type, verify, verbose), _rst_pin(rst_pin),
@ -28,6 +29,11 @@ Ice40::Ice40(FtdiSpi* spi, const std::string &filename,
_spi = spi;
_spi->gpio_set_input(_done_pin);
_spi->gpio_set_output(_rst_pin);
if (prg_type == Device::WR_FLASH)
_mode = Device::SPI_MODE;
else
_mode = Device::MEM_MODE;
}
Ice40::~Ice40()
@ -51,6 +57,56 @@ void Ice40::reset()
printSuccess("DONE");
}
bool Ice40::program_cram(uint8_t *data, uint32_t length)
{
uint32_t timeout = 1000;
/* configure SPI */
_spi->setMode(3); // IDLE high, write on falling
_spi->setCSmode(FtdiSpi::SPI_CS_MANUAL);
/* reset device */
_spi->clearCs();
_spi->gpio_clear(_rst_pin);
usleep(100); // 200 ns ...
_spi->gpio_set(_rst_pin);
usleep(2000); // 800 -> 1200 us + guard
/* load configuration data MSB first
*/
ProgressBar progress("Loading to CRAM", length, 50, _verbose);
uint8_t *ptr = data;
int size = 0;
for (uint32_t addr = 0; addr < length; addr += size, ptr+=size) {
size = (addr + 256 > length)?(length-addr) : 256;
if (_spi->spi_put(ptr, NULL, size) == -1)
return -1;
progress.display(addr);
}
progress.done();
/* send 48 to 100 dummy bits */
uint8_t dummy[12];
_spi->spi_put(dummy, NULL, 12);
/* wait CDONE */
usleep(12000);
printInfo("Wait for CDONE ", false);
do {
timeout--;
usleep(12000);
} while (((_spi->gpio_get(true) & _done_pin) == 0) && timeout > 0);
if (timeout == 0)
printError("FAIL");
else
printSuccess("DONE");
_spi->setCs();
return true;
}
void Ice40::program(unsigned int offset, bool unprotect_flash)
{
uint32_t timeout = 1000;
@ -71,6 +127,11 @@ void Ice40::program(unsigned int offset, bool unprotect_flash)
uint8_t *data = bit.getData();
int length = bit.getLength() / 8;
if (_mode == Device::MEM_MODE) {
program_cram(data, length);
return;
}
_spi->gpio_clear(_rst_pin);
SPIFlash flash(reinterpret_cast<SPIInterface *>(_spi), unprotect_flash,

View File

@ -16,11 +16,13 @@ class Ice40: public Device, SPIInterface {
public:
Ice40(FtdiSpi *spi, const std::string &filename,
const std::string &file_type,
Device::prog_type_t prg_type,
uint16_t rst_pin, uint16_t done_pin,
bool verify, int8_t verbose);
~Ice40();
void program(unsigned int offset, bool unprotect_flash) override;
bool program_cram(uint8_t *data, uint32_t length);
bool dumpFlash(uint32_t base_addr, uint32_t len);
bool protect_flash(uint32_t len) override;
bool unprotect_flash() override;