mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2025-02-16 12:19:11 +01:00
update format and stuff
This commit is contained in:
parent
9dd8fc7445
commit
a72996dffb
@ -55,7 +55,7 @@ SECTIONS {
|
||||
. = ALIGN(4);
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(8);
|
||||
. = ALIGN(4);
|
||||
} > rom
|
||||
|
||||
_estack = ORIGIN(ram) + LENGTH(ram);
|
||||
|
@ -1,9 +1,9 @@
|
||||
EXE_NAME = app
|
||||
LD_SCRIPT = app.ld
|
||||
BUILD_DIR = build_app
|
||||
BUILD_DIR = build/app
|
||||
SRC_FILES = \
|
||||
app_startup.S \
|
||||
app_main.c \
|
||||
app.S \
|
||||
app.c \
|
||||
cfg.c \
|
||||
cic.c \
|
||||
dd.c \
|
||||
@ -22,4 +22,4 @@ SRC_FILES = \
|
||||
|
||||
include common.mk
|
||||
|
||||
$(BUILD_DIR)/app_startup.S.o: ../build_loader/loader.bin
|
||||
$(BUILD_DIR)/app.S.o: ../build/loader/loader.bin
|
||||
|
@ -58,7 +58,7 @@ SECTIONS {
|
||||
_srodata = .;
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
. = ALIGN(8);
|
||||
. = ALIGN(4);
|
||||
_erodata = .;
|
||||
} > ram AT > rom
|
||||
|
||||
|
@ -1,14 +1,12 @@
|
||||
EXE_NAME = loader
|
||||
LD_SCRIPT = loader.ld
|
||||
BUILD_DIR = build_loader
|
||||
BUILD_DIR = build/loader
|
||||
SRC_FILES = \
|
||||
loader_startup.S \
|
||||
boot.c \
|
||||
debug.c \
|
||||
loader.S \
|
||||
fpga.c \
|
||||
hw.c \
|
||||
lcmxo2.c \
|
||||
loader_main.c \
|
||||
loader.c \
|
||||
update.c
|
||||
|
||||
include common.mk
|
||||
|
@ -6,7 +6,7 @@
|
||||
.section .loader, "a", %progbits
|
||||
.type g_pfnVectors, %object
|
||||
loader:
|
||||
.incbin "../build_loader/loader.bin"
|
||||
.incbin "../build/loader/loader.bin"
|
||||
|
||||
|
||||
.section .text.Reset_Handler
|
||||
@ -43,7 +43,7 @@ init_bss:
|
||||
bcc 1b
|
||||
|
||||
run:
|
||||
bl app_main
|
||||
bl app
|
||||
|
||||
loop:
|
||||
b loop
|
@ -16,7 +16,7 @@ uint8_t rtc_stack[RTC_STACK_SIZE] __attribute__((aligned(8)));
|
||||
uint8_t gvr_stack[GVR_STACK_SIZE] __attribute__((aligned(8)));
|
||||
|
||||
|
||||
void app_main (void) {
|
||||
void app (void) {
|
||||
hw_init();
|
||||
cic_hw_init();
|
||||
|
||||
@ -25,6 +25,4 @@ void app_main (void) {
|
||||
task_create(TASK_ID_GVR, gvr_task, gvr_stack, GVR_STACK_SIZE);
|
||||
|
||||
task_scheduler_start();
|
||||
|
||||
while (1);
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
#include <stdbool.h>
|
||||
#include "cfg.h"
|
||||
#include "dd.h"
|
||||
#include "flash.h"
|
||||
@ -346,7 +345,7 @@ void cfg_process (void) {
|
||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
||||
return;
|
||||
}
|
||||
usb_create_packet(&packet_info, PACKET_CMD_USB_OUTPUT);
|
||||
usb_create_packet(&packet_info, PACKET_CMD_DEBUG_OUTPUT);
|
||||
packet_info.dma_length = args[1];
|
||||
packet_info.dma_address = args[0];
|
||||
packet_info.done_callback = cfg_set_usb_output_ready;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define CFG_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
// Original code from https://github.com/jago85/UltraCIC_C licensed under the MIT License
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "cic.h"
|
||||
#include "hw.h"
|
||||
|
@ -1,6 +1,4 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "dd.h"
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "fpga.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "dd.h"
|
||||
#include "cfg.h"
|
||||
#include "dd.h"
|
||||
#include "flashram.h"
|
||||
#include "fpga.h"
|
||||
#include "isv.h"
|
||||
|
@ -45,7 +45,7 @@ typedef struct {
|
||||
} gpio_irq_callback_t;
|
||||
|
||||
|
||||
static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB };
|
||||
static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB, 0, 0, 0, 0, 0, 0 };
|
||||
static gpio_irq_callback_t gpio_irq_callbacks[16];
|
||||
static volatile uint8_t *i2c_data_txptr;
|
||||
static volatile uint8_t *i2c_data_rxptr;
|
||||
@ -61,10 +61,6 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp
|
||||
uint8_t pin = (id & 0x0F);
|
||||
uint8_t afr = ((pin < 8) ? 0 : 1);
|
||||
|
||||
if (!gpio) {
|
||||
return;
|
||||
}
|
||||
|
||||
tmp.MODER = (gpio->MODER & ~(GPIO_MODER_MODE0_Msk << (pin * 2)));
|
||||
tmp.OTYPER = (gpio->OTYPER & ~(GPIO_OTYPER_OT0_Msk << pin));
|
||||
tmp.OSPEEDR = (gpio->OSPEEDR & ~(GPIO_OSPEEDR_OSPEED0_Msk << (pin * 2)));
|
||||
@ -81,7 +77,7 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp
|
||||
}
|
||||
|
||||
void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void)) {
|
||||
uint8_t port = ((id >> 4) & 0x0F);
|
||||
uint8_t port = ((id >> 4) & 0x07);
|
||||
uint8_t pin = (id & 0x0F);
|
||||
if (irq == GPIO_IRQ_FALLING) {
|
||||
EXTI->FTSR1 |= (EXTI_FTSR1_FT0 << pin);
|
||||
@ -214,6 +210,12 @@ void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)) {
|
||||
tim_callbacks[id] = callback;
|
||||
}
|
||||
|
||||
void hw_tim_stop (tim_id_t id) {
|
||||
TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id]));
|
||||
tim->CR1 &= ~(TIM_CR1_CEN);
|
||||
tim_callbacks[id] = 0;
|
||||
}
|
||||
|
||||
void hw_tim_disable_irq (tim_id_t id) {
|
||||
switch (id) {
|
||||
case TIM_ID_CIC:
|
||||
@ -252,10 +254,26 @@ void hw_tim_enable_irq (tim_id_t id) {
|
||||
}
|
||||
}
|
||||
|
||||
void hw_tim_stop (tim_id_t id) {
|
||||
TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id]));
|
||||
tim->CR1 &= ~(TIM_CR1_CEN);
|
||||
tim_callbacks[id] = 0;
|
||||
void hw_delay_ms (uint32_t ms) {
|
||||
SysTick->VAL = 0;
|
||||
for (uint32_t i = 0; i < ms; i++) {
|
||||
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
|
||||
}
|
||||
}
|
||||
|
||||
void hw_crc32_reset (void) {
|
||||
CRC->CR |= CRC_CR_RESET;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
return CRC->DR;
|
||||
}
|
||||
|
||||
uint32_t hw_flash_size (void) {
|
||||
return FLASH_SIZE;
|
||||
}
|
||||
|
||||
static void hw_flash_unlock (void) {
|
||||
@ -274,12 +292,12 @@ void hw_flash_erase (void) {
|
||||
FLASH->CR &= ~(FLASH_CR_MER1);
|
||||
}
|
||||
|
||||
void hw_flash_program (uint32_t address, uint64_t value) {
|
||||
void hw_flash_program (uint32_t offset, hw_flash_t value) {
|
||||
hw_flash_unlock();
|
||||
FLASH->CR |= FLASH_CR_PG;
|
||||
*(__IO uint32_t *) (address) = ((value) & 0xFFFFFFFF);
|
||||
*(__IO uint32_t *) (FLASH_BASE + offset) = ((value) & 0xFFFFFFFF);
|
||||
__ISB();
|
||||
*(__IO uint32_t *) (address + 4) = ((value >> 32) & 0xFFFFFFFF);
|
||||
*(__IO uint32_t *) (FLASH_BASE + offset + 4) = ((value >> 32) & 0xFFFFFFFF);
|
||||
while (FLASH->SR & FLASH_SR_BSY1);
|
||||
if (FLASH->SR & FLASH_SR_EOP) {
|
||||
FLASH->SR |= FLASH_SR_EOP;
|
||||
@ -287,31 +305,30 @@ void hw_flash_program (uint32_t address, uint64_t value) {
|
||||
FLASH->CR &= ~(FLASH_CR_PG);
|
||||
}
|
||||
|
||||
void hw_loader_reset (uint32_t *parameters) {
|
||||
hw_flash_t hw_flash_read (uint32_t offset) {
|
||||
return *(uint64_t *) (FLASH_BASE + offset);
|
||||
}
|
||||
|
||||
void hw_loader_reset (loader_parameters_t *parameters) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN;
|
||||
PWR->CR1 |= PWR_CR1_DBP;
|
||||
TAMP->BKP0R = *parameters++;
|
||||
TAMP->BKP1R = *parameters++;
|
||||
TAMP->BKP2R = *parameters++;
|
||||
TAMP->BKP3R = *parameters++;
|
||||
TAMP->BKP4R = *parameters++;
|
||||
TAMP->BKP0R = parameters->magic;
|
||||
TAMP->BKP1R = parameters->mcu_address;
|
||||
TAMP->BKP2R = parameters->mcu_length;
|
||||
TAMP->BKP3R = parameters->fpga_address;
|
||||
TAMP->BKP4R = parameters->fpga_length;
|
||||
PWR->CR1 &= ~(PWR_CR1_DBP);
|
||||
RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
void hw_loader_get_parameters (uint32_t *parameters) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN;
|
||||
*parameters++ = TAMP->BKP0R;
|
||||
*parameters++ = TAMP->BKP1R;
|
||||
*parameters++ = TAMP->BKP2R;
|
||||
*parameters++ = TAMP->BKP3R;
|
||||
*parameters++ = TAMP->BKP4R;
|
||||
RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN);
|
||||
}
|
||||
|
||||
void hw_loader_clear_parameters (void) {
|
||||
void hw_loader_get_parameters (loader_parameters_t *parameters) {
|
||||
RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN;
|
||||
parameters->magic = TAMP->BKP0R;
|
||||
parameters->mcu_address = TAMP->BKP1R;
|
||||
parameters->mcu_length = TAMP->BKP2R;
|
||||
parameters->fpga_address = TAMP->BKP3R;
|
||||
parameters->fpga_length = TAMP->BKP4R;
|
||||
PWR->CR1 |= PWR_CR1_DBP;
|
||||
TAMP->BKP0R = 0;
|
||||
TAMP->BKP1R = 0;
|
||||
@ -420,6 +437,12 @@ 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;
|
||||
|
||||
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);
|
||||
|
@ -5,10 +5,6 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define HW_UPDATE_START_MAGIC (0x54535055)
|
||||
#define HW_UPDATE_DONE_MAGIC (0x4B4F5055)
|
||||
#define HW_FLASH_ADDRESS (0x08000000)
|
||||
|
||||
#define GPIO_PORT_PIN(p, n) ((((p) & 0x07) << 4) | ((n) & 0x0F))
|
||||
|
||||
typedef enum {
|
||||
@ -45,6 +41,16 @@ typedef enum {
|
||||
SPI_RX,
|
||||
} spi_direction_t;
|
||||
|
||||
typedef uint64_t hw_flash_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
uint32_t mcu_address;
|
||||
uint32_t mcu_length;
|
||||
uint32_t fpga_address;
|
||||
uint32_t fpga_length;
|
||||
} loader_parameters_t;
|
||||
|
||||
|
||||
void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void));
|
||||
uint32_t hw_gpio_get (gpio_id_t id);
|
||||
@ -63,13 +69,17 @@ void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void));
|
||||
void hw_tim_stop (tim_id_t id);
|
||||
void hw_tim_disable_irq (tim_id_t id);
|
||||
void hw_tim_enable_irq (tim_id_t id);
|
||||
void hw_delay_ms (uint32_t ms);
|
||||
void hw_crc32_reset (void);
|
||||
uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length);
|
||||
uint32_t hw_flash_size (void);
|
||||
void hw_flash_erase (void);
|
||||
void hw_flash_program (uint32_t address, uint64_t value);
|
||||
void hw_loader_reset (uint32_t *parameters);
|
||||
void hw_loader_get_parameters (uint32_t *parameters);
|
||||
void hw_loader_clear_parameters (void);
|
||||
void hw_loader_init (void);
|
||||
void hw_flash_program (uint32_t offset, hw_flash_t value);
|
||||
hw_flash_t hw_flash_read (uint32_t offset);
|
||||
void hw_loader_reset (loader_parameters_t *parameters);
|
||||
void hw_loader_get_parameters (loader_parameters_t *parameters);
|
||||
void hw_init (void);
|
||||
void hw_loader_init (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <stdint.h>
|
||||
#include "fpga.h"
|
||||
#include "isv.h"
|
||||
#include "usb.h"
|
||||
|
@ -40,7 +40,7 @@ init_bss:
|
||||
bcc 1b
|
||||
|
||||
run:
|
||||
bl loader_main
|
||||
bl loader
|
||||
|
||||
boot:
|
||||
ldr r0, =_app_magic
|
@ -1,8 +1,16 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32g030xx.h>
|
||||
#include "hw.h"
|
||||
#include "update.h"
|
||||
|
||||
|
||||
void loader (void) {
|
||||
if (update_check()) {
|
||||
hw_loader_init();
|
||||
update_perform();
|
||||
}
|
||||
}
|
||||
|
||||
void no_valid_image (void) {
|
||||
hw_gpio_set(GPIO_ID_LED);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include "hw.h"
|
||||
#include "update.h"
|
||||
|
||||
|
||||
void loader_main (void) {
|
||||
uint32_t parameters[5];
|
||||
|
||||
hw_loader_get_parameters(parameters);
|
||||
|
||||
if (parameters[0] == HW_UPDATE_START_MAGIC) {
|
||||
hw_loader_clear_parameters();
|
||||
hw_loader_init();
|
||||
|
||||
hw_gpio_set(GPIO_ID_LED);
|
||||
|
||||
update_perform(parameters);
|
||||
|
||||
hw_gpio_reset(GPIO_ID_LED);
|
||||
|
||||
parameters[0] = HW_UPDATE_DONE_MAGIC;
|
||||
hw_loader_reset(parameters);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
#include <stdint.h>
|
||||
#include <stm32g0xx.h>
|
||||
#include "task.h"
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <stdint.h>
|
||||
#include "fpga.h"
|
||||
#include "hw.h"
|
||||
#include "update.h"
|
||||
@ -6,64 +5,243 @@
|
||||
#include "vendor.h"
|
||||
|
||||
|
||||
static uint32_t update_mcu_address;
|
||||
static uint32_t update_mcu_length;
|
||||
static uint32_t update_fpga_address;
|
||||
static uint32_t update_fpga_length;
|
||||
#define UPDATE_MAGIC_START (0x54535055)
|
||||
|
||||
|
||||
uint32_t update_backup (uint32_t address) {
|
||||
// TODO: create backup
|
||||
return 0;
|
||||
typedef enum {
|
||||
UPDATE_STATUS_NONE = 0,
|
||||
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_ERROR = 0xFF,
|
||||
} update_status_t;
|
||||
|
||||
typedef enum {
|
||||
CHUNK_ID_UPDATE_INFO = 1,
|
||||
CHUNK_ID_MCU_DATA = 2,
|
||||
CHUNK_ID_FPGA_DATA = 3,
|
||||
} chunk_id_t;
|
||||
|
||||
|
||||
static loader_parameters_t parameters;
|
||||
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_NONE,
|
||||
};
|
||||
|
||||
|
||||
static uint32_t update_checksum (uint32_t address, uint32_t length) {
|
||||
uint32_t remaining = length;
|
||||
uint32_t block_size;
|
||||
uint32_t checksum;
|
||||
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;
|
||||
fpga_mem_read(address, block_size, buffer);
|
||||
checksum = hw_crc32_calculate(buffer, sizeof(buffer));
|
||||
remaining -= block_size;
|
||||
}
|
||||
|
||||
return checksum;
|
||||
}
|
||||
|
||||
static uint32_t update_write_token (uint32_t *address) {
|
||||
uint32_t length = sizeof(update_token);
|
||||
fpga_mem_write(*address, sizeof(update_token), update_token);
|
||||
*address += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
static uint32_t update_prepare_chunk (uint32_t *address, chunk_id_t chunk_id) {
|
||||
uint32_t id = (uint32_t) (chunk_id);
|
||||
uint32_t length = sizeof(id) + (2 * sizeof(uint32_t));
|
||||
fpga_mem_write(*address, sizeof(id), (uint8_t *) (&id));
|
||||
*address += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
static uint32_t update_finalize_chunk (uint32_t *address, uint32_t length) {
|
||||
uint32_t checksum = update_checksum(*address, length);
|
||||
fpga_mem_write(*address - (2 * sizeof(uint32_t)), sizeof(length), (uint8_t *) (&length));
|
||||
fpga_mem_write(*address - sizeof(uint32_t), sizeof(checksum), (uint8_t *) (&checksum));
|
||||
*address += length;
|
||||
return length;
|
||||
}
|
||||
|
||||
static bool update_check_token (uint32_t *address) {
|
||||
uint8_t buffer[sizeof(update_token)];
|
||||
fpga_mem_read(*address, sizeof(update_token), buffer);
|
||||
for (int i = 0; i < sizeof(update_token); i++) {
|
||||
if (buffer[i] != update_token[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*address += sizeof(update_token);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool update_get_chunk (uint32_t *address, chunk_id_t *chunk_id, uint32_t *data_address, uint32_t *data_length) {
|
||||
uint32_t id;
|
||||
uint32_t checksum;
|
||||
fpga_mem_read(*address, sizeof(id), (uint8_t *) (id));
|
||||
*address += sizeof(id);
|
||||
fpga_mem_read(*address, sizeof(*data_length), (uint8_t *) (data_length));
|
||||
*address += sizeof(*data_length);
|
||||
fpga_mem_read(*address, sizeof(checksum), (uint8_t *) (checksum));
|
||||
*address += sizeof(checksum);
|
||||
*data_address = *address;
|
||||
*address += *data_length;
|
||||
if (checksum != update_checksum(*data_address, *data_length)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void update_blink_led (uint32_t on, uint32_t off, int repeat) {
|
||||
for (int i = 0; i < repeat; i++) {
|
||||
hw_gpio_set(GPIO_ID_LED);
|
||||
hw_delay_ms(on);
|
||||
hw_gpio_reset(GPIO_ID_LED);
|
||||
hw_delay_ms(off);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_status_notify (update_status_t status) {
|
||||
status_data[sizeof(status_data) - 1] = (uint8_t) (status);
|
||||
for (int i = 0; i < sizeof(status_data); i++) {
|
||||
while (!(fpga_usb_status_get() & USB_STATUS_TXE));
|
||||
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 {
|
||||
update_blink_led(1000, 1000, 30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
update_error_t update_backup (uint32_t address, uint32_t *length) {
|
||||
hw_flash_t buffer;
|
||||
uint32_t fpga_length;
|
||||
|
||||
*length += update_write_token(&address);
|
||||
|
||||
*length += update_prepare_chunk(&address, CHUNK_ID_MCU_DATA);
|
||||
for (uint32_t offset = 0; offset < hw_flash_size(); offset += sizeof(hw_flash_t)) {
|
||||
buffer = hw_flash_read(offset);
|
||||
fpga_mem_write(address + offset, sizeof(hw_flash_t), (uint8_t *) (&buffer));
|
||||
}
|
||||
*length += update_finalize_chunk(&address, hw_flash_size());
|
||||
|
||||
*length += update_prepare_chunk(&address, CHUNK_ID_FPGA_DATA);
|
||||
if (vendor_backup(address, &fpga_length) != VENDOR_OK) {
|
||||
return UPDATE_ERROR_READ;
|
||||
}
|
||||
*length += update_finalize_chunk(&address, fpga_length);
|
||||
|
||||
return UPDATE_OK;
|
||||
}
|
||||
|
||||
update_error_t update_prepare (uint32_t address, uint32_t length) {
|
||||
// TODO: validate image
|
||||
update_mcu_address = 0;
|
||||
update_mcu_length = 0;
|
||||
update_fpga_address = 0;
|
||||
update_fpga_length = 0;
|
||||
uint32_t end_address = address + length;
|
||||
chunk_id_t id;
|
||||
uint32_t data_address;
|
||||
uint32_t data_length;
|
||||
|
||||
if (update_check_token(&address)) {
|
||||
return UPDATE_ERROR_TOKEN;
|
||||
}
|
||||
|
||||
parameters.mcu_address = 0;
|
||||
parameters.mcu_length = 0;
|
||||
parameters.fpga_address = 0;
|
||||
parameters.fpga_length = 0;
|
||||
|
||||
while (address < end_address) {
|
||||
if (update_get_chunk(&address, &id, &data_address, &data_length)) {
|
||||
return UPDATE_ERROR_CHECKSUM;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case CHUNK_ID_UPDATE_INFO:
|
||||
break;
|
||||
|
||||
case CHUNK_ID_MCU_DATA:
|
||||
parameters.mcu_address = data_address;
|
||||
parameters.mcu_length = data_length;
|
||||
break;
|
||||
|
||||
case CHUNK_ID_FPGA_DATA:
|
||||
parameters.fpga_address = data_address;
|
||||
parameters.fpga_length = data_length;
|
||||
break;
|
||||
|
||||
default:
|
||||
return UPDATE_ERROR_UNKNOWN_CHUNK;
|
||||
}
|
||||
}
|
||||
|
||||
return UPDATE_OK;
|
||||
}
|
||||
|
||||
void update_start (void) {
|
||||
uint32_t parameters[5] = {
|
||||
HW_UPDATE_START_MAGIC,
|
||||
update_mcu_address,
|
||||
update_mcu_length,
|
||||
update_fpga_address,
|
||||
update_fpga_length,
|
||||
};
|
||||
hw_loader_reset(parameters);
|
||||
parameters.magic = UPDATE_MAGIC_START;
|
||||
hw_loader_reset(¶meters);
|
||||
}
|
||||
|
||||
void update_perform (uint32_t *parameters) {
|
||||
uint64_t buffer;
|
||||
bool update_check (void) {
|
||||
hw_loader_get_parameters(¶meters);
|
||||
return (parameters.magic == UPDATE_MAGIC_START);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (parameters[2] != 0) {
|
||||
hw_flash_erase();
|
||||
for (int i = 0; i < parameters[2]; i += sizeof(buffer)) {
|
||||
fpga_mem_read(parameters[1] + i, sizeof(buffer), (uint8_t *) (&buffer));
|
||||
hw_flash_program(HW_FLASH_ADDRESS + i, buffer);
|
||||
|
||||
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?
|
||||
}
|
||||
}
|
||||
|
||||
update_status_notify(UPDATE_STATUS_MCU_DONE);
|
||||
}
|
||||
|
||||
if (parameters[4] != 0) {
|
||||
vendor_update(parameters[3], parameters[4]);
|
||||
if (parameters.fpga_length != 0) {
|
||||
update_status_notify(UPDATE_STATUS_FPGA_START);
|
||||
|
||||
if (vendor_update(parameters.fpga_address, parameters.fpga_length) != VENDOR_OK) {
|
||||
update_status_notify(UPDATE_STATUS_ERROR);
|
||||
while (1); // TODO: jump to STM32 bootloader?
|
||||
}
|
||||
|
||||
update_status_notify(UPDATE_STATUS_FPGA_DONE);
|
||||
}
|
||||
|
||||
update_status_notify(UPDATE_STATUS_DONE);
|
||||
|
||||
vendor_reconfigure();
|
||||
}
|
||||
|
||||
void update_notify_done (void) {
|
||||
uint32_t parameters[5];
|
||||
usb_tx_info_t packet;
|
||||
|
||||
hw_loader_get_parameters(parameters);
|
||||
|
||||
if (parameters[0] == HW_UPDATE_DONE_MAGIC) {
|
||||
hw_loader_clear_parameters();
|
||||
usb_create_packet(&packet, PACKET_CMD_UPDATE_DONE);
|
||||
usb_enqueue_packet(&packet);
|
||||
}
|
||||
|
||||
parameters.magic = 0;
|
||||
hw_loader_reset(¶meters);
|
||||
}
|
||||
|
@ -2,21 +2,24 @@
|
||||
#define UPDATE_H__
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
UPDATE_OK,
|
||||
UPDATE_ERROR_INVALID_HEADER,
|
||||
UPDATE_ERROR_TOKEN,
|
||||
UPDATE_ERROR_CHECKSUM,
|
||||
UPDATE_ERROR_UNKNOWN_CHUNK,
|
||||
UPDATE_ERROR_READ,
|
||||
} update_error_t;
|
||||
|
||||
|
||||
uint32_t update_backup (uint32_t address);
|
||||
update_error_t update_backup (uint32_t address, uint32_t *length);
|
||||
update_error_t update_prepare (uint32_t address, uint32_t length);
|
||||
void update_start (void);
|
||||
void update_perform (uint32_t *parameters);
|
||||
void update_notify_done (void);
|
||||
bool update_check (void);
|
||||
void update_perform (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,3 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "cfg.h"
|
||||
#include "cic.h"
|
||||
#include "dd.h"
|
||||
@ -211,8 +209,8 @@ static void usb_rx_process (void) {
|
||||
p.response_info.dma_length = p.rx_args[1];
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
case 'D':
|
||||
case 'M':
|
||||
if (usb_dma_ready()) {
|
||||
if (!p.rx_dma_running) {
|
||||
fpga_reg_set(REG_USB_DMA_ADDRESS, p.rx_args[0]);
|
||||
@ -251,10 +249,11 @@ static void usb_rx_process (void) {
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
p.response_info.data[0] = update_backup(p.rx_args[0]);
|
||||
p.response_info.data[0] = update_backup(p.rx_args[0], &p.response_info.data[1]);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 4;
|
||||
p.response_error = (p.response_info.data[0] != UPDATE_OK);
|
||||
p.response_info.data_length = 8;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
@ -355,8 +354,8 @@ static void usb_tx_process (void) {
|
||||
}
|
||||
|
||||
|
||||
void usb_create_packet (usb_tx_info_t *info, uint8_t cmd) {
|
||||
info->cmd = cmd;
|
||||
void usb_create_packet (usb_tx_info_t *info, usb_packet_cmd_e cmd) {
|
||||
info->cmd = (uint8_t) (cmd);
|
||||
info->data_length = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
info->data[i] = 0;
|
||||
@ -394,7 +393,7 @@ void usb_get_read_info (uint32_t *args) {
|
||||
args[0] |= (p.read_length > 0) ? (1 << 24) : 0;
|
||||
}
|
||||
|
||||
static void usb_reinit (void) {
|
||||
void usb_init (void) {
|
||||
fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP);
|
||||
fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH);
|
||||
|
||||
@ -414,17 +413,12 @@ static void usb_reinit (void) {
|
||||
usb_rx_cmd_counter = 0;
|
||||
}
|
||||
|
||||
void usb_init (void) {
|
||||
usb_reinit();
|
||||
update_notify_done();
|
||||
}
|
||||
|
||||
void usb_process (void) {
|
||||
if (fpga_reg_get(REG_USB_SCR) & USB_SCR_RESET_PENDING) {
|
||||
if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) {
|
||||
p.tx_info.done_callback();
|
||||
}
|
||||
usb_reinit();
|
||||
usb_init();
|
||||
fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK);
|
||||
} else {
|
||||
usb_rx_process();
|
||||
|
@ -8,9 +8,9 @@
|
||||
|
||||
typedef enum packet_cmd {
|
||||
PACKET_CMD_DD_REQUEST = 'D',
|
||||
PACKET_CMD_DEBUG_OUTPUT = 'U',
|
||||
PACKET_CMD_ISV_OUTPUT = 'I',
|
||||
PACKET_CMD_USB_OUTPUT = 'U',
|
||||
PACKET_CMD_UPDATE_DONE = 'F',
|
||||
PACKET_CMD_UPDATE_STATUS = 'F',
|
||||
} usb_packet_cmd_e;
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ typedef struct usb_tx_info {
|
||||
} usb_tx_info_t;
|
||||
|
||||
|
||||
void usb_create_packet (usb_tx_info_t *info, uint8_t cmd);
|
||||
void usb_create_packet (usb_tx_info_t *info, usb_packet_cmd_e cmd);
|
||||
bool usb_enqueue_packet (usb_tx_info_t *info);
|
||||
bool usb_prepare_read (uint32_t *args);
|
||||
void usb_get_read_info (uint32_t *args);
|
||||
|
Loading…
x
Reference in New Issue
Block a user