From 6081391bca6d6d19ccd62a890058c1594063547f Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Thu, 19 Jan 2023 17:15:09 +0100 Subject: [PATCH] [SC64][SW] Made I2C in primer stable --- sw/bootloader/Makefile | 2 +- sw/bootloader/N64.ld | 7 ++ sw/bootloader/tools/strip.py | 25 +++++ sw/controller/src/hw.c | 62 +++++++---- sw/controller/src/hw.h | 3 +- sw/controller/src/lcmxo2.c | 208 +++++++++++++++++------------------ sw/controller/src/primer.c | 10 +- sw/update/update.py | 19 +++- 8 files changed, 197 insertions(+), 139 deletions(-) create mode 100644 sw/bootloader/tools/strip.py diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index bdbb28a..18001b4 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -70,7 +70,7 @@ $(BUILD_DIR)/bootloader.elf: $(OBJS) N64.ld $(BUILD_DIR)/bootloader.bin: $(BUILD_DIR)/bootloader.elf @$(OBJCOPY) -O binary $< $@ @chksum64 $@ > /dev/null - @truncate --size=1028k $@ + @$(PYTHON) tools/strip.py $@ $(BUILD_DIR)/bootloader.hex: $(BUILD_DIR)/bootloader.bin @$(OBJCOPY) -I binary -O ihex $< $@ diff --git a/sw/bootloader/N64.ld b/sw/bootloader/N64.ld index 0d88ed9..f495947 100644 --- a/sw/bootloader/N64.ld +++ b/sw/bootloader/N64.ld @@ -55,6 +55,13 @@ SECTIONS { . += __stack_size; _sp = .; + .fill : { + . = ALIGN(1024); + FILL(0xFFFFFFFF); + BYTE(0xFFFFFFFF); + . = ORIGIN(rom) + LENGTH(rom); + } > rom + /DISCARD/ : { *(.MIPS.*) } diff --git a/sw/bootloader/tools/strip.py b/sw/bootloader/tools/strip.py new file mode 100644 index 0000000..0693835 --- /dev/null +++ b/sw/bootloader/tools/strip.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import sys + + + +if __name__ == "__main__": + if (len(sys.argv) != 2): + print(f"Usage: python {sys.argv[0]} file_path") + sys.exit(1) + + file = sys.argv[1] + + try: + data = b'' + with open(file, 'rb') as f: + data = f.read() + with open(file, 'wb') as f: + f.write(data.strip(b'\xFF')) + except FileNotFoundError: + print(f"Couldn't open file \"{file}\"") + sys.exit(2) + except Exception as e: + print(e) + sys.exit(3) diff --git a/sw/controller/src/hw.c b/sw/controller/src/hw.c index 7b0d054..fb6b189 100644 --- a/sw/controller/src/hw.c +++ b/sw/controller/src/hw.c @@ -126,6 +126,10 @@ void hw_uart_write (uint8_t *data, int length) { } } +void hw_uart_wait_busy (void) { + while (!(USART1->ISR & USART_ISR_TC)); +} + void hw_spi_start (void) { hw_gpio_reset(GPIO_ID_SPI_CS); } @@ -195,26 +199,42 @@ uint32_t hw_i2c_get_error (void) { return (I2C1->ISR & I2C_ISR_NACKF); } -void hw_i2c_raw (uint8_t i2c_address, uint8_t *data, int length, i2c_type_t type) { - if (type & I2C_START) { +void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) { + while (I2C1->ISR & I2C_ISR_BUSY); + + if (tx_length > 0) { I2C1->ICR = I2C_ICR_NACKCF; - } - I2C1->CR2 = ( - ((type & I2C_AUTOEND) ? I2C_CR2_AUTOEND : 0) | - (length << I2C_CR2_NBYTES_Pos) | - ((type & I2C_STOP) ? I2C_CR2_STOP : 0) | - ((type & I2C_START) ? I2C_CR2_START : 0) | - ((type & I2C_READ) ? I2C_CR2_RD_WRN : 0) | - (i2c_address << I2C_CR2_SADD_Pos) - ); - for (int i = 0; i < length; i++) { - if (type & I2C_READ) { - while (!(I2C1->ISR & I2C_ISR_RXNE)); - *data++ = I2C1->RXDR; - } else if (type & I2C_WRITE) { - while (!(I2C1->ISR & I2C_ISR_TXE)); - I2C1->TXDR = *data++; + I2C1->CR2 = ( + ((rx_length == 0) ? I2C_CR2_AUTOEND : 0) | + (tx_length << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START | + (i2c_address << I2C_CR2_SADD_Pos) + ); + for (int i = 0; i < tx_length; i++) { + while (!(I2C1->ISR & I2C_ISR_TXIS)); + I2C1->TXDR = *tx_data++; } + if (!(I2C1->CR2 & I2C_CR2_AUTOEND)) { + while (!(I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_TC))); + } + } + + if (rx_length > 0) { + I2C1->CR2 = ( + I2C_CR2_AUTOEND | + (rx_length << I2C_CR2_NBYTES_Pos) | + I2C_CR2_START | + I2C_CR2_RD_WRN | + (i2c_address << I2C_CR2_SADD_Pos) + ); + for (int i = 0; i < rx_length; i++) { + while (!(I2C1->ISR & I2C_ISR_RXNE)); + *rx_data++ = I2C1->RXDR; + } + } + + if ((tx_length > 0) || (rx_length > 0)) { + while (!(I2C1->ISR & I2C_ISR_STOPF)); } } @@ -438,7 +458,7 @@ static void hw_init_spi (void) { static void hw_init_i2c (void) { RCC->APBENR1 |= RCC_APBENR1_I2C1EN; - I2C1->TIMINGR = 0x10B17DB5UL; + I2C1->TIMINGR = 0x00C12166UL; I2C1->CR1 |= (I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE | I2C_CR1_PE); hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); @@ -450,12 +470,12 @@ static void hw_init_uart (void) { SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); - hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, GPIO_AF_1, 0); + hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); USART1->BRR = (64000000UL) / UART_BAUD; - USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; USART1->RQR = USART_RQR_TXFRQ | USART_RQR_RXFRQ; + USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } static void hw_init_tim (void) { diff --git a/sw/controller/src/hw.h b/sw/controller/src/hw.h index 850be40..afc830f 100644 --- a/sw/controller/src/hw.h +++ b/sw/controller/src/hw.h @@ -73,13 +73,14 @@ void hw_gpio_set (gpio_id_t id); void hw_gpio_reset (gpio_id_t id); void hw_uart_read (uint8_t *data, int length); void hw_uart_write (uint8_t *data, int length); +void hw_uart_wait_busy (void); void hw_spi_start (void); void hw_spi_stop (void); void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction); void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)); void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)); uint32_t hw_i2c_get_error (void); -void hw_i2c_raw (uint8_t i2c_address, uint8_t *data, int length, i2c_type_t type); +void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length); void hw_i2c_disable_irq (void); void hw_i2c_enable_irq (void); void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)); diff --git a/sw/controller/src/lcmxo2.c b/sw/controller/src/lcmxo2.c index c00251c..a485299 100644 --- a/sw/controller/src/lcmxo2.c +++ b/sw/controller/src/lcmxo2.c @@ -36,12 +36,14 @@ #define LSC_READ_FEABITS (0xFB) #define ISC_NOOP (0xFF) +#define ISC_ERASE_SRAM (1 << 16) #define ISC_ERASE_FEATURE (1 << 17) #define ISC_ERASE_CFG (1 << 18) #define ISC_ERASE_UFM (1 << 19) -#define LSC_STATUS_1_BUSY (1 << 4) -#define LSC_STATUS_1_FAIL (1 << 5) +#define LSC_STATUS_CFG_ENABLE (1 << 9) +#define LSC_STATUS_BUSY (1 << 12) +#define LSC_STATUS_FAIL (1 << 13) #define DEVICE_ID_SIZE (4) @@ -69,50 +71,8 @@ static void lcmxo2_reg_set (uint8_t reg, uint8_t value) { ); while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); } -#endif - -static void lcmxo2_reset_bus (void) { -#ifdef LCMXO2_I2C - uint8_t reset_data = 0; - hw_i2c_raw(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), I2C_START | I2C_AUTOEND | I2C_WRITE); -#else - lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE); - lcmxo2_reg_set(LCMXO2_CFGCR, 0); -#endif -} - -static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type) { -#ifdef LCMXO2_I2C - uint8_t data[4] = { cmd, ((arg >> 16) & 0xFF), ((arg >> 8) & 0xFF), (arg & 0xFF) }; - int length = CMD_TWO_OP ? 3 : 4; - hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, data, length, I2C_START | I2C_WRITE); -#else - uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF); - lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE); - fpga_reg_set(REG_VENDOR_DATA, data); - fpga_reg_set(REG_VENDOR_SCR, - (LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) | - (type == CMD_DELAYED ? VENDOR_SCR_DELAY : 0) | - ((type == CMD_TWO_OP ? 2 : 3) << VENDOR_SCR_LENGTH_BIT) | - VENDOR_SCR_WRITE | - VENDOR_SCR_START - ); - while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); -#endif -} - -static void lcmxo2_finish_cmd (void) { -#ifdef LCMXO2_I2C - hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, NULL, 0, I2C_STOP); -#else - lcmxo2_reg_set(LCMXO2_CFGCR, 0); -#endif -} static void lcmxo2_read_data (uint8_t *buffer, uint32_t length) { -#ifdef LCMXO2_I2C - hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, buffer, length, I2C_START | I2C_READ); -#else while (length > 0) { uint32_t block_size = (length > 4) ? 4 : length; fpga_reg_set(REG_VENDOR_SCR, @@ -129,13 +89,9 @@ static void lcmxo2_read_data (uint8_t *buffer, uint32_t length) { length -= 1; } } -#endif } static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) { -#ifdef LCMXO2_I2C - hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, buffer, length, I2C_WRITE); -#else while (length > 0) { uint32_t block_size = (length > 4) ? 4 : length; uint32_t data = 0; @@ -153,94 +109,128 @@ static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) { ); while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); } +} +#endif + +static void lcmxo2_reset_bus (void) { +#ifdef LCMXO2_I2C + uint8_t reset_data = 0; + hw_i2c_raw(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), NULL, 0); +#else + lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE); + lcmxo2_reg_set(LCMXO2_CFGCR, 0); +#endif +} + +static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint8_t *buffer, uint8_t length, bool write) { +#ifdef LCMXO2_I2C + uint8_t packet[20] = { cmd, ((arg >> 16) & 0xFF), ((arg >> 8) & 0xFF), (arg & 0xFF) }; + int packet_length = ((type == CMD_TWO_OP) ? 3 : 4); + if (write) { + for (int i = 0; i < length; i++) { + packet[packet_length + i] = buffer[i]; + } + packet_length += length; + } + hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length)); +#else + uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF); + lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE); + fpga_reg_set(REG_VENDOR_DATA, data); + fpga_reg_set(REG_VENDOR_SCR, + (LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) | + (type == CMD_DELAYED ? VENDOR_SCR_DELAY : 0) | + ((type == CMD_TWO_OP ? 2 : 3) << VENDOR_SCR_LENGTH_BIT) | + VENDOR_SCR_WRITE | + VENDOR_SCR_START + ); + while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); + if (length > 0) { + if (write) { + lcmxo2_write_data(buffer, length); + } else { + lcmxo2_read_data(buffer, length); + } + } + lcmxo2_reg_set(LCMXO2_CFGCR, 0); #endif } static void lcmxo2_read_device_id (uint8_t *id) { - lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL); - lcmxo2_read_data(id, DEVICE_ID_SIZE); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL, id, DEVICE_ID_SIZE, false); +} + +static uint32_t lcmxo2_read_status (void) { + uint32_t status = 0; + lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL, (uint8_t *) (&status), 4, false); + return SWAP32(status); } static bool lcmxo2_wait_busy (void) { - uint8_t status[4]; + uint32_t status; do { - lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL); - lcmxo2_read_data(status, 4); - lcmxo2_finish_cmd(); - } while(status[2] & LSC_STATUS_1_BUSY); - return status[2] & LSC_STATUS_1_FAIL; + status = lcmxo2_read_status(); + } while(status & LSC_STATUS_BUSY); + return (status & LSC_STATUS_FAIL); } static bool lcmxo2_enable_flash (void) { #ifdef LCMXO2_I2C - lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_NORMAL); + lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_TWO_OP, NULL, 0, false); #else - lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL); + lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL, NULL, 0, false); #endif - lcmxo2_finish_cmd(); return lcmxo2_wait_busy(); } static void lcmxo2_disable_flash (void) { lcmxo2_wait_busy(); - lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP); - lcmxo2_finish_cmd(); - lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP, NULL, 0, false); + lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL, NULL, 0, false); } -static bool lcmxo2_erase_flash (void) { - lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_UFM | ISC_ERASE_CFG, CMD_NORMAL); - lcmxo2_finish_cmd(); +static bool lcmxo2_erase_sram (void) { + lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_SRAM, CMD_NORMAL, NULL, 0, false); return lcmxo2_wait_busy(); } -static bool lcmxo2_erase_all (void) { - lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_UFM | ISC_ERASE_CFG | ISC_ERASE_FEATURE, CMD_NORMAL); - lcmxo2_finish_cmd(); +static bool lcmxo2_erase_featbits (void) { + lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_FEATURE, CMD_NORMAL, NULL, 0, false); + return lcmxo2_wait_busy(); +} + +static bool lcmxo2_erase_flash (void) { + lcmxo2_execute_cmd(ISC_ERASE, (ISC_ERASE_UFM | ISC_ERASE_CFG), CMD_NORMAL, NULL, 0, false); return lcmxo2_wait_busy(); } static void lcmxo2_reset_flash_address (void) { - lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL, NULL, 0, false); } static bool lcmxo2_write_flash_page (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL); - lcmxo2_write_data(buffer, FLASH_PAGE_SIZE); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL, buffer, FLASH_PAGE_SIZE, true); return lcmxo2_wait_busy(); } static void lcmxo2_read_flash_page (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED); - lcmxo2_read_data(buffer, FLASH_PAGE_SIZE); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED, buffer, FLASH_PAGE_SIZE, false); } static void lcmxo2_program_done (void) { - lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL); - lcmxo2_finish_cmd(); - lcmxo2_wait_busy(); + lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL, NULL, 0, false); } static void lcmxo2_write_featbits (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL); - lcmxo2_write_data(buffer, FEATBITS_SIZE); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, true); } static void lcmxo2_read_featbits (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL); - lcmxo2_read_data(buffer, FEATBITS_SIZE); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, false); } static void lcmxo2_refresh (void) { - lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP); - lcmxo2_finish_cmd(); + lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP, NULL, 0, false); } static vendor_error_t lcmxo2_fail (vendor_error_t error) { @@ -248,6 +238,7 @@ static vendor_error_t lcmxo2_fail (vendor_error_t error) { return error; } + uint32_t vendor_flash_size (void) { return (FLASH_PAGE_SIZE * FLASH_NUM_PAGES); } @@ -324,6 +315,10 @@ vendor_error_t vendor_reconfigure (void) { } +#define FEATBITS_0_SPI_OFF (1 << 1) +#define FEATBITS_1_PROGRAMN_OFF (1 << 5) + + typedef enum { CMD_GET_PRIMER_ID = '?', CMD_PROBE_FPGA = '#', @@ -331,13 +326,12 @@ typedef enum { CMD_GET_DEVICE_ID = 'I', CMD_ENABLE_FLASH = 'E', CMD_DISABLE_FLASH = 'D', - CMD_ERASE_ALL = 'X', + CMD_ERASE_FLASH = 'X', CMD_RESET_ADDRESS = 'A', CMD_WRITE_PAGE = 'W', CMD_READ_PAGE = 'R', CMD_PROGRAM_DONE = 'F', - CMD_WRITE_FEATBITS = 'Q', - CMD_READ_FEATBITS = 'Y', + CMD_INIT_FEATBITS = 'Q', CMD_REFRESH = 'B', } primer_cmd_e; @@ -346,14 +340,13 @@ static bool primer_check_rx_length (primer_cmd_e cmd, size_t rx_length) { switch (cmd) { case CMD_WRITE_PAGE: return (rx_length != FLASH_PAGE_SIZE); - case CMD_WRITE_FEATBITS: - return (rx_length != FEATBITS_SIZE); default: return (rx_length != 0); } return true; } + void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_response_t send_response) { bool runninng = true; primer_cmd_e cmd; @@ -386,7 +379,6 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons case CMD_PROBE_FPGA: buffer[0] = fpga_id_get(); tx_length = 1; - error = (buffer[0] != FPGA_ID); break; case CMD_RESTART: @@ -403,11 +395,14 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons break; case CMD_DISABLE_FLASH: - lcmxo2_disable_flash(); + if (lcmxo2_read_status() & LSC_STATUS_CFG_ENABLE) { + error = lcmxo2_erase_sram(); + lcmxo2_disable_flash(); + } break; - - case CMD_ERASE_ALL: - error = lcmxo2_erase_all(); + + case CMD_ERASE_FLASH: + error = lcmxo2_erase_flash(); break; case CMD_RESET_ADDRESS: @@ -427,18 +422,19 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons lcmxo2_program_done(); break; - case CMD_WRITE_FEATBITS: - lcmxo2_write_featbits(buffer); - break; - - case CMD_READ_FEATBITS: + case CMD_INIT_FEATBITS: lcmxo2_read_featbits(buffer); - tx_length = FEATBITS_SIZE; + if ((buffer[0] != FEATBITS_0_SPI_OFF) && (buffer[1] != FEATBITS_1_PROGRAMN_OFF)) { + buffer[0] = FEATBITS_0_SPI_OFF; + buffer[1] = FEATBITS_1_PROGRAMN_OFF; + lcmxo2_erase_featbits(); + lcmxo2_write_featbits(buffer); + } break; case CMD_REFRESH: lcmxo2_refresh(); - hw_delay_ms(1000); + hw_delay_ms(100); break; default: diff --git a/sw/controller/src/primer.c b/sw/controller/src/primer.c index 207f282..94e22a3 100644 --- a/sw/controller/src/primer.c +++ b/sw/controller/src/primer.c @@ -4,16 +4,11 @@ #include "vendor.h" -static const uint8_t primer_hello[] = "SC64 Primer\n"; static const uint8_t cmd_token[3] = { 'C', 'M', 'D' }; static const uint8_t rsp_token[3] = { 'R', 'S', 'P' }; static const uint8_t err_token[3] = { 'E', 'R', 'R' }; -static void primer_send_hello (void) { - hw_uart_write((uint8_t *) (primer_hello), sizeof(primer_hello) - 1); -} - static void primer_get_and_calculate_crc32 (uint8_t *buffer, uint8_t rx_length, uint32_t *crc32) { hw_uart_read(buffer, rx_length); *crc32 = hw_crc32_calculate(buffer, rx_length); @@ -74,10 +69,7 @@ static void primer_send_response (uint8_t cmd, uint8_t *buffer, uint8_t tx_lengt void primer (void) { hw_primer_init(); - - primer_send_hello(); - vendor_initial_configuration(primer_get_command, primer_send_response); - + hw_uart_wait_busy(); hw_reset(NULL); } diff --git a/sw/update/update.py b/sw/update/update.py index af7a1f6..2889056 100755 --- a/sw/update/update.py +++ b/sw/update/update.py @@ -19,6 +19,7 @@ class JedecFile: __fuse_length: int = 0 __fuse_offset: int = 0 __fuse_data: bytes = b'' + __fuse_ignore: bool = False __byte_buffer: int = 0 def __handle_q_field(self, f: BufferedRandom) -> None: @@ -77,6 +78,19 @@ class JedecFile: else: raise JedecError('Unexpected byte inside L field fuse data') + def __handle_n_field(self, f: BufferedRandom) -> None: + data = b'' + buffer = b'' + while (buffer != b'*'): + buffer = f.read(1) + if (buffer == b''): + raise JedecError('Unexpected end of file') + if (buffer != b'*'): + data += buffer + if (data == b'OTE END CONFIG DATA'): + self.__fuse_length = self.__fuse_offset + self.__fuse_ignore = True + def __ignore_field(self, f: BufferedRandom) -> None: data = None while (data != b'*'): @@ -88,6 +102,7 @@ class JedecFile: self.__fuse_length = 0 self.__fuse_offset = 0 self.__fuse_data = b'' + self.__fuse_ignore = False self.__byte_buffer = 0 field = None @@ -104,8 +119,10 @@ class JedecFile: field = f.read(1) if (field == b'Q'): self.__handle_q_field(f) - elif (field == b'L'): + elif (field == b'L' and not self.__fuse_ignore): self.__handle_l_field(f) + elif (field == b'N'): + self.__handle_n_field(f) elif (field == b'\r' or field == b'\n'): pass elif (field == b'\x03'):