#include "string.h"
#include "stm32f1xx_ll_system.h"
#define FLASH_PAGE_SIZE ((uint32_t)0x00000400)
#define LL_FLASH_GET_FLAG(__FLAG__) (((__FLAG__) == FLASH_FLAG_OPTVERR) ? \
(FLASH->OBR & FLASH_OBR_OPTERR) : \
(FLASH->SR & (__FLAG__)))
#define OBR_REG_INDEX 1U
#define FLASH_FLAG_BSY FLASH_SR_BSY /*!< FLASH Busy flag */
#define FLASH_FLAG_PGERR FLASH_SR_PGERR /*!< FLASH Programming error flag */
#define FLASH_FLAG_WRPERR FLASH_SR_WRPRTERR /*!< FLASH Write protected error flag */
#define FLASH_FLAG_EOP FLASH_SR_EOP /*!< FLASH End of Operation flag */
#define FLASH_FLAG_OPTVERR ((OBR_REG_INDEX << 8U | FLASH_OBR_OPTERR)) /*!< Option Byte Error */
#define HAL_MAX_DELAY 0xFFFFFFFFU
#define FLASH_TIMEOUT_VALUE 50000U /* 50 s */
uint8_t FailSafe_Flag;
#define FLASH_PAGES_TO_BE_PROTECTED OB_WRP_Pages0to3
#if 1
/**
* @brief Wait for a FLASH operation to complete.
* @param Timeout maximum flash operation timeout
* @retval HAL Status
*/
int 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 */
uint32_t tickstart = SysTick->VAL;
while(LL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
{
if (Timeout != 10000)
{
if((Timeout == 0U) || ((SysTick->VAL-tickstart) > Timeout))
{
return 1;
}
}
}
/* Check FLASH End of Operation flag */
if (LL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
{
/* Clear FLASH End of Operation pending bit */
LL_FLASH_GET_FLAG(FLASH_FLAG_EOP);
}
if(LL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||
LL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) ||
LL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
{
/*Save the error code*/
// FLASH_SetErrorCode();
return 2;
}
/* There is no error flag set */
return 0;
}
#endif
void Flash_Erase(uint32_t PageAddress, uint8_t NbrOfPage)
{
uint32_t address = 0U;
int status= 0;
/* Page Erase requested on address located on bank1 */
/* Wait for last operation to be completed */
if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == 0)
{
/*Initialization of PageError variable*/
// *PageError = 0xFFFFFFFFU;
/* Erase page by page to be done*/
for(address = PageAddress;
address < ((NbrOfPage * FLASH_PAGE_SIZE) + PageAddress);
address += FLASH_PAGE_SIZE)
{
/* Proceed to erase the page */
SET_BIT(FLASH->CR, FLASH_CR_PER);
WRITE_REG(FLASH->AR, PageAddress);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
/* 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 != 0)
{
/* In case of error, stop erase procedure and return the faulty address */
// *PageError = address;
break;
}
}
}
/*
uint8_t i = 0;
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
for (i = 0; i < NbrOfPage; i++)
{
FLASH_ErasePage(addr + (FLASH_PAGE_SIZE * i));
}*/
}
void Flash_Program_HalfWord(uint32_t WriteAddr, uint16_t Data)
{
/* Proceed to program the new data */
SET_BIT(FLASH->CR, FLASH_CR_PG);
/* Write data in the address */
*(__IO uint16_t*)WriteAddr = Data;
/*
if (FLASH_ProgramHalfWord(WriteAddr, Data) != FLASH_COMPLETE)
{
while (1)
{
RED_LED_FLICKER;
Delay_Ms(200);
}
}*/
}
void Flash_Program_Word(uint32_t WriteAddr, uint32_t Data)
{
uint8_t index = 0;
uint8_t nbiterations = 0;
/* Wait for last operation to be completed */
int status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
if(status == 0)
{
{
/* Program word (32-bit = 2*16-bit) at a specified address. */
nbiterations = 2U;
}
for (index = 0U; index < nbiterations; index++)
{
Flash_Program_HalfWord((WriteAddr + (2U*index)), (uint16_t)(Data >> (16U*index)));
/* 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 programation procedure */
if (status != 0)
{
break;
}
}
}
/*
if (FLASH_ProgramWord(WriteAddr, Data) != FLASH_COMPLETE)
{
while (1)
{
RED_LED_FLICKER;
Delay_Ms(200);
}
}
*/
}
void Flash_Program_Allow(void)
{
//__set_PRIMASK(1);
LL_mDelay(1);
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
{
/* Authorize the FLASH Registers access */
WRITE_REG(FLASH->KEYR, FLASH_KEY1);
WRITE_REG(FLASH->KEYR, FLASH_KEY2);
/* Verify Flash is unlocked */
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
{
}
}
/*
__set_PRIMASK(1);
Delay_Ms(1);
FLASH_Unlock();
*/
}
void Flash_Program_Forbid(void)
{
SET_BIT(FLASH->CR, FLASH_CR_LOCK);
LL_mDelay(1);
// __set_PRIMASK(0);
/*
FLASH_Lock();
Delay_Ms(1);
__set_PRIMASK(0);
*/
}
void Flash_Data_Save(void)
{
Flash_Program_Allow();
Flash_Erase(Rx_Data_Addr, 1);
for (uint16_t i = 0; i < 25; i++)
Flash_Program_Word(Rx_Data_Addr + 4 * i, RF_Para.Flash_Data[i]);
Flash_Program_Forbid();
}