ST意法半导体
直播中

李超

8年用户 1394经验值
私信 关注
[问答]

stm32f205的内存在42kbytes的12个扇区被擦除了是为什么?

我正在将一些代码从 STM32f105 移植到 stm32f205。
  • stm32f105 的内存在 64 页 2kbytes 中被擦除(我可以处理这个)
  • stm32f205的内存在42kbytes的12个扇区被擦除!!?(闪存大小为 512kB)
(来自 stm32f2xx_hal_flash_ex.h)
  • /** @defgroup FLASHEx_Sectors FLASH Sectors
  •   * @{
  •   */
  • #define FLASH_SECTOR_0     0U  /*!< Sector Number 0   */
  • #define FLASH_SECTOR_1     1U  /*!< Sector Number 1   */
  • #define FLASH_SECTOR_2     2U  /*!< Sector Number 2   */
  • #define FLASH_SECTOR_3     3U  /*!< Sector Number 3   */
  • #define FLASH_SECTOR_4     4U  /*!< Sector Number 4   */
  • #define FLASH_SECTOR_5     5U  /*!< Sector Number 5   */
  • #define FLASH_SECTOR_6     6U  /*!< Sector Number 6   */
  • #define FLASH_SECTOR_7     7U  /*!< Sector Number 7   */
  • #define FLASH_SECTOR_8     8U  /*!< Sector Number 8   */
  • #define FLASH_SECTOR_9     9U  /*!< Sector Number 9   */
  • #define FLASH_SECTOR_10    10U /*!< Sector Number 10  */
  • #define FLASH_SECTOR_11    11U /*!< Sector Number 11  */
我在这里错过了什么吗?
这是非常不方便的,因为我没有足够的内存来在表中复制我不想在擦除之前擦除的扇区部分。




回帖(1)

黄登高

2023-1-5 10:30:02
是的,有些页面大小不同。您的方法将根据您的需求而有所不同。
我也不明白为什么他们让页面大小比 ram 大,如果你开发一个 fw 并且你稍后会看到这个问题,它会造成很多麻烦。
如果是为了制作bootloader和更新固件,不用太在意,把bootloader写在第一页。
要更新,只需擦除所有其他内容并开始编写。
当您想将闪存用作 eeprom 来存储设置时,这有点棘手,但可以做到。
选择一个大小适合你的内存的页面,你需要将页面复制进去,因为要存储新数据你必须先擦除它。
制作一个具有页面大小(或数据大小)的时间数组,将闪存数据复制到其中,修改任何你想要的,擦除并写回。
最简单的方法是制作一个 typedef:


  • #define FLASH_ADDR        0x8000000        // Set the flash address (aligned to page)
  • #define FLASH_PAGES        1                // Number of pages

  • typedef struct{
  •         uint8_t hw_version;
  •         uint8_t sw_version;
  •         uint32_t serial;
  •         uint8_t option1;
  •         uint8_t option2;
  •         uint8_t option3;
  •         uint8_t option4;
  • }settings_t;

制作一个指向闪存地址的结构指针:


  • settings_t *flashSettings = (settings_t*)FLASH_ADDR        // Whatever the address is

在 ram 中创建一个结构缓冲区:


  • settings_t ramSettings;

将闪存内容复制到内存中:


  • ramSettings = *flashSettings;        // This is basically a memcpy

现在你可以只修改你需要的选项。
写入前,必须先擦除flash:


  • uint32_t error=0;
  • HAL_FLASH_Unlock();                //unlock flash writing
  • FLASH_EraseInitTypeDef erase;        // Flash erase struct
  • erase.NbPages = FLASH_PAGES;
  • erase.PageAddress = FLASH_ADDR ;         
  • erase.TypeErase = FLASH_TYPEERASE_PAGES;        // Tell we are going to erase flash in pages

  • // Erase flash
  • if(HAL_FLASHEx_Erase(&erase, &error)!=HAL_OK){
  •         HAL_FLASH_Lock();
  •         Error();
  • }

  • // This should be the value if all pages were correctly erased
  • if(error != 0xFFFFFFFF){           
  •         HAL_FLASH_Lock();
  •         Error();
  • }

  • // Ensure that the flash contents are erased
  • // Divide by 2 because we use 16 bit pointer
  • for (uint16_t i = 0; i < (number of bytes per page)/2; i++) {      
  •         if( *(uint16_t*)(FLASH_ADDR+(i*2)) != 0xFFFF){        // Erased flash is always "1"
  •                 HAL_FLASH_Lock();
  •                 Error();
  •         }
  • }


现在,存储您的设置:


  • // Store settings. Again we divide by 2 because we use 16 bit pointers.
  • for (uint16_t i = 0; i < sizeof(settings_t) / 2; i++) {
  •         if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD,
  •         (((uint32_t)flashSettings+i*2)), *(((uint16_t*)&ramSettings)+i) ) != HAL_OK){
  •                 HAL_FLASH_Lock();
  •                 Error();
  •         }
  • }
  • HAL_FLASH_Lock();        // Lock the flash writing

然后,我还要确保写入的闪存数据与 ram 数据匹配。
闪存不应该用作“非易失性内存”,你会磨损闪存并损坏它。
对于经常变化的值,使用 NVRAM,它类似于 SPI/I2C EEPROM,但不会磨损。
检查一下,这是我几个月前开发的烙铁固件,我从中获取了示例。
https://github.com/deividAlfa/stm32_soldering_iron_controller/blob/master/Core/Src/settings.c
https://github.com/deividAlfa/stm32_soldering_iron_controller/blob/master/Core/Inc/settings.h
  
我用设置存储了一个闪存阵列。
使用 DMA+CRC 硬件每 1 秒检查一次 ram 设置(这非常快)。
当检测到变化时,它会存储校验和、当前时间并设置“设置已更改”标志。
每次检测到更改时,它都会重置时间并更新校验和。
有一个超时(5 秒),如果没有检测到更多更改,它将新设置存储到闪存中。
这样闪存就不会因为每一个微小的变化而被覆盖,从而延长了它的使用寿命。
此外,如果您打算将闪存用作存储,您需要告诉链接器不要使用该空间。
您可以通过修改链接描述文件 (STM32FXXXXXXX_FLASH.ld) 来实现。
例如::


  • MEMORY
  • {
  •   RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  •   FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH =64K
  • }

更改为:


  • MEMORY
  • {
  •   RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  •   FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH =62K
  •   SETTINGS    (rx)    : ORIGIN = 0x800F800,   LENGTH = 2K
  • }

现在您可以安全地使用地址 0x800F800 来写入/读取 2KB 的数据。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分