解决STM8 IAR优化等级过高导致FLASH块编程失败的问题

1 篇文章 0 订阅

STM8块编程的步骤为:
1、解锁FLASH权限
2、块编程
3、上锁FLASH权限

Note:如果你不是调用官方库函数对FLASH进行解锁,则要注意顺序,FLASH与EEPROM的解锁顺序是刚好相反的,解锁函数原型如下

/**
  * @brief   Unlocks the program or data EEPROM memory
  * @param  FLASH_MemType : Memory type to unlock
  *         This parameter can be a value of @ref FLASH_MemType_TypeDef
  * @retval None
  */
void FLASH_Unlock(FLASH_MemType_TypeDef FLASH_MemType)
{
    /* Check parameter */
    assert_param(IS_MEMORY_TYPE_OK(FLASH_MemType));

    /* Unlock program memory */
    if (FLASH_MemType == FLASH_MEMTYPE_PROG)
    {
        FLASH->PUKR = FLASH_RASS_KEY1;
        FLASH->PUKR = FLASH_RASS_KEY2;
    }
    /* Unlock data memory */
    else
    {
        FLASH->DUKR = FLASH_RASS_KEY2; /* Warning: keys are reversed on data memory !!! */
        FLASH->DUKR = FLASH_RASS_KEY1;
    }
}

STM8块编程官方库函数原型如下:

/**
  * @brief  Programs a memory block
  * @note   This function should be called and executed from RAM.
  * @param  FLASH_MemType : The type of memory to program
  * @param  BlockNum : The block number
  * @param  FLASH_ProgMode : The programming mode.
  * @param  Buffer : Pointer to buffer containing source data.
  * @retval None.
  */
IN_RAM(void FLASH_ProgramBlock(uint16_t BlockNum, FLASH_MemType_TypeDef FLASH_MemType, 
                        FLASH_ProgramMode_TypeDef FLASH_ProgMode, uint8_t *Buffer))
{
    uint16_t Count = 0;
    uint32_t startaddress = 0;

    /* Check parameters */
    assert_param(IS_MEMORY_TYPE_OK(FLASH_MemType));
    assert_param(IS_FLASH_PROGRAM_MODE_OK(FLASH_ProgMode));
    if (FLASH_MemType == FLASH_MEMTYPE_PROG)
    {
        assert_param(IS_FLASH_PROG_BLOCK_NUMBER_OK(BlockNum));
        startaddress = FLASH_PROG_START_PHYSICAL_ADDRESS;
    }
    else
    {
        assert_param(IS_FLASH_DATA_BLOCK_NUMBER_OK(BlockNum));
        startaddress = FLASH_DATA_START_PHYSICAL_ADDRESS;
    }

    /* Point to the first block address */
    startaddress = startaddress + ((uint32_t)BlockNum * FLASH_BLOCK_SIZE);

    /* Selection of Standard or Fast programming mode */
    if (FLASH_ProgMode == FLASH_PROGRAMMODE_STANDARD)
    {
        /* Standard programming mode */ /*No need in standard mode */
        FLASH->CR2 |= FLASH_CR2_PRG;
        FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NPRG);
    }
    else
    {
        /* Fast programming mode */
        FLASH->CR2 |= FLASH_CR2_FPRG;
        FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NFPRG);
    }

    /* Copy data bytes from RAM to FLASH memory */
    for (Count = 0; Count < FLASH_BLOCK_SIZE; Count++)
    {
#if defined (STM8S208) || defined(STM8S207) || defined(STM8S105) || defined (STM8AF62Ax) ||\
    defined (STM8AF52Ax) || defined (STM8AF626x)
  *((PointerAttr uint8_t*) (uint16_t)startaddress + Count) = ((uint8_t)(Buffer[Count]));
#elif defined (STM8S103) || defined (STM8S903)
  *((PointerAttr uint8_t*) (uint16_t)startaddress + Count) = ((uint8_t)(Buffer[Count]));
#endif       
    }
}

注意事项:如果调用官方块编程的库函数,默认是关闭的状态,所以你需要把IN_RAM改为开启状态,因为IN_RAM#define RAM_EXECUTION (0) 控制,把(0)改为(1),然后重新编译即可。

回到正题!!!
如果你确保块编程的函数操作没有任何问题,逻辑都正确的情况下,程序跑到块编程执行烧写FLASH时,程序就卡死不动了,那就有可能是IAR优化等级过高导致的,博主实测优化等级开到HIGH高等级模式下,块编程操作失败,导致程序卡死。
在这里插入图片描述
如果你的程序空间不够,一定要开到最高优化等级,别担心,还有办法!!!
直接上代码

//写入一块数据
//选择不优化该函数,防止优化等级过高导致块编程失败卡死
#pragma optimize= none  
__ramfunc void STMFLASH_WriteBlock(u16 block,u8 *block_buff)
{
  uint8_t i;
  u32 addr;
  addr = block;
  addr *=BLOCK_BYTES;
  addr +=FLASH_PROG_START_PHYSICAL_ADDRESS;
  
  /* Unlock program memory */
  FLASH->PUKR = FLASH_RASS_KEY1;
  FLASH->PUKR = FLASH_RASS_KEY2;
        
  //Flash标准块编程:FLASH_NCR2_NPRG  快速块编程:FLASH_NCR2_NFPRG
  FLASH->CR2 |= FLASH_CR2_PRG;
  FLASH->NCR2 &= (uint8_t)(~FLASH_NCR2_NPRG); 

  for(i=0; i<BLOCK_BYTES; i++)
  {
    *((PointerAttr uint8_t*)(u32)addr + i) = (u8)block_buff[i];
  }
  while( (FLASH->IAPSR & (FLASH_IAPSR_EOP | FLASH_IAPSR_WR_PG_DIS)) == 0);
  
  /* Lock memory */
  FLASH->IAPSR &= (uint8_t)FLASH_MEMTYPE_PROG;
}

参考链接:
iar选择性优化函数模块设置

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值