aboutsummaryrefslogtreecommitdiff
path: root/stm-ice40mkm.c
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2021-12-20 12:52:23 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2021-12-20 12:52:23 +0300
commit200a616758fa9c7aa83737e9620fb6a927d0c45a (patch)
treef6d998e5f03edf130f10838d2c7d4982c631bd47 /stm-ice40mkm.c
parente3a5752a303dff144dec71f909b5721cf2ffdb64 (diff)
Reworked the way iCE40-based MKM is configured. The bitmap is now stored rightice40mkm
after the main FPGA's bitstream (was placed at the very end of the configuration memory previously). This makes it possible to flash two devices at the same time, but needs a somewhat smarter supporting routine. Instead of just looking at the very last sector of the config memy we now to need to swipe through all the sectors looking for the Lattice magic bitmap marker to determine where the MKM firmware starts.
Diffstat (limited to 'stm-ice40mkm.c')
-rw-r--r--stm-ice40mkm.c52
1 files changed, 34 insertions, 18 deletions
diff --git a/stm-ice40mkm.c b/stm-ice40mkm.c
index 5a03525..a7eb9a9 100644
--- a/stm-ice40mkm.c
+++ b/stm-ice40mkm.c
@@ -92,10 +92,10 @@ int ice40mkm_configure(void)
size_t c;
uint8_t prom_buf[N25Q128_PAGE_SIZE];
uint8_t prom_marker[] = ICE40_MAGIC_MARKER;
- int prom_marker_bad = 0, cdone_state;
+ int prom_marker_bad = 1, cdone_state;
- uint32_t prom_addr, prom_offset = N25Q128_SECTOR_SIZE *
- (N25Q128_NUM_SECTORS - ICE40_BITSTREAM_SECTORS);
+
+ uint32_t prom_addr, prom_sector_index;
uint32_t page, num_pages = ICE40_BITSTREAM_SECTORS *
(N25Q128_SECTOR_SIZE / N25Q128_PAGE_SIZE);
@@ -124,8 +124,8 @@ int ice40mkm_configure(void)
/*
* device is now ready to receive the bitstream
*
- * the bitstream is stored in the last two sectors of the main
- * FPGA configuration memory
+ * the mkm bitmap is stored right after the main bitstream and is aligned
+ * on sector boundary
*
* the very first page of the bitstream starts with a magic marker,
* which can be used to detect whether the bitstream is present
@@ -135,26 +135,44 @@ int ice40mkm_configure(void)
fpgacfg_access_control(ALLOW_ARM);
/*
- * read the bitstream page-by-page and send it over SPI3
+ * first read the very first page of each sector to find the offset of
+ * the mkm bitmap, skip the very first sector (there's no
+ * sane way for the mkm bitmap may start there)
+ *
+ * then read the bitstream page-by-page and send it over SPI3
+ *
* note, that bitstream is slightly smaller than two sectors, so we're
* sending some 0xFF's after the binary image, which is harmless
* (just some dummy clock cycles)
*/
- prom_addr = prom_offset;
- for (page=0; page<num_pages; page++)
+ for (prom_sector_index = 1; prom_sector_index < N25Q128_NUM_SECTORS; prom_sector_index += 1)
{
/* read next page */
+ prom_addr = prom_sector_index * N25Q128_SECTOR_SIZE;
prom_ok = fpgacfg_read_data(prom_addr, prom_buf, N25Q128_PAGE_SIZE);
if (prom_ok != HAL_OK) break;
/* check magic marker */
- if (page == 0) {
- for (c=0; c<sizeof prom_marker; c++)
- if (prom_buf[c] != prom_marker[c]) {
- prom_marker_bad = 1;
- break;
- }
- }
+ prom_marker_bad = 0;
+ for (c=0; c<sizeof prom_marker; c++)
+ if (prom_buf[c] != prom_marker[c]) {
+ prom_marker_bad = 1;
+ break;
+ }
+
+ /* mkm bitmap found! */
+ if (!prom_marker_bad) break;
+ }
+
+ /* check, that magic marker was correct */
+ if (prom_marker_bad) return 2;
+
+ /* send the mkm bitmap */
+ for (page=0; page<num_pages; page++)
+ {
+ /* read next page */
+ prom_ok = fpgacfg_read_data(prom_addr, prom_buf, N25Q128_PAGE_SIZE);
+ if (prom_ok != HAL_OK) break;
/* send page to iCE40 */
prom_ok = HAL_SPI_Transmit(&hspi_ice40mkm, prom_buf, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT);
@@ -167,10 +185,8 @@ int ice40mkm_configure(void)
/* relinquish access to FPGA config storage */
fpgacfg_access_control(ALLOW_FPGA);
- /* check, that magic marker was correct */
/* check, that all the pages were written */
- if (prom_marker_bad) return 2;
- else if (page != num_pages) return 1;
+ if (page != num_pages) return 1;
/* clear chip-select */
_ice40mkm_chip_deselect();