/* ----------------------------------------------------------------------------- * Copyright (c) 2014 - 2019 ARM Ltd. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. Permission is granted to anyone to use this * software for any purpose, including commercial applications, and to alter * it and redistribute it freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in * a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. * * * $Date: 2021-7-1 * $Revision: V1.0.0 * * Project: Flash Programming Functions for Puya PY32F030xx Flash * --------------------------------------------------------------------------- */ /* History: * Version 1.0.0 * Initial release */ #include "FlashOS.h" /* FlashOS Structures */ typedef volatile unsigned char vu8; typedef unsigned char u8; typedef volatile unsigned short vu16; typedef unsigned short u16; typedef volatile unsigned long vu32; typedef unsigned long u32; #define M8(adr) (*((vu8 *) (adr))) #define M16(adr) (*((vu16 *) (adr))) #define M32(adr) (*((vu32 *) (adr))) #define SET_BIT(REG, BIT) ((REG) |= (BIT)) #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) #define READ_BIT(REG, BIT) ((REG) & (BIT)) #define CLEAR_REG(REG) ((REG) = (0x0)) #define WRITE_REG(REG, VAL) ((REG) = (VAL)) #define READ_REG(REG) ((REG)) #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) /* Peripheral Memory Map */ #define FLASH_BASE (0x08000000UL) /*!< FLASH base address */ #define FLASH_END (0x0803FFFFUL) /*!< FLASH end address */ #define FLASH_SIZE (FLASH_END - FLASH_BASE + 1) #define FLASH_PAGE_SIZE 0x00000100U /*!< FLASH Page Size, 256 Bytes */ #define FLASH_PAGE_NB (FLASH_SIZE / FLASH_PAGE_SIZE) #define FLASH_SECTOR_SIZE 0x00002000U /*!< FLASH Sector Size, 8k Bytes */ #define FLASH_SECTOR_NB (FLASH_SIZE / FLASH_SECTOR_SIZE) #define SRAM1_BASE (0x20000000UL) /*!< SRAM1(8 KB) base address */ #define SRAM2_BASE (0x20002000UL) /*!< SRAM2(24 KB) base address */ #define OB_BASE (0x1FFF1D00UL) /*!< Flash Option Bytes base address */ #define UID_BASE (0x1FFF1C00UL) /*!< Unique device ID register base address */ #define OTP_BASE (0x1FFF1A00UL) #define RCC_BASE 0x40021000 #define IWDG_BASE 0x40003000 #define WWDG_BASE 0x40002C00 #define FLASH_R_BASE 0x40022000 #define FLAHS_SIZE_ADDR 0x1FFF1FFC #define FLAHS_BANK_SIZE (((M32(FLAHS_SIZE_ADDR) & 0x3) + 1) * 32 * 1024) #define RCC ((RCC_TypeDef*) RCC_BASE) #define IWDG ((IWDG_TypeDef *) IWDG_BASE) #define WWDG ((WWDG_TypeDef *) WWDG_BASE) #define FLASH ((FLASH_TypeDef*) FLASH_R_BASE) #define HSI_24M_TRIM_ADDR (0x1FFF1E10UL) #define FLASH_24M_TRIM_ADDR (0x1FFF1E98UL) /** * @brief RCC Registers */ typedef struct { vu32 CR; /*!< RCC CR Register, Address offset: 0x00 */ vu32 ICSCR; /*!< RCC ICSCR Register, Address offset: 0x04 */ } RCC_TypeDef; /** * @brief IWDG Registers */ typedef struct { vu32 KR; /*!< IWDG KR Register, Address offset: 0x0 */ vu32 PR; /*!< IWDG PR Register, Address offset: 0x4 */ vu32 RLR; /*!< IWDG RLR Register, Address offset: 0x8 */ vu32 SR; /*!< IWDG SR Register, Address offset: 0xC */ vu32 ICNTR; /*!< IWDG ICNTR Register, Address offset: 0x10 */ vu32 ICR; /*!< IWDG ICR Register, Address offset: 0x14 */ } IWDG_TypeDef; /** * @brief WWDG Registers */ typedef struct { vu32 CR; /*!< WWDR CR Register, Address offset: 0x0 */ vu32 CFR; /*!< WWDG CFR Register, Address offset: 0x4 */ vu32 SR; /*!< WWDG SR Register, Address offset: 0x8 */ } WWDG_TypeDef; /** * @brief FLASH Registers */ typedef struct { vu32 ACR; /*!< FLASH ACR Register, Address offset: 0x00 */ vu32 RESERVED1; vu32 KEYR; /*!< FLASH KEYR Register, Address offset: 0x08 */ vu32 OPTKEYR; /*!< FLASH OPTKEYR Register, Address offset: 0x0C */ vu32 SR; /*!< FLASH SR Register, Address offset: 0x10 */ vu32 CR; /*!< FLASH CR Register, Address offset: 0x14 */ vu32 ECCR; /*!< FLASH ECCR Register, Address offset: 0x18 */ vu32 RESERVED2; vu32 OPTR; /*!< FLASH OPTR Register, Address offset: 0x20 */ vu32 RESERVED3; vu32 WRPR; /*!< FLASH WRPR Register, Address offset: 0x28 */ vu32 RESERVED4; vu32 PCROPR0; /*!< FLASH PCROPR0 Register, Address offset: 0x30 */ vu32 PCROPR1; /*!< FLASH PCROPR1 Register, Address offset: 0x34 */ vu32 RESERVED5[22]; vu32 LPCR; /*!< FLASH LPCR Register, Address offset: 0x90 */ vu32 RESERVED6[27]; vu32 TS0; /*!< FLASH TS0 Register, Address offset: 0x100 */ vu32 TS1; /*!< FLASH TS1 Register, Address offset: 0x104 */ vu32 TS2P; /*!< FLASH TS2P Register, Address offset: 0x108 */ vu32 TPS3; /*!< FLASH TPS3 Register, Address offset: 0x10C */ vu32 TS3; /*!< FLASH TS3 Register, Address offset: 0x110 */ vu32 PERTPE; /*!< FLASH PERTPE Register, Address offset: 0x114 */ vu32 SMERTPE; /*!< FLASH SMERTPE Register, Address offset: 0x118 */ vu32 PRGTPE; /*!< FLASH PRGTPE Register, Address offset: 0x11C */ vu32 PRETPE; /*!< FLASH PRETPE Register, Address offset: 0x120 */ vu32 TACLK2PW; /*!< FLASH TACLK2PW Register, Address offset: 0x124 */ } FLASH_TypeDef; /* Flash Keys */ #define FLASH_KEY1 ((unsigned int)0x45670123) #define FLASH_KEY2 ((unsigned int)0xCDEF89AB) #define FLASH_OPTKEY1 ((unsigned int)0x08192A3B) #define FLASH_OPTKEY2 ((unsigned int)0x4C5D6E7F) #define RCC_CR_MSIDIV_Pos (0U) #define RCC_CR_MSIDIV_Msk (0x7UL<KEYR = FLASH_KEY1; /* Unlock Flash */ FLASH->KEYR = FLASH_KEY2; InitRccAndFlashParam(); #ifdef FLASH_OB FLASH->OPTKEYR = FLASH_OPTKEY1; /* Unlock Option Bytes */ FLASH->OPTKEYR = FLASH_OPTKEY2; #endif FLASH->ACR &= ~FLASH_ACR_LATENCY; /* Zero Wait State, no Prefetch */ FLASH->SR |= FLASH_SR_EOP; /* Clear EOP flag */ while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)); /* Check FLASH_SR_BSY */ if ((FLASH->OPTR & FLASH_OPTR_WWDG_SW) == 0) /* Test if WWDG is running (IWDG in HW mode) */ { /* Set WWDG time out to maximum */ WWDG->CFR |= WWDG_CFR_WDGTB; /* Set prescaler to maximum */ SET_BIT(WWDG->CR, WWDG_CR_T); /* Reload WWDG */ } if ((FLASH->OPTR & FLASH_OPTR_IWDG_SW) == 0) /* Test if IWDG is running (IWDG in HW mode) */ { /* Set IWDG time out to maximum */ IWDG->KR = 0xAAAA; /* Reload IWDG */ IWDG->KR = 0x5555; /* Enable write access to IWDG_PR and IWDG_RLR */ IWDG->PR = 0x06; /* Set prescaler to maximum */ IWDG->RLR = 0xFFF; /* Set reload value to maximum */ } return (0); } /* * De-Initialize Flash Programming Functions * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) * Return Value: 0 - OK, 1 - Failed */ int UnInit(unsigned long fnc) { UnInitRccAndFlashParam(); FLASH->CR |= FLASH_CR_LOCK; /* Lock Flash */ #ifdef FLASH_OB FLASH->CR |= FLASH_CR_OPTLOCK; /* Lock Option Bytes */ #endif return (0); } /* * Erase complete Flash Memory * Return Value: 0 - OK, 1 - Failed */ int EraseChip(void) { #ifdef FLASH_OTP EraseSector(OTP_BASE); #endif /* FLASH_OTP */ #ifdef FLASH_MEM FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ if (READ_BIT(FLASH->OPTR, FLASH_OPTR_BFB) != FLASH_OPTR_BFB) { FLASH->CR |= FLASH_CR_MER0; /* Mass BANK0 Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(FLASH_BASE) = 0xFF; /*BANK0*/ __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; /* Reload WWDG */ IWDG->KR = 0xAAAAU; /* Reload IWDG */ } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~(FLASH_CR_MER0); /* Mass Erase Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ FLASH->CR |= FLASH_CR_MER1; /* Mass BANK1 Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(FLASH_BASE + FLAHS_BANK_SIZE) = 0xFF; /*BANK1*/ } else { FLASH->CR |= FLASH_CR_MER1; /* Mass BANK1 Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(FLASH_BASE + FLAHS_BANK_SIZE) = 0xFF; /*BANK1*/ __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; /* Reload WWDG */ IWDG->KR = 0xAAAAU; /* Reload IWDG */ } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~(FLASH_CR_MER1); /* Mass Erase Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ FLASH->CR |= FLASH_CR_MER0; /* Mass BANK0 Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(FLASH_BASE) = 0xFF; /*BANK0*/ } __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; /* Reload WWDG */ IWDG->KR = 0xAAAAU; /* Reload IWDG */ } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~(FLASH_CR_MER0 | FLASH_CR_MER1); /* Mass Erase Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ #endif /* FLASH_MEM */ return (0); /* Done */ } /* * Erase Sector in Flash Memory * Parameter: adr: Sector Address * Return Value: 0 - OK, 1 - Failed */ #ifdef FLASH_MEM int EraseSector(unsigned long adr) { FLASH->SR |= FLASH_SR_EOP; /* Clear EOP flag */ FLASH->CR |= FLASH_CR_SER; /* Sector Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(adr) = 0xFFFFFFFF; /* Sector Address */ while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; /* Reload WWDG */ IWDG->KR = 0xAAAAU; /* Reload IWDG */ } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_SER; /* Sector Erase Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; return (0); /* Done */ } #endif #ifdef FLASH_OTP int EraseSector(unsigned long adr) { FLASH->SR |= FLASH_SR_EOP; FLASH->CR |= FLASH_CR_UPER; FLASH->CR |= FLASH_CR_EOPIE; M32(adr) = 0xFF; __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; IWDG->KR = 0xAAAAU; } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_UPER; FLASH->CR &= ~FLASH_CR_EOPIE; return (0); /* Done */ } #endif /* FLASH_OTP */ #ifdef FLASH_OB int EraseSector(unsigned long adr) { return (0); } #endif /* FLASH_OB */ /* * Program Page in Flash Memory * Parameter: adr: Page Start Address * sz: Page Size * buf: Page Data * Return Value: 0 - OK, 1 - Failed */ #ifdef FLASH_MEM int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf) { sz = (sz + (FLASH_PAGE_SIZE - 1)) & ~(FLASH_PAGE_SIZE - 1); /* Adjust size for 32 Words */ SET_BIT(FLASH->SR, FLASH_SR_EOP); /* Clear EOP flag */ while (sz) { FLASH->CR |= FLASH_CR_PG; /* Programming Enabled */ for (u8 i = 0; i < FLASH_PAGE_SIZE / 4; i++) { M32(adr + i * 4) = *((u32 *)(buf + i * 4)); /* Program the first word of the Double Word */ if (i == (FLASH_PAGE_SIZE / 4 - 2)) { FLASH->CR |= FLASH_CR_PGSTRT; } } __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; IWDG->KR = 0x0000AAAAU; } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_PG; /* Programming Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ adr += FLASH_PAGE_SIZE; /* Go to next Page */ buf += FLASH_PAGE_SIZE; sz -= FLASH_PAGE_SIZE; } return (0); /* Done */ } #endif /* FLASH_MEM */ #ifdef FLASH_OTP int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf) { sz = (sz + (FLASH_PAGE_SIZE - 1)) & ~(FLASH_PAGE_SIZE - 1); /* Adjust size for 32 Words */ SET_BIT(FLASH->SR, FLASH_SR_EOP); /* Clear EOP flag */ while (sz) { FLASH->CR |= FLASH_CR_UPG; /* Programming Enabled */ for (u8 i = 0; i < FLASH_PAGE_SIZE / 4; i++) { M32(adr + i * 4) = *((u32 *)(buf + i * 4)); /* Program the first word of the Double Word */ if (i == (FLASH_PAGE_SIZE / 4 - 2)) { FLASH->CR |= FLASH_CR_PGSTRT; } } while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; IWDG->KR = 0x0000AAAAU; } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_UPG; /* Programming Disabled */ adr += FLASH_PAGE_SIZE; /* Go to next Page */ buf += FLASH_PAGE_SIZE; sz -= FLASH_PAGE_SIZE; } return (0); /* Done */ } #endif /* FLASH_OTP */ #ifdef FLASH_OB int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf) { u32 optr; u32 wrpr; u32 pcropr0; u32 pcropr1; optr = M16(buf + 0x00) | (M16(buf + 0x04) << 16); wrpr = M16(buf + 0x10) | (M16(buf + 0x14) << 16); pcropr0 = M16(buf + 0x18) | (M16(buf + 0x1C) << 16); pcropr1 = M32(buf + 0x20) | (M16(buf + 0x24) << 16); FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ FLASH->OPTR = optr & 0x03FFFFFF; FLASH->WRPR = wrpr & 0xFFFFFFFF; FLASH->PCROPR0 = pcropr0 & 0x01FF01FF; FLASH->PCROPR1 = pcropr1 & 0x01FF01FF; FLASH->CR |= FLASH_CR_OPTSTRT; FLASH->CR |= FLASH_CR_EOPIE; M32(0x1FFF1D00) = 0xFFFFFFFF; while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; IWDG->KR = 0xAAAAU; } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_OPTSTRT; /* Programming Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ return (0); /* Done */ } #endif /* FLASH_OB */ #ifdef FLASH_OB unsigned long Verify(unsigned long adr, unsigned long sz, unsigned char *buf) { unsigned long baseaddr = 0x1FFF1D00; unsigned long offset = 0; if (adr != baseaddr || sz < 0x24) { return (adr); } if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x4; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x10; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x14; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x18; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x1C; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x20; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } offset = 0x24; if (M16(buf + offset) != M16(baseaddr + offset)) { return (baseaddr + offset); } return (adr + sz); } #endif /* FLASH_OB */ #ifdef FLASH_MEM int ErasePage(unsigned long adr) { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ FLASH->CR |= FLASH_CR_PER; /* page Erase Enabled */ FLASH->CR |= FLASH_CR_EOPIE; M32(adr) = 0xFF; /* Sector Address */ __asm("DSB"); while (FLASH->SR & (FLASH_SR_BSY0 | FLASH_SR_BSY1)) { WWDG->CR |= WWDG_CR_T; IWDG->KR = 0xAAAAU; } if (FLASH_SR_EOP != (FLASH->SR & FLASH_SR_EOP)) /* Check for FLASH_SR_EOP */ { FLASH->SR |= FLASH_SR_EOP; /* Reset FLASH_EOP */ return (1); /* Failed */ } FLASH->CR &= ~FLASH_CR_PER; /* page Erase Disabled */ FLASH->CR &= ~FLASH_CR_EOPIE; /* Reset FLASH_EOPIE */ return (0); /* Done */ } #endif /* FLASH_MEM */ #define RCC_HSICALIBRATION_8MHz ((0x1<<13) | ((*(vu32 *)(0x1FFF1E04)) & 0x1FFF)) /*!< 8MHz HSI calibration trimming value */ #define RCC_HSICALIBRATION_16MHz ((0x2<<13) | ((*(vu32 *)(0x1FFF1E08)) & 0x1FFF)) /*!< 16MHz HSI calibration trimming value */ #define RCC_HSICALIBRATION_22p12MHz ((0x3<<13) | ((*(vu32 *)(0x1FFF1E0C)) & 0x1FFF)) /*!< 22.12MHz HSI calibration trimming value */ #define RCC_HSICALIBRATION_24MHz ((0x4<<13) | ((*(vu32 *)(0x1FFF1E10)) & 0x1FFF)) /*!< 24MHz HSI calibration trimming value */ #define RCC_HSICALIBRATION_48MHz ((0x5<<13) | ((*(vu32 *)(0x1FFF1E14)) & 0x1FFF)) /*!< 48MHz HSI calibration trimming value */ #define RCC_HSICALIBRATION_64MHz ((0x6<<13) | ((*(vu32 *)(0x1FFF1E18)) & 0x1FFF)) /*!< 64MHz HSI calibration trimming value */ /********************************* Bit definition for RCC_CR register ***********************************************/ #define RCC_CR_HSIRDY_Pos (10U) #define RCC_CR_HSIRDY_Msk (0x1UL<ICSCR, RCC_ICSCR_HSI_FS_OPCR); MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_24MHz); /* HSI_24MHz */ while (RCC_CR_HSIRDY != READ_BIT(RCC->CR, RCC_CR_HSIRDY)); } /* Set HSI and Triming Data defult*/ void UnInitRccAndFlashParam(void) { MODIFY_REG(RCC->ICSCR, RCC_ICSCR_HSI_FS_OPCR, RCC_ICSCR_HSI_FS_RESTORE); switch (RCC_ICSCR_HSI_FS_RESTORE) { case (RCC_ICSCR_HSI_FS_OPCR_1|RCC_ICSCR_HSI_FS_OPCR_2): /* 64MHz */ FLASH->ACR |= FLASH_ACR_LATENCY_1; /* 2 Wait State */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_64MHz); /* HSI_64MHz */ break; case (RCC_ICSCR_HSI_FS_OPCR_0|RCC_ICSCR_HSI_FS_OPCR_2): /* 48MHz */ FLASH->ACR |= FLASH_ACR_LATENCY_0; /* 1 Wait State */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_48MHz); /* HSI_48MHz */ break; case RCC_ICSCR_HSI_FS_OPCR_2: /* 24MHz */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_24MHz); /* HSI_24MHz */ break; case (RCC_ICSCR_HSI_FS_OPCR_0|RCC_ICSCR_HSI_FS_OPCR_1): /* 22.12MHz */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_22p12MHz); /* HSI_22.12MHz */ break; case RCC_ICSCR_HSI_FS_OPCR_1: /* 16MHz */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_16MHz); /* HSI_16MHz */ break; default: /* 8MHz */ MODIFY_REG(RCC->ICSCR, (RCC_ICSCR_HSI_FS_OPCR | RCC_ICSCR_HSI_TRIMCR), RCC_HSICALIBRATION_8MHz); /* HSI_16MHz */ break; } while (RCC_CR_HSIRDY != READ_BIT(RCC->CR, RCC_CR_HSIRDY)); }