From bad51b7760722c1435d2ec04e4a6cc70eb905f77 Mon Sep 17 00:00:00 2001 From: Nate Meyer Date: Mon, 6 Oct 2025 20:37:50 -0400 Subject: [PATCH 1/3] Upgrade SPIflash to handle new litespi register map. Add GW_ID field to device status. Fix bug parsing bitstream length. --- bindings/python/tslitex.pxd | 1 + example/thunderscope_fw.cpp | 1 + example/thunderscope_test.cpp | 3 + include/ts_common.h | 1 + litepcie/public_h/csr.h | 67 +++++------ src/spiflash.c | 215 +++++++++++++++++++++++----------- src/spiflash.h | 1 + src/thunderscope.c | 1 + src/ts_fw_manager.c | 2 +- 9 files changed, 189 insertions(+), 103 deletions(-) diff --git a/bindings/python/tslitex.pxd b/bindings/python/tslitex.pxd index fd53389..7ebdecf 100644 --- a/bindings/python/tslitex.pxd +++ b/bindings/python/tslitex.pxd @@ -35,6 +35,7 @@ cdef extern from "thunderscope.h": cdef struct tsDeviceInfo_s: uint32_t device_id uint32_t hw_id + uint32_t gw_id char device_path[256] char identity[256] char serial_number[256] diff --git a/example/thunderscope_fw.cpp b/example/thunderscope_fw.cpp index d44c464..7025d3f 100644 --- a/example/thunderscope_fw.cpp +++ b/example/thunderscope_fw.cpp @@ -224,6 +224,7 @@ int main(int argc, char** argv) { printf("HW Rev Beta\n"); } + printf("Gateware Rev 0x%08X\n", infos.gw_id); if(0 == strcmp(arg, "factory_restore")) { diff --git a/example/thunderscope_test.cpp b/example/thunderscope_test.cpp index b7db2f1..71ccf76 100644 --- a/example/thunderscope_test.cpp +++ b/example/thunderscope_test.cpp @@ -524,6 +524,7 @@ static void flash_test(char* arg, file_t fd) printf("Done!\n"); outFile.flush(); outFile.close(); + free(flash_data); } else if(0 == strcmp(arg, "test")) { @@ -758,6 +759,8 @@ int main(int argc, char** argv) { printf("HW Rev Beta\n"); } + printf("Gateware Rev: 0x%08X\n", + litepcie_readl(fd, CSR_DEV_STATUS_GW_REV_ADDR)); #ifdef CSR_DNA_BASE printf("FPGA DNA: 0x%08x%08x\n", litepcie_readl(fd, CSR_DNA_ID_ADDR + 4 * 0), diff --git a/include/ts_common.h b/include/ts_common.h index 63b5fd7..c9dde37 100644 --- a/include/ts_common.h +++ b/include/ts_common.h @@ -57,6 +57,7 @@ typedef struct tsDeviceInfo_s { uint32_t device_id; uint32_t hw_id; /**< hw_id[9] - ID Valid, hw_id[8] - PCIe/USB, hw_id[7:4] - Reserved, hw_id[3:0] - Revision */ + uint32_t gw_id; // 32-bit version ID char device_path[TS_IDENT_STR_LEN]; char identity[TS_IDENT_STR_LEN]; char serial_number[TS_IDENT_STR_LEN]; diff --git a/litepcie/public_h/csr.h b/litepcie/public_h/csr.h index 9f2619a..4d754fe 100644 --- a/litepcie/public_h/csr.h +++ b/litepcie/public_h/csr.h @@ -1,5 +1,5 @@ //-------------------------------------------------------------------------------- -// Auto-generated by LiteX (a1ea5a2f6) on 2025-10-02 02:25:33 +// Auto-generated by LiteX (05ddccb20) on 2025-10-04 10:32:08 //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- @@ -192,41 +192,36 @@ #define CSR_CTRL_RESET_CPU_RST_OFFSET 1 #define CSR_CTRL_RESET_CPU_RST_SIZE 1 -/* SPIFLASH_CORE Registers */ -#define CSR_SPIFLASH_CORE_BASE (CSR_BASE + 0x3800L) -#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR (CSR_BASE + 0x3800L) -#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_SIZE 1 -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_ADDR (CSR_BASE + 0x3804L) -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_CS_ADDR (CSR_BASE + 0x3808L) -#define CSR_SPIFLASH_CORE_MASTER_CS_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR (CSR_BASE + 0x380cL) -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR (CSR_BASE + 0x3810L) -#define CSR_SPIFLASH_CORE_MASTER_RXTX_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR (CSR_BASE + 0x3814L) -#define CSR_SPIFLASH_CORE_MASTER_STATUS_SIZE 1 - -/* SPIFLASH_CORE Fields */ -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_WRITE_ENABLE_OFFSET 0 -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_WRITE_ENABLE_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_SIZE 8 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 8 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_SIZE 4 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_OFFSET 16 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_SIZE 8 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET 0 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_TX_READY_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET 1 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_RX_READY_SIZE 1 - -/* SPIFLASH_PHY Registers */ -#define CSR_SPIFLASH_PHY_BASE (CSR_BASE + 0x4000L) -#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_BASE + 0x4000L) +/* SPIFLASH Registers */ +#define CSR_SPIFLASH_BASE (CSR_BASE + 0x3800L) +#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_BASE + 0x3800L) #define CSR_SPIFLASH_PHY_CLK_DIVISOR_SIZE 1 - -/* SPIFLASH_PHY Fields */ +#define CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR (CSR_BASE + 0x3804L) +#define CSR_SPIFLASH_MMAP_DUMMY_BITS_SIZE 1 +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_ADDR (CSR_BASE + 0x3808L) +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_SIZE 1 +#define CSR_SPIFLASH_MASTER_CS_ADDR (CSR_BASE + 0x380cL) +#define CSR_SPIFLASH_MASTER_CS_SIZE 1 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR (CSR_BASE + 0x3810L) +#define CSR_SPIFLASH_MASTER_PHYCONFIG_SIZE 1 +#define CSR_SPIFLASH_MASTER_RXTX_ADDR (CSR_BASE + 0x3814L) +#define CSR_SPIFLASH_MASTER_RXTX_SIZE 1 +#define CSR_SPIFLASH_MASTER_STATUS_ADDR (CSR_BASE + 0x3818L) +#define CSR_SPIFLASH_MASTER_STATUS_SIZE 1 + +/* SPIFLASH Fields */ +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_WRITE_ENABLE_OFFSET 0 +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_WRITE_ENABLE_SIZE 1 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_OFFSET 0 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_SIZE 8 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_OFFSET 8 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_SIZE 4 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_OFFSET 16 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_SIZE 8 +#define CSR_SPIFLASH_MASTER_STATUS_TX_READY_OFFSET 0 +#define CSR_SPIFLASH_MASTER_STATUS_TX_READY_SIZE 1 +#define CSR_SPIFLASH_MASTER_STATUS_RX_READY_OFFSET 1 +#define CSR_SPIFLASH_MASTER_STATUS_RX_READY_SIZE 1 /* FLASH_ADAPTER Registers */ #define CSR_FLASH_ADAPTER_BASE (CSR_BASE + 0x4800L) @@ -273,6 +268,8 @@ #define CSR_DEV_STATUS_LEDS_SIZE 1 #define CSR_DEV_STATUS_HW_ID_ADDR (CSR_BASE + 0x6004L) #define CSR_DEV_STATUS_HW_ID_SIZE 1 +#define CSR_DEV_STATUS_GW_REV_ADDR (CSR_BASE + 0x6008L) +#define CSR_DEV_STATUS_GW_REV_SIZE 1 /* DEV_STATUS Fields */ #define CSR_DEV_STATUS_HW_ID_HW_REV_OFFSET 0 diff --git a/src/spiflash.c b/src/spiflash.c index 3637d70..cce63b3 100644 --- a/src/spiflash.c +++ b/src/spiflash.c @@ -27,10 +27,80 @@ #define SPI_FLASH_WRITE_ENABLE_CMD (0x06) #define SPI_FLASH_WRITE_DISABLE_CMD (0x04) +/** + * LiteSPI Register Maps + */ +/** pre-2025 liteSPI **/ +/* SPIFLASH_CORE Registers */ +#ifndef CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR +#define CSR_SPIFLASH_CORE_BASE CSR_SPIFLASH_BASE +#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x00L) +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_ADDR (CSR_SPIFLASH_CORE_BASE + 0x04L) +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_CS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x08L) +#define CSR_SPIFLASH_CORE_MASTER_CS_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR (CSR_SPIFLASH_CORE_BASE + 0x0cL) +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR (CSR_SPIFLASH_CORE_BASE + 0x10L) +#define CSR_SPIFLASH_CORE_MASTER_RXTX_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x14L) +#define CSR_SPIFLASH_CORE_MASTER_STATUS_SIZE 1 +/* SPIFLASH_PHY Registers */ +#define CSR_SPIFLASH_CORE_PHY_CLK_DIVISOR_ADDR (CSR_SPIFLASH_CORE_BASE + 0x800L) +#endif + +/** post 2025 liteSPI **/ +/* SPIFLASH Registers */ +#ifndef CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR +#define CSR_SPIFLASH_BASE CSR_SPIFLASH_CORE_BASE +#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_SPIFLASH_BASE + 0x00L) +#define CSR_SPIFLASH_PHY_CLK_DIVISOR_SIZE 1 +#define CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR (CSR_SPIFLASH_BASE + 0x04L) +#define CSR_SPIFLASH_MMAP_DUMMY_BITS_SIZE 1 +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_ADDR (CSR_SPIFLASH_BASE + 0x08L) +#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_SIZE 1 +#define CSR_SPIFLASH_MASTER_CS_ADDR (CSR_SPIFLASH_BASE + 0x0cL) +#define CSR_SPIFLASH_MASTER_CS_SIZE 1 +#define CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR (CSR_SPIFLASH_BASE + 0x10L) +#define CSR_SPIFLASH_MASTER_PHYCONFIG_SIZE 1 +#define CSR_SPIFLASH_MASTER_RXTX_ADDR (CSR_SPIFLASH_BASE + 0x14L) +#define CSR_SPIFLASH_MASTER_RXTX_SIZE 1 +#define CSR_SPIFLASH_MASTER_STATUS_ADDR (CSR_SPIFLASH_BASE + 0x18L) +#define CSR_SPIFLASH_MASTER_STATUS_SIZE 1 +#endif + #ifndef min #define min(x, y) (((x) < (y)) ? (x) : (y)) #endif +typedef struct spiflash_regs_s { + uint32_t PHY_CLK_DIV; + uint32_t MASTER_CS; + uint32_t MASTER_RXTX; + uint32_t MASTER_STATUS; + uint32_t MASTER_PHYCONFIG; + uint32_t DUMMY_BITS; +} spiflash_regs_t; + +static const spiflash_regs_t spiflash_regs[] = { + { + .PHY_CLK_DIV = CSR_SPIFLASH_CORE_PHY_CLK_DIVISOR_ADDR, + .MASTER_CS = CSR_SPIFLASH_CORE_MASTER_CS_ADDR, + .MASTER_RXTX = CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR, + .MASTER_STATUS = CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR, + .MASTER_PHYCONFIG = CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR, + .DUMMY_BITS = CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR + }, + { + .PHY_CLK_DIV = CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR, + .MASTER_CS = CSR_SPIFLASH_MASTER_CS_ADDR, + .MASTER_RXTX = CSR_SPIFLASH_MASTER_RXTX_ADDR, + .MASTER_STATUS = CSR_SPIFLASH_MASTER_STATUS_ADDR, + .MASTER_PHYCONFIG = CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR, + .DUMMY_BITS = CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR + } +}; + static const spiflash_ops_t s25fl256s_ops = { .read = 0x6C, //4QOR .program = 0x12, //4PP @@ -45,21 +115,21 @@ static const spiflash_ops_t mx25u6432f_ops = { .cmd_addr_len = 3 }; -static uint32_t get_flash_data(file_t fd, uint32_t flash_addr, uint8_t* pData, uint32_t data_len) +static uint32_t get_flash_data(spiflash_dev_t* dev, uint32_t flash_addr, uint8_t* pData, uint32_t data_len) { const uint32_t flash_base = 0x10000; uint32_t index = 0; uint32_t flash_data = 0; - uint32_t flash_window = litepcie_readl(fd, CSR_FLASH_ADAPTER_WINDOW0_ADDR); + uint32_t flash_window = litepcie_readl(dev->fd, CSR_FLASH_ADAPTER_WINDOW0_ADDR); while(index < data_len) { if(flash_window != ((flash_addr+index) >> 16)) { flash_window = (flash_addr+index) >> 16; - litepcie_writel(fd, CSR_FLASH_ADAPTER_WINDOW0_ADDR, flash_window); + litepcie_writel(dev->fd, CSR_FLASH_ADAPTER_WINDOW0_ADDR, flash_window); } - flash_data = litepcie_readl(fd, (flash_base + ((flash_addr+index) & 0xFFFF))); + flash_data = litepcie_readl(dev->fd, (flash_base + ((flash_addr+index) & 0xFFFF))); *(uint32_t*)&pData[index] = flash_data; index += 4; } @@ -67,67 +137,65 @@ static uint32_t get_flash_data(file_t fd, uint32_t flash_addr, uint8_t* pData, u return index; } -#ifdef CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR -static void spiflash_dummy_bits_setup(file_t fd, unsigned int dummy_bits) + +static void spiflash_dummy_bits_setup(spiflash_dev_t* dev, unsigned int dummy_bits) { - litepcie_writel(fd, CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR, dummy_bits); - LOG_DEBUG("Dummy bits set to: %" PRIx32 , litepcie_readl(fd, CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR)); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].DUMMY_BITS, dummy_bits); + LOG_DEBUG("Dummy bits set to: %" PRIx32 , litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].DUMMY_BITS)); } -#endif -static void spiflash_len_mask_width_write(file_t fd, uint32_t len, uint32_t width, uint32_t mask) +static void spiflash_len_mask_width_write(spiflash_dev_t* dev, uint32_t len, uint32_t width, uint32_t mask) { - uint32_t tmp = len & ((1 << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_SIZE) - 1); - uint32_t word = tmp << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET; - tmp = width & ((1 << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_SIZE) - 1); - word |= tmp << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET; - tmp = mask & ((1 << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_SIZE) - 1); - word |= tmp << CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_OFFSET; - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR, word); + uint32_t tmp = len & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_SIZE) - 1); + uint32_t word = tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_OFFSET; + tmp = width & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_SIZE) - 1); + word |= tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_OFFSET; + tmp = mask & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_SIZE) - 1); + word |= tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_OFFSET; + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_PHYCONFIG, word); } -static bool spiflash_tx_ready(file_t fd) +static bool spiflash_tx_ready(spiflash_dev_t* dev) { - return (litepcie_readl(fd, CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR) >> CSR_SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET) & 1; + return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> CSR_SPIFLASH_MASTER_STATUS_TX_READY_OFFSET) & 1; } -static bool spiflash_rx_ready(file_t fd) +static bool spiflash_rx_ready(spiflash_dev_t* dev) { - return (litepcie_readl(fd, CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR) >> CSR_SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET) & 1; + return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> CSR_SPIFLASH_MASTER_STATUS_RX_READY_OFFSET) & 1; } -static void spiflash_master_write(file_t fd, uint32_t val, size_t len, size_t width, uint32_t mask) +static void spiflash_master_write(spiflash_dev_t* dev, uint32_t val, size_t len, size_t width, uint32_t mask) { /* Be sure to empty RX queue before doing Xfer. */ - while (spiflash_rx_ready(fd)) - litepcie_readl(fd, CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR); + while (spiflash_rx_ready(dev)) + litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); /* Configure Master */ - spiflash_len_mask_width_write(fd, 8*len, width, mask); + spiflash_len_mask_width_write(dev, 8*len, width, mask); /* Set CS. */ - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_CS_ADDR, 1UL); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_CS, 1UL); /* Do Xfer. */ - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR, val); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX, val); - while (!spiflash_rx_ready(fd)); + while (!spiflash_rx_ready(dev)); /* Clear CS. */ - // spiflash_core_master_cs_write(0); - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_CS_ADDR, 0UL); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_CS, 0UL); } static uint8_t w_buf[SPI_FLASH_PROG_SIZE + 5]; static uint8_t r_buf[SPI_FLASH_PROG_SIZE + 5]; -static void transfer_cmd(file_t fd, const uint8_t *bs, uint8_t *resp, int len) +static void transfer_cmd(spiflash_dev_t* dev, const uint8_t *bs, uint8_t *resp, int len) { uint32_t xfer_word = 0; uint32_t xfer_num_bytes = 0; - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_CS_ADDR, 1UL); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_CS, 1UL); for (int i=0; i < len; i+=4) { @@ -141,19 +209,22 @@ static void transfer_cmd(file_t fd, const uint8_t *bs, uint8_t *resp, int len) xfer_word = (xfer_word << 8) | (uint32_t)bs[i+3]; - spiflash_len_mask_width_write(fd, (8*xfer_num_bytes), 1, 1); + spiflash_len_mask_width_write(dev, (8*xfer_num_bytes), 1, 1); /* wait for tx ready */ - while (!spiflash_tx_ready(fd)); + while (!spiflash_tx_ready(dev)) + { + litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); + } - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR, (uint32_t)xfer_word); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX, (uint32_t)xfer_word); /* wait for rx ready */ - while (!spiflash_rx_ready(fd)) + while (!spiflash_rx_ready(dev)) { NS_DELAY(250); } - xfer_word = litepcie_readl(fd, CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR); + xfer_word = litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); resp[i] = (uint8_t)((xfer_word >> (8*(xfer_num_bytes-1))) & 0xFF); if(xfer_num_bytes > 1) resp[i+1] = (uint8_t)((xfer_word >> (8*(xfer_num_bytes-2))) & 0xFF); @@ -163,17 +234,17 @@ static void transfer_cmd(file_t fd, const uint8_t *bs, uint8_t *resp, int len) resp[i+3] = (uint8_t)((xfer_word) & 0xFF); } - litepcie_writel(fd, CSR_SPIFLASH_CORE_MASTER_CS_ADDR, 0UL); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_CS, 0UL); } -static uint32_t spiflash_read_id_register(file_t fd) +static uint32_t spiflash_read_id_register(spiflash_dev_t* dev) { uint8_t buf[4]; w_buf[0] = SPI_FLASH_JEDEC_READ_ID_CMD; w_buf[1] = 0x00; w_buf[2] = 0x00; w_buf[3] = 0x00; - transfer_cmd(fd, w_buf, buf, 4); + transfer_cmd(dev, w_buf, buf, 4); LOG_DEBUG("[ID: %02x %02x %02x %02x]", buf[0], buf[1], buf[2], buf[3]); @@ -181,30 +252,30 @@ static uint32_t spiflash_read_id_register(file_t fd) return flash_id; } -static uint32_t spiflash_read_status_register(file_t fd) +static uint32_t spiflash_read_status_register(spiflash_dev_t* dev) { uint8_t buf[2]; w_buf[0] = SPI_FLASH_JEDEC_READ_STATUS_REG_1_CMD; w_buf[1] = 0x00; - transfer_cmd(fd, w_buf, buf, 2); + transfer_cmd(dev, w_buf, buf, 2); LOG_DEBUG("[SR: %02x %02x]", buf[0], buf[1]); return buf[1]; } -static void spiflash_write_enable(file_t fd) +static void spiflash_write_enable(spiflash_dev_t* dev) { uint8_t buf[1]; w_buf[0] = SPI_FLASH_WRITE_ENABLE_CMD; - transfer_cmd(fd, w_buf, buf, 1); + transfer_cmd(dev, w_buf, buf, 1); } -static void spiflash_write_disable(file_t fd) +static void spiflash_write_disable(spiflash_dev_t* dev) { uint8_t buf[1]; w_buf[0] = SPI_FLASH_WRITE_DISABLE_CMD; - transfer_cmd(fd, w_buf, buf, 1); + transfer_cmd(dev, w_buf, buf, 1); } static void page_program(spiflash_dev_t* dev, uint32_t addr, uint8_t *data, int len) @@ -219,7 +290,7 @@ static void page_program(spiflash_dev_t* dev, uint32_t addr, uint8_t *data, int w_buf[cmd_idx++] = addr>>8; w_buf[cmd_idx++] = addr>>0; memcpy((void *)(&w_buf[cmd_idx]), (void *)data, len); - transfer_cmd(dev->fd, w_buf, r_buf, len+cmd_idx); + transfer_cmd(dev, w_buf, r_buf, len+cmd_idx); } static void spiflash_sector_erase(spiflash_dev_t* dev, uint32_t addr) @@ -233,7 +304,7 @@ static void spiflash_sector_erase(spiflash_dev_t* dev, uint32_t addr) w_buf[cmd_idx++] = addr>>16; w_buf[cmd_idx++] = addr>>8; w_buf[cmd_idx++] = addr>>0; - transfer_cmd(dev->fd, w_buf, r_buf, cmd_idx); + transfer_cmd(dev, w_buf, r_buf, cmd_idx); } int32_t spiflash_erase(spiflash_dev_t* dev, uint32_t addr, uint32_t len) @@ -249,17 +320,17 @@ int32_t spiflash_erase(spiflash_dev_t* dev, uint32_t addr, uint32_t len) for (i=0; ifd); + spiflash_write_enable(dev); spiflash_sector_erase(dev, addr+i); - while (spiflash_read_status_register(dev->fd) & 1) { - NS_DELAY(250000000); + while (spiflash_read_status_register(dev) & 1) { + NS_DELAY(10000000); } /* check if region was really erased */ for (j = 0; j < SPI_FLASH_ERASE_SIZE; j+=4) { uint32_t flash_word; - get_flash_data(dev->fd, (addr+i+j), (uint8_t*)&flash_word, sizeof(uint32_t)); + get_flash_data(dev, (addr+i+j), (uint8_t*)&flash_word, sizeof(uint32_t)); if (flash_word != 0xffffffff) { LOG_ERROR("Error: location 0x%08x not erased (0x%08x)", addr+i+j, flash_word); return TS_STATUS_ERROR; @@ -272,7 +343,7 @@ int32_t spiflash_erase(spiflash_dev_t* dev, uint32_t addr, uint32_t len) dev->op_progress(dev->op_progress_ctx, SPI_FLASH_ERASE_SIZE, len); } } - spiflash_write_disable(dev->fd); + spiflash_write_disable(dev); return TS_STATUS_OK; } @@ -287,18 +358,18 @@ int32_t spiflash_write(spiflash_dev_t* dev, uint32_t addr, const uint8_t *pData, LOG_DEBUG("Write SPI Flash @0x%08lx", ((uint32_t)addr)); while(w_len) { - spiflash_write_enable(dev->fd); + spiflash_write_enable(dev); page_program(dev, addr+offset, (uint8_t*)pData+offset, w_len); - while(spiflash_read_status_register(dev->fd) & 1) { + while(spiflash_read_status_register(dev) & 1) { NS_DELAY(10000); } - get_flash_data(dev->fd, addr+offset, (uint8_t*)r_buf, w_len); + get_flash_data(dev, addr+offset, (uint8_t*)r_buf, w_len); for (j = 0; j < w_len; j++) { if (r_buf[j] != pData[offset+j]) { LOG_ERROR("Error: verify failed at 0x%08x (0x%02x should be 0x%02x)", (uint32_t)(addr+offset+j), r_buf[j], pData[offset+j]); - spiflash_write_disable(dev->fd); + spiflash_write_disable(dev); return TS_STATUS_ERROR; } } @@ -313,7 +384,7 @@ int32_t spiflash_write(spiflash_dev_t* dev, uint32_t addr, const uint8_t *pData, w_len = min(len-offset, SPI_FLASH_PROG_SIZE); res = offset; } - spiflash_write_disable(dev->fd); + spiflash_write_disable(dev); return res; } @@ -322,18 +393,28 @@ int32_t spiflash_init(file_t fd, spiflash_dev_t* dev) { uint32_t flash_id = 0; uint32_t divisor = SPI_FLASH_CLK_DIV_DEFAULT; + uint32_t ip_version = 0; dev->fd = fd; -#ifdef CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR - spiflash_dummy_bits_setup(fd, 8); -#endif + // Get IP Version + ip_version = litepcie_readl(fd, CSR_DEV_STATUS_GW_REV_ADDR); + if(ip_version >= 0x0300) + { + dev->ip_rev = 1; + } + else + { + dev->ip_rev = 0; + } + + spiflash_dummy_bits_setup(dev, 8); while(divisor <= SPI_FLASH_CLK_DIV_MAX) { - litepcie_writel(fd, CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR, divisor); - flash_id = spiflash_read_id_register(dev->fd); //First ID read returns garbage? - flash_id = spiflash_read_id_register(dev->fd); + litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].PHY_CLK_DIV, divisor); + flash_id = spiflash_read_id_register(dev); //First ID read returns garbage? + flash_id = spiflash_read_id_register(dev); if((flash_id == 0x010219) || (flash_id == 0xC22017) || @@ -405,7 +486,7 @@ int32_t spiflash_read(spiflash_dev_t* dev, uint32_t addr, uint8_t* pData, uint32 if(addr % 4 != 0) { - read_len = get_flash_data(dev->fd, tempAddr, flashBytes, 4); + read_len = get_flash_data(dev, tempAddr, flashBytes, 4); if( 4 != read_len ) { LOG_ERROR("Failed to read with length 0"); @@ -418,7 +499,7 @@ int32_t spiflash_read(spiflash_dev_t* dev, uint32_t addr, uint8_t* pData, uint32 remaining -= read_len; } - read_len = get_flash_data(dev->fd, addr, pData, (remaining/4)*4); + read_len = get_flash_data(dev, addr, pData, (remaining/4)*4); addr += read_len; pData += read_len; remaining -= read_len; @@ -430,7 +511,7 @@ int32_t spiflash_read(spiflash_dev_t* dev, uint32_t addr, uint8_t* pData, uint32 else if(0 != remaining) { //Should only be 1-3 bytes left - if( 4 != get_flash_data(dev->fd, addr, flashBytes, 4)) + if( 4 != get_flash_data(dev, addr, flashBytes, 4)) { LOG_ERROR("Failed to read end of data (%d / %d)", read_len, len); return TS_STATUS_ERROR; diff --git a/src/spiflash.h b/src/spiflash.h index 1636685..f279148 100644 --- a/src/spiflash.h +++ b/src/spiflash.h @@ -33,6 +33,7 @@ typedef struct spiflash_ops_s { typedef struct spiflash_dev_s { file_t fd; + uint32_t ip_rev; uint8_t mfg_code; uint16_t part_id; spiflash_ops_t ops; diff --git a/src/thunderscope.c b/src/thunderscope.c index ad4ae11..ab5c4b8 100644 --- a/src/thunderscope.c +++ b/src/thunderscope.c @@ -57,6 +57,7 @@ int32_t thunderscopeListDevices(uint32_t devIndex, tsDeviceInfo_t *info) { info->device_id = devIndex; info->hw_id = litepcie_readl(testDev, CSR_DEV_STATUS_HW_ID_ADDR); + info->gw_id = litepcie_readl(testDev, CSR_DEV_STATUS_GW_REV_ADDR); //Copy device identifier for (uint32_t i = 0; i < TS_IDENT_STR_LEN; i++) { diff --git a/src/ts_fw_manager.c b/src/ts_fw_manager.c index 472af88..4a46d24 100644 --- a/src/ts_fw_manager.c +++ b/src/ts_fw_manager.c @@ -58,7 +58,7 @@ static uint32_t ts_fw_get_idcode(file_t fd) static const char* ts_fw_parse_bit_header(const char* header, const char** part, uint32_t* bin_len) { - const char* position = header; + const uint8_t* position = header; uint16_t key_len = 0; //First Field ('0FF0...') From 682d8d8f5769214bc9f514c984507a6f3cffb8dc Mon Sep 17 00:00:00 2001 From: Nate Meyer Date: Sun, 19 Oct 2025 00:09:39 -0400 Subject: [PATCH 2/3] Fixes for spiflash registers and divisor. Add gateware and LiteX version registers. Add ADC Frame sync status bit. Bug fix for listing available devices on Windows. --- bindings/python/tslitex.pxd | 2 + example/thunderscope_fw.cpp | 25 ++++++- example/thunderscope_test.cpp | 3 + include/ts_common.h | 9 ++- litepcie/public_h/csr.h | 69 +++++++++++--------- litepcie/src/litepcie_helpers.c | 2 +- src/spiflash.c | 111 ++++++++++++++------------------ src/thunderscope.c | 1 + src/ts_channel.c | 5 +- 9 files changed, 131 insertions(+), 96 deletions(-) diff --git a/bindings/python/tslitex.pxd b/bindings/python/tslitex.pxd index 7ebdecf..3f23899 100644 --- a/bindings/python/tslitex.pxd +++ b/bindings/python/tslitex.pxd @@ -36,6 +36,7 @@ cdef extern from "thunderscope.h": uint32_t device_id uint32_t hw_id uint32_t gw_id + uint32_t litex char device_path[256] char identity[256] char serial_number[256] @@ -70,6 +71,7 @@ cdef extern from "thunderscope.h": uint32_t adc_lost_buffer_count uint32_t flags uint8_t adc_state + uint8_t adc_sync uint8_t power_state uint8_t pll_state uint8_t afe_state diff --git a/example/thunderscope_fw.cpp b/example/thunderscope_fw.cpp index 7025d3f..6a6a5ad 100644 --- a/example/thunderscope_fw.cpp +++ b/example/thunderscope_fw.cpp @@ -199,6 +199,28 @@ int main(int argc, char** argv) exit(0); } + if(0 == strcmp(arg, "list")) + { + uint32_t i = 0; + while(TS_STATUS_OK == thunderscopeListDevices(i, &infos)) + { + if(i==0) + { + printf("Found ThunderScope(s):\n"); + } + printf("\t%3d | Serial Number: %s\n", i, infos.serial_number); + printf("\t | HW Rev: 0x%x\n", infos.hw_id); + printf("\t | GW Rev: 0x%x\n", infos.gw_id); + printf("\t | LiteX Rev: 0x%x\n", infos.litex); + i++; + } + if(i == 0) + { + printf("No devices present\n"); + } + exit(EXIT_SUCCESS); + } + result = thunderscopeListDevices(idx, &infos); if(result == TS_STATUS_ERROR) { @@ -224,7 +246,8 @@ int main(int argc, char** argv) { printf("HW Rev Beta\n"); } - printf("Gateware Rev 0x%08X\n", infos.gw_id); + printf("Gateware Rev 0x%08X\n", infos.gw_id); + printf("LiteX Release 0x%08X\n", infos.litex); if(0 == strcmp(arg, "factory_restore")) { diff --git a/example/thunderscope_test.cpp b/example/thunderscope_test.cpp index 71ccf76..e4f270e 100644 --- a/example/thunderscope_test.cpp +++ b/example/thunderscope_test.cpp @@ -761,6 +761,9 @@ int main(int argc, char** argv) } printf("Gateware Rev: 0x%08X\n", litepcie_readl(fd, CSR_DEV_STATUS_GW_REV_ADDR)); + printf("LiteX Release: 0x%08X\n", + litepcie_readl(fd, CSR_DEV_STATUS_LITEX_REL_ADDR)); + #ifdef CSR_DNA_BASE printf("FPGA DNA: 0x%08x%08x\n", litepcie_readl(fd, CSR_DNA_ID_ADDR + 4 * 0), diff --git a/include/ts_common.h b/include/ts_common.h index c9dde37..3d76558 100644 --- a/include/ts_common.h +++ b/include/ts_common.h @@ -34,6 +34,11 @@ extern "C" { #define TS_HW_ID_VARIANT_MASK (1 << 8) #define TS_HW_ID_VALID_MASK (1 << 9) +#define TS_GW_VERSION(major, minor, patch) ((((major) & 0xFFFF) << 16) + \ + (((minor) & 0xFF) << 8) + \ + (((patch) & 0x3F) << 1)) + +#define LITEX_VERSION(major, minor) ((((major) & 0xFFFF) << 16) + ((minor) & 0xFFFF)) /** * @brief Opaque Handle to a Thunderscope device instance * @@ -57,7 +62,8 @@ typedef struct tsDeviceInfo_s { uint32_t device_id; uint32_t hw_id; /**< hw_id[9] - ID Valid, hw_id[8] - PCIe/USB, hw_id[7:4] - Reserved, hw_id[3:0] - Revision */ - uint32_t gw_id; // 32-bit version ID + uint32_t gw_id; /**< 32-bit version ID: gw_id[31:16] - Major, gw_id[15:8] - Minor, gw_id[7:1] - Patch, gw_id[0] - next */ + uint32_t litex; /**< 32-bit LiteX version: litex[31:16] - Year, litex[15:0] - Month */ char device_path[TS_IDENT_STR_LEN]; char identity[TS_IDENT_STR_LEN]; char serial_number[TS_IDENT_STR_LEN]; @@ -94,6 +100,7 @@ typedef struct tsScopeState_s uint32_t flags; struct { uint8_t adc_state:1; + uint8_t adc_sync:1; uint8_t power_state:1; uint8_t pll_state:1; uint8_t afe_state:1; diff --git a/litepcie/public_h/csr.h b/litepcie/public_h/csr.h index 4d754fe..19a16b4 100644 --- a/litepcie/public_h/csr.h +++ b/litepcie/public_h/csr.h @@ -1,5 +1,5 @@ //-------------------------------------------------------------------------------- -// Auto-generated by LiteX (05ddccb20) on 2025-10-04 10:32:08 +// Auto-generated by LiteX (a1ea5a2f6) on 2025-10-18 14:34:05 //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- @@ -192,36 +192,41 @@ #define CSR_CTRL_RESET_CPU_RST_OFFSET 1 #define CSR_CTRL_RESET_CPU_RST_SIZE 1 -/* SPIFLASH Registers */ -#define CSR_SPIFLASH_BASE (CSR_BASE + 0x3800L) -#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_BASE + 0x3800L) +/* SPIFLASH_CORE Registers */ +#define CSR_SPIFLASH_CORE_BASE (CSR_BASE + 0x3800L) +#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR (CSR_BASE + 0x3800L) +#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_SIZE 1 +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_ADDR (CSR_BASE + 0x3804L) +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_CS_ADDR (CSR_BASE + 0x3808L) +#define CSR_SPIFLASH_CORE_MASTER_CS_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR (CSR_BASE + 0x380cL) +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR (CSR_BASE + 0x3810L) +#define CSR_SPIFLASH_CORE_MASTER_RXTX_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR (CSR_BASE + 0x3814L) +#define CSR_SPIFLASH_CORE_MASTER_STATUS_SIZE 1 + +/* SPIFLASH_CORE Fields */ +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_WRITE_ENABLE_OFFSET 0 +#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_WRITE_ENABLE_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_OFFSET 0 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_LEN_SIZE 8 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_OFFSET 8 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_WIDTH_SIZE 4 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_OFFSET 16 +#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_MASK_SIZE 8 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_TX_READY_OFFSET 0 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_TX_READY_SIZE 1 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_RX_READY_OFFSET 1 +#define CSR_SPIFLASH_CORE_MASTER_STATUS_RX_READY_SIZE 1 + +/* SPIFLASH_PHY Registers */ +#define CSR_SPIFLASH_PHY_BASE (CSR_BASE + 0x4000L) +#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_BASE + 0x4000L) #define CSR_SPIFLASH_PHY_CLK_DIVISOR_SIZE 1 -#define CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR (CSR_BASE + 0x3804L) -#define CSR_SPIFLASH_MMAP_DUMMY_BITS_SIZE 1 -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_ADDR (CSR_BASE + 0x3808L) -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_SIZE 1 -#define CSR_SPIFLASH_MASTER_CS_ADDR (CSR_BASE + 0x380cL) -#define CSR_SPIFLASH_MASTER_CS_SIZE 1 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR (CSR_BASE + 0x3810L) -#define CSR_SPIFLASH_MASTER_PHYCONFIG_SIZE 1 -#define CSR_SPIFLASH_MASTER_RXTX_ADDR (CSR_BASE + 0x3814L) -#define CSR_SPIFLASH_MASTER_RXTX_SIZE 1 -#define CSR_SPIFLASH_MASTER_STATUS_ADDR (CSR_BASE + 0x3818L) -#define CSR_SPIFLASH_MASTER_STATUS_SIZE 1 - -/* SPIFLASH Fields */ -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_WRITE_ENABLE_OFFSET 0 -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_WRITE_ENABLE_SIZE 1 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_OFFSET 0 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_SIZE 8 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_OFFSET 8 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_SIZE 4 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_OFFSET 16 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_SIZE 8 -#define CSR_SPIFLASH_MASTER_STATUS_TX_READY_OFFSET 0 -#define CSR_SPIFLASH_MASTER_STATUS_TX_READY_SIZE 1 -#define CSR_SPIFLASH_MASTER_STATUS_RX_READY_OFFSET 1 -#define CSR_SPIFLASH_MASTER_STATUS_RX_READY_SIZE 1 + +/* SPIFLASH_PHY Fields */ /* FLASH_ADAPTER Registers */ #define CSR_FLASH_ADAPTER_BASE (CSR_BASE + 0x4800L) @@ -270,6 +275,8 @@ #define CSR_DEV_STATUS_HW_ID_SIZE 1 #define CSR_DEV_STATUS_GW_REV_ADDR (CSR_BASE + 0x6008L) #define CSR_DEV_STATUS_GW_REV_SIZE 1 +#define CSR_DEV_STATUS_LITEX_REL_ADDR (CSR_BASE + 0x600cL) +#define CSR_DEV_STATUS_LITEX_REL_SIZE 1 /* DEV_STATUS Fields */ #define CSR_DEV_STATUS_HW_ID_HW_REV_OFFSET 0 @@ -319,6 +326,8 @@ #define CSR_ADC_CONTROL_PWR_DOWN_SIZE 1 #define CSR_ADC_STATUS_ACQ_PG_OFFSET 0 #define CSR_ADC_STATUS_ACQ_PG_SIZE 1 +#define CSR_ADC_STATUS_FRAME_SYNC_OFFSET 1 +#define CSR_ADC_STATUS_FRAME_SYNC_SIZE 1 #define CSR_ADC_TRIGGER_CONTROL_ENABLE_OFFSET 0 #define CSR_ADC_TRIGGER_CONTROL_ENABLE_SIZE 1 #define CSR_ADC_HMCAD1520_CONTROL_FRAME_RST_OFFSET 0 diff --git a/litepcie/src/litepcie_helpers.c b/litepcie/src/litepcie_helpers.c index b00eb5b..15b0c83 100644 --- a/litepcie/src/litepcie_helpers.c +++ b/litepcie/src/litepcie_helpers.c @@ -42,7 +42,7 @@ static void getDeviceName(PWCHAR devName, DWORD maxLen, DWORD devIdx) HDEVINFO hwDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_litepciedrv, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); devData.cbSize = sizeof(devData); - if (!SetupDiEnumDeviceInterfaces(hwDevInfo, NULL, &GUID_DEVINTERFACE_litepciedrv, 0, &devData)) + if (!SetupDiEnumDeviceInterfaces(hwDevInfo, NULL, &GUID_DEVINTERFACE_litepciedrv, devIdx, &devData)) { //Print Error fprintf(stderr, "No Devices Found\n"); diff --git a/src/spiflash.c b/src/spiflash.c index cce63b3..a859468 100644 --- a/src/spiflash.c +++ b/src/spiflash.c @@ -19,7 +19,7 @@ #define SPI_FLASH_WINDOW_SIZE 0x10000 -#define SPI_FLASH_CLK_DIV_DEFAULT (1) +#define SPI_FLASH_CLK_DIV_DEFAULT (3) #define SPI_FLASH_CLK_DIV_MAX (10) #define SPI_FLASH_JEDEC_READ_ID_CMD (0x9F) @@ -31,43 +31,23 @@ * LiteSPI Register Maps */ /** pre-2025 liteSPI **/ -/* SPIFLASH_CORE Registers */ -#ifndef CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR +#ifndef CSR_SPIFLASH_CORE_BASE #define CSR_SPIFLASH_CORE_BASE CSR_SPIFLASH_BASE -#define CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x00L) -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_ADDR (CSR_SPIFLASH_CORE_BASE + 0x04L) -#define CSR_SPIFLASH_CORE_MMAP_WRITE_CONFIG_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_CS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x08L) -#define CSR_SPIFLASH_CORE_MASTER_CS_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR (CSR_SPIFLASH_CORE_BASE + 0x0cL) -#define CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR (CSR_SPIFLASH_CORE_BASE + 0x10L) -#define CSR_SPIFLASH_CORE_MASTER_RXTX_SIZE 1 -#define CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR (CSR_SPIFLASH_CORE_BASE + 0x14L) -#define CSR_SPIFLASH_CORE_MASTER_STATUS_SIZE 1 -/* SPIFLASH_PHY Registers */ -#define CSR_SPIFLASH_CORE_PHY_CLK_DIVISOR_ADDR (CSR_SPIFLASH_CORE_BASE + 0x800L) #endif /** post 2025 liteSPI **/ -/* SPIFLASH Registers */ -#ifndef CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR +#ifndef CSR_SPIFLASH_BASE #define CSR_SPIFLASH_BASE CSR_SPIFLASH_CORE_BASE -#define CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR (CSR_SPIFLASH_BASE + 0x00L) -#define CSR_SPIFLASH_PHY_CLK_DIVISOR_SIZE 1 -#define CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR (CSR_SPIFLASH_BASE + 0x04L) -#define CSR_SPIFLASH_MMAP_DUMMY_BITS_SIZE 1 -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_ADDR (CSR_SPIFLASH_BASE + 0x08L) -#define CSR_SPIFLASH_MMAP_WRITE_CONFIG_SIZE 1 -#define CSR_SPIFLASH_MASTER_CS_ADDR (CSR_SPIFLASH_BASE + 0x0cL) -#define CSR_SPIFLASH_MASTER_CS_SIZE 1 -#define CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR (CSR_SPIFLASH_BASE + 0x10L) -#define CSR_SPIFLASH_MASTER_PHYCONFIG_SIZE 1 -#define CSR_SPIFLASH_MASTER_RXTX_ADDR (CSR_SPIFLASH_BASE + 0x14L) -#define CSR_SPIFLASH_MASTER_RXTX_SIZE 1 -#define CSR_SPIFLASH_MASTER_STATUS_ADDR (CSR_SPIFLASH_BASE + 0x18L) -#define CSR_SPIFLASH_MASTER_STATUS_SIZE 1 #endif +#define SPIFLASH_PHYCONFIG_LEN_OFFSET 0 +#define SPIFLASH_PHYCONFIG_LEN_SIZE 8 +#define SPIFLASH_PHYCONFIG_WIDTH_OFFSET 8 +#define SPIFLASH_PHYCONFIG_WIDTH_SIZE 4 +#define SPIFLASH_PHYCONFIG_MASK_OFFSET 16 +#define SPIFLASH_PHYCONFIG_MASK_SIZE 8 + +#define SPIFLASH_STATUS_TX_READY_OFFSET 0 +#define SPIFLASH_STATUS_RX_READY_OFFSET 1 #ifndef min #define min(x, y) (((x) < (y)) ? (x) : (y)) @@ -84,20 +64,20 @@ typedef struct spiflash_regs_s { static const spiflash_regs_t spiflash_regs[] = { { - .PHY_CLK_DIV = CSR_SPIFLASH_CORE_PHY_CLK_DIVISOR_ADDR, - .MASTER_CS = CSR_SPIFLASH_CORE_MASTER_CS_ADDR, - .MASTER_RXTX = CSR_SPIFLASH_CORE_MASTER_RXTX_ADDR, - .MASTER_STATUS = CSR_SPIFLASH_CORE_MASTER_STATUS_ADDR, - .MASTER_PHYCONFIG = CSR_SPIFLASH_CORE_MASTER_PHYCONFIG_ADDR, - .DUMMY_BITS = CSR_SPIFLASH_CORE_MMAP_DUMMY_BITS_ADDR + .PHY_CLK_DIV = (CSR_SPIFLASH_CORE_BASE + 0x800L), + .MASTER_CS = (CSR_SPIFLASH_CORE_BASE + 0x08L), + .MASTER_RXTX = (CSR_SPIFLASH_CORE_BASE + 0x10L), + .MASTER_STATUS = (CSR_SPIFLASH_CORE_BASE + 0x14L), + .MASTER_PHYCONFIG = (CSR_SPIFLASH_CORE_BASE + 0x0cL), + .DUMMY_BITS = (CSR_SPIFLASH_CORE_BASE + 0x00L) }, { - .PHY_CLK_DIV = CSR_SPIFLASH_PHY_CLK_DIVISOR_ADDR, - .MASTER_CS = CSR_SPIFLASH_MASTER_CS_ADDR, - .MASTER_RXTX = CSR_SPIFLASH_MASTER_RXTX_ADDR, - .MASTER_STATUS = CSR_SPIFLASH_MASTER_STATUS_ADDR, - .MASTER_PHYCONFIG = CSR_SPIFLASH_MASTER_PHYCONFIG_ADDR, - .DUMMY_BITS = CSR_SPIFLASH_MMAP_DUMMY_BITS_ADDR + .PHY_CLK_DIV = (CSR_SPIFLASH_BASE + 0x00L), + .MASTER_CS = (CSR_SPIFLASH_BASE + 0x0cL), + .MASTER_RXTX = (CSR_SPIFLASH_BASE + 0x14L), + .MASTER_STATUS = (CSR_SPIFLASH_BASE + 0x18L), + .MASTER_PHYCONFIG = (CSR_SPIFLASH_BASE + 0x10L), + .DUMMY_BITS = (CSR_SPIFLASH_BASE + 0x04L) } }; @@ -147,23 +127,23 @@ static void spiflash_dummy_bits_setup(spiflash_dev_t* dev, unsigned int dummy_bi static void spiflash_len_mask_width_write(spiflash_dev_t* dev, uint32_t len, uint32_t width, uint32_t mask) { - uint32_t tmp = len & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_SIZE) - 1); - uint32_t word = tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_LEN_OFFSET; - tmp = width & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_SIZE) - 1); - word |= tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_WIDTH_OFFSET; - tmp = mask & ((1 << CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_SIZE) - 1); - word |= tmp << CSR_SPIFLASH_MASTER_PHYCONFIG_MASK_OFFSET; + uint32_t tmp = len & ((1 << SPIFLASH_PHYCONFIG_LEN_SIZE) - 1); + uint32_t word = tmp << SPIFLASH_PHYCONFIG_LEN_OFFSET; + tmp = width & ((1 << SPIFLASH_PHYCONFIG_WIDTH_SIZE) - 1); + word |= tmp << SPIFLASH_PHYCONFIG_WIDTH_OFFSET; + tmp = mask & ((1 << SPIFLASH_PHYCONFIG_MASK_SIZE) - 1); + word |= tmp << SPIFLASH_PHYCONFIG_MASK_OFFSET; litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_PHYCONFIG, word); } static bool spiflash_tx_ready(spiflash_dev_t* dev) { - return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> CSR_SPIFLASH_MASTER_STATUS_TX_READY_OFFSET) & 1; + return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> SPIFLASH_STATUS_TX_READY_OFFSET) & 1; } static bool spiflash_rx_ready(spiflash_dev_t* dev) { - return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> CSR_SPIFLASH_MASTER_STATUS_RX_READY_OFFSET) & 1; + return (litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_STATUS) >> SPIFLASH_STATUS_RX_READY_OFFSET) & 1; } static void spiflash_master_write(spiflash_dev_t* dev, uint32_t val, size_t len, size_t width, uint32_t mask) @@ -197,6 +177,19 @@ static void transfer_cmd(spiflash_dev_t* dev, const uint8_t *bs, uint8_t *resp, litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_CS, 1UL); + /* Flush RX */ + while (spiflash_rx_ready(dev)) + { + litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); + } + + /* wait for tx ready */ + while (!spiflash_tx_ready(dev)) + { + litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); + } + + for (int i=0; i < len; i+=4) { xfer_num_bytes = min((len - i), 4); @@ -207,16 +200,9 @@ static void transfer_cmd(spiflash_dev_t* dev, const uint8_t *bs, uint8_t *resp, xfer_word = (xfer_word << 8) | (uint32_t)bs[i+2]; if(xfer_num_bytes > 3) xfer_word = (xfer_word << 8) | (uint32_t)bs[i+3]; - - + spiflash_len_mask_width_write(dev, (8*xfer_num_bytes), 1, 1); - /* wait for tx ready */ - while (!spiflash_tx_ready(dev)) - { - litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); - } - litepcie_writel(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX, (uint32_t)xfer_word); /* wait for rx ready */ @@ -224,6 +210,7 @@ static void transfer_cmd(spiflash_dev_t* dev, const uint8_t *bs, uint8_t *resp, { NS_DELAY(250); } + xfer_word = litepcie_readl(dev->fd, spiflash_regs[dev->ip_rev].MASTER_RXTX); resp[i] = (uint8_t)((xfer_word >> (8*(xfer_num_bytes-1))) & 0xFF); if(xfer_num_bytes > 1) @@ -398,8 +385,8 @@ int32_t spiflash_init(file_t fd, spiflash_dev_t* dev) dev->fd = fd; // Get IP Version - ip_version = litepcie_readl(fd, CSR_DEV_STATUS_GW_REV_ADDR); - if(ip_version >= 0x0300) + ip_version = litepcie_readl(fd, CSR_DEV_STATUS_LITEX_REL_ADDR); + if(ip_version >= LITEX_VERSION(2025, 4)) // 2025.4+ { dev->ip_rev = 1; } diff --git a/src/thunderscope.c b/src/thunderscope.c index ab5c4b8..6904762 100644 --- a/src/thunderscope.c +++ b/src/thunderscope.c @@ -58,6 +58,7 @@ int32_t thunderscopeListDevices(uint32_t devIndex, tsDeviceInfo_t *info) info->device_id = devIndex; info->hw_id = litepcie_readl(testDev, CSR_DEV_STATUS_HW_ID_ADDR); info->gw_id = litepcie_readl(testDev, CSR_DEV_STATUS_GW_REV_ADDR); + info->litex = litepcie_readl(testDev, CSR_DEV_STATUS_LITEX_REL_ADDR); //Copy device identifier for (uint32_t i = 0; i < TS_IDENT_STR_LEN; i++) { diff --git a/src/ts_channel.c b/src/ts_channel.c index 4e1f6aa..426e050 100644 --- a/src/ts_channel.c +++ b/src/ts_channel.c @@ -521,9 +521,12 @@ tsScopeState_t ts_channel_scope_status(tsChannelHdl_t tsChannels) tsScopeState_t state = {0}; return state; } + ts_channel_t* pTsHdl = (ts_channel_t*)tsChannels; + + pTsHdl->status.adc_sync = (litepcie_readl(pTsHdl->ctrl_handle, CSR_ADC_STATUS_ADDR) & (1 << CSR_ADC_STATUS_FRAME_SYNC_OFFSET)) ? 1 : 0; //Update XADC values - ts_channel_health_update((ts_channel_t*)tsChannels); + ts_channel_health_update(pTsHdl); return ((ts_channel_t*)tsChannels)->status; } From ecf3871a923120045e813bb63fce7b888552fe9f Mon Sep 17 00:00:00 2001 From: Nate Meyer Date: Sun, 19 Oct 2025 20:46:41 -0400 Subject: [PATCH 3/3] Populate info fields when opening TS. --- litepcie/src/litepcie_helpers.c | 1 - src/thunderscope.c | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/litepcie/src/litepcie_helpers.c b/litepcie/src/litepcie_helpers.c index 15b0c83..8f8dcc0 100644 --- a/litepcie/src/litepcie_helpers.c +++ b/litepcie/src/litepcie_helpers.c @@ -72,7 +72,6 @@ static void getDeviceName(PWCHAR devName, DWORD maxLen, DWORD devIdx) if (SetupDiGetDeviceInterfaceDetail(hwDevInfo, &devData, pDetail, detailLen, NULL, NULL)) { wcsncpy_s(devName, maxLen, pDetail->DevicePath, _TRUNCATE); - fwprintf(stdout, L"Found device: %s\n", pDetail->DevicePath); } else { diff --git a/src/thunderscope.c b/src/thunderscope.c index 6904762..307290e 100644 --- a/src/thunderscope.c +++ b/src/thunderscope.c @@ -101,6 +101,8 @@ tsHandle_t thunderscopeOpen(uint32_t devIdx, bool skip_init) //Get Device Info pInst->identity.device_id = devIdx; pInst->identity.hw_id = litepcie_readl(pInst->ctrl, CSR_DEV_STATUS_HW_ID_ADDR); + pInst->identity.gw_id = litepcie_readl(pInst->ctrl, CSR_DEV_STATUS_GW_REV_ADDR); + pInst->identity.litex = litepcie_readl(pInst->ctrl, CSR_DEV_STATUS_LITEX_REL_ADDR); //Copy device identifier for (uint32_t i = 0; i < TS_IDENT_STR_LEN; i++) {