#include "common.h" #define REG32(addr) (*(volatile u32 *)(addr)) #define RCC_BASE 0x40021000u #define RCC_CR REG32(RCC_BASE + 0x00u) #define RCC_CFGR REG32(RCC_BASE + 0x04u) #define RCC_CIR REG32(RCC_BASE + 0x08u) #define RCC_APB2RSTR REG32(RCC_BASE + 0x0cu) #define RCC_APB1RSTR REG32(RCC_BASE + 0x10u) #define RCC_AHBENR REG32(RCC_BASE + 0x14u) #define RCC_APB2ENR REG32(RCC_BASE + 0x18u) #define RCC_APB1ENR REG32(RCC_BASE + 0x1cu) #define FLASH_BASE_REG 0x40022000u #define FLASH_ACR REG32(FLASH_BASE_REG + 0x00u) #define FLASH_KEYR REG32(FLASH_BASE_REG + 0x04u) #define FLASH_SR REG32(FLASH_BASE_REG + 0x0cu) #define FLASH_CR REG32(FLASH_BASE_REG + 0x10u) #define FLASH_AR REG32(FLASH_BASE_REG + 0x14u) #define FLASH_OBR REG32(FLASH_BASE_REG + 0x1cu) #define SCB_VTOR REG32(0xe000ed08u) #define FLASH_KEY1 0x45670123u #define FLASH_KEY2 0xcdef89abu #define FLASH_FLAG_ALL 0x35u #define RCC_HSE_ON 0x00010000u #define RCC_PLLSRC_HSE 0x00010000u #define RCC_PLLMUL_9 0x001c0000u #define RCC_FLAG_HSERDY 0x31u #define RCC_FLAG_PLLRDY 0x39u __attribute__((used, section(".loader_state"))) volatile u32 EraseCounter; __attribute__((used, section(".loader_state"))) volatile u32 NbrOfPage; __attribute__((used, section(".loader_state"))) volatile FLASH_Status FLASHStatus; __attribute__((used, section(".loader_state"))) volatile TestStatus MemoryProgramStatus; __attribute__((used, section(".loader_state"))) volatile ErrorStatus HSEStartUpStatus; __attribute__((used, section(".flash_info"))) volatile FLASH_INFO Flash_Info; static void delay(void) { volatile u32 i = 0x0fffu; while (i != 0u) { i--; } } void RCC_DeInit(void) { RCC_APB2RSTR = 0; RCC_APB1RSTR = 0; RCC_AHBENR = 0x14u; RCC_APB2ENR = 0; RCC_APB1ENR = 0; RCC_CR |= 0x00000001u; RCC_CFGR &= 0xf8ff0000u; RCC_CR &= 0xfef6ffffu; RCC_CR &= 0xfffbffffu; RCC_CFGR &= 0xff80ffffu; RCC_CIR = 0; } void RCC_HSEConfig(u32 value) { RCC_CR &= ~0x00010000u; RCC_CR &= ~0x00040000u; if (value == 0x00010000u) { RCC_CR |= 0x00010000u; } else if (value == 0x00040000u) { RCC_CR |= 0x00050000u; } } FlagStatus RCC_GetFlagStatus(u8 flag) { u32 bit = 1u << (flag & 0x1fu); return ((RCC_CR & bit) != 0u) ? SET : RESET; } ErrorStatus RCC_WaitForHSEStartUp(void) { u32 timeout = 0x0500u; FlagStatus status; do { status = RCC_GetFlagStatus(RCC_FLAG_HSERDY); timeout--; } while (status == RESET && timeout != 0u); return (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) ? SUCCESS : ERROR; } void RCC_HCLKConfig(u32 value) { RCC_CFGR = (RCC_CFGR & 0xffffff0fu) | value; } void RCC_PCLK1Config(u32 value) { RCC_CFGR = (RCC_CFGR & 0xfffff8ffu) | value; } void RCC_PCLK2Config(u32 value) { RCC_CFGR = (RCC_CFGR & 0xffffc7ffu) | (value << 3); } void RCC_PLLConfig(u32 source, u32 mul) { RCC_CFGR = (RCC_CFGR & 0xffc0ffffu) | source | mul; } void RCC_PLLCmd(FunctionalState state) { if (state != DISABLE) { RCC_CR |= 0x01000000u; } else { RCC_CR &= ~0x01000000u; } } void RCC_SYSCLKConfig(u32 source) { RCC_CFGR = (RCC_CFGR & 0xfffffffcu) | source; } u8 RCC_GetSYSCLKSource(void) { return (u8)(RCC_CFGR & 0x0cu); } void NVIC_SetVectorTable(u32 vectorTable, u32 offset) { SCB_VTOR = vectorTable | (offset & 0x1fffff80u); } void FLASH_SetLatency(u32 latency) { FLASH_ACR = (FLASH_ACR & 0x38u) | latency; } void FLASH_PrefetchBufferCmd(u32 value) { FLASH_ACR = (FLASH_ACR & ~0x10u) | value; } void FLASH_Unlock(void) { FLASH_KEYR = FLASH_KEY1; FLASH_KEYR = FLASH_KEY2; } void FLASH_ClearFlag(u32 flags) { FLASH_SR = flags; } FLASH_Status FLASH_GetStatus(void) { if ((FLASH_SR & 0x01u) != 0u) { return FLASH_BUSY; } if ((FLASH_SR & 0x04u) != 0u) { return FLASH_ERROR_PG; } if ((FLASH_SR & 0x10u) != 0u) { return FLASH_ERROR_WRP; } return FLASH_COMPLETE; } FLASH_Status FLASH_WaitForLastOperation(u32 timeout) { FLASH_Status status = FLASH_GetStatus(); while (status == FLASH_BUSY && timeout != 0u) { delay(); status = FLASH_GetStatus(); timeout--; } return (timeout == 0u) ? FLASH_TIMEOUT : status; } FLASH_Status FLASH_ErasePage(u32 pageAddress) { FLASH_Status status = FLASH_WaitForLastOperation(0x0fffu); if (status == FLASH_COMPLETE) { FLASH_CR |= 0x02u; FLASH_AR = pageAddress; FLASH_CR |= 0x40u; status = FLASH_WaitForLastOperation(0x0fffu); if (status != FLASH_BUSY) { FLASH_CR &= 0x00001ffdu; } } return status; } FLASH_Status FLASH_ProgramHalfWord(u32 targetP, const u16 *srcP) { FLASH_Status status = FLASH_WaitForLastOperation(0x000fu); if (status == FLASH_COMPLETE) { FLASH_CR |= 0x01u; *(volatile u16 *)targetP = *srcP; status = FLASH_WaitForLastOperation(0x000fu); if (status != FLASH_BUSY) { FLASH_CR &= 0x00001ffeu; } } return status; } void RCC_Configuration(void) { RCC_DeInit(); RCC_HSEConfig(RCC_HSE_ON); HSEStartUpStatus = RCC_WaitForHSEStartUp(); if (HSEStartUpStatus == SUCCESS) { RCC_HCLKConfig(0); RCC_PCLK2Config(0); RCC_PCLK1Config(0x400u); FLASH_SetLatency(2); FLASH_PrefetchBufferCmd(0x10u); RCC_PLLConfig(RCC_PLLSRC_HSE, RCC_PLLMUL_9); RCC_PLLCmd(ENABLE); while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { } RCC_SYSCLKConfig(2); while (RCC_GetSYSCLKSource() != 0x08u) { } } } void NVIC_Configuration(void) { NVIC_SetVectorTable(FLASH_BASE, 0); } void Flash_Init(void) { FLASHStatus = FLASH_COMPLETE; MemoryProgramStatus = PASSED; RCC_Configuration(); NVIC_Configuration(); FLASH_Unlock(); NbrOfPage = FLASH_PAGE_COUNT; FLASH_ClearFlag(FLASH_FLAG_ALL); } void ReadChipID(void) { Flash_Info.Result = 1; } void EraseSector(void) { u32 i; Flash_Info.Result = 0; for (i = 0; i < (NbrOfPage - 1u); i++) { if ((FLASH_BASE + ((i + 1u) * FLASH_PAGE_SIZE)) > Flash_Info.TargetAddr) { break; } } while (i < (NbrOfPage - 1u) && FLASHStatus == FLASH_COMPLETE && (Flash_Info.TargetAddr + Flash_Info.Length) > (FLASH_BASE + (i * FLASH_PAGE_SIZE))) { FLASHStatus = FLASH_ErasePage(FLASH_BASE + (i * FLASH_PAGE_SIZE)); if (FLASHStatus == 0) { return; } i++; } Flash_Info.Result = 1; } void EraseAll(void) { EraseCounter = 0; while (EraseCounter < NbrOfPage && FLASHStatus == FLASH_COMPLETE) { FLASHStatus = FLASH_ErasePage(FLASH_BASE + (EraseCounter * FLASH_PAGE_SIZE)); EraseCounter++; } Flash_Info.Result = 1; } void Program(void) { u32 targetP = Flash_Info.TargetAddr; const u16 *srcP = (const u16 *)Flash_Info.Buf; u32 i; for (i = 0; i < Flash_Info.Length; i += 2u) { FLASHStatus = FLASH_ProgramHalfWord(targetP, srcP); targetP += 2u; srcP++; } Flash_Info.Result = 1; } void Main(void) { Flash_Init(); switch (Flash_Info.Command) { case FPROGRAM: Program(); break; case FERASEALL: EraseAll(); break; case FERASESEC: EraseSector(); break; case FREADID: ReadChipID(); break; default: Flash_Info.Result = 0; break; } } int BlankCheck(unsigned long targetAddr, unsigned long targetSize) { volatile unsigned long *targetP = (volatile unsigned long *)targetAddr; unsigned long i; for (i = 0; i < targetSize; i += 4u) { if (*targetP++ != 0xffffffffu) { return 0; } } return 1; } int Verification(unsigned long targetAddr, unsigned long limit, unsigned long srcAddr) { volatile unsigned long *targetP = (volatile unsigned long *)targetAddr; volatile unsigned long *sourceP = (volatile unsigned long *)srcAddr; unsigned long i; for (i = 0; i < limit; i += 4u) { if (*targetP++ != *sourceP++) { return 0; } } return 1; }