diff --git a/build.sh b/build.sh index 54aa9eb..fa02595 100755 --- a/build.sh +++ b/build.sh @@ -47,9 +47,9 @@ build_controller () { pushd sw/controller > /dev/null if [ "$FORCE_CLEAN" = true ]; then - make clean + ./build.sh clean fi - make all -j USER_FLAGS="$USER_FLAGS" + USER_FLAGS="$USER_FLAGS" ./build.sh all popd > /dev/null BUILT_CONTROLLER=true diff --git a/sw/controller/.gitignore b/sw/controller/.gitignore index 5743e15..7ef01c0 100644 --- a/sw/controller/.gitignore +++ b/sw/controller/.gitignore @@ -1,2 +1,3 @@ -/build +/build_app +/build_loader *.svd diff --git a/sw/controller/STM32G030F6Px_FLASH.ld b/sw/controller/app.ld similarity index 78% rename from sw/controller/STM32G030F6Px_FLASH.ld rename to sw/controller/app.ld index 2a3edca..641c293 100644 --- a/sw/controller/STM32G030F6Px_FLASH.ld +++ b/sw/controller/app.ld @@ -1,11 +1,18 @@ MEMORY { - rom (rx) : org = 0x08000000, len = 32k + loader (rx) : org = 0x08000000, len = 4k + rom (rx) : org = 0x08001000, len = 28k ram (rwx) : org = 0x20000000, len = 8k } ENTRY(Reset_Handler) SECTIONS { + .loader : { + . = ALIGN(4); + KEEP(*(.loader)) + . = ALIGN(4); + } > loader + .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) @@ -22,23 +29,6 @@ SECTIONS { _etext = .; } > rom - .rodata : { - . = ALIGN(4); - *(.rodata) - *(.rodata*) - . = ALIGN(4); - } > rom - - .data : { - _sidata = LOADADDR(.data); - . = ALIGN(4); - _sdata = .; - *(.data) - *(.data*) - . = ALIGN(4); - _edata = .; - } > ram AT > rom - .bss : { . = ALIGN(4); _sbss = .; @@ -51,5 +41,22 @@ SECTIONS { __bss_end__ = _ebss; } > ram + .data : { + _sidata = LOADADDR(.data); + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } > ram AT > rom + + .rodata : { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(8); + } > rom + _estack = ORIGIN(ram) + LENGTH(ram); } diff --git a/sw/controller/app.mk b/sw/controller/app.mk new file mode 100644 index 0000000..b828545 --- /dev/null +++ b/sw/controller/app.mk @@ -0,0 +1,25 @@ +EXE_NAME = app +LD_SCRIPT = app.ld +BUILD_DIR = build_app +SRC_FILES = \ + app_startup.S \ + app_main.c \ + cfg.c \ + cic.c \ + dd.c \ + debug.c \ + flash.c \ + flashram.c \ + fpga.c \ + gvr.c \ + hw.c \ + isv.c \ + lcmxo2.c \ + rtc.c \ + task.c \ + update.c \ + usb.c + +include common.mk + +$(BUILD_DIR)/app_startup.S.o: ../build_loader/loader.bin diff --git a/sw/controller/build.sh b/sw/controller/build.sh new file mode 100644 index 0000000..b2345b3 --- /dev/null +++ b/sw/controller/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash + + +case "$1" in + all) + make all -j -f loader.mk USER_FLAGS="$USER_FLAGS" + make all -j -f app.mk USER_FLAGS="$USER_FLAGS" + ;; + clean) + make clean -f loader.mk + make clean -f app.mk + ;; +esac diff --git a/sw/controller/Makefile b/sw/controller/common.mk similarity index 57% rename from sw/controller/Makefile rename to sw/controller/common.mk index 040d7f8..54447b8 100644 --- a/sw/controller/Makefile +++ b/sw/controller/common.mk @@ -10,25 +10,6 @@ CFLAGS = -Og -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP - LDFLAGS = -nostartfiles -Wl,--gc-sections SRC_DIR = src -BUILD_DIR = build - -SRC_FILES = \ - startup.S \ - cfg.c \ - cic.c \ - dd.c \ - debug.c \ - flash.c \ - flashram.c \ - fpga.c \ - gvr.c \ - hw.c \ - isv.c \ - lcmxo2.c \ - main.c \ - rtc.c \ - task.c \ - usb.c SRCS = $(addprefix $(SRC_DIR)/, $(SRC_FILES)) OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %,%.o,$(SRCS)))) @@ -44,23 +25,23 @@ $(BUILD_DIR)/%.S.o: %.S $(BUILD_DIR)/%.c.o: %.c $(CC) $(FLAGS) $(CFLAGS) -c $< -o $@ -$(BUILD_DIR)/controller.elf: $(OBJS) STM32G030F6Px_FLASH.ld - $(CXX) $(FLAGS) $(LDFLAGS) -TSTM32G030F6Px_FLASH.ld $(OBJS) -o $@ - @$(OBJDUMP) -S -D $@ > $(BUILD_DIR)/controller.lst +$(BUILD_DIR)/$(EXE_NAME).elf: $(OBJS) $(LD_SCRIPT) + $(CXX) $(FLAGS) $(LDFLAGS) -T$(LD_SCRIPT) $(OBJS) -o $@ + @$(OBJDUMP) -S -D $@ > $(BUILD_DIR)/$(EXE_NAME).lst -$(BUILD_DIR)/controller.bin: $(BUILD_DIR)/controller.elf - @$(OBJCOPY) -O binary $< $@ +$(BUILD_DIR)/$(EXE_NAME).bin: $(BUILD_DIR)/$(EXE_NAME).elf + $(OBJCOPY) -O binary $< $@ -$(BUILD_DIR)/controller.hex: $(BUILD_DIR)/controller.bin +$(BUILD_DIR)/$(EXE_NAME).hex: $(BUILD_DIR)/$(EXE_NAME).bin @$(OBJCOPY) -I binary -O ihex $< $@ -print_size: $(BUILD_DIR)/controller.elf +print_size: $(BUILD_DIR)/$(EXE_NAME).elf @echo 'Size of modules:' @$(SIZE) -B -d -t --common $(OBJS) - @echo 'Size of controller:' + @echo 'Size of $(EXE_NAME):' @$(SIZE) -B -d $< -all: $(BUILD_DIR)/controller.hex print_size +all: $(BUILD_DIR)/$(EXE_NAME).hex print_size clean: @rm -rf ./$(BUILD_DIR)/* diff --git a/sw/controller/loader.ld b/sw/controller/loader.ld new file mode 100644 index 0000000..29a5f48 --- /dev/null +++ b/sw/controller/loader.ld @@ -0,0 +1,68 @@ +MEMORY { + rom (rx) : org = 0x08000000, len = 4k + ram (rwx) : org = 0x20000000, len = 8k +} + +ENTRY(Reset_Handler) + +SECTIONS { + .isr_vector : { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } > rom + + .startup : { + . = ALIGN(4); + *(.text.Reset_Handler) + . = ALIGN(4); + } > rom + + .text : { + _sitext = LOADADDR(.text); + . = ALIGN(4); + _stext = .; + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + . = ALIGN(4); + _etext = .; + } > ram AT > rom + + .bss : { + . = ALIGN(4); + _sbss = .; + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } > ram + + .data : { + _sidata = LOADADDR(.data); + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } > ram AT > rom + + .rodata : { + _sirodata = LOADADDR(.rodata); + . = ALIGN(4); + _srodata = .; + *(.rodata) + *(.rodata*) + . = ALIGN(8); + _erodata = .; + } > ram AT > rom + + _app_header = ORIGIN(rom) + LENGTH(rom); + _app_magic = _app_header + 16; + _estack = ORIGIN(ram) + LENGTH(ram); +} diff --git a/sw/controller/loader.mk b/sw/controller/loader.mk new file mode 100644 index 0000000..4681637 --- /dev/null +++ b/sw/controller/loader.mk @@ -0,0 +1,13 @@ +EXE_NAME = loader +LD_SCRIPT = loader.ld +BUILD_DIR = build_loader +SRC_FILES = \ + loader_startup.S \ + boot.c \ + debug.c \ + fpga.c \ + hw.c \ + lcmxo2.c \ + loader_main.c + +include common.mk diff --git a/sw/controller/src/main.c b/sw/controller/src/app_main.c similarity index 92% rename from sw/controller/src/main.c rename to sw/controller/src/app_main.c index caf8aaf..5ce6a2d 100644 --- a/sw/controller/src/main.c +++ b/sw/controller/src/app_main.c @@ -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 main (void) { +void app_main (void) { hw_init(); cic_hw_init(); diff --git a/sw/controller/src/startup.S b/sw/controller/src/app_startup.S similarity index 92% rename from sw/controller/src/startup.S rename to sw/controller/src/app_startup.S index 669c83f..4c640cd 100644 --- a/sw/controller/src/startup.S +++ b/sw/controller/src/app_startup.S @@ -3,6 +3,12 @@ .fpu softvfp .thumb +.section .loader, "a", %progbits +.type g_pfnVectors, %object +loader: + .incbin "../build_loader/loader.bin" + + .section .text.Reset_Handler .type Reset_Handler, %function Reset_Handler: @@ -37,7 +43,7 @@ init_bss: bcc 1b run: - bl main + bl app_main loop: b loop @@ -57,7 +63,7 @@ g_pfnVectors: .word Reset_Handler .word NMI_Handler .word HardFault_Handler - .word 0 + .word 0x34364353 .word 0 .word 0 .word 0 diff --git a/sw/controller/src/boot.c b/sw/controller/src/boot.c new file mode 100644 index 0000000..1c36f13 --- /dev/null +++ b/sw/controller/src/boot.c @@ -0,0 +1,12 @@ +#include +#include +#include "hw.h" + + +void no_valid_image (void) { + hw_gpio_set(GPIO_ID_LED); +} + +void set_vector_table_offset (uint32_t offset) { + SCB->VTOR = (__IOM uint32_t) (offset); +} diff --git a/sw/controller/src/hw.c b/sw/controller/src/hw.c index db03ebf..e01d9db 100644 --- a/sw/controller/src/hw.c +++ b/sw/controller/src/hw.c @@ -55,7 +55,7 @@ static const TIM_TypeDef *tims[] = { TIM14, TIM16, TIM17, TIM3 }; static void (*volatile tim_callbacks[4])(void); -void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_ospeed_t ospeed, gpio_pupd_t pupd, gpio_af_t af, int value) { +static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_ospeed_t ospeed, gpio_pupd_t pupd, gpio_af_t af, int value) { GPIO_TypeDef tmp; GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); @@ -258,7 +258,71 @@ void hw_tim_stop (tim_id_t id) { tim_callbacks[id] = 0; } -void hw_init (void) { +static void hw_flash_unlock (void) { + while (FLASH->SR & FLASH_SR_BSY1); + if (FLASH->CR & FLASH_CR_LOCK) { + FLASH->KEYR = 0x45670123; + FLASH->KEYR = 0xCDEF89AB; + } +} + +void hw_flash_erase (void) { + hw_flash_unlock(); + FLASH->CR |= FLASH_CR_MER1; + FLASH->CR |= FLASH_CR_STRT; + while (FLASH->SR & FLASH_SR_BSY1); + FLASH->CR &= ~(FLASH_CR_MER1); +} + +void hw_flash_program (uint32_t address, uint64_t value) { + hw_flash_unlock(); + FLASH->CR |= FLASH_CR_PG; + *(__IO uint32_t *) (address) = ((value) & 0xFFFFFFFF); + __ISB(); + *(__IO uint32_t *) (address + 4) = ((value >> 32) & 0xFFFFFFFF); + while (FLASH->SR & FLASH_SR_BSY1); + if (FLASH->SR & FLASH_SR_EOP) { + FLASH->SR |= FLASH_SR_EOP; + } + FLASH->CR &= ~(FLASH_CR_PG); +} + +void hw_loader_reset (uint32_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++; + 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) { + RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; + PWR->CR1 |= PWR_CR1_DBP; + TAMP->BKP0R = 0; + TAMP->BKP1R = 0; + TAMP->BKP2R = 0; + TAMP->BKP3R = 0; + TAMP->BKP4R = 0; + PWR->CR1 &= ~(PWR_CR1_DBP); + RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); +} + +static void hw_init_mcu (void) { FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos)); while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos)); @@ -276,37 +340,21 @@ void hw_init (void) { RCC->CFGR = RCC_CFGR_SW_1; while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1); - RCC->AHBENR |= RCC_AHBENR_DMA1EN; - RCC->APBENR1 |= ( - RCC_APBENR1_DBGEN | - RCC_APBENR1_I2C1EN | - RCC_APBENR1_TIM3EN - ); - RCC->APBENR2 |= ( - RCC_APBENR2_TIM17EN | - RCC_APBENR2_TIM16EN | - RCC_APBENR2_TIM14EN | - RCC_APBENR2_USART1EN | - RCC_APBENR2_SPI1EN | - RCC_APBENR2_SYSCFGEN - ); - - DBG->APBFZ2 = ( - DBG_APB_FZ2_DBG_TIM17_STOP | - DBG_APB_FZ2_DBG_TIM16_STOP | - DBG_APB_FZ2_DBG_TIM14_STOP - ); - RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; + hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0); +} + +static void hw_init_spi (void) { + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + RCC->APBENR2 |= RCC_APBENR2_SPI1EN; + DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos); DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos); DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR); DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR); - SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); - SPI1->CR2 = ( SPI_CR2_FRXTH | (8 - 1) << SPI_CR2_DS_Pos | @@ -322,32 +370,68 @@ void hw_init (void) { SPI_CR1_CPHA ); - USART1->BRR = (64000000UL) / 1000000; - USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_TE | USART_CR1_UE; - - I2C1->TIMINGR = 0x10B17DB5UL; - I2C1->CR1 |= (I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE | I2C_CR1_PE); - - 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); - - hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0); - hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1); hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); - hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); +} - 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_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, GPIO_AF_1, 0); +static void hw_init_i2c (void) { + RCC->APBENR1 |= RCC_APBENR1_I2C1EN; + + I2C1->TIMINGR = 0x10B17DB5UL; + 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); hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); - hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); +} + +static void hw_init_uart (void) { + RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN); + + SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); + + USART1->BRR = (64000000UL) / 1000000; + USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_TE | USART_CR1_UE; + + 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_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_NONE, GPIO_AF_1, 0); +} + +static void hw_init_tim (void) { + RCC->APBENR1 |= ( + RCC_APBENR1_DBGEN | + RCC_APBENR1_TIM3EN + ); + RCC->APBENR2 |= ( + RCC_APBENR2_TIM17EN | + RCC_APBENR2_TIM16EN | + RCC_APBENR2_TIM14EN | + RCC_APBENR2_USART1EN + ); + + DBG->APBFZ2 |= ( + DBG_APB_FZ2_DBG_TIM17_STOP | + DBG_APB_FZ2_DBG_TIM16_STOP | + DBG_APB_FZ2_DBG_TIM14_STOP + ); +} + +static void hw_init_misc (void) { + 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); +} + +void hw_init (void) { + hw_init_mcu(); + hw_init_spi(); + hw_init_i2c(); + hw_init_uart(); + hw_init_tim(); + hw_init_misc(); NVIC_SetPriority(EXTI0_1_IRQn, 0); NVIC_SetPriority(EXTI2_3_IRQn, 1); @@ -367,6 +451,11 @@ void hw_init (void) { NVIC_EnableIRQ(TIM3_IRQn); } +void hw_loader_init (void) { + hw_init_mcu(); + hw_init_spi(); +} + void EXTI0_1_IRQHandler (void) { for (int i = 0; i <= 1; i++) { diff --git a/sw/controller/src/hw.h b/sw/controller/src/hw.h index e897d15..c53a2db 100644 --- a/sw/controller/src/hw.h +++ b/sw/controller/src/hw.h @@ -5,6 +5,10 @@ #include +#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 { @@ -59,6 +63,12 @@ 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_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_init (void); diff --git a/sw/controller/src/loader_main.c b/sw/controller/src/loader_main.c new file mode 100644 index 0000000..88eb67a --- /dev/null +++ b/sw/controller/src/loader_main.c @@ -0,0 +1,37 @@ +#include +#include "fpga.h" +#include "hw.h" +#include "vendor.h" + + +void loader_main (void) { + uint32_t parameters[5]; + uint64_t buffer; + + 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); + + 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); + } + } + + if (parameters[4] != 0) { + vendor_update(parameters[3], parameters[4]); + vendor_reconfigure(); + } + + hw_gpio_reset(GPIO_ID_LED); + + parameters[0] = HW_UPDATE_DONE_MAGIC; + hw_loader_reset(parameters); + } +} diff --git a/sw/controller/src/loader_startup.S b/sw/controller/src/loader_startup.S new file mode 100644 index 0000000..3ec4396 --- /dev/null +++ b/sw/controller/src/loader_startup.S @@ -0,0 +1,99 @@ +.syntax unified +.cpu cortex-m0plus +.fpu softvfp +.thumb + +.section .text.Reset_Handler +.type Reset_Handler, %function +Reset_Handler: + .global Reset_Handler + cpsid i + +init_text: + ldr r0, =_stext + ldr r1, =_etext + ldr r2, =_sitext + bl copy_section + +init_rodata: + ldr r0, =_srodata + ldr r1, =_erodata + ldr r2, =_sirodata + bl copy_section + +init_data: + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + bl copy_section + +init_bss: + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b 2f +1: + str r3, [r2] + adds r2, r2, #4 +2: + cmp r2, r4 + bcc 1b + +run: + bl loader_main + +boot: + ldr r0, =_app_magic + ldr r0, [r0] + ldr r1, =0x34364353 + cmp r0, r1 + bne empty_image + + ldr r0, =_app_header + push {r0} + bl set_vector_table_offset + pop {r0} + ldr r1, [r0, #0] + msr MSP, r1 + ldr r1, [r0, #4] + blx r1 + +empty_image: + bl no_valid_image + +loop: + b loop + +copy_section: + movs r3, #0 + b 2f +1: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 +2: + adds r4, r0, r3 + cmp r4, r1 + bcc 1b + bx lr + + +.section .text.Default_Handler, "ax", %progbits +Default_Handler: + .global Default_Handler + b Default_Handler + + +.section .isr_vector, "a", %progbits +.type g_pfnVectors, %object +g_pfnVectors: + .global g_pfnVectors + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + + .weak NMI_Handler + .thumb_set NMI_Handler, Default_Handler + .weak HardFault_Handler + .thumb_set HardFault_Handler, Default_Handler diff --git a/sw/controller/src/update.c b/sw/controller/src/update.c new file mode 100644 index 0000000..8076b0f --- /dev/null +++ b/sw/controller/src/update.c @@ -0,0 +1,49 @@ +#include +#include "hw.h" +#include "update.h" +#include "usb.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; + + +uint32_t update_backup (uint32_t address) { + // TODO: create backup + return 0; +} + +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; + 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); +} + +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); + } +} diff --git a/sw/controller/src/update.h b/sw/controller/src/update.h new file mode 100644 index 0000000..cac8364 --- /dev/null +++ b/sw/controller/src/update.h @@ -0,0 +1,21 @@ +#ifndef UPDATE_H__ +#define UPDATE_H__ + + +#include + + +typedef enum { + UPDATE_OK, + UPDATE_ERROR_INVALID_HEADER, + UPDATE_ERROR_CHECKSUM, +} update_error_t; + + +uint32_t update_backup (uint32_t address); +update_error_t update_prepare (uint32_t address, uint32_t length); +void update_start (void); +void update_notify_done (void); + + +#endif diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index 5db9508..b32d727 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -6,8 +6,8 @@ #include "flash.h" #include "fpga.h" #include "rtc.h" +#include "update.h" #include "usb.h" -#include "vendor.h" enum rx_state { @@ -251,21 +251,20 @@ static void usb_rx_process (void) { break; case 'f': - p.response_info.data[0] = vendor_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 = 8; - if (p.response_info.data[0] != VENDOR_OK) { - p.response_error = true; - } - break; - - case 'F': - p.response_info.data[0] = vendor_update(p.rx_args[0], p.rx_args[1]); + p.response_info.data[0] = update_backup(p.rx_args[0]); p.rx_state = RX_STATE_IDLE; p.response_pending = true; p.response_info.data_length = 4; - if (p.response_info.data[0] != VENDOR_OK) { + break; + + case 'F': + p.response_info.data[0] = update_prepare(p.rx_args[0], p.rx_args[1]); + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + p.response_info.data_length = 4; + if (p.response_info.data[0] == UPDATE_OK) { + p.response_info.done_callback = update_start; + } else { p.response_error = true; } break; @@ -371,10 +370,8 @@ bool usb_enqueue_packet (usb_tx_info_t *info) { if (p.packet_pending) { return false; } - p.packet_pending = true; p.packet_info = *info; - return true; } @@ -397,7 +394,7 @@ void usb_get_read_info (uint32_t *args) { args[0] |= (p.read_length > 0) ? (1 << 24) : 0; } -void usb_init (void) { +static void usb_reinit (void) { fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP); fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH); @@ -417,12 +414,17 @@ void usb_init (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_init(); + usb_reinit(); fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK); } else { usb_rx_process(); diff --git a/sw/controller/src/usb.h b/sw/controller/src/usb.h index 33bf286..ea6e864 100644 --- a/sw/controller/src/usb.h +++ b/sw/controller/src/usb.h @@ -10,6 +10,7 @@ typedef enum packet_cmd { PACKET_CMD_DD_REQUEST = 'D', PACKET_CMD_ISV_OUTPUT = 'I', PACKET_CMD_USB_OUTPUT = 'U', + PACKET_CMD_UPDATE_DONE = 'F', } usb_packet_cmd_e;