diff --git a/fw/project/lcmxo2/.gitignore b/fw/project/lcmxo2/.gitignore index 9eb10ae..c5bd274 100644 --- a/fw/project/lcmxo2/.gitignore +++ b/fw/project/lcmxo2/.gitignore @@ -1,5 +1,6 @@ .recovery *.dir/ +*.ccl *.html *.ini *.rva diff --git a/sw/bootloader/src/exception.c b/sw/bootloader/src/exception.c index 0c40225..4c7101a 100644 --- a/sw/bootloader/src/exception.c +++ b/sw/bootloader/src/exception.c @@ -28,6 +28,8 @@ static io32_t exception_framebuffer[SCREEN_WIDTH * SCREEN_HEIGHT] __attribute__((aligned(64))); +static int char_x; +static int char_y; static const vi_regs_t vi_config[] = {{ .CR = ( VI_CR_PIXEL_ADVANCE_1 | @@ -75,6 +77,9 @@ static void exception_init_screen (void) { const vi_regs_t *cfg = &vi_config[OS_INFO->tv_type]; uint32_t *background_data = (uint32_t *) (&assets_exception_background); + char_x = BORDER_WIDTH; + char_y = BORDER_HEIGHT; + for (int i = 0; i < (SCREEN_WIDTH * SCREEN_HEIGHT); i += 2) { io_write(&exception_framebuffer[i], *background_data); io_write(&exception_framebuffer[i + 1], *background_data); @@ -98,18 +103,15 @@ static void exception_init_screen (void) { } static void exception_draw_character (char c) { - static int x = BORDER_WIDTH; - static int y = BORDER_HEIGHT; - if (c == '\n') { - x = BORDER_WIDTH; - y += LINE_HEIGHT; + char_x = BORDER_WIDTH; + char_y += LINE_HEIGHT; return; } - if ((x + FONT_WIDTH) > (SCREEN_WIDTH - BORDER_WIDTH)) { - x = BORDER_WIDTH; - y += LINE_HEIGHT; + if ((char_x + FONT_WIDTH) > (SCREEN_WIDTH - BORDER_WIDTH)) { + char_x = BORDER_WIDTH; + char_y += LINE_HEIGHT; } if ((c < ' ') || (c > '~')) { @@ -117,8 +119,8 @@ static void exception_draw_character (char c) { } for (int i = 0; i < (FONT_WIDTH * FONT_HEIGHT); i++) { - int c_x = x + (i % FONT_WIDTH); - int c_y = y + (i / FONT_WIDTH); + int c_x = char_x + (i % FONT_WIDTH); + int c_y = char_y + (i / FONT_WIDTH); if ((c_x >= (SCREEN_WIDTH - BORDER_WIDTH)) || (c_y >= (SCREEN_HEIGHT - BORDER_HEIGHT))) { break; @@ -130,7 +132,7 @@ static void exception_draw_character (char c) { } } - x += FONT_WIDTH; + char_x += FONT_WIDTH; } static void exception_print_string (const char *s) { diff --git a/sw/controller/.gitignore b/sw/controller/.gitignore index 7ef01c0..5743e15 100644 --- a/sw/controller/.gitignore +++ b/sw/controller/.gitignore @@ -1,3 +1,2 @@ -/build_app -/build_loader +/build *.svd diff --git a/sw/controller/src/app.c b/sw/controller/src/app.c index 16ce5b7..f2b7020 100644 --- a/sw/controller/src/app.c +++ b/sw/controller/src/app.c @@ -8,7 +8,7 @@ #define CIC_STACK_SIZE (256) #define RTC_STACK_SIZE (256) -#define GVR_STACK_SIZE (1024) +#define GVR_STACK_SIZE (1536) uint8_t cic_stack[CIC_STACK_SIZE] __attribute__((aligned(8))); diff --git a/sw/controller/src/hw.c b/sw/controller/src/hw.c index ac09769..f5ccc29 100644 --- a/sw/controller/src/hw.c +++ b/sw/controller/src/hw.c @@ -267,9 +267,9 @@ void hw_crc32_reset (void) { uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length) { for (uint32_t i = 0; i < length; i++) { - *(__IO uint8_t *) (CRC->DR) = data[i]; + *(__IO uint8_t *) (&CRC->DR) = data[i]; } - return CRC->DR; + return (CRC->DR ^ 0xFFFFFFFF); } uint32_t hw_flash_size (void) { @@ -359,6 +359,10 @@ static void hw_init_mcu (void) { RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; + SysTick->LOAD = (((64000000 / 1000)) - 1); + SysTick->VAL = 0; + SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk); + hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0); } @@ -437,12 +441,10 @@ static void hw_init_tim (void) { } static void hw_init_misc (void) { - SysTick->LOAD = (((64000000 / 1000)) - 1); - SysTick->VAL = 0; - SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk); - RCC->AHBENR |= RCC_AHBENR_CRCEN; + CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0); + hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_OUTPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 1); diff --git a/sw/controller/src/lcmxo2.c b/sw/controller/src/lcmxo2.c index e0b78b7..4990444 100644 --- a/sw/controller/src/lcmxo2.c +++ b/sw/controller/src/lcmxo2.c @@ -56,16 +56,6 @@ static void lcmxo2_reg_set (uint8_t reg, uint8_t value) { while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); } -static uint8_t lcmxo2_reg_get (uint8_t reg) { - fpga_reg_set(REG_VENDOR_SCR, - (reg << VENDOR_SCR_ADDRESS_BIT) | - (0 << VENDOR_SCR_LENGTH_BIT) | - VENDOR_SCR_START - ); - while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); - return fpga_reg_get(REG_VENDOR_DATA) & 0xFF; -} - static void lcmxo2_reset_bus (void) { lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE); lcmxo2_reg_set(LCMXO2_CFGCR, 0); @@ -91,14 +81,41 @@ static void lcmxo2_cleanup (void) { } static void lcmxo2_read_data (uint8_t *buffer, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - *buffer++ = lcmxo2_reg_get(LCMXO2_CFGRXDR); + while (length > 0) { + uint32_t block_size = (length > 4) ? 4 : length; + fpga_reg_set(REG_VENDOR_SCR, + (LCMXO2_CFGRXDR << VENDOR_SCR_ADDRESS_BIT) | + ((block_size - 1) << VENDOR_SCR_LENGTH_BIT) | + VENDOR_SCR_START + ); + while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); + uint32_t data = fpga_reg_get(REG_VENDOR_DATA); + data <<= ((4 - block_size) * 8); + for (int i = 0; i < block_size; i++) { + *buffer++ = ((data >> 24) & 0xFF); + data <<= 8; + length -= 1; + } } } static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) { - for (uint32_t i = 0; i < length; i++) { - lcmxo2_reg_set(LCMXO2_CFGTXDR, *buffer++); + while (length > 0) { + uint32_t block_size = (length > 4) ? 4 : length; + uint32_t data = 0; + for (int i = 0; i < block_size; i++) { + data = ((data << 8) | *buffer++); + length -= 1; + } + data <<= ((4 - block_size) * 8); + fpga_reg_set(REG_VENDOR_DATA, data); + fpga_reg_set(REG_VENDOR_SCR, + (LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) | + ((block_size - 1) << VENDOR_SCR_LENGTH_BIT) | + VENDOR_SCR_WRITE | + VENDOR_SCR_START + ); + while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); } } diff --git a/sw/controller/src/update.c b/sw/controller/src/update.c index 9277d22..f03b77d 100644 --- a/sw/controller/src/update.c +++ b/sw/controller/src/update.c @@ -9,12 +9,9 @@ typedef enum { - UPDATE_STATUS_START = 1, - UPDATE_STATUS_MCU_START = 2, - UPDATE_STATUS_MCU_DONE = 3, - UPDATE_STATUS_FPGA_START = 4, - UPDATE_STATUS_FPGA_DONE = 5, - UPDATE_STATUS_DONE = 6, + UPDATE_STATUS_MCU = 1, + UPDATE_STATUS_FPGA = 2, + UPDATE_STATUS_DONE = 0x80, UPDATE_STATUS_ERROR = 0xFF, } update_status_t; @@ -30,25 +27,22 @@ static const uint8_t update_token[16] = "SC64 Update v2.0"; static uint8_t status_data[12] = { 'P', 'K', 'T', PACKET_CMD_UPDATE_STATUS, 0, 0, 0, 4, - 0, 0, 0, UPDATE_STATUS_START, + 0, 0, 0, UPDATE_STATUS_ERROR, }; static uint32_t update_checksum (uint32_t address, uint32_t length) { - uint32_t remaining = length; + uint8_t buffer[32]; uint32_t block_size; uint32_t checksum = 0; - uint8_t buffer[32]; - hw_crc32_reset(); - - for (uint32_t i = 0; i < length; i += sizeof(buffer)) { - block_size = (remaining > sizeof(buffer)) ? sizeof(buffer) : remaining; + while (length > 0) { + block_size = (length > sizeof(buffer)) ? sizeof(buffer) : length; fpga_mem_read(address, block_size, buffer); checksum = hw_crc32_calculate(buffer, block_size); - remaining -= block_size; + address += block_size; + length -= block_size; } - return checksum; } @@ -91,6 +85,7 @@ static bool update_get_chunk (uint32_t *address, chunk_id_t *chunk_id, uint32_t uint32_t id; uint32_t checksum; fpga_mem_read(*address, sizeof(id), (uint8_t *) (&id)); + *chunk_id = (chunk_id_t) (id); *address += sizeof(id); fpga_mem_read(*address, sizeof(*data_length), (uint8_t *) (data_length)); *address += sizeof(*data_length); @@ -120,11 +115,13 @@ static void update_status_notify (update_status_t status) { fpga_usb_push(status_data[i]); } fpga_reg_set(REG_USB_SCR, USB_SCR_WRITE_FLUSH); - if (status != UPDATE_STATUS_ERROR) { - update_blink_led(100, 250, status); - hw_delay_ms(1000); - } else { + if (status == UPDATE_STATUS_DONE) { + update_blink_led(15, 85, 10); + } else if (status == UPDATE_STATUS_ERROR) { update_blink_led(1000, 1000, 30); + } else { + update_blink_led(15, 185, 2); + hw_delay_ms(500); } } @@ -134,7 +131,7 @@ update_error_t update_backup (uint32_t address, uint32_t *length) { uint32_t mcu_length; uint32_t fpga_length; - *length += update_write_token(&address); + *length = update_write_token(&address); *length += update_prepare_chunk(&address, CHUNK_ID_MCU_DATA); mcu_length = hw_flash_size(); @@ -214,35 +211,25 @@ bool update_check (void) { void update_perform (void) { hw_flash_t buffer; - update_status_notify(UPDATE_STATUS_START); - if (parameters.mcu_length != 0) { - update_status_notify(UPDATE_STATUS_MCU_START); - + update_status_notify(UPDATE_STATUS_MCU); hw_flash_erase(); - for (uint32_t offset = 0; offset < parameters.mcu_length; offset += sizeof(hw_flash_t)) { fpga_mem_read(parameters.mcu_address + offset, sizeof(hw_flash_t), (uint8_t *) (&buffer)); hw_flash_program(offset, buffer); - if (hw_flash_read(offset) != buffer) { update_status_notify(UPDATE_STATUS_ERROR); - while (1); // TODO: jump to STM32 bootloader? + while (1); } } - - update_status_notify(UPDATE_STATUS_MCU_DONE); } if (parameters.fpga_length != 0) { - update_status_notify(UPDATE_STATUS_FPGA_START); - + update_status_notify(UPDATE_STATUS_FPGA); if (vendor_update(parameters.fpga_address, parameters.fpga_length) != VENDOR_OK) { update_status_notify(UPDATE_STATUS_ERROR); - while (1); // TODO: jump to STM32 bootloader? + while (1); } - - update_status_notify(UPDATE_STATUS_FPGA_DONE); } update_status_notify(UPDATE_STATUS_DONE);