From 803bdfeccea09652c924e7e74493d4825b380f05 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 18 Jun 2025 18:57:26 +0200 Subject: [PATCH] altera: MAX10: added --flash-sector support with arbitrary binary file --- doc/figs/max10_flash-memory.png | Bin 0 -> 18923 bytes doc/vendors/intel.rst | 70 +++++++++---- src/altera.cpp | 173 +++++++++++++++++++++++--------- src/altera.hpp | 13 ++- 4 files changed, 190 insertions(+), 66 deletions(-) create mode 100644 doc/figs/max10_flash-memory.png diff --git a/doc/figs/max10_flash-memory.png b/doc/figs/max10_flash-memory.png new file mode 100644 index 0000000000000000000000000000000000000000..657d12f6ad9a2abd47588cfcb8fa764147437861 GIT binary patch literal 18923 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 DI6X=D literal 0 HcmV?d00001 diff --git a/doc/vendors/intel.rst b/doc/vendors/intel.rst index 464c58c..00d9cd6 100644 --- a/doc/vendors/intel.rst +++ b/doc/vendors/intel.rst @@ -93,12 +93,32 @@ Supported Boards: Supported File Types: * ``svf`` -* ``svf`` +* ``pof`` * ``bin`` (arbitrary binary files) +Internal Flash Organization +--------------------------- + +The internal flash is divided into five sections: + +- ``UFM1`` and ``UFM0`` for user data +- ``CFM2``, ``CFM1``, and ``CFM0`` for storing one or two bitstreams + +.. image:: ../figs/max10_flash-memory.png + :alt: max10 internal flash memory structure + +Flash usage depends on the configuration mode. In all modes: + +- ``CFM0`` is used to store a bitstream +- ``UFM0`` and ``UFM1`` are available for user data +- The remaining ``CFMx`` sections (``CFM1``, ``CFM2``) can be used for + additional bitstreams or user data + Using ``svf`` ------------- +This method is the **simplest** (and slowest) way to load or write a bitstream. + .. note:: This method is required to load a bitstream into *SRAM*. @@ -107,7 +127,7 @@ Using ``svf`` openFPGALoader [-b boardname] -c cablename the_svf_file.svf -Parameters: +**Parameters:** * ``boardname``: One of the boards supported by ``openFPGALoader`` (optional). * ``cablename``: One of the supported cables (see ``--list-cables``). @@ -115,53 +135,69 @@ Parameters: Using ``pof`` ------------- -When writing the bitstream to internal flash, using a ``pof`` file is the fastest approach. +To write a bitstream into the internal flash, using a ``pof`` file is the +**fastest** approach. .. code-block:: bash openFPGALoader [-b boardname] [--flash-sector] -c cablename the_pof_file.pof -Parameters: +**Parameters:** -* ``boardname``: One of the boards supported by ``openFPGALoader`` (optional). +* ``boardname``: A board supported by ``openFPGALoader`` (optional). * ``cablename``: One of the supported cables (see ``--list-cables``). -* ``--flash-sector``: Specifies which internal flash sectors to erase/update instead of modifying the entire flash. One - or more section may be provided, with ``,`` as separator. When this option isn't provided a full internal flash erase/ - update is performed +* ``--flash-sector``: Optional. Comma-separated list of sectors to update. + If omitted, the entire flash is erased and reprogrammed. Accepted Flash Sectors: * ``UFM0``, ``UFM1``: User Flash Memory sections. * ``CFM0``, ``CFM1``, ``CFM2``: Configuration Flash Memory sectors. -Example: +**Example:** .. code-block:: bash openFPGALoader -c usb-blaster --flash-sector UFM1,CFM0,CFM2 the_pof_file.pof -This command updates ``UFM1``, ``CFM0``, and ``CFM2``, while leaving other sectors unchanged. +This command updates ``UFM1``, ``CFM0``, and ``CFM2``, leaving all other +sectors unchanged. Using an arbitrary binary file ------------------------------ -This command updates only *User Flash Memory* sectors without modifying ``CFMx``. Unlike Altera Quartus, it supports -any binary format without limitations (not limited to a ``.bin``. +Unlike Altera Quartus, it supports any binary format without limitations +(not limited to a ``.bin``). +With this feature, it's not required to provides the file at gateware build +time: it may be updated at any time without gateware modification/rebuild. .. note:: This approach is useful to updates, for example, a softcore CPU firmware. +**Basic usage:** + .. code-block:: bash - openFPGALoader [-b boardname] -c cablename the_bin_file.bin + openFPGALoader [-b boardname] -c cablename [--offset $OFFSET] the_bin_file.bin -* ``boardname``: One of the boards supported by ``openFPGALoader`` (optional). +* ``boardname``: a boards supported by ``openFPGALoader`` (optional). * ``cablename``: One of the supported cables (see ``--list-cables``). +* ``$OFFSET``: To start writing ``$OFFSET`` bytes after *User Flash memory* + start address (optional, default: 0x00). -Behavior: +This command erases and writes the contents of ``the_bin_file.bin`` into +``UFM1`` and ``UFM0``. If ``--offset`` is specified, the binary content is +written starting from that offset. -``UFM0`` and ``UFM1`` will be erased before writing the binary file. +Depending on the max10 configuration mode (see picture), it's possible to +extend *User Flash Memory* area by using `CFM2` and `CFM1`. This is not the +default behavior and user must explictly change this by using +`--flash-sector` argument: -.. note:: Depending on the internal flash configuration, ``CFM1`` and ``CFM2`` may also store arbitrary data. However, currently, ``openFPGALoader`` only supports writing to ``UFMx``. +* ``--flash-sector UFMx`` or ``--flash-sector CFMy`` (with x= 1 or 0 and + y = 2 or 1) to specify only one sector +* ``--flash-sector UFM1,UFM0`` is equivalent to the default behavior +* ``--flash-sector UFM1,CFM2`` to erase and update ``UFM1``, ``UFM0`` + and ``CFM2`` (equivalent to ``--flash-sector UFM1,UFM0,CFM2``) Intel/Altera (Old Boards) ========================= diff --git a/src/altera.cpp b/src/altera.cpp index 22ac908..448c317 100644 --- a/src/altera.cpp +++ b/src/altera.cpp @@ -341,17 +341,47 @@ const std::map Altera::max10_memory_map = { }, }; -/* Write an arbitrary file in UFM1 and UFM0 - * FIXME: in some mode its also possible to uses CFM2 & CFM1 +/* Write an arbitrary file in UFM1, UFM0 by default and also CFM2 and CFM1 if + * requested. */ -bool Altera::max10_program_ufm(const Altera::max10_mem_t *mem, unsigned int offset) +bool Altera::max10_program_ufm(const Altera::max10_mem_t *mem, uint32_t offset, + uint8_t update_sectors) { + uint32_t start_addr = 0; // 32bit align + uint32_t end_addr = 0; // 32bit align + uint8_t erase_sectors_mask; + + /* check CFM0 is not mentionned */ + if (update_sectors & (1 << 4)) + std::runtime_error("Error: CFM0 cant't be used to store User Binary"); + + /* First task: search for the first and the last sector to use */ + sectors_mask_start_end_addr(mem, update_sectors, + &start_addr, &end_addr, &erase_sectors_mask); + RawParser _bit(_filename, true); _bit.parse(); - _bit.displayHeader(); + if (_verbose) + _bit.displayHeader(); + const uint8_t *data = _bit.getData(); const uint32_t length = _bit.getLength() / 8; - const uint32_t base_addr = mem->ufm_addr + offset; + const uint32_t base_addr = start_addr + offset / 4; // 32bit align + const uint32_t flash_len = (end_addr - base_addr) * 4; // Byte align + + /* check */ + if (base_addr > end_addr) { // wrong offset + printError("Error: start offset is out of xFM region"); + return false; + } + if (flash_len < length) { // too big file + printError("Error: no enough space to write\n"); + return false; + } + if (base_addr + (length / 4) > end_addr) { + printError("Error: end address is out of xFM region"); + return false; + } uint8_t *buff = (uint8_t *)malloc(length); if (!buff) { @@ -359,17 +389,6 @@ bool Altera::max10_program_ufm(const Altera::max10_mem_t *mem, unsigned int offs return false; } - /* check */ - const uint32_t ufmx_len = 4 * (mem->ufm_len[0] + mem->ufm_len[1]); - if (base_addr > length) { - printError("Error: start offset is out of UFM region"); - return false; - } - if (base_addr + length > ufmx_len) { - printError("Error: end address is out of UFM region"); - return false; - } - /* data needs to be re-ordered */ for (uint32_t i = 0; i < length; i+=4) { for (int b = 0; b < 4; b++) { @@ -377,18 +396,23 @@ bool Altera::max10_program_ufm(const Altera::max10_mem_t *mem, unsigned int offs } } + printf("%x %x %x %x\n", update_sectors, erase_sectors_mask, + base_addr, end_addr); + // Start! max10_flow_enable(); - /* Erase UFM1 & UFM0 */ - printInfo("Erase UFM ", false); - max10_flow_erase(mem, 0x3); + /* Erase xFM sectors */ + printInfo("Erase xFM ", false); + max10_flow_erase(mem, erase_sectors_mask); printInfo("Done"); - /* Program UFM1 & UFM0 */ + /* Program xFM */ // Simplify code: - // UFM0 follows UFM1, so we don't need to iterate - printInfo("Write UFM"); + // UFM0 follows UFM1, + // CFM2 follow UFM0, etc... + // so we don't need to iterate + printInfo("Write xFM"); writeXFM(buff, base_addr, 0, length / 4); /* Verify */ @@ -417,8 +441,12 @@ void Altera::max10_program(unsigned int offset) } const Altera::max10_mem_t mem = mem_map->second; + /* Check for a full update or only for a subset */ + update_sectors = max10_flash_sectors_to_mask(_flash_sectors); + if (_file_extension != "pof") { - max10_program_ufm(&mem, offset); + max10_program_ufm(&mem, offset, + (_flash_sectors.size() == 0) ? 0 : update_sectors); return; } @@ -471,10 +499,10 @@ void Altera::max10_program(unsigned int offset) // UFM Mapping ufm_data[1] = _bit.getData("UFM"); - ufm_data[0] = &ufm_data[1][mem.ufm_len[0] * 4]; // Just after UFM1 (but size may differs + ufm_data[0] = &ufm_data[1][mem.ufm_len[1] * 4]; // Just after UFM1 (but size may differs // CFM Mapping - cfm_data[2] = &ufm_data[0][mem.ufm_len[1] * 4]; // First CFM section in FPGA internal flash + cfm_data[2] = &ufm_data[0][mem.ufm_len[0] * 4]; // First CFM section in FPGA internal flash cfm_data[1] = &cfm_data[2][mem.cfm_len[2] * 4]; // Second CFM section but just after CFM2 cfm_data[0] = &cfm_data[1][mem.cfm_len[1] * 4]; // last CFM section but just after CFM1 @@ -482,28 +510,6 @@ void Altera::max10_program(unsigned int offset) const uint8_t *dsm_data = _bit.getData("ICB"); const int dsm_len = _bit.getLength("ICB") / 32; // getLength (bits) dsm_len in 32bits word - /* Check for a full update or only for a subset */ - if (_flash_sectors.size() > 0) { - const std::vector sectors = splitString(_flash_sectors, ','); - update_sectors = 0; - for (const auto §or: sectors) { - if (sector == "UFM1") - update_sectors |= (1 << 0); - else if (sector == "UFM0") - update_sectors |= (1 << 1); - else if (sector == "CFM2") - update_sectors |= (1 << 2); - else if (sector == "CFM1") - update_sectors |= (1 << 3); - else if (sector == "CFM0") - update_sectors |= (1 << 4); - else - throw std::runtime_error("Unknown sector " + sector); - } - } else { // full update - update_sectors = 0x1F; - } - // Start! max10_flow_enable(); @@ -913,6 +919,79 @@ bool Altera::max10_dump() return true; } +uint8_t Altera::max10_flash_sectors_to_mask(std::string flash_sectors) +{ + uint8_t mask = 0; + + if (flash_sectors.size() > 0) { + const std::vector sectors = splitString(flash_sectors, ','); + for (const auto §or: sectors) { + if (sector == "UFM1") + mask |= (1 << 0); + else if (sector == "UFM0") + mask |= (1 << 1); + else if (sector == "CFM2") + mask |= (1 << 2); + else if (sector == "CFM1") + mask |= (1 << 3); + else if (sector == "CFM0") + mask |= (1 << 4); + else + throw std::runtime_error("Unknown sector " + sector); + } + } else { // full update + mask = 0x1F; + } + + return mask; +} + +bool Altera::sectors_mask_start_end_addr(const Altera::max10_mem_t *mem, + const uint8_t update_sectors, uint32_t *start, uint32_t *end, + uint8_t *sectors_mask) +{ + uint32_t saddr = mem->ufm_addr; + uint32_t eaddr = saddr; + uint8_t start_bit = 0, end_bit = 0; + /* For sake of simplicity: create an array with all length aligned + * as it in MAX10 devices + */ + const uint32_t mem_map_length[] = { + mem->ufm_len[1], mem->ufm_len[0], + mem->cfm_len[2], mem->cfm_len[1] + }; + + if (update_sectors == 0) { + eaddr = mem->ufm_addr + (mem->ufm_len[0] + mem->ufm_len[1]); + *sectors_mask = 0x3; + } else { + /* eaddr start with full memory size */ + for (uint8_t i = 0; i < 4; i++) + eaddr += mem_map_length[i]; + /* search first bit == 1 and increment start address */ + for (uint8_t i = 0; i < 4; i++) { + if (update_sectors & (1 << i)) { + start_bit = i; + break; + } + saddr += mem_map_length[i]; + } + + /* decrement eaddr until last bit == 1 found */ + for (uint8_t i = 3; i >= 0; i--) { + if (update_sectors & (1 << i)) { + end_bit = i + 1; + break; + } + eaddr -= mem_map_length[i]; + } + *sectors_mask = ((1 << end_bit) - 1) - ((1 << start_bit) - 1); + } + *start = saddr; + *end = eaddr; + return true; +} + /* SPI interface */ int Altera::spi_put(uint8_t cmd, const uint8_t *tx, uint8_t *rx, uint32_t len) diff --git a/src/altera.hpp b/src/altera.hpp index 8c0e9f9..82a7bb7 100644 --- a/src/altera.hpp +++ b/src/altera.hpp @@ -97,13 +97,16 @@ class Altera: public Device, SPIInterface { /*************************/ /* max10 specific */ /*************************/ +public: struct max10_mem_t; +private: static const std::map max10_memory_map; /* Write a full POF file, or updates UFM with an arbitrary binary file */ void max10_program(uint32_t offset); /* Write something in UFMx sections after erase */ - bool max10_program_ufm(const max10_mem_t *mem, uint32_t offset); + bool max10_program_ufm(const max10_mem_t *mem, uint32_t offset, + uint8_t update_sectors); /* Write len Word from cfg_data at a specific address */ void writeXFM(const uint8_t *cfg_data, uint32_t base_addr, uint32_t offset, uint32_t len); /* Compare cfg_data with data stored at base_addr */ @@ -120,7 +123,13 @@ class Altera: public Device, SPIInterface { bool max10_dsm_verify(); bool max10_dump(); bool max10_read_section(FILE *fd, const uint32_t base_addr, const uint32_t addr); - + /* Utils methods */ +public: + static uint8_t max10_flash_sectors_to_mask(std::string flash_sectors); + static bool sectors_mask_start_end_addr(const Altera::max10_mem_t *mem, + const uint8_t update_sectors, uint32_t *start, uint32_t *end, + uint8_t *sectors_mask); +private: /*! * \brief with intel devices SPI flash direct access is not possible * so a bridge must be loaded in RAM to access flash