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****/