IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32L151 解决FLASH_ProgramHalfPage写入失败,并将半页写入耗时从100ms提升到3ms的方法 -> 正文阅读

[嵌入式]STM32L151 解决FLASH_ProgramHalfPage写入失败,并将半页写入耗时从100ms提升到3ms的方法

一、解决FLASH_ProgramHalfPage写入失败

? ? ? ? 这一章节是摘自一位网友的文章,因为我遇到跟他一样的问题,解决办法也是一样的,所以懒得再自己截图了。因此将他的图文搬过来了,如有侵权行为,请联系我删除,谢谢!

????????最近在研究IAP,在实现Flash半页写入时(FLASH_ProgramHalfPage)出现了问题。我按照官网给的flash操作例程:解锁flash -> 擦除 -> 半字写入 -> 检验数据。

????????程序下载到MCU,运行到 FLASH_ProgramHalfPage() 函数时,程序卡死,并导致STLink无法下载,显示无法停止Cortex-M设备(如图1)。下载程序只能在复位按钮复位MCU瞬间将程序下载进去。

图1

图1

MCU无法下载程序,原因可能是Flash写入操作错误,导致Flash锁住。
为找到原因仔细阅读数据手册,手册相关部份截图(图2)(图3)

图2
图2

?图3

图3

发现 FLASH_PECR 寄存器 PROG 位描述是Flash字写入时候不需要置1

仔细分析 FLASH_ProgramHalfPage() 库函数中半页写入,实际是连续写入32个字(图4),所以在半页写入时不需要将 PROG置位,但是库函数中却置位了(图5),这应该是库函数的一个BUG。

图4
图4

?图5

图5

????????取消 PROG 置位后,程序可以正常运行,实现了Flash半页字写入。同时进行Flash读取与写入数据对比校验,数据正确。

二、FLASH_ProgramHalfPage半页写入耗时从100ms提升到3ms的方法

? ? ? ? 上面一章确实可以将FLASH_ProgramHalfPage半页写失败的问题解决掉了。但是,我在测试中发现,FLASH_ProgramHalfPage每次调用竟然都需要耗时100毫秒。下面是我用一个IO口和逻辑分析仪抓波形的方法验证半页写耗时的情况:

#if 1
#define TEST_PORT        GPIOA
#define TEST_PIN         GPIO_PIN_0
#define TEST_L           HAL_GPIO_WritePin(TEST_PORT, TEST_PIN, GPIO_PIN_RESET)
#define TEST_H           HAL_GPIO_WritePin(TEST_PORT, TEST_PIN, GPIO_PIN_SET)
#define TEST_STATUS      HAL_GPIO_ReadPin(TEST_PORT, TEST_PIN)
#endif

? ? ? ?代码段1:PA0宏定义

????????上面代码定义了PA0作为测试用途,初始化时默认拉高。

__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_HalfPageProgram(uint32_t Address, uint32_t* pBuffer)
{
  uint32_t primask_bit;
  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)
  {
    /* Disable all IRQs */
    primask_bit = __get_PRIMASK();
    __disable_irq();

    /* Proceed to program the new half page */
    SET_BIT(FLASH->PECR, FLASH_PECR_FPRG);
    //SET_BIT(FLASH->PECR, FLASH_PECR_PROG);
    
    TEST_L; //写Flash前将PA0拉低
	
    /* Write one half page directly with 32 different words */
    while(count < 32U)
    {
      *(__IO uint32_t*) ((uint32_t)(Address + (4 * count))) = *pBuffer;
      pBuffer++;
      count ++;  
    }

    TEST_H; //写Flash后将PA0重新拉高

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

    /* Enable IRQs */
    __set_PRIMASK(primask_bit);
  }
   
  /* Return the Write Status */
  return status;
}

? ? ? ?代码段2:在FLASH_ProgramHalfPage函数中添加PA0的控制,测试耗时

????????上面代码是在FLASH_ProgramHalfPage函数中,写FLash前将PA0拉低,写完之后重新将PA0拉高。

? ? ? ? ?上图是用分析仪看到的结果,图中可以看到FLASH_ProgramHalfPage函数消耗了100多毫秒,这如果是在写入的数据量多的情况下是不能接受的。

? ? ? ? 翻了一下数据手册,发现半页写消耗的时间应该是在3点几毫秒而已。

? ? ? ? ?那么,是什么原因导致实测和手册上描述的不一样呢?我们再看手册:

? ? ? ? 看到没?原来手册上面写得很清楚了。“Half Page Write is possible only from SRAM
”?!!!

? ? ? ? 在请教公司一位大神之后,终于找到了解决办法,那就是:

????????1、首先,将FLASH_ProgramHalfPage函数所在的文件stm32l1xx_hal_flash_ramfunc.c,以及stm32l1xx_hal_flash_ex.c文件,将该俩文件中的所有函数设置为在SRAM中运行。设置方法如下面两图所示:

?

? ? ? ? ?设置完后编译,我们可以打开.map文件查看一下,FLASH_ProgramHalfPage函数确实已经在SRAM中了。

? ? ? ? ?2、然后,再将FLASH_ProgramHalfPage函数内之前注释的SET_BIT(FLASH->PECR, FLASH_PECR_PROG);重新打开:

? ? ? ? 其实,如果认真看并且有经验的话,FLASH_ProgramHalfPage函数上面已经有说明的了,只是之前没往心里去而已。从这点可以看出,经验真的很重要!!!

? ? ? ? ?经过上面两点的修改之后,FLASH_ProgramHalfPage函数的消耗时间确实与手册上面的一致了:

?

三、吃过的亏

? ? ? ? 在上面第二章的调试过程中,遇到了一个问题,在将FLASH_ProgramHalfPage函数设置到SRAM后,我在如下面的FLASH_ProgramHalfPage函数中加入PA0的电平切换,用来验证写FLash的耗时。结果Debug的时候发现,程序一直死在FLASH_ProgramHalfPage函数里出不来了。

__RAM_FUNC HAL_StatusTypeDef HAL_FLASHEx_HalfPageProgram(uint32_t Address, uint32_t* pBuffer)
{
  uint32_t primask_bit;
  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)
  {
    /* Disable all IRQs */
    primask_bit = __get_PRIMASK();
    __disable_irq();

    /* Proceed to program the new half page */
    SET_BIT(FLASH->PECR, FLASH_PECR_FPRG);
    SET_BIT(FLASH->PECR, FLASH_PECR_PROG);
    
    #if 1
    TEST_L;
	#endif
	
    /* Write one half page directly with 32 different words */
    while(count < 32U)
    {
      *(__IO uint32_t*) ((uint32_t)(Address + (4 * count))) = *pBuffer;
      pBuffer++;
      count ++;  
    }

    #if 1
    TEST_H;
	#endif

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

    /* Enable IRQs */
    __set_PRIMASK(primask_bit);
  }
   
  /* Return the Write Status */
  return status;
}

? ? ? ? 于是乎,将PA0的电平切换操作抽出来在FLASH_ProgramHalfPage函数外面来操作,就OK了。这个亏虽然解决了,但是目前还未得知为什么!!!有大神说可能是因为FLASH_ProgramHalfPage函数前解了锁,而且该函数是在SRAM中运行,因此在该函数内调用非SRAM中的函数就要从Flash中读取,所以就出错了。这个说法不知道真假,反正我也不是很理解,如果有大神知道的可以赐教,谢谢大家!!!


	TEST_L;

    ret = HAL_FLASHEx_HalfPageProgram( flash_addr, p_actual );

	TEST_H;

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-30 12:12:35  更:2021-08-30 12:24:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 7:58:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计