硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3708|回复: 6
收起左侧

[客户分享] STM32F407 不需要重映射向量表就可以读写16K一块Flash的方法分享

[复制链接]

3

主题

43

回帖

52

积分

初级会员

积分
52
发表于 2020-9-15 23:13:45 | 显示全部楼层 |阅读模式
本帖最后由 lhb292 于 2020-9-15 23:16 编辑

  • STM32F407 不需要重映射向量表就可以读写16K一块Flash的方法分享如下,今天刚调出来的!实验证明可行
    1. #ifndef _FLASH_H_
    2. #define _FLASH_H_

    3. #include "driver_about.h"
    4. ////////////////////////////////////////////////////
    5. #define FlashAddr_ReadWrite    (0x0800C000)////块3:0x0800 C000 - 0x0800 FFFF 16K

    6. #define STM32_FLASH_BASE 0x08000000         //STM32 FLASH的起始地址
    7. #define ADDR_FLASH_SECTOR_0     ((u32)0x08000000)         //扇区0起始地址, 16 Kbytes
    8. #define ADDR_FLASH_SECTOR_1     ((u32)0x08004000)         //扇区1起始地址, 16 Kbytes  
    9. #define ADDR_FLASH_SECTOR_2     ((u32)0x08008000)         //扇区2起始地址, 16 Kbytes  
    10. #define ADDR_FLASH_SECTOR_3     ((u32)0x0800C000)         //扇区3起始地址, 16 Kbytes  
    11. #define ADDR_FLASH_SECTOR_4     ((u32)0x08010000)         //扇区4起始地址, 64 Kbytes  
    12. #define ADDR_FLASH_SECTOR_5     ((u32)0x08020000)         //扇区5起始地址, 128 Kbytes  
    13. #define ADDR_FLASH_SECTOR_6     ((u32)0x08040000)         //扇区6起始地址, 128 Kbytes  
    14. #define ADDR_FLASH_SECTOR_7     ((u32)0x08060000)         //扇区7起始地址, 128 Kbytes  
    15. #define ADDR_FLASH_SECTOR_8     ((u32)0x08080000)         //扇区8起始地址, 128 Kbytes  
    16. #define ADDR_FLASH_SECTOR_9     ((u32)0x080A0000)         //扇区9起始地址, 128 Kbytes  
    17. #define ADDR_FLASH_SECTOR_10    ((u32)0x080C0000)         //扇区10起始地址,128 Kbytes  
    18. #define ADDR_FLASH_SECTOR_11    ((u32)0x080E0000)         //扇区11起始地址,128 Kbytes  

    19. u32 FLASH_Read4Byte(u32 flashaddr);
    20. s8  FLASH_Read(u32 ReadAddr,u8 *pReadData,u32 ByteNums);
    21. s8  FLASH_EraseOneSector(u32 WriteAddr);
    22. s8  FLASH_Write(u32 WriteAddr,u8 *pWriteData,u32 ByteNums);
    23. #endif


    24. #include "flash.h"
    25. <font color="#ff0000">const char EEROM_Buff[1024*16] __attribute__((at(FlashAddr_ReadWrite))) = {0xff,0xff,0xff,0xff};//块3:0x0800 C000 - 0x0800 FFFF 16K</font>

    26. u32 FLASH_Read4Byte(u32 flashaddr)//读取指定地址的数据4个字节 返回值:对应数据[0 ... 3]
    27. {
    28.         return *(vu32*)flashaddr;
    29. }  

    30. s8 FLASH_Read(u32 ReadAddr,u8 *pReadData,u32 ByteNums)//从指定地址开始读出指定长度的数据      
    31. {
    32.         u32 data,i,inte,remd;
    33.         inte=ByteNums/4*4;//4的整数部分
    34.         remd=ByteNums%4;  //余数
    35.         for(i=0;i<inte;)
    36.         {
    37.                 *((u32*)&pReadData[i])=FLASH_Read4Byte(ReadAddr);//读取4个字节
    38.                 i+=4;
    39.                 ReadAddr+=4;
    40.         }
    41.       
    42.         data=FLASH_Read4Byte(ReadAddr);
    43.         for(i=0;i<remd;i++)
    44.         {
    45.           pReadData[inte+i]=(u8)(data>>(i*8));//取1个字节
    46.         }
    47.         return 0;
    48. }

    49. uint16_t FLASH_GetFlashSector(u32 flashaddr)//获取某个地址所在的flash扇区
    50. {
    51.              if(flashaddr<ADDR_FLASH_SECTOR_1) return FLASH_Sector_0;
    52.         else if(flashaddr<ADDR_FLASH_SECTOR_2) return FLASH_Sector_1;
    53.         else if(flashaddr<ADDR_FLASH_SECTOR_3) return FLASH_Sector_2;
    54.         else if(flashaddr<ADDR_FLASH_SECTOR_4) return FLASH_Sector_3;
    55.         else if(flashaddr<ADDR_FLASH_SECTOR_5) return FLASH_Sector_4;
    56.         else if(flashaddr<ADDR_FLASH_SECTOR_6) return FLASH_Sector_5;
    57.         else if(flashaddr<ADDR_FLASH_SECTOR_7) return FLASH_Sector_6;
    58.         else if(flashaddr<ADDR_FLASH_SECTOR_8) return FLASH_Sector_7;
    59.         else if(flashaddr<ADDR_FLASH_SECTOR_9) return FLASH_Sector_8;
    60.         else if(flashaddr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;
    61.         else if(flashaddr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10;
    62.         return FLASH_Sector_11;      
    63. }

    64. s8 FLASH_EraseOneSector(u32 WriteAddr)//擦除一个以WriteAddr为开始地址的块
    65. {
    66.        FLASH_Status status = FLASH_COMPLETE;
    67.        if((WriteAddr<STM32_FLASH_BASE)||(WriteAddr%4)) return -1;   
    68.       
    69.         FLASH_Unlock();                                                        //解锁
    70.         FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
    71.         FLASH_DataCacheCmd(DISABLE);  //FLASH擦除期间,必须禁止数据缓存
    72.         if(WriteAddr<0X1FFF0000)                  
    73.         {
    74.                 status=FLASH_EraseSector(FLASH_GetFlashSector(WriteAddr),VoltageRange_3);//擦除块
    75.                 if(status!=FLASH_COMPLETE) return status;        //发生错误了
    76.         }
    77.       
    78.   FLASH_DataCacheCmd(ENABLE);        //FLASH擦除结束,开启数据缓存
    79.   FLASH_Lock();//上锁
    80.   return 0;
    81. }

    82. s8 FLASH_Write(u32 WriteAddr,u8 *pWriteData,u32 ByteNums)//写入pWriteData中的ByteNums字节数据到以WriteAddr地址为开始的Flash中
    83. {
    84.   FLASH_Status status = FLASH_COMPLETE;
    85.   u32 endaddr=0;      
    86.   if((WriteAddr<STM32_FLASH_BASE)||(WriteAddr%4)) return -1;        //非法地址
    87.       
    88.   FLASH_Unlock();                                                        //解锁
    89.   FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
    90.   //FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存
    91.                
    92.   endaddr =WriteAddr+ByteNums;//写入的结束地址      
    93.         while(WriteAddr<endaddr)//写数据
    94.         {
    95.                 status=FLASH_ProgramWord(WriteAddr,*(u32*)pWriteData);//写入数据
    96.                 if(status!=FLASH_COMPLETE) return status;        //写入异常
    97.                 WriteAddr+=4;
    98.                 pWriteData+=4;
    99.         }

    100.   //FLASH_DataCacheCmd(ENABLE);        //FLASH擦除结束,开启数据缓存
    101.   FLASH_Lock();//上锁
    102.   return 0;
    103. }
    复制代码


评分

参与人数 1金币 +50 收起 理由
eric2013 + 50 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107112
QQ
发表于 2020-9-16 09:22:53 | 显示全部楼层
很给力,谢谢楼主分享。
回复

使用道具 举报

3

主题

1233

回帖

1242

积分

至尊会员

积分
1242
发表于 2020-9-16 09:25:17 | 显示全部楼层
首先感谢分享! 另外我问下,这个功能用在什么场景下的,谢谢!
回复

使用道具 举报

3

主题

43

回帖

52

积分

初级会员

积分
52
 楼主| 发表于 2020-9-21 17:51:51 | 显示全部楼层
本帖最后由 lhb292 于 2020-9-21 17:56 编辑
morning_enr6U 发表于 2020-9-16 09:25
首先感谢分享! 另外我问下,这个功能用在什么场景下的,谢谢!

适用于应用程序比较大,想用F407前几个16Kflash块存储应用数据的情况下,当然如果应用程序不大,最后几块128K的块剩余比较多,也可以直接用最后一个128K块,而不必使用本方法
回复

使用道具 举报

335

主题

2040

回帖

3050

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3050
发表于 2020-9-23 10:41:46 | 显示全部楼层
lhb292 发表于 2020-9-21 17:51
适用于应用程序比较大,想用F407前几个16Kflash块存储应用数据的情况下,当然如果应用程序不大,最后几块 ...

最后的那一块128KB,空间太大了,擦除时间比较长,高达一两秒钟,有点不好用。
回复

使用道具 举报

335

主题

2040

回帖

3050

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3050
发表于 2020-9-23 10:43:59 | 显示全部楼层
这个思路简单有效! 使用强制地址定义一个变量,把这个16KB先给占用了!
回复

使用道具 举报

3

主题

43

回帖

52

积分

初级会员

积分
52
 楼主| 发表于 2020-9-27 16:36:52 | 显示全部楼层
caicaptain2 发表于 2020-9-23 10:43
这个思路简单有效! 使用强制地址定义一个变量,把这个16KB先给占用了!

对的 就是这个思路
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-18 12:31 , Processed in 0.202717 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表