你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32l431 flash无法写入的问题

[复制链接]
liyue12 提问时间:2020-6-4 17:19 /
  芯片型号是STM32L431RC,用HAL库往flash里写入一个双字无法成功。stm32l4 系列只能双字写,或者fast写(写一个ROW,另外我试了这种方式也没成功)。

代码如下:
        __disable_irq();
        HAL_FLASH_Unlock();

        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGAERR | FLASH_FLAG_WRPERR);

        FLASH_PageErase(100, FLASH_BANK_1);           //stm32l431一页2048字节,100页对应0x8032000,FLASH容量256kb,也没有超                                                                            //只有bank1
        ret = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, 0x8032000, 0x0102030405060708);
        printf("errcode = %x\n", pFlash.ErrorCode);

        HAL_FLASH_Lock();
        __enable_irq();


  实验现象是:返回错误代码0xA0,查数据手册是 PGAERR 和 PGSERR。数据手册说PGSERR是在PGAERR置位的情况下置位的,所以错误原因应该是PGAERR. 可是写入数据的地址是0x803200,是8的倍数。

  有没有人知道要怎么样才能写成功?



收藏 评论7 发布时间:2020-6-4 17:19

举报

7个回答
liyue12 回答时间:2020-6-5 13:40:57
谢谢各位的回复,我发现我的程序问题出在哪里了,是我用的HAL库函数不对。擦除应该用HAL_FLASHEx_Erase这个函数。
如果用  FLASH_PageErase 这个函数,那在后面加一句
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB))关CR寄存器的PER位也行

是4楼给我的思路,我发现他提供的HAL包中的代码,用的擦除函数是HAL_FLASHEx_Erase,去看函数源码,
发现里面调用了FLASH_PageErase和FLASH_MassErase这两个函数(针对不同擦除方式)
在FLASH_PageErase这个函数后有CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB))
在FLASH_MassErase这个函数后有CLEAR_BIT(FLASH->CR, (FLASH_CR_MER1))
所以问题是函数用错了,导致该清零的位没有清零。

另外3楼说的,可能是您理解错了,stm32的内存控制寄存器平时是锁着的,操作内存时是要先解锁,操作完了再上锁,所以顺序是对的。
MrJiu 回答时间:2020-6-5 00:21:56
没用过用HAL写flash,自己直接用的寄存器实现的...好像问题不大!!!
慎微 回答时间:2020-6-5 10:03:52
初看一下,您的  HAL_FLASH_Unlock()和  HAL_FLASH_Loock() 位置应互换一下;锁定 flash,是不许别的进程来处理 flash 资源。当前 flash 处理后,unlock 它,许可别的task,别的进程,处理 flash

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

watershade 回答时间:2020-6-5 12:14:54
这是HAL包中的代码,多了一个__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR)和__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PEMPTY)。还有一个选择Bank的过程:


  1. int main(void)
  2. {
  3.   uint8_t data_index = 0;

  4.   /* STM32L4xx HAL library initialization:
  5.        - Configure the Flash prefetch, Instruction cache, Data cache
  6.        - Systick timer is configured by default as source of time base, but user
  7.          can eventually implement his proper time base source (a general purpose
  8.          timer for example or other time source), keeping in mind that Time base
  9.          duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
  10.          handled in milliseconds basis.
  11.        - Set NVIC Group Priority to 4
  12.        - Low Level Initialization
  13.      */
  14.   HAL_Init();

  15.   /* Configure the system clock to 120 MHz */
  16.   SystemClock_Config();

  17.   /* Initialize LED1, LED2 and LED3 */
  18.   BSP_LED_Init(LED1);
  19.   BSP_LED_Init(LED2);
  20.   BSP_LED_Init(LED3);

  21.   /* Unlock the Flash to enable the flash control register access *************/
  22.   HAL_FLASH_Unlock();

  23.   /* Erase the user Flash area
  24.     (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

  25.   /* Clear OPTVERR bit set on virgin samples */
  26.   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);

  27.   /* Clear PEMPTY bit set (as the code is executed from Flash which is not empty) */
  28.   if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY) != 0)
  29.   {
  30.     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PEMPTY);
  31.   }

  32.   /* Get the bank */
  33.   BankNumber = GetBank(FLASH_USER_START_ADDR);

  34.   /* Fill EraseInit structure*/
  35.   EraseInitStruct.TypeErase = FLASH_TYPEERASE_MASSERASE;
  36.   EraseInitStruct.Banks     = BankNumber;

  37.   if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK)
  38.   {
  39.     /*
  40.       Error occurred while mass erase.
  41.       User can add here some code to deal with this error.
  42.       To know the code error, user can call function 'HAL_FLASH_GetError()'
  43.     */
  44.     /* Infinite loop */
  45.     while (1)
  46.     {
  47.       BSP_LED_On(LED3);
  48.     }
  49.   }

  50.   /* Program the user Flash area word by word
  51.     (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

  52.   Address = FLASH_USER_START_ADDR;

  53.   while (Address < (FLASH_USER_END_ADDR - (FLASH_ROW_SIZE*sizeof(uint64_t))))
  54.   {
  55.     if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, Address, (uint64_t)Data64_To_Prog) == HAL_OK)
  56.     {
  57.       Address = Address + (FLASH_ROW_SIZE*sizeof(uint64_t));
  58.     }
  59.    else
  60.     {
  61.       /* Error occurred while writing data in Flash memory.
  62.          User can add here some code to deal with this error */
  63.       while (1)
  64.       {
  65.         BSP_LED_On(LED3);
  66.       }
  67.     }
  68.   }

  69.   if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST_AND_LAST, Address, (uint64_t)Data64_To_Prog) != HAL_OK)
  70.   {
  71.     /* Error occurred while writing data in Flash memory.
  72.        User can add here some code to deal with this error */
  73.     while (1)
  74.     {
  75.       BSP_LED_On(LED3);
  76.     }
  77.   }

  78.   /* Lock the Flash to disable the flash control register access (recommended
  79.      to protect the FLASH memory against possible unwanted operation) *********/
  80.   HAL_FLASH_Lock();

  81.   /* Check if the programmed data is OK
  82.       MemoryProgramStatus = 0: data programmed correctly
  83.       MemoryProgramStatus != 0: number of words not programmed correctly ******/
  84.   Address = FLASH_USER_START_ADDR;
  85.   MemoryProgramStatus = 0x0;

  86.   while (Address < FLASH_USER_END_ADDR)
  87.   {
  88.     for (data_index = 0; data_index < FLASH_ROW_SIZE; data_index++)
  89.     {
  90.       data64 = *(__IO uint64_t *)Address;
  91.    
  92.       if(data64 != Data64_To_Prog[data_index])
  93.       {
  94.         MemoryProgramStatus++;
  95.       }
  96.       Address = Address + sizeof(uint64_t);
  97.     }
  98.   }

  99.   /*Check if there is an issue to program data*/
  100.   if (MemoryProgramStatus == 0)
  101.   {
  102.     /* No error detected. Switch on LED1*/
  103.     BSP_LED_On(LED1);
  104.   }
  105.   else
  106.   {
  107.     /* Error detected. Switch on LED2*/
  108.     BSP_LED_On(LED2);
  109.   }

  110.   /* Infinite loop */
  111.   while (1)
  112.   {
  113.   }
  114. }
复制代码

评分

参与人数 1蝴蝶豆 +3 收起 理由
STMCU + 3

查看全部评分

sxying 回答时间:2020-6-5 16:55:40
在擦除那句后面加两句。
                        FLASH_WaitForLastOperation(FLASH_WAITETIME);                    //等待上次操作完成
                        CLEAR_BIT(FLASH->CR, FLASH_CR_PER);               

stm32l433 亲测可行。


评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

liyue12 回答时间:2020-6-5 19:00:27
是的,还要加上 FLASH_WaitForLastOperation(FLASH_WAITETIME) 这句话,等擦除完成
butterflyspring 回答时间:2020-6-12 12:15:34
建议用 HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError) 这个函数擦除。这个函数里包含了对CACHE的禁止,逻辑更完整。具体可以参考官方例程

评分

参与人数 1蝴蝶豆 +2 收起 理由
STMCU + 2

查看全部评分

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版