#include "boot_port.h" #include "boot_image.h" #include "boot_writer.h" #include "stm32g4xx_hal.h" #include #define COMMIT 0x53455442UL static g474_writer writer; static bool geometry_valid(void) { __HAL_RCC_SYSCFG_CLK_ENABLE(); return g474_geometry_supported(*(const uint16_t *)FLASHSIZE_BASE, (FLASH->OPTR & FLASH_OPTR_DBANK) != 0, (FLASH->OPTR & FLASH_OPTR_BFB2) != 0 || (SYSCFG->MEMRMP & SYSCFG_MEMRMP_FB_MODE) != 0); } static bool erase_page(uint32_t address) { FLASH_EraseInitTypeDef config = {0}; uint32_t bank, page, error; if (!g474_flash_page(address, (FLASH->OPTR & FLASH_OPTR_DBANK) != 0, &bank, &page)) return false; config.TypeErase = FLASH_TYPEERASE_PAGES; config.Banks = bank == 2U ? FLASH_BANK_2 : FLASH_BANK_1; config.Page = page; config.NbPages = 1; return HAL_FLASHEx_Erase(&config, &error) == HAL_OK; } static bool invalidate(void *user) { bool ok; (void)user; if (!geometry_valid() || HAL_FLASH_Unlock() != HAL_OK) return false; __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); ok = erase_page(G474_META_BASE); (void)HAL_FLASH_Lock(); return ok; } static bool erase(void *user, uint32_t size) { uint32_t address, step; bool ok = true; (void)user; if (size < 8 || size > G474_APP_SIZE || !geometry_valid()) return false; g474_writer_init(&writer, size); if (HAL_FLASH_Unlock() != HAL_OK) return false; __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); step = (FLASH->OPTR & FLASH_OPTR_DBANK) ? 2048U : 4096U; for (address = G474_APP_BASE; address < G474_APP_BASE + size; address += step) { if (!erase_page(address)) { ok = false; break; } } (void)HAL_FLASH_Lock(); return ok; } static bool program_word(void *user, uint32_t offset, uint64_t word) { uint64_t actual; (void)user; if ((offset & 7U) || offset > G474_APP_SIZE - 8U) return false; if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, G474_APP_BASE + offset, word) != HAL_OK) return false; memcpy(&actual, (const void *)(G474_APP_BASE + offset), 8); return actual == word; } static bool write(void *user, uint32_t offset, const uint8_t *data, uint16_t length) { bool ok; (void)user; if (HAL_FLASH_Unlock() != HAL_OK) return false; __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); ok = g474_writer_write(&writer, offset, data, length, program_word, 0); (void)HAL_FLASH_Lock(); return ok; } static bool verify(void *user, uint32_t size, uint32_t crc) { (void)user; return !writer.failed && !writer.used && writer.received == size && writer.size == size && g474_vectors_valid((const uint8_t *)G474_APP_BASE, size) && setp_crc32((const uint8_t *)G474_APP_BASE, size) == crc; } static bool commit(void *user, uint32_t size, uint32_t crc) { uint32_t record[4] = {size, crc, ~size, COMMIT}; uint64_t word; unsigned i; bool ok = true; (void)user; if (HAL_FLASH_Unlock() != HAL_OK) return false; __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); for (i = 0; i < sizeof(record); i += 8) { memcpy(&word, (const uint8_t *)record + i, 8); if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, G474_META_BASE + i, word) != HAL_OK) { ok = false; break; } } (void)HAL_FLASH_Lock(); return ok && !memcmp((const void *)G474_META_BASE, record, sizeof(record)); } bool g474_app_valid(void) { /* Same reset policy as F407: SWD images need no USB commit record. */ return geometry_valid() && g474_vectors_valid((const uint8_t *)G474_APP_BASE, G474_APP_SIZE); } static void activate(void *user) { (void)user; } const setp_boot_ops g474_boot_ops = {invalidate, erase, write, verify, commit, activate}; __attribute__((naked,noreturn)) static void enter(uint32_t sp, uint32_t pc) { __asm volatile("msr msp, r0\nmovs r2, #0\nmsr control, r2\ndsb\nisb\ncpsie i\nbx r1\n"); } void g474_jump_app(void) { unsigned i; uint32_t sp = *(const uint32_t *)G474_APP_BASE; uint32_t pc = *(const uint32_t *)(G474_APP_BASE + 4); __disable_irq(); SysTick->CTRL = 0; for (i = 0; i < 8; ++i) { NVIC->ICER[i] = 0xffffffff; NVIC->ICPR[i] = 0xffffffff; } SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk | SCB_ICSR_PENDSVCLR_Msk; SCB->VTOR = G474_APP_BASE; enter(sp, pc); }