diff --git a/firmware/common/fpga.c b/firmware/common/fpga.c index 6a5ad42d..4a68f81b 100644 --- a/firmware/common/fpga.c +++ b/firmware/common/fpga.c @@ -137,6 +137,31 @@ static int rx_samples(const unsigned int num_samples, uint32_t max_cycles) return rc; } +bool fpga_spi_selftest() +{ + // Skip if FPGA configuration failed. + if (selftest.fpga_image_load != PASSED) { + selftest.fpga_spi = SKIPPED; + return false; + } + + // Test writing a register and reading it back. + uint8_t reg = 5; + uint8_t write_value = 0xA5; + ssp1_set_mode_ice40(); + ice40_spi_write(&ice40, reg, write_value); + uint8_t read_value = ice40_spi_read(&ice40, reg); + ssp1_set_mode_max283x(); + + // Update selftest result. + selftest.fpga_spi = (read_value == write_value) ? PASSED : FAILED; + if (selftest.fpga_spi != PASSED) { + selftest.report.pass = false; + } + + return selftest.fpga_spi == PASSED; +} + static uint8_t lfsr_advance(uint8_t v) { const uint8_t feedback = ((v >> 3) ^ (v >> 4) ^ (v >> 5) ^ (v >> 7)) & 1; @@ -145,15 +170,10 @@ static uint8_t lfsr_advance(uint8_t v) bool fpga_sgpio_selftest() { -#if defined(DFU_MODE) || defined(RAM_MODE) - selftest.sgpio_rx = SKIPPED; - return false; -#endif - bool timeout = false; - // Skip if FPGA configuration failed. - if (selftest.fpga_image_load != PASSED) { + // Skip if FPGA configuration failed or its SPI bus is not working. + if ((selftest.fpga_image_load != PASSED) || (selftest.fpga_spi != PASSED)) { selftest.sgpio_rx = SKIPPED; return false; } @@ -241,15 +261,10 @@ static bool in_range(int value, int expected, int error) bool fpga_if_xcvr_selftest() { -#if defined(DFU_MODE) || defined(RAM_MODE) - selftest.xcvr_loopback = SKIPPED; - return false; -#endif - bool timeout = false; - // Skip if FPGA configuration failed. - if (selftest.fpga_image_load != PASSED) { + // Skip if FPGA configuration failed or its SPI bus is not working. + if ((selftest.fpga_image_load != PASSED) || (selftest.fpga_spi != PASSED)) { selftest.xcvr_loopback = SKIPPED; return false; } diff --git a/firmware/common/fpga.h b/firmware/common/fpga.h index b28c062b..11f90789 100644 --- a/firmware/common/fpga.h +++ b/firmware/common/fpga.h @@ -25,6 +25,7 @@ #include bool fpga_image_load(unsigned int index); +bool fpga_spi_selftest(); bool fpga_sgpio_selftest(); bool fpga_if_xcvr_selftest(); diff --git a/firmware/common/selftest.h b/firmware/common/selftest.h index 3860cf76..0e57d626 100644 --- a/firmware/common/selftest.h +++ b/firmware/common/selftest.h @@ -51,6 +51,7 @@ typedef struct { bool si5351_readback_ok; #ifdef PRALINE test_result_t fpga_image_load; + test_result_t fpga_spi; test_result_t sgpio_rx; test_result_t xcvr_loopback; diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 1e5c462c..65a5f09b 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -290,6 +290,7 @@ int main(void) #else fpga_image_load(0); delay_us_at_mhz(100, 204); + fpga_spi_selftest(); fpga_sgpio_selftest(); #endif diff --git a/firmware/hackrf_usb/usb_api_selftest.c b/firmware/hackrf_usb/usb_api_selftest.c index ce7d86ad..3e541609 100644 --- a/firmware/hackrf_usb/usb_api_selftest.c +++ b/firmware/hackrf_usb/usb_api_selftest.c @@ -116,6 +116,9 @@ void generate_selftest_report(void) append(&s, &c, "FPGA configuration: "); append(&s, &c, test_result_to_str(selftest.fpga_image_load)); append(&s, &c, "\n"); + append(&s, &c, "FPGA SPI: "); + append(&s, &c, test_result_to_str(selftest.fpga_spi)); + append(&s, &c, "\n"); append(&s, &c, "SGPIO RX test: "); append(&s, &c, test_result_to_str(selftest.sgpio_rx)); append(&s, &c, "\n");