522 lines
17 KiB
C
522 lines
17 KiB
C
/**
|
|
******************************************************************************
|
|
* @file stm32l0xx_hal_flash_ramfunc.c
|
|
* @author MCD Application Team
|
|
* @brief FLASH RAMFUNC driver.
|
|
* This file provides a Flash firmware functions which should be
|
|
* executed from internal SRAM
|
|
*
|
|
* @verbatim
|
|
|
|
*** ARM Compiler ***
|
|
--------------------
|
|
[..] RAM functions are defined using the toolchain options.
|
|
Functions that are be 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.
|
|
|
|
*** ICCARM Compiler ***
|
|
-----------------------
|
|
[..] RAM functions are defined using a specific toolchain keyword "__ramfunc".
|
|
|
|
*** GNU Compiler ***
|
|
--------------------
|
|
[..] RAM functions are defined using a specific toolchain attribute
|
|
"__attribute__((section(".RamFunc")))".
|
|
|
|
@endverbatim
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© Copyright (c) 2016 STMicroelectronics.
|
|
* All rights reserved.</center></h2>
|
|
*
|
|
* 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 "stm32l0xx_hal.h"
|
|
|
|
/** @addtogroup STM32L0xx_HAL_Driver
|
|
* @{
|
|
*/
|
|
|
|
#ifdef HAL_FLASH_MODULE_ENABLED
|
|
|
|
/** @addtogroup FLASH
|
|
* @{
|
|
*/
|
|
/** @addtogroup FLASH_Private_Variables
|
|
* @{
|
|
*/
|
|
extern FLASH_ProcessTypeDef pFlash;
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/** @defgroup FLASH_RAMFUNC FLASH_RAMFUNC
|
|
* @brief FLASH functions executed from RAM
|
|
* @{
|
|
*/
|
|
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
/* Private macro -------------------------------------------------------------*/
|
|
/* Private variables ---------------------------------------------------------*/
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
/** @defgroup FLASH_RAMFUNC_Private_Functions FLASH RAM Private Functions
|
|
* @{
|
|
*/
|
|
|
|
static __RAM_FUNC HAL_StatusTypeDef FLASHRAM_WaitForLastOperation(uint32_t Timeout);
|
|
static __RAM_FUNC HAL_StatusTypeDef FLASHRAM_SetErrorCode(void);
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
/** @defgroup FLASH_RAMFUNC_Exported_Functions FLASH RAM Exported Functions
|
|
*
|
|
@verbatim
|
|
===============================================================================
|
|
##### ramfunc functions #####
|
|
===============================================================================
|
|
[..]
|
|
This subsection provides a set of functions that should be executed from RAM
|
|
transfers.
|
|
|
|
@endverbatim
|
|
* @{
|
|
*/
|
|
|
|
/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group1 Peripheral features functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Enable the power down mode during RUN mode.
|
|
* @note This function can be used only when the user code is running from Internal SRAM.
|
|
* @retval HAL status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EnableRunPowerDown(void)
|
|
{
|
|
/* Enable the Power Down in Run mode*/
|
|
__HAL_FLASH_POWER_DOWN_ENABLE();
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Disable the power down mode during RUN mode.
|
|
* @note This function can be used only when the user code is running from Internal SRAM.
|
|
* @retval HAL status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_DisableRunPowerDown(void)
|
|
{
|
|
/* Disable the Power Down in Run mode*/
|
|
__HAL_FLASH_POWER_DOWN_DISABLE();
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group2 Programming and erasing operation functions
|
|
*
|
|
@verbatim
|
|
@endverbatim
|
|
* @{
|
|
*/
|
|
|
|
#if defined(FLASH_PECR_PARALLBANK)
|
|
/**
|
|
* @brief Erases a specified 2 pages in program memory in parallel.
|
|
* @note This function can be used only for STM32L07xxx/STM32L08xxx devices.
|
|
* To correctly run this function, the @ref HAL_FLASH_Unlock() function
|
|
* must be called before.
|
|
* Call the @ref HAL_FLASH_Lock() to disable the flash memory access
|
|
* (recommended to protect the FLASH memory against possible unwanted operation).
|
|
* @param Page_Address1: The page address in program memory to be erased in
|
|
* the first Bank (BANK1). This parameter should be between FLASH_BASE
|
|
* and FLASH_BANK1_END.
|
|
* @param Page_Address2: The page address in program memory to be erased in
|
|
* the second Bank (BANK2). This parameter should be between FLASH_BANK2_BASE
|
|
* and FLASH_BANK2_END.
|
|
* @note A Page is erased in the Program memory only if the address to load
|
|
* is the start address of a page (multiple of @ref FLASH_PAGE_SIZE bytes).
|
|
* @retval HAL status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_EraseParallelPage(uint32_t Page_Address1, uint32_t Page_Address2)
|
|
{
|
|
HAL_StatusTypeDef status = HAL_OK;
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
|
|
if(status == HAL_OK)
|
|
{
|
|
/* Proceed to erase the page */
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_PARALLBANK);
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_ERASE);
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
|
|
/* Write 00000000h to the first word of the first program page to erase */
|
|
*(__IO uint32_t *)Page_Address1 = 0x00000000U;
|
|
/* Write 00000000h to the first word of the second program page to erase */
|
|
*(__IO uint32_t *)Page_Address2 = 0x00000000U;
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
|
|
/* If the erase operation is completed, disable the ERASE, PROG and PARALLBANK bits */
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_ERASE);
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_PARALLBANK);
|
|
}
|
|
/* Return the Erase Status */
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief Program 2 half pages in program memory in parallel (half page size is 16 Words).
|
|
* @note This function can be used only for STM32L07xxx/STM32L08xxx devices.
|
|
* @param Address1: specifies the first address to be written in the first bank
|
|
* (BANK1). This parameter should be between FLASH_BASE and (FLASH_BANK1_END - FLASH_PAGE_SIZE).
|
|
* @param pBuffer1: pointer to the buffer containing the data to be written
|
|
* to the first half page in the first bank.
|
|
* @param Address2: specifies the second address to be written in the second bank
|
|
* (BANK2). This parameter should be between FLASH_BANK2_BASE and (FLASH_BANK2_END - FLASH_PAGE_SIZE).
|
|
* @param pBuffer2: pointer to the buffer containing the data to be written
|
|
* to the second half page in the second bank.
|
|
* @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
|
|
* must be called before.
|
|
* Call the @ref HAL_FLASH_Lock() to disable the flash memory access
|
|
* (recommended to protect the FLASH memory against possible unwanted operation).
|
|
* @note Half page write is possible only from SRAM.
|
|
* @note A half page is written to the program memory only if the first
|
|
* address to load is the start address of a half page (multiple of 64
|
|
* bytes) and the 15 remaining words to load are in the same half page.
|
|
* @note During the Program memory half page write all read operations are
|
|
* forbidden (this includes DMA read operations and debugger read
|
|
* operations such as breakpoints, periodic updates, etc.).
|
|
* @note If a PGAERR is set during a Program memory half page write, the
|
|
* complete write operation is aborted. Software should then reset the
|
|
* FPRG and PROG/DATA bits and restart the write operation from the
|
|
* beginning.
|
|
* @retval HAL status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_ProgramParallelHalfPage(uint32_t Address1, uint32_t* pBuffer1, uint32_t Address2, uint32_t* pBuffer2)
|
|
{
|
|
uint32_t count = 0U;
|
|
HAL_StatusTypeDef status = HAL_OK;
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
|
|
if(status == HAL_OK)
|
|
{
|
|
/* Proceed to program the new half page */
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_PARALLBANK);
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_FPRG);
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
if(status == HAL_OK)
|
|
{
|
|
/* Disable all IRQs */
|
|
__disable_irq();
|
|
|
|
/* Write the first half page directly with 16 different words */
|
|
while(count < 16U)
|
|
{
|
|
/* Address1 doesn't need to be increased */
|
|
*(__IO uint32_t*) Address1 = *pBuffer1;
|
|
pBuffer1++;
|
|
count ++;
|
|
}
|
|
|
|
/* Write the second half page directly with 16 different words */
|
|
count = 0U;
|
|
while(count < 16U)
|
|
{
|
|
/* Address2 doesn't need to be increased */
|
|
*(__IO uint32_t*) Address2 = *pBuffer2;
|
|
pBuffer2++;
|
|
count ++;
|
|
}
|
|
|
|
/* Enable IRQs */
|
|
__enable_irq();
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
}
|
|
|
|
/* if the write operation is completed, disable the PROG, FPRG and PARALLBANK bits */
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_FPRG);
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_PARALLBANK);
|
|
}
|
|
|
|
/* Return the Write Status */
|
|
return status;
|
|
}
|
|
#endif /* FLASH_PECR_PARALLBANK */
|
|
|
|
/**
|
|
* @brief Program a half page in program memory.
|
|
* @param Address specifies the address to be written.
|
|
* @param pBuffer pointer to the buffer containing the data to be written to
|
|
* the half page.
|
|
* @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
|
|
* must be called before.
|
|
* Call the @ref HAL_FLASH_Lock() to disable the flash memory access
|
|
* (recommended to protect the FLASH memory against possible unwanted operation)
|
|
* @note Half page write is possible only from SRAM.
|
|
* @note A half page is written to the program memory only if the first
|
|
* address to load is the start address of a half page (multiple of 64
|
|
* bytes) and the 15 remaining words to load are in the same half page.
|
|
* @note During the Program memory half page write all read operations are
|
|
* forbidden (this includes DMA read operations and debugger read
|
|
* operations such as breakpoints, periodic updates, etc.).
|
|
* @note If a PGAERR is set during a Program memory half page write, the
|
|
* complete write operation is aborted. Software should then reset the
|
|
* FPRG and PROG/DATA bits and restart the write operation from the
|
|
* beginning.
|
|
* @retval HAL status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_HalfPageProgram(uint32_t Address, uint32_t* pBuffer)
|
|
{
|
|
uint32_t count = 0U;
|
|
HAL_StatusTypeDef status = HAL_OK;
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
|
|
if(status == HAL_OK)
|
|
{
|
|
/* Proceed to program the new half page */
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_FPRG);
|
|
SET_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
|
|
/* Disable all IRQs */
|
|
__disable_irq();
|
|
|
|
/* Write one half page directly with 16 different words */
|
|
while(count < 16U)
|
|
{
|
|
/* Address doesn't need to be increased */
|
|
*(__IO uint32_t*) Address = *pBuffer;
|
|
pBuffer++;
|
|
count ++;
|
|
}
|
|
|
|
/* Enable IRQs */
|
|
__enable_irq();
|
|
|
|
/* Wait for last operation to be completed */
|
|
status = FLASHRAM_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
|
|
|
/* If the write operation is completed, disable the PROG and FPRG bits */
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_PROG);
|
|
CLEAR_BIT(FLASH->PECR, FLASH_PECR_FPRG);
|
|
}
|
|
|
|
/* Return the Write Status */
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/** @defgroup FLASH_RAMFUNC_Exported_Functions_Group3 Peripheral errors functions
|
|
* @brief Peripheral errors functions
|
|
*
|
|
@verbatim
|
|
===============================================================================
|
|
##### Peripheral errors functions #####
|
|
===============================================================================
|
|
[..]
|
|
This subsection permit to get in run-time errors of the FLASH peripheral.
|
|
|
|
@endverbatim
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Get the specific FLASH errors flag.
|
|
* @param Error pointer is the error value. It can be a mixed of:
|
|
* @arg @ref HAL_FLASH_ERROR_RD FLASH Read Protection error flag (PCROP)
|
|
* @arg @ref HAL_FLASH_ERROR_SIZE FLASH Programming Parallelism error flag
|
|
* @arg @ref HAL_FLASH_ERROR_PGA FLASH Programming Alignment error flag
|
|
* @arg @ref HAL_FLASH_ERROR_WRP FLASH Write protected error flag
|
|
* @arg @ref HAL_FLASH_ERROR_OPTV FLASH Option valid error flag
|
|
* @arg @ref HAL_FLASH_ERROR_FWWERR FLASH Write or Erase operation aborted
|
|
* @arg @ref HAL_FLASH_ERROR_NOTZERO FLASH Write operation is done in a not-erased region
|
|
* @retval HAL Status
|
|
*/
|
|
__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_GetError(uint32_t * Error)
|
|
{
|
|
*Error = pFlash.ErrorCode;
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/** @addtogroup FLASH_RAMFUNC_Private_Functions
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Set the specific FLASH error flag.
|
|
* @retval HAL Status
|
|
*/
|
|
static __RAM_FUNC HAL_StatusTypeDef FLASHRAM_SetErrorCode(void)
|
|
{
|
|
uint32_t flags = 0;
|
|
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
|
|
flags |= FLASH_FLAG_WRPERR;
|
|
}
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_PGA;
|
|
flags |= FLASH_FLAG_PGAERR;
|
|
}
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_SIZE;
|
|
flags |= FLASH_FLAG_SIZERR;
|
|
}
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
|
|
{
|
|
/* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
|
|
* (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
|
|
* as expected. If the user run an application using the first
|
|
* cut of the STM32L031xx device or the first cut of the STM32L041xx
|
|
* device, this error should be ignored. The revId of the device
|
|
* can be retrieved via the HAL_GetREVID() function.
|
|
*
|
|
*/
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
|
|
flags |= FLASH_FLAG_OPTVERR;
|
|
}
|
|
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_RD;
|
|
flags |= FLASH_FLAG_RDERR;
|
|
}
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_FWWERR;
|
|
flags |= HAL_FLASH_ERROR_FWWERR;
|
|
}
|
|
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR))
|
|
{
|
|
pFlash.ErrorCode |= HAL_FLASH_ERROR_NOTZERO;
|
|
flags |= FLASH_FLAG_NOTZEROERR;
|
|
}
|
|
|
|
/* Clear FLASH error pending bits */
|
|
__HAL_FLASH_CLEAR_FLAG(flags);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Wait for a FLASH operation to complete.
|
|
* @param Timeout maximum flash operationtimeout
|
|
* @retval HAL status
|
|
*/
|
|
static __RAM_FUNC HAL_StatusTypeDef FLASHRAM_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 */
|
|
|
|
while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY) && (Timeout != 0x00U))
|
|
{
|
|
Timeout--;
|
|
}
|
|
|
|
if(Timeout == 0x00U)
|
|
{
|
|
return HAL_TIMEOUT;
|
|
}
|
|
|
|
/* Check FLASH End of Operation flag */
|
|
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
|
|
{
|
|
/* Clear FLASH End of Operation pending bit */
|
|
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
|
|
}
|
|
|
|
if( __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_FWWERR) ||
|
|
__HAL_FLASH_GET_FLAG(FLASH_FLAG_NOTZEROERR) )
|
|
{
|
|
/*Save the error code*/
|
|
|
|
/* WARNING : On the first cut of STM32L031xx and STM32L041xx devices,
|
|
* (RefID = 0x1000) the FLASH_FLAG_OPTVERR bit was not behaving
|
|
* as expected. If the user run an application using the first
|
|
* cut of the STM32L031xx device or the first cut of the STM32L041xx
|
|
* device, this error should be ignored. The revId of the device
|
|
* can be retrieved via the HAL_GetREVID() function.
|
|
*
|
|
*/
|
|
FLASHRAM_SetErrorCode();
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
/* There is no error flag set */
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
#endif /* HAL_FLASH_MODULE_ENABLED */
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
|
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|