From 20e4363001564ffd0f9f5b0107beaa1fda3256ab Mon Sep 17 00:00:00 2001 From: IOsetting Date: Sat, 18 Feb 2023 02:44:36 +0800 Subject: [PATCH] feat: ll flash peripheral lib(migrate from hal) --- .../Inc/py32f0xx_ll_flash.h | 667 ++++++++++ .../Src/py32f0xx_ll_flash.c | 1081 +++++++++++++++++ 2 files changed, 1748 insertions(+) create mode 100644 Libraries/PY32F0xx_LL_Driver/Inc/py32f0xx_ll_flash.h create mode 100644 Libraries/PY32F0xx_LL_Driver/Src/py32f0xx_ll_flash.c diff --git a/Libraries/PY32F0xx_LL_Driver/Inc/py32f0xx_ll_flash.h b/Libraries/PY32F0xx_LL_Driver/Inc/py32f0xx_ll_flash.h new file mode 100644 index 0000000..6031205 --- /dev/null +++ b/Libraries/PY32F0xx_LL_Driver/Inc/py32f0xx_ll_flash.h @@ -0,0 +1,667 @@ +/** + ****************************************************************************** + * @file py32f0xx_hal_flash.h + * @author MCU Application Team + * @brief Header file of FLASH HAL module. + ****************************************************************************** + * @attention + * + *

© Copyright (c) Puya Semiconductor Co. + * All rights reserved.

+ * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __PY32F0xx_LL_FLASH_H +#define __PY32F0xx_LL_FLASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "py32f0xx.h" + +/** @addtogroup PY32F0xx_LL_Driver + * @{ + */ + +/** @addtogroup FLASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Types FLASH Exported Types + * @{ + */ + +/** + * @brief LL Lock structures definition + */ +typedef enum +{ + LL_UNLOCKED = 0x00U, + LL_LOCKED = 0x01U +} LL_LockTypeDef; + +/** + * @brief FLASH Erase structure definition + */ +typedef struct +{ + uint32_t TypeErase; /*!< Mass erase or page erase. + This parameter can be a value of @ref FLASH_Type_Erase */ + uint32_t PageAddress; /*!< PageAdress: Initial FLASH page address to erase when mass erase and sector erase is disabled + This parameter must be a number between Min_Data = FLASH_BASE and Max_Data = FLASH_END */ + uint32_t NbPages; /*!< Number of pages to be erased. + This parameter must be a value between 1 and (FLASH_PAGE_NB - value of initial page)*/ + uint32_t SectorAddress; /*!< PageAdress: Initial FLASH page address to erase when mass erase and page erase is disabled + This parameter must be a number between Min_Data = FLASH_BASE and Max_Data = FLASH_BANK1_END */ + uint32_t NbSectors; /*!< Number of sectors to be erased. + This parameter must be a value between 1 and (FLASH_SECTOR_NB - value of initial sector)*/ + +} FLASH_EraseInitTypeDef; + +/** + * @brief FLASH Option Bytes PROGRAM structure definition + */ +typedef struct +{ + uint32_t OptionType; /*!< OptionType: Option byte to be configured. + This parameter can be a value of @ref FLASH_Option_Type */ + + uint32_t WRPSector; /*!< WRPSector: This bitfield specifies the sector (s) which are write protected. + This parameter can be a combination of @ref FLASH_Option_Bytes_Write_Protection */ + + uint32_t SDKStartAddr; /*!< SDK Start address (used for FLASH_SDKR). It represents first address of start block + to protect. Make sure this parameter is multiple of SDK granularity: 2048 Bytes.*/ + + uint32_t SDKEndAddr; /*!< SDK End address (used for FLASH_SDKR). It represents first address of end block + to protect. Make sure this parameter is multiple of SDK granularity: 2048 Bytes.*/ + + uint32_t RDPLevel; /*!< RDPLevel: Set the read protection level. + This parameter can be a value of @ref FLASH_OB_Read_Protection */ + + uint32_t USERType; /*!< User option byte(s) to be configured (used for OPTIONBYTE_USER). + This parameter can be a combination of @ref FLASH_OB_USER_Type */ + + uint32_t USERConfig; /*!< Value of the user option byte (used for OPTIONBYTE_USER). + This parameter can be a combination of + @ref FLASH_OB_USER_BOR_ENABLE, + @ref FLASH_OB_USER_BOR_LEVEL, + @ref FLASH_OB_USER_RESET_CONFIG, + @ref FLASH_OB_USER_IWDG_SW, + @ref FLASH_OB_USER_WWDG_SW, + @ref FLASH_OB_USER_nBOOT1 */ +} FLASH_OBProgramInitTypeDef; + +/** +* @brief FLASH handle Structure definition +*/ +typedef struct +{ + LL_LockTypeDef Lock; /* FLASH locking object */ + uint32_t ErrorCode; /* FLASH error code */ + uint32_t ProcedureOnGoing; /* Internal variable to indicate which procedure is ongoing or not in IT context */ + uint32_t Address; /* Internal variable to save address selected for program in IT context */ + uint32_t PageOrSector; /* Internal variable to define the current page or sector which is erasing in IT context */ + uint32_t NbPagesSectorsToErase; /* Internal variable to save the remaining pages to erase in IT context */ +} FLASH_ProcessTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Constants FLASH Exported Constants + * @{ + */ + +/** + * @} + */ + +/** @defgroup FLASH_Latency FLASH Latency + * @{ + */ +#define FLASH_LATENCY_0 0x00000000UL /*!< FLASH Zero wait state */ +#define FLASH_LATENCY_1 FLASH_ACR_LATENCY /*!< FLASH One wait state */ +/** + * @} + */ + +/** @defgroup FLASH_Type_Erase FLASH erase type + * @{ + */ +#define FLASH_TYPEERASE_MASSERASE (0x01U) /*!ACR, FLASH_ACR_LATENCY, (__LATENCY__)) + +/** + * @brief Get the FLASH Latency. + * @retval FLASH Latency + * Returned value can be one of the following values : + * @arg @ref FLASH_LATENCY_0 FLASH Zero wait state + * @arg @ref FLASH_LATENCY_1 FLASH One wait state + * + */ +#define __LL_FLASH_GET_LATENCY() READ_BIT(FLASH->ACR, FLASH_ACR_LATENCY) + +/** @defgroup FLASH_Interrupt FLASH Interrupts Macros + * @brief macros to handle FLASH interrupts + * @{ + */ + +/** + * @brief Enable the specified FLASH interrupt. + * @param __INTERRUPT__ FLASH interrupt + * This parameter can be any combination of the following values: + * @arg @ref FLASH_IT_EOP End of FLASH Operation Interrupt + * @arg @ref FLASH_IT_OPERR Error Interrupt + * @note (*) availability depends on devices + * @retval none + */ +#define __LL_FLASH_ENABLE_IT(__INTERRUPT__) SET_BIT(FLASH->CR, (__INTERRUPT__)) + +/** + * @brief Disable the specified FLASH interrupt. + * @param __INTERRUPT__ FLASH interrupt + * This parameter can be any combination of the following values: + * @arg @ref FLASH_IT_EOP End of FLASH Operation Interrupt + * @arg @ref FLASH_IT_OPERR Error Interrupt + * @note (*) availability depends on devices + * @retval none + */ +#define __LL_FLASH_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(FLASH->CR, (__INTERRUPT__)) + +/** + * @brief Check whether the specified FLASH flag is set or not. + * @param __FLAG__ specifies the FLASH flag to check. + * This parameter can be one of the following values: + * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag + * @arg @ref FLASH_FLAG_WRPERR FLASH Write protection error flag + * @arg @ref FLASH_FLAG_OPTVERR FLASH Option validity error flag + * @arg @ref FLASH_FLAG_BSY FLASH write/erase operations in progress flag + * @arg @ref FLASH_FLAG_ALL_ERRORS FLASH All errors flags + * @note (*) availability depends on devices + * @retval The new state of FLASH_FLAG (SET or RESET). + */ +#define __LL_FLASH_GET_FLAG(__FLAG__) (READ_BIT(FLASH->SR, (__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the FLASHs pending flags. + * @param __FLAG__ specifies the FLASH flags to clear. + * This parameter can be any combination of the following values: + * @arg @ref FLASH_FLAG_EOP FLASH End of Operation flag + * @arg @ref FLASH_FLAG_WRPERR FLASH Write protection error flag + * @arg @ref FLASH_FLAG_OPTVERR FLASH Option validity error flag + * @arg @ref FLASH_FLAG_ALL_ERRORS FLASH All errors flags + * @retval None + */ +#define __LL_FLASH_CLEAR_FLAG(__FLAG__) do { WRITE_REG(FLASH->SR, (__FLAG__)); \ + } while(0U) +/** + * @} + */ + +#define __LL_FLASH_TIME_REG_SET(__EPPARA0__,__EPPARA1__,__EPPARA2__,__EPPARA3__,__EPPARA4__) \ + do { \ + FLASH->TS0 = (__EPPARA0__)&0xFF; \ + FLASH->TS1 = ((__EPPARA0__)>>16)&0x1FF; \ + FLASH->TS3 = ((__EPPARA0__)>>8)&0xFF; \ + FLASH->TS2P = (__EPPARA1__)&0xFF; \ + FLASH->TPS3 = ((__EPPARA1__)>>16)&0x7FF; \ + FLASH->PERTPE = (__EPPARA2__)&0x1FFFF; \ + FLASH->SMERTPE = (__EPPARA3__)&0x1FFFF; \ + FLASH->PRGTPE = (__EPPARA4__)&0xFFFF; \ + FLASH->PRETPE = ((__EPPARA4__)>>16)&0x3FFF; \ + } while(0U) + +#define __LL_FLASH_IS_INVALID_TIMMING_SEQUENCE(_INDEX_) (((FLASH->TS0) != ((*(uint32_t *)(_FlashTimmingParam[_INDEX_]))&0xFF)) || \ + ((FLASH->TS1) != (((*(uint32_t *)(_FlashTimmingParam[_INDEX_]))>>16)&0x1FF)) || \ + ((FLASH->TS3) != (((*(uint32_t *)(_FlashTimmingParam[_INDEX_]))>>8)&0xFF)) || \ + ((FLASH->TS2P) != ((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+4))&0xFF)) || \ + ((FLASH->TPS3) != (((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+4))>>16)&0x7FF)) || \ + ((FLASH->PERTPE) != ((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+8))&0x1FFFF)) || \ + ((FLASH->SMERTPE) != ((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+12))&0x1FFFF)) || \ + ((FLASH->PRGTPE) != ((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+16))&0xFFFF)) || \ + ((FLASH->PRETPE) != (((*(uint32_t *)(_FlashTimmingParam[_INDEX_]+16))>>16)&0x3FFF))) + +#define __LL_FLASH_TIMMING_SEQUENCE_CONFIG() do{ \ + uint32_t tmpreg = (RCC->ICSCR & RCC_ICSCR_HSI_FS) >> RCC_ICSCR_HSI_FS_Pos; \ + if (__LL_FLASH_IS_INVALID_TIMMING_SEQUENCE(tmpreg)) \ + { \ + __LL_FLASH_TIME_REG_SET((*(uint32_t *)(_FlashTimmingParam[tmpreg])), \ + (*(uint32_t *)(_FlashTimmingParam[tmpreg]+4)), \ + (*(uint32_t *)(_FlashTimmingParam[tmpreg]+8)), \ + (*(uint32_t *)(_FlashTimmingParam[tmpreg]+12)), \ + (*(uint32_t *)(_FlashTimmingParam[tmpreg]+16))); \ + } \ + }while(0U) + +/* Include FLASH HAL Extended module */ +/* Exported variables --------------------------------------------------------*/ +/** @defgroup FLASH_Exported_Variables FLASH Exported Variables + * @{ + */ +extern FLASH_ProcessTypeDef pFlash; +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FLASH_Exported_Functions + * @{ + */ + +/* Program operation functions ***********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group1 + * @{ + */ +ErrorStatus LL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t *DataAddr ); +ErrorStatus LL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t *DataAddr); +ErrorStatus LL_FLASH_PageProgram(uint32_t Address, uint32_t *DataAddr ); +ErrorStatus LL_FLASH_PageProgram_IT(uint32_t Address, uint32_t *DataAddr); +/* FLASH IRQ handler method */ +void LL_FLASH_IRQHandler(void); +/* Callbacks in non blocking modes */ +void LL_FLASH_EndOfOperationCallback(uint32_t ReturnValue); +void LL_FLASH_OperationErrorCallback(uint32_t ReturnValue); +ErrorStatus LL_FLASH_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError); +ErrorStatus LL_FLASH_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit); + +#define LL_FLASHEx_Erase LL_FLASH_Erase +#define LL_FLASHEx_Erase_IT LL_FLASH_Erase_IT +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup FLASH_Exported_Functions_Group2 + * @{ + */ +ErrorStatus LL_FLASH_Unlock(void); +ErrorStatus LL_FLASH_Lock(void); +/* Option bytes control */ +ErrorStatus LL_FLASH_OB_Unlock(void); +ErrorStatus LL_FLASH_OB_Lock(void); +ErrorStatus LL_FLASH_OB_Launch(void); +ErrorStatus LL_FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit); +void LL_FLASH_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit); +ErrorStatus LL_FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup FLASH_Exported_Functions_Group3 + * @{ + */ +uint32_t LL_FLASH_GetError(void); +/** + * @} + */ + +/** + * @} + */ + +/* Private types --------------------------------------------------------*/ +/** @defgroup FLASH_Private_types FLASH Private Types + * @{ + */ +ErrorStatus FLASH_WaitForLastOperation(uint32_t Timeout); +/** + * @} + */ + +/* Private constants --------------------------------------------------------*/ +/** @defgroup FLASH_Private_Constants FLASH Private Constants + * @{ + */ +#define FLASH_TIMEOUT_VALUE 1000U /*!< FLASH Execution Timeout, 1 s */ + +#define FLASH_TYPENONE 0x00000000U /*!< No Programmation Procedure On Going */ + +#define FLASH_FLAG_SR_ERROR (FLASH_FLAG_OPTVERR | FLASH_FLAG_WRPERR) /*!< All SR error flags */ + +#define FLASH_FLAG_SR_CLEAR (FLASH_FLAG_SR_ERROR | FLASH_SR_EOP) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FLASH_Private_Macros FLASH Private Macros + * @{ + */ +#define IS_FLASH_MAIN_MEM_ADDRESS(__ADDRESS__) (((__ADDRESS__) >= (FLASH_BASE)) && ((__ADDRESS__) <= (FLASH_BASE + FLASH_SIZE - 1UL))) + +#define IS_FLASH_PROGRAM_MAIN_MEM_ADDRESS(__ADDRESS__) (((__ADDRESS__) >= (FLASH_BASE)) && ((__ADDRESS__) <= (FLASH_BASE + FLASH_SIZE - 8UL))) + +#define IS_FLASH_PROGRAM_ADDRESS(__ADDRESS__) (IS_FLASH_PROGRAM_MAIN_MEM_ADDRESS(__ADDRESS__)) + +#define IS_FLASH_NB_PAGES(__ADDRESS__, __VALUE__) (((__ADDRESS__) >= (FLASH_BASE)) && ((__ADDRESS__ + (__VALUE__*FLASH_PAGE_SIZE)) <= (FLASH_BASE + FLASH_SIZE - 1UL))) + +#define IS_FLASH_NB_SECTORS(__ADDRESS__, __VALUE__) (((__ADDRESS__) >= (FLASH_BASE)) && ((__ADDRESS__ + (__VALUE__*FLASH_SECTOR_SIZE)) <= (FLASH_BASE + FLASH_SIZE - 1UL))) + +#define IS_FLASH_FAST_PROGRAM_ADDRESS(__ADDRESS__) (((__ADDRESS__) >= (FLASH_BASE)) && ((__ADDRESS__) <= (FLASH_BASE + FLASH_SIZE - 256UL))) + +#define IS_FLASH_PAGE(__PAGE__) ((__PAGE__) < FLASH_PAGE_NB) + +#define IS_FLASH_BANK(__BANK__) ((__BANK__) == 0x00UL) + +#define IS_FLASH_TYPEERASE(__VALUE__) (((__VALUE__) == FLASH_TYPEERASE_PAGEERASE) || \ + ((__VALUE__) == FLASH_TYPEERASE_SECTORERASE) || \ + ((__VALUE__) == FLASH_TYPEERASE_MASSERASE)) + +#define IS_FLASH_TYPEPROGRAM(__VALUE__) ((__VALUE__) == FLASH_TYPEPROGRAM_PAGE) + +#define IS_FLASH_TIMECONFIG_CLOCK(__VALUE__) (((__VALUE__) == FLASH_PROGRAM_ERASE_CLOCK_4MHZ) || \ + ((__VALUE__) == FLASH_PROGRAM_ERASE_CLOCK_8MHZ) || \ + ((__VALUE__) == FLASH_PROGRAM_ERASE_CLOCK_16MHZ) || \ + ((__VALUE__) == FLASH_PROGRAM_ERASE_CLOCK_22p12MHZ) || \ + ((__VALUE__) == FLASH_PROGRAM_ERASE_CLOCK_24MHZ)) + +#define IS_OPTIONBYTE(__VALUE__) ((((__VALUE__) & OPTIONBYTE_ALL) != 0x00U) && \ + (((__VALUE__) & ~OPTIONBYTE_ALL) == 0x00U)) + +#define IS_OB_RDP_LEVEL(__LEVEL__) (((__LEVEL__) == OB_RDP_LEVEL_0) ||\ + ((__LEVEL__) == OB_RDP_LEVEL_1)) + +#define IS_OB_USER_TYPE(__TYPE__) ((((__TYPE__) & OB_USER_ALL) != 0x00U) && \ + (((__TYPE__) & ~OB_USER_ALL) == 0x00U)) + +#define IS_OB_USER_CONFIG(__TYPE__,__CONFIG__) ((~(__TYPE__) & (__CONFIG__)) == 0x00U) + +#if defined(FLASH_PCROP_SUPPORT) +#define IS_OB_PCROP_CONFIG(__CONFIG__) (((__CONFIG__) & ~(OB_PCROP_ZONE_A | OB_PCROP_ZONE_B | OB_PCROP_RDP_ERASE)) == 0x00U) +#endif + +#if defined(FLASH_SECURABLE_MEMORY_SUPPORT) +#define IS_OB_SEC_BOOT_LOCK(__VALUE__) (((__VALUE__) == OB_BOOT_ENTRY_FORCED_NONE) || ((__VALUE__) == OB_BOOT_ENTRY_FORCED_FLASH)) + +#define IS_OB_SEC_SIZE(__VALUE__) ((__VALUE__) < (FLASH_PAGE_NB + 1U)) +#endif + +#define IS_FLASH_LATENCY(__LATENCY__) (((__LATENCY__) == FLASH_LATENCY_0) || \ + ((__LATENCY__) == FLASH_LATENCY_1)) + +#define IS_WRPSTATE(__VALUE__) (((__VALUE__) == OB_WRPSTATE_DISABLE) || \ + ((__VALUE__) == OB_WRPSTATE_ENABLE)) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __PY32F0xx_LL_FLASH_H */ + +/************************ (C) COPYRIGHT Puya *****END OF FILE****/ diff --git a/Libraries/PY32F0xx_LL_Driver/Src/py32f0xx_ll_flash.c b/Libraries/PY32F0xx_LL_Driver/Src/py32f0xx_ll_flash.c new file mode 100644 index 0000000..ba58098 --- /dev/null +++ b/Libraries/PY32F0xx_LL_Driver/Src/py32f0xx_ll_flash.c @@ -0,0 +1,1081 @@ +/** + ****************************************************************************** + * @file py32f0xx_ll_flash.c + * @author MCU Application Team + * @brief FLASH LL module driver. + * This file provides firmware functions to manage the following + * functionalities of the internal FLASH memory: + * + Program operations functions + * + Memory Control functions + * + Peripheral Errors functions + * + @verbatim + + ****************************************************************************** + * @attention + * + *

© Copyright (c) Puya Semiconductor Co. + * All rights reserved.

+ * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "py32f0xx_ll_flash.h" +#include "py32f0xx_ll_utils.h" + +#ifdef USE_FULL_ASSERT + #include "py32_assert.h" +#else + #define assert_param(expr) ((void)0U) +#endif + + +/** @defgroup FLASH FLASH + * @brief FLASH LL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ + +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ +#ifndef __weak +#define __weak __attribute__((weak)) +#endif /* __weak */ +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif /* __packed */ +#endif /* __GNUC__ */ + +/** + * @brief __RAM_FUNC definition + */ +#if defined ( __CC_ARM ) +/* ARM Compiler + ------------ + RAM functions are defined using the toolchain options. + Functions that are executed in RAM should reside in a separate source module. + Using the 'Options for File' dialog you can simply change the 'Code / Const' + area of a module to a memory space in physical RAM. + Available memory areas are declared in the 'Target' tab of the 'Options for Target' + dialog. +*/ +#define __RAM_FUNC + +#elif defined ( __ICCARM__ ) +/* ICCARM Compiler + --------------- + RAM functions are defined using a specific toolchain keyword "__ramfunc". +*/ +#define __RAM_FUNC __ramfunc + +#elif defined ( __GNUC__ ) +/* GNU Compiler + ------------ + RAM functions are defined using a specific toolchain attribute + "__attribute__((section(".RamFunc")))". +*/ +#define __RAM_FUNC __attribute__((section(".RamFunc"))) + +#endif + +#define __HAL_LOCK(__HANDLE__) \ + do{ \ + if((__HANDLE__)->Lock == LL_LOCKED) \ + { \ + return ERROR; \ + } \ + else \ + { \ + (__HANDLE__)->Lock = LL_LOCKED; \ + } \ + }while (0U) + +#define __HAL_UNLOCK(__HANDLE__) \ + do{ \ + (__HANDLE__)->Lock = LL_UNLOCKED; \ + }while (0U) + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup FLASH_Private_Variables FLASH Private Variables + * @{ + */ +/** + * @brief Variable used for Program/Erase sectors under interruption + * HAL_UNLOCKED = 0x00U, + * HAL_LOCKED = 0x01U + */ +FLASH_ProcessTypeDef pFlash = {.Lock = 0x00U, \ + .ErrorCode = LL_FLASH_ERROR_NONE, \ + .ProcedureOnGoing = FLASH_TYPENONE, \ + .Address = 0U, \ + .PageOrSector = 0U, \ + .NbPagesSectorsToErase = 0U + }; +/** + * @} + */ +const uint32_t _FlashTimmingParam[8] = {0x1FFF0F1C, 0x1FFF0F30, 0x1FFF0F44, 0x1FFF0F58, 0x1FFF0F6C, 0x1FFF0F1C, 0x1FFF0F1C, 0x1FFF0F1C}; + +/** + * @brief Option byte program. + * @note Enable this configuration, you need to add the corresponding optionbyte FLM file + */ +#ifdef FLASH_OPT_PROGRAM_ENABLED +#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */ + const uint32_t u32ICG[] __attribute__((section(".opt_sec"))) = +#elif defined (__CC_ARM) + const uint32_t u32ICG[] __attribute__((at(OB_BASE))) = +#elif defined (__ICCARM__) + __root const uint32_t u32ICG[] @ OB_BASE = +#else + #error "unsupported compiler!!" +#endif +{ + FLASH_OPTR_CONSTANT, + FLASH_SDKR_CONSTANT, + 0xFFFFFFFF, + FLASH_WRPR_CONSTANT, +}; +#endif /* FLASH_OPT_PROGRAM_ENABLED */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup FLASH_Private_Functions FLASH Private Functions + * @{ + */ +static void FLASH_MassErase(void); +static void FLASH_Program_Page(uint32_t Address, uint32_t * DataAddress); +static void FLASH_PageErase(uint32_t PageAddress); +/** + * @} + */ + +/** + * @brief Unlock the FLASH control register access. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_Unlock(void) +{ + ErrorStatus status = SUCCESS; + + if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U) + { + /* Authorize the FLASH Registers access */ + WRITE_REG(FLASH->KEYR, FLASH_KEY1); + WRITE_REG(FLASH->KEYR, FLASH_KEY2); + + /* verify Flash is unlock */ + if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U) + { + status = ERROR; + } + } + + return status; +} + +/** + * @brief Lock the FLASH control register access. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_Lock(void) +{ + ErrorStatus status = ERROR; + + /* Set the LOCK Bit to lock the FLASH Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_LOCK); + + /* verify Flash is locked */ + if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00u) + { + status = SUCCESS; + } + + return status; +} + +/** + * @brief Unlock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_OB_Unlock(void) +{ + ErrorStatus status = ERROR; + + if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00U) + { + /* Authorizes the Option Byte register programming */ + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1); + WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2); + + /* verify option bytes are unlocked */ + if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0x00U) + { + status = SUCCESS; + } + } + + return status; +} + +/** + * @brief Lock the FLASH Option Bytes Registers access. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_OB_Lock(void) +{ + ErrorStatus status = ERROR; + + /* Set the OPTLOCK Bit to lock the FLASH Option Byte Registers access */ + SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK); + + /* verify option bytes are locked */ + if (READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0x00u) + { + status = SUCCESS; + } + + return status; +} + +/** + * @brief Launch the option byte loading. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_OB_Launch(void) +{ + /* Set the bit to force the option byte reloading */ + SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH); + + /* We should not reach here : Option byte launch generates Option byte reset + so return error */ + return ERROR; +} + +/** + * @brief Get the specific FLASH error flag. + * @retval FLASH_ErrorCode The returned value can be + * @arg @ref LL_FLASH_ERROR_NONE No error set + * @arg @ref LL_FLASH_ERROR_WRP FLASH Write protection error + * @arg @ref LL_FLASH_ERROR_OPTV FLASH Option validity error + * @note (*) availability depends on devices + */ +uint32_t LL_FLASH_GetError(void) +{ + return pFlash.ErrorCode; +} + +/** + * @brief Wait for a FLASH operation to complete. + * @param Timeout maximum flash operation timeout + * @retval ErrorStatus HAL Status + */ +ErrorStatus FLASH_WaitForLastOperation(uint32_t Timeout) +{ + /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset. + Even if the FLASH operation fails, the BUSY flag will be reset and an error + flag will be set */ + + /* Wait if any operation is ongoing */ + while (__LL_FLASH_GET_FLAG(FLASH_FLAG_BSY) != 0x00U) + { + if (Timeout-- == 0) + { + return ERROR; + } + LL_mDelay(1); + } + + /* Clear SR register */ + FLASH->SR = FLASH_FLAG_SR_CLEAR; + + return SUCCESS; +} + +/** + * @brief Full erase of FLASH memory Bank + * + * @retval None + */ +static void FLASH_MassErase(void) +{ + /* Clean the error context */ + pFlash.ErrorCode = LL_FLASH_ERROR_NONE; + /* Only bank1 will be erased*/ + SET_BIT(FLASH->CR, FLASH_CR_MER); + *(__IO uint32_t *)(0x08000000) = 0x12344321; +} + +/** + * @brief Page erase of FLASH memory + * + * @retval None + */ +static void FLASH_PageErase(uint32_t PageAddress) +{ + /* Clean the error context */ + pFlash.ErrorCode = LL_FLASH_ERROR_NONE; + SET_BIT(FLASH->CR, FLASH_CR_PER); + *(__IO uint32_t *)(PageAddress) = 0xFF; +} + +/** + * @brief Sector erase of FLASH memory + * + * @retval None + */ +static void FLASH_SectorErase(uint32_t SectorAddress) +{ + SET_BIT(FLASH->CR, FLASH_CR_SER); + *(__IO uint32_t *)(SectorAddress) = 0xFF; +} + +/** + * @brief Page program of FLASH memory + * + * @retval None + */ +static __RAM_FUNC void FLASH_Program_Page(uint32_t Address, uint32_t * DataAddress) +{ + + uint8_t index=0; + uint32_t dest = Address; + uint32_t * src = DataAddress; + uint32_t primask_bit; + + SET_BIT(FLASH->CR, FLASH_CR_PG); + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __disable_irq(); + /* 32 words*/ + while(index<32U) + { + *(uint32_t *)dest = *src; + src += 1U; + dest += 4U; + index++; + if(index==31) + { + SET_BIT(FLASH->CR, FLASH_CR_PGSTRT); + } + } + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); +} + +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages + * @note To correctly run this function, the @ref LL_FLASH_Unlock() function + * must be called before. + * Call the @ref LL_FLASH_Lock() to disable the flash memory access + * (recommended to protect the FLASH memory against possible unwanted operation) + * @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * + * @param[out] PageSectorError pointer to variable that + * contains the configuration information on faulty page or sector in case of error + * (0xFFFFFFFF means that all the pages or sectors have been correctly erased) + * + * @retval ErrorStatus HAL Status + */ +ErrorStatus LL_FLASH_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageSectorError) +{ + ErrorStatus status = ERROR; + uint32_t address = 0U; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Config flash timming */ + __LL_FLASH_TIMMING_SEQUENCE_CONFIG(); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Mass Erase requested for Bank1 */ + /* Wait for last operation to be completed */ + if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == SUCCESS) + { + /*Mass erase to be done*/ + FLASH_MassErase(); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* If the erase operation is completed, disable the MER Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_MER); + } + }else if(pEraseInit->TypeErase == FLASH_TYPEERASE_PAGEERASE) + { + /* Page Erase is requested */ + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress)); + assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages)); + + /* Wait for last operation to be completed */ + if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == SUCCESS) + { + /*Initialization of PageSectorError variable*/ + *PageSectorError = 0xFFFFFFFFU; + + /* Erase page by page to be done*/ + for(address = pEraseInit->PageAddress; + address < ((pEraseInit->NbPages * FLASH_PAGE_SIZE) + pEraseInit->PageAddress); + address += FLASH_PAGE_SIZE) + { + FLASH_PageErase(address); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + /* If the erase operation is completed, disable the PER Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_PER); + if (status != SUCCESS) + { + /* In case of error, stop erase procedure and return the faulty address */ + *PageSectorError = address; + break; + } + } + } + } + else if(pEraseInit->TypeErase == FLASH_TYPEERASE_SECTORERASE) + { + /* Sector Erase is requested */ + /* Check the parameters */ + assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->SectorAddress)); + assert_param(IS_FLASH_NB_SECTORS(pEraseInit->SectorAddress, pEraseInit->NbSectors)); + + /* Wait for last operation to be completed */ + if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == SUCCESS) + { + /*Initialization of PageSectorError variable*/ + *PageSectorError = 0xFFFFFFFFU; + + /* Erase page by page to be done*/ + for(address = pEraseInit->SectorAddress; + address < ((pEraseInit->NbSectors * FLASH_SECTOR_SIZE) + pEraseInit->SectorAddress); + address += FLASH_SECTOR_SIZE) + { + FLASH_SectorErase(address); + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + /* If the erase operation is completed, disable the SER Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_SER); + if (status != SUCCESS) + { + /* In case of error, stop erase procedure and return the faulty address */ + *PageSectorError = address; + break; + } + } + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + + +/** + * @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled. + * @param pEraseInit Pointer to an @ref FLASH_EraseInitTypeDef structure that + * contains the configuration information for the erasing. + * @retval HAL Status + */ +ErrorStatus LL_FLASH_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit) +{ + ErrorStatus status; + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Config flash timming */ + __LL_FLASH_TIMMING_SEQUENCE_CONFIG(); + + /* Reset error code */ + pFlash.ErrorCode = LL_FLASH_ERROR_NONE; + + /* save procedure for interrupt treatment */ + pFlash.ProcedureOnGoing = pEraseInit->TypeErase; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + + if (status != SUCCESS) + { + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + } + else + { + /* Enable End of Operation and Error interrupts */ + FLASH->CR |= FLASH_CR_EOPIE | FLASH_CR_ERRIE; + + if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) + { + /* Set Page to 0 for Interrupt callback management */ + pFlash.PageOrSector = 0; + + /* Proceed to Mass Erase */ + FLASH_MassErase(); + }else if (pEraseInit->TypeErase == FLASH_TYPEERASE_PAGEERASE) + { + /* Erase by page to be done */ + pFlash.NbPagesSectorsToErase = pEraseInit->NbPages; + pFlash.PageOrSector = pEraseInit->PageAddress; + + /*Erase 1st page and wait for IT */ + FLASH_PageErase(pEraseInit->PageAddress); + }else if (pEraseInit->TypeErase == FLASH_TYPEERASE_SECTORERASE) + { + /* Erase by sector to be done */ + pFlash.NbPagesSectorsToErase = pEraseInit->NbSectors; + pFlash.PageOrSector = pEraseInit->SectorAddress; + + FLASH_SectorErase(pEraseInit->SectorAddress); + } + } + + /* return status */ + return status; +} + +/** + * @brief Program of a page at a specified address. + * @param Address Specifies the address to be programmed. + * @param DataAddr:Page Start Address + * + * @retval ErrorStatus HAL Status + */ +ErrorStatus LL_FLASH_PageProgram(uint32_t Address, uint32_t * DataAddr ) +{ + return LL_FLASH_Program(FLASH_TYPEPROGRAM_PAGE, Address, DataAddr); +} + +/** + * @brief Program of a page at a specified address. + * @param TypeProgram Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address Specifies the address to be programmed. + * @param DataAddr:Page Start Address + * + * @retval ErrorStatus HAL Status + */ +ErrorStatus LL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t * DataAddr ) +{ + ErrorStatus status = ERROR; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Config flash timming */ + __LL_FLASH_TIMMING_SEQUENCE_CONFIG(); + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); + + /* must be the first address of the PAGE */ + if(Address%FLASH_PAGE_SIZE) + { + return ERROR; + } + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + + if(status == SUCCESS) + { + FLASH_Program_Page(Address, DataAddr); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + /* If the program operation is completed, disable the PG Bit */ + CLEAR_BIT(FLASH->CR, FLASH_CR_PG); + /* In case of error, stop programming procedure */ + if (status != SUCCESS) + { + return status; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Program of a page at a specified address with interrupt enabled. + * @param Address Specifies the address to be programmed. + * @param DataAddr Specifies the buffer address to be programmed. + * + * @retval HAL Status + */ +ErrorStatus LL_FLASH_PageProgram_IT(uint32_t Address, uint32_t *DataAddr) +{ + return LL_FLASH_Program_IT(FLASH_TYPEPROGRAM_PAGE, Address, DataAddr); +} + +/** + * @brief Program of a page at a specified address with interrupt enabled. + * @param TypeProgram Indicate the way to program at a specified address. + * This parameter can be a value of @ref FLASH_Type_Program + * @param Address Specifies the address to be programmed. + * @param DataAddr Specifies the buffer address to be programmed. + * + * @retval HAL Status + */ +ErrorStatus LL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint32_t *DataAddr) +{ + ErrorStatus status; + + /* Check the parameters */ + assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram)); + assert_param(IS_FLASH_PROGRAM_ADDRESS(Address)); + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Config flash timming */ + __LL_FLASH_TIMMING_SEQUENCE_CONFIG(); + + /* Reset error code */ + pFlash.ErrorCode = LL_FLASH_ERROR_NONE; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE); + + if (status != SUCCESS) + { + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + }else + { + /* Set internal variables used by the IRQ handler */ + pFlash.ProcedureOnGoing = TypeProgram; + pFlash.Address = Address; + + /* Enable End of Operation and Error interrupts */ + __LL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + FLASH_Program_Page(Address, DataAddr); + } + + /* return status */ + return status; +} + +/** + * @brief Set the read protection level. + * @param ReadProtectLevel specifies the read protection level. + * This parameter can be one of the following values: + * @arg @ref OB_RDP_LEVEL_0 No protection + * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory + * + * @note Warning: When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0 + * @retval HAL status + */ +ErrorStatus LL_FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_OB_RDP_LEVEL(ReadProtectLevel)); + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + if(status == SUCCESS) + { + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Clean the error context */ + pFlash.ErrorCode = LL_FLASH_ERROR_NONE; + + /* If the previous operation is completed, proceed to erase the option bytes */ + SET_BIT(FLASH->OPTR, ReadProtectLevel); + + /* starts to modify Flash Option bytes */ + FLASH->CR|=FLASH_CR_OPTSTRT; + + /* set bit EOPIE */ + FLASH->CR|=FLASH_CR_EOPIE; + + /* trigger program */ + *((__IO uint32_t *)(0x40022080))=0xff; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + } + + return status; +} + +/** + * @brief Return the FLASH User Option Byte value. + * @retval The FLASH User Option Bytes values. It will be a combination of all the following values: + * @arg @ref FLASH_OB_USER_BOR_ENABLE + * @arg @ref FLASH_OB_USER_BOR_LEVEL + * @arg @ref FLASH_OB_USER_RESET_CONFIG + * @arg @ref FLASH_OB_USER_IWDG_SW + * @arg @ref FLASH_OB_USER_WWDG_SW + * @arg @ref FLASH_OB_USER_nBOOT1 + */ +static uint32_t FLASH_OB_GetUser(void) +{ + uint32_t user = ((FLASH->OPTR & ~FLASH_OPTR_RDP) & OB_USER_ALL); + return user; +} + +/** + * @brief Return the FLASH Read Protection level. + * @retval FLASH ReadOut Protection Status: + * This return value can be one of the following values: + * @arg @ref OB_RDP_LEVEL_0 No protection + * @arg @ref OB_RDP_LEVEL_1 Read protection of the memory + */ +static uint32_t FLASH_OB_GetRDP(void) +{ + uint32_t rdplvl = READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP); + + if (rdplvl == OB_RDP_LEVEL_0) + { + return (OB_RDP_LEVEL_0); + }else + { + return rdplvl; + } +} + +/** + * @brief Set user & RDP configuration + * @param UserType The FLASH User Option Bytes to be modified. + * This parameter can be a combination of @ref FLASH_OB_USER_Type + * @param UserConfig The FLASH User Option Bytes values. + * This parameter can be a combination of: + * @arg @ref FLASH_OB_USER_BOR_ENABLE + * @arg @ref FLASH_OB_USER_BOR_LEVEL + * @arg @ref FLASH_OB_USER_RESET_CONFIG + * @arg @ref FLASH_OB_USER_IWDG_SW + * @arg @ref FLASH_OB_USER_WWDG_SW + * @arg @ref FLASH_OB_USER_nBOOT1 + * @param RDPLevel specifies the read protection level. + * This parameter can be one of the following values: + * @arg @ref OB_RDP_LEVEL_0 No protection + * @arg @ref OB_RDP_LEVEL_1 Memory Read protection + * @note (*) availability depends on devices + * @retval None + */ +static void FLASH_OB_OptrConfig(uint32_t UserType, uint32_t UserConfig, uint32_t RDPLevel) +{ + uint32_t optr; + + /* Check the parameters */ + assert_param(IS_OB_USER_TYPE(UserType)); + assert_param(IS_OB_USER_CONFIG(UserType, UserConfig)); + assert_param(IS_OB_RDP_LEVEL(RDPLevel)); + + /* Configure the RDP level in the option bytes register */ + optr = FLASH->OPTR; + optr &= ~(UserType | FLASH_OPTR_RDP); + FLASH->OPTR = (optr | UserConfig | RDPLevel); +} + +/** + * @brief Program option bytes + * @note The function @ref LL_FLASH_Unlock() should be called before to unlock the FLASH interface + * The function @ref LL_FLASH_OB_Unlock() should be called before to unlock the options bytes + * The function @ref LL_FLASH_OB_Launch() should be called after to force the reload of the options bytes + * (system reset will occur) + * + * @param pOBInit pointer to an FLASH_OBInitStruct structure that + * contains the configuration information for the programming. + * + * @retval ErrorStatus HAL Status + */ +ErrorStatus LL_FLASH_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit) +{ + uint32_t optr; + ErrorStatus status = ERROR; + + /* Process Locked */ + __HAL_LOCK(&pFlash); + + /* Config flash timming */ + __LL_FLASH_TIMMING_SEQUENCE_CONFIG(); + + /* Check the parameters */ + assert_param(IS_OPTIONBYTE(pOBInit->OptionType)); + + /* WRP register */ + if ((pOBInit->OptionType & OPTIONBYTE_WRP) != 0) + { + /* Write protection configuration */ + FLASH->WRPR = (uint16_t)(~(pOBInit->WRPSector)); + } + + /* SDK register */ + if ((pOBInit->OptionType & OPTIONBYTE_SDK) != 0) + { + /* SDK protection configuration */ + FLASH->SDKR = (pOBInit->SDKStartAddr) | (pOBInit->SDKEndAddr<<8); + } + + /* Option register */ + if ((pOBInit->OptionType & (OPTIONBYTE_RDP | OPTIONBYTE_USER)) == (OPTIONBYTE_RDP | OPTIONBYTE_USER)) + { + /* Fully modify OPTR register with RDP & user data */ + FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, pOBInit->RDPLevel); + } + else if((pOBInit->OptionType & OPTIONBYTE_RDP) != 0x00U) + { + /* Only modify RDP so get current user data */ + optr = FLASH_OB_GetUser(); + FLASH_OB_OptrConfig(optr, optr, pOBInit->RDPLevel); + } + else if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0x00U) + { + /* Only modify user so get current RDP level */ + optr = FLASH_OB_GetRDP(); + FLASH_OB_OptrConfig(pOBInit->USERType, pOBInit->USERConfig, optr); + } + else + { + /* nothing to do */ + } + + /* starts to modify Flash Option bytes */ + FLASH->CR|=FLASH_CR_OPTSTRT; + + /* set bit EOPIE */ + FLASH->CR|=FLASH_CR_EOPIE; + + /* trigger program */ + *((__IO uint32_t *)(0x40022080))=0xff; + + /* Wait for last operation to be completed */ + status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + + return status; +} + +/** + * @brief Get the Option byte configuration + * @param pOBInit pointer to an FLASH_OBInitStruct structure that + * contains the configuration information for the programming. + * + * @retval None + */ +void LL_FLASH_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit) +{ + pOBInit->OptionType = OPTIONBYTE_ALL; + + /* Get WRP sector */ + pOBInit->WRPSector = (uint16_t)(~FLASH->WRPR); + + /* Get SDK sector */ + pOBInit->SDKStartAddr = (FLASH->SDKR)&0x1F; + pOBInit->SDKEndAddr = ((FLASH->SDKR)&0x1F00)>>8; + + /*Get RDP Level*/ + if (((FLASH->OPTR)&0xFF) == OB_RDP_LEVEL_0) + { + pOBInit->RDPLevel = OB_RDP_LEVEL_0; + } else + { + pOBInit->RDPLevel = OB_RDP_LEVEL_1; + } + + /*Get USER*/ + pOBInit->USERType = OB_USER_ALL; +#if defined(FLASH_OPTR_WWDG_SW) + pOBInit->USERConfig = (FLASH->OPTR)&(FLASH_OPTR_WWDG_SW | FLASH_OPTR_IWDG_SW | \ + FLASH_OPTR_NRST_MODE |FLASH_OPTR_BOR_EN | \ + FLASH_OPTR_BOR_LEV |FLASH_OPTR_nBOOT1); +#else + pOBInit->USERConfig = (FLASH->OPTR)&(FLASH_OPTR_IWDG_SW | \ + FLASH_OPTR_NRST_MODE |FLASH_OPTR_BOR_EN | \ + FLASH_OPTR_BOR_LEV |FLASH_OPTR_nBOOT1); + +#endif +} + +/** + * @brief Handle FLASH interrupt request. + * @retval None + */ +void LL_FLASH_IRQHandler(void) +{ + uint32_t param = 0xFFFFFFFFU; + uint32_t error; + + /* Save flash errors. Only ECC detection can be checked here as ECCC + generates NMI */ + error = (FLASH->SR & FLASH_FLAG_SR_ERROR); + + CLEAR_BIT(FLASH->CR, pFlash.ProcedureOnGoing); + + /* A] Set parameter for user or error callbacks */ + /* check operation was a program or erase */ + if ((pFlash.ProcedureOnGoing & (FLASH_TYPEPROGRAM_PAGE)) != 0x00U) + { + /* return adress being programmed */ + param = pFlash.Address; + }else if ((pFlash.ProcedureOnGoing & (FLASH_TYPEERASE_MASSERASE | FLASH_TYPEERASE_SECTORERASE | FLASH_TYPEERASE_PAGEERASE)) != 0x00U) + { + /* return page number being erased (0 for mass erase) */ + param = pFlash.PageOrSector; + }else + { + /* Nothing to do */ + } + + /* B] Check errors */ + if (error != 0x00U) + { + /*Save the error code*/ + pFlash.ErrorCode |= error; + + /* clear error flags */ + __LL_FLASH_CLEAR_FLAG(error); + + /*Stop the procedure ongoing*/ + pFlash.ProcedureOnGoing = FLASH_TYPENONE; + + /* Error callback */ + LL_FLASH_OperationErrorCallback(param); + } + + /* C] Check FLASH End of Operation flag */ + if (__LL_FLASH_GET_FLAG(FLASH_FLAG_EOP) != 0x00U) + { + /* Clear FLASH End of Operation pending bit */ + __LL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP); + + if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_PAGEERASE) + { + /* Nb of pages to erased can be decreased */ + pFlash.NbPagesSectorsToErase--; + + /* Check if there are still pages to erase*/ + if (pFlash.NbPagesSectorsToErase != 0x00U) + { + /* Increment page number */ + pFlash.PageOrSector += FLASH_PAGE_SIZE; + FLASH_PageErase(pFlash.PageOrSector); + }else + { + /* No more pages to erase: stop erase pages procedure */ + pFlash.ProcedureOnGoing = FLASH_TYPENONE; + } + } + else if (pFlash.ProcedureOnGoing == FLASH_TYPEERASE_SECTORERASE) + { + /* Nb of sectors to erased can be decreased */ + pFlash.NbPagesSectorsToErase--; + + /* Check if there are still pages to erase*/ + if (pFlash.NbPagesSectorsToErase != 0x00U) + { + /* Increment page number */ + pFlash.PageOrSector += FLASH_SECTOR_SIZE; + FLASH_SectorErase(pFlash.PageOrSector); + }else + { + /* No more pages to erase: stop erase pages procedure */ + pFlash.ProcedureOnGoing = FLASH_TYPENONE; + } + } + else + { + /*Stop the ongoing procedure */ + pFlash.ProcedureOnGoing = FLASH_TYPENONE; + } + + /* User callback */ + LL_FLASH_EndOfOperationCallback(param); + } + + if (pFlash.ProcedureOnGoing == FLASH_TYPENONE) + { + /* Disable End of Operation and Error interrupts */ + __LL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_OPERR); + + /* Process Unlocked */ + __HAL_UNLOCK(&pFlash); + } +} + +/** + * @brief FLASH end of operation interrupt callback. + * @param ReturnValue The value saved in this parameter depends on the ongoing procedure + * Mass Erase: 0 + * Page Erase: Page which has been erased + * Program: Address which was selected for data program + * @retval None + */ +__weak void LL_FLASH_EndOfOperationCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + (void)(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the LL_FLASH_EndOfOperationCallback could be implemented in the user file + */ +} + +/** + * @brief FLASH operation error interrupt callback. + * @param ReturnValue The value saved in this parameter depends on the ongoing procedure + * Mass Erase: 0 + * Page Erase: Page number which returned an error + * Program: Address which was selected for data program + * @retval None + */ +__weak void LL_FLASH_OperationErrorCallback(uint32_t ReturnValue) +{ + /* Prevent unused argument(s) compilation warning */ + (void)(ReturnValue); + + /* NOTE : This function should not be modified, when the callback is needed, + the LL_FLASH_OperationErrorCallback could be implemented in the user file + */ +} + +/* LL_FLASH_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT Puya *****END OF FILE****/