【问题标题】:Erasing my Flash on STM32L1在 STM32L1 上擦除我的 Flash
【发布时间】:2015-06-17 11:03:40
【问题描述】:

我的擦除功能遇到问题。 我尝试擦除 Flash 的 15 个扇区,以便放置一个新的二进制文件。 我不明白为什么,但我的功能冻结了,我无法擦除我需要的所有内存。

如果你想试一试,这是我的代码

/*
 * bootloader.c
 *
 *  Created on: 9 juin 2015
 *      Author: tgloaguen
 */
#include "usart.h"
#include "stm32l1xx_flash.h"
#define WRITE_START_ADDR 0x08000000
#define WRITE_END_ADDR 0x0800FFFF
#define FLASH_PAGE_SIZE    ((uint16_t)0x100) //If a page is 256 bits
#define MY_BL_FUNCTIONS __attribute__((section(".bootsection")))

void BootLoader(void) MY_BL_FUNCTIONS;
FLASH_Status Flash_Write ( uint32_t StartAddress, uint8_t *p, uint32_t Size ) MY_BL_FUNCTIONS;
uint8_t Flash_Erase() MY_BL_FUNCTIONS;
void Receive_Data(char * buffer,int size)MY_BL_FUNCTIONS;
void Receive_Size(char * buffer, int *sizeData)MY_BL_FUNCTIONS;

void BootLoader(void) {

    //clear all ITs
    USART_ITConfig( USART1, USART_IT_RXNE, DISABLE );
    //SendString("HELLO",USART2);
    uint8_t status,i;
    char buffer[33];
    //en dur
    uint16_t *adr = WRITE_START_ADDR;
    uint16_t sizeBin = 51400,k = 0,k_hexa = 0x20;
    SendString("BOOTLOADER",USART2);


    Flash_Erase();
    SendString("ERASEOK",USART2);
    //if sizeBin ok
}

和擦除功能

uint8_t Flash_Erase() {

    uint32_t EraseCounter = 0x00, Address = 0x00;//Erase count, write address
    uint32_t NbrOfPage = 0x00;//Recording to erase the pages
    volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;/*FLASH complete erasure marks*/
      /*Unlock FLASH*/

    FLASH_Unlock();
      /*Calculate the number of FLASH pages need to erase */
    NbrOfPage = (WRITE_END_ADDR - WRITE_START_ADDR) / FLASH_PAGE_SIZE;
      /* Remove all hang flags */
    FLASH_ClearFlag ( FLASH_FLAG_EOP     |
                            FLASH_FLAG_WRPERR  |
                            FLASH_FLAG_PGAERR  |
                            FLASH_FLAG_SIZERR  |
                            FLASH_FLAG_OPTVERR );
      /* Erase the FLASH page*/
    for(EraseCounter = 0; (EraseCounter <NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
      {
        SendString("ok |",USART2);
        FLASHStatus = FLASH_ErasePage(WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));

      }
      FLASH_Lock ( );

    return (uint8_t)FLASHStatus;
}

【问题讨论】:

  • 您的引导加载程序可以重定位吗?您是在 RAM 中运行,还是您的引导加载程序在 Flash_Erase 函数未取消的闪存页面上?
  • 我的bootloader是FLASH的结尾,一般不会被函数擦除
  • 如果 Flash_Erase() 函数是从 flash 中执行的,那么我不希望它工作。想象一下,当它在写入闪存擦除命令时,它也在从闪存读取指令。指令读取会干扰擦除命令序列。我相信您需要将 Flash_Erase() 复制到 RAM 并从那里执行它。 (Flash_Program() 也是如此。)
  • @kkrambo 通常在 cortex M 内核(或没有 MMU 的 MCU)中擦除/编程从闪存执行的程序闪存。您必须小心/避免擦除代码正在执行的扇区/页面。
  • 我刚刚阅读了有关 STM32F4xx 的信息,因此不确定这是否也适用于 'L1xx(但很可能):在编程时,访问 Flash 会停止。这可能是中断的问题。如果您明确添加 what 出错了,这将很有帮助。您是否阅读了您设备的“闪存编程手册”?如果它在调试器控制下运行,可能会有额外的怪癖(不确定 STM,但我有其他 MCU 出现此类问题)。

标签: c embedded flash-memory


【解决方案1】:

在您的代码中,您试图擦除整个闪存,但您正在从最终扇区的闪存执行引导加载程序。

根据 REF 人员的报告

在对 NVM 进行写/擦除操作期间(半页编程或双字除外) 擦除/写入),任何读取同一组 NVM 的尝试都会停止总线。

那么你必须根据你的内存映射保留引导加载程序更改WRITE_END_ADDR定义的空间。

示例:如果您的引导加载程序长度为 4K 并且属于最后一个扇区 (0x0801 F000 - 0x0801 FFFF),那么 WRITE_END_ADDR 必须是 0x0801 EFFF

编辑 正如@Olaf 所写,请注意属于地址 0 闪存中前 8 个字节的 ISP(初始堆栈指针)和 IPC(初始程序计数器)。

【讨论】:

  • 他仍然会擦除第一个扇区中的复位向量。
  • @Olaf 问题是引导加载程序属于闪存末尾,我完全不同意。反正取消和重刷ISP和IPC是没有问题的,但是风险很大。关于向量表,许多嵌入式微型 rtos(FreeRTOS、MQX ...)在启动时将向量表重新映射到 RAM。我希望引导加载程序在其扇区中有向量表。最后,OP 可以做尝试做的事情,但第一次出现问题时(例如,在 ISP 和 IPC 重写期间断电)应用程序会受到影响。
  • 事实上,我在这里要做的是编写自己的引导加载程序,我必须擦除足够多的扇区才能从 USART 闪存我的新程序。问题是我只能刷新第一个扇区并且它冻结,也许我的引导加载程序位于错误的位置,我尝试同时读/写......我检查了我的链接器脚本,但我不知道如何放置我想要的引导加载程序....
  • 我的问题是:我必须在哪里刷新我的新代码?由于向量表,我必须让扇区 0 吗?以及如何将引导加载程序放在 FLASH 的末尾
  • 这取决于很多事情。首先:您确定您的引导加载程序属于最后一个扇区吗?如果是,它的向量表属于哪里?引导加载程序启动时是否重新映射了向量表 RAM?例如,如果我们的引导加载程序从地址 0 映射向量表,则您无法擦除它并通过中断使用 uart。无论如何,我的建议是将引导加载程序放入第一个扇区。这使得 IPC 和 ISP 在损坏时得以保留。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-11
  • 2021-10-20
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
相关资源
最近更新 更多