Add shared emulator services, waveform generation and STM32 USB boot ports
This commit is contained in:
109
c/set-protocol/ports/stm32g474-usb-boot/boot_flash.c
Normal file
109
c/set-protocol/ports/stm32g474-usb-boot/boot_flash.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "boot_port.h"
|
||||
#include "boot_image.h"
|
||||
#include "boot_writer.h"
|
||||
#include "stm32g4xx_hal.h"
|
||||
#include <string.h>
|
||||
#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);
|
||||
}
|
||||
Reference in New Issue
Block a user