STM32 LL库 操作FLASH 保存数据

本文档详细介绍了STM32F1xx系列微控制器中使用LL_FLASH库进行页面擦除和编程的操作流程,包括等待操作完成、错误检测与处理。通过定义宏和函数,展示了如何处理FLASH_BUSY、PGERR、WRPERR和OPTVERR等标志。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#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();

}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值