OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 585|回复: 0

正点原子片上flash移植到stm32g473vet6 flash读写错误

[复制链接]

14

主题

20

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
254
金钱
254
注册时间
2022-11-5
在线时间
28 小时
发表于 2024-6-3 16:09:43 | 显示全部楼层 |阅读模式
看着正点原子的stm32f103的片上flash代码移植到自己的工程中出错,因为stm32g473的hal库中没有半字写入,所以我把他改成了以双字(64位)的形式写入数据。每次写入一个双字,然后地址增加4,
stm32f103中的宏定义为:

#define FLASH_TYPEPROGRAM_HALFWORD             0x01U  /*!<Program a half-word (16-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_WORD                 0x02U  /*!<Program a word (32-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_DOUBLEWORD           0x03U  /*!<Program a double word (64-bit) at a specified address*/
stm32g473中为:
#define FLASH_TYPEPROGRAM_DOUBLEWORD    0x00U              /*!< Program a double-word (64-bit) at a specified address.*/
#define FLASH_TYPEPROGRAM_FAST          0x01U              /*!< Fast program a 32 row double-word (64-bit) at a specified address.
                                                                And another 32 row double-word (64-bit) will be programmed */
#define FLASH_TYPEPROGRAM_FAST_AND_LAST 0x02U              /*!< Fast program a 32 row double-word (64-bit) at a specified address.
                                                                And this is the last 32 row double-word (64-bit) programmed */




下面是我的代码
  1. u16 STMFLASH_ReadHalfWord(u32 faddr)
  2. {
  3.     return *(vu16 *)faddr;
  4. }
  5. #if STM32_FLASH_WREN // 如果使能了写
  6. // 不检查的写入
  7. // WriteAddr:起始地址
  8. // pBuffer:数据指针
  9. // NumToWrite:半字(16位)数
  10. // 以**半字(16位)**的形式写入数据。每次写入一个半字,然后地址增加2。这是因为一个半字包含1个16位的数据,所以地址需要增加2。
  11. // void STMFLASH_Write_NoCheck(u32 WriteAddr, u16 *pBuffer, u16 NumToWrite)
  12. // {
  13. //     u16 i;
  14. //     for (i = 0; i < NumToWrite; i++)
  15. //     {
  16. //         HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, WriteAddr, pBuffer);
  17. //         WriteAddr += 2; // 地址增加2.
  18. //     }
  19. // }
  20. // 以**双字(64位)**的形式写入数据。每次写入一个双字,然后地址增加4。这是因为一个双字包含4个16位的数据,所以地址需要增加4。
  21. void STMFLASH_Write_NoCheck(u32 WriteAddr, u16 *pBuffer, u16 NumToWrite)
  22. {
  23.     u16 i;
  24.     u32 buffer;
  25.     for (i = 0; i < NumToWrite; i += 2)
  26.     {
  27.         buffer = ((u32)pBuffer) | ((u32)pBuffer[i + 1] << 16);
  28.         HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, WriteAddr, buffer);
  29.         WriteAddr += 4; // 地址增加4.
  30.     }
  31. }
  32. // 从指定地址开始写入指定长度的数据
  33. // WriteAddr:起始地址(此地址必须为2的倍数!!)
  34. // pBuffer:数据指针
  35. // NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
  36. #if STM32_FLASH_SIZE < 256
  37. #define STM_SECTOR_SIZE 1024 // 字节
  38. #else
  39. #define STM_SECTOR_SIZE 2048
  40. #endif
  41. u16 STMFLASH_BUF[STM_SECTOR_SIZE / 2]; // 最多是2K字节
  42. void STMFLASH_Write(u32 WriteAddr, u16 *pBuffer, u16 NumToWrite)
  43. {
  44.     u32 secpos;    // 扇区地址
  45.     u16 secoff;    // 扇区内偏移地址(16位字计算)
  46.     u16 secremain; // 扇区内剩余地址(16位字计算)
  47.     u16 i;
  48.     u32 offaddr; // 去掉0X08000000后的地址
  49.     if (WriteAddr < STM32_FLASH_BASE || (WriteAddr >= (STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE)))
  50.         return; // 非法地址
  51.     HAL_FLASH_Unlock();                       // 解锁
  52.     offaddr = WriteAddr - STM32_FLASH_BASE;   // 实际偏移地址.
  53.     secpos = offaddr / STM_SECTOR_SIZE;       // 扇区地址  0~127 for STM32F103RBT6
  54.     secoff = (offaddr % STM_SECTOR_SIZE) / 2; // 在扇区内的偏移(2个字节为基本单位.)
  55.     secremain = STM_SECTOR_SIZE / 2 - secoff; // 扇区剩余空间大小
  56.     if (NumToWrite <= secremain)
  57.         secremain = NumToWrite; // 不大于该扇区范围
  58.     while (1)
  59.     {
  60.         STMFLASH_Read(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE / 2); // 读出整个扇区的内容
  61.         for (i = 0; i < secremain; i++)                                                                // 校验数据
  62.         {
  63.             if (STMFLASH_BUF[secoff + i] != 0XFFFF)
  64.                 break; // 需要擦除
  65.         }
  66.         if (i < secremain) // 需要擦除
  67.         {
  68.             FLASH_PageErase(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, FLASH_BANK_1); // 擦除这个扇区
  69.             FLASH_WaitForLastOperation(FLASH_WAITETIME);                                // 等待上次操作完成
  70.             CLEAR_BIT(FLASH->CR, FLASH_CR_PER);                                         // 清除CR寄存器的PER位,此操作应该在FLASH_PageErase()中完成!
  71.                                                                                         // 但是HAL库里面并没有做,应该是HAL库bug!
  72.             for (i = 0; i < secremain; i++)                                             // 复制
  73.             {
  74.                 STMFLASH_BUF[i + secoff] = pBuffer;
  75.             }
  76.             STMFLASH_Write_NoCheck(secpos * STM_SECTOR_SIZE + STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE / 2); // 写入整个扇区
  77.         }
  78.         else
  79.         {
  80.             FLASH_WaitForLastOperation(FLASH_WAITETIME);           // 等待上次操作完成
  81.             STMFLASH_Write_NoCheck(WriteAddr, pBuffer, secremain); // 写已经擦除了的,直接写入扇区剩余区间.
  82.         }
  83.         if (NumToWrite == secremain)
  84.             break; // 写入结束了
  85.         else       // 写入未结束
  86.         {
  87.             secpos++;                   // 扇区地址增1
  88.             secoff = 0;                 // 偏移位置为0
  89.             pBuffer += secremain;       // 指针偏移
  90.             WriteAddr += secremain * 2; // 写地址偏移(16位数据地址,需要*2)
  91.             NumToWrite -= secremain;    // 字节(16位)数递减
  92.             if (NumToWrite > (STM_SECTOR_SIZE / 2))
  93.                 secremain = STM_SECTOR_SIZE / 2; // 下一个扇区还是写不完
  94.             else
  95.                 secremain = NumToWrite; // 下一个扇区可以写完了
  96.         }
  97.     };
  98.     HAL_FLASH_Lock(); // 上锁
  99. }
  100. #endif
  101. // 从指定地址开始读出指定长度的数据
  102. // ReadAddr:起始地址
  103. // pBuffer:数据指针
  104. // NumToWrite:半字(16位)数
  105. void STMFLASH_Read(u32 ReadAddr, u16 *pBuffer, u16 NumToRead)
  106. {
  107.     u16 i;
  108.     for (i = 0; i < NumToRead; i++)
  109.     {
  110.         pBuffer = STMFLASH_ReadHalfWord(ReadAddr); // 读取2个字节.
  111.         ReadAddr += 2;                                // 偏移2个字节.
  112.     }
  113. }
复制代码
其中函数STMFLASH_Write_NoCheck被注释的是正点原子的代码,下面是我修改的,现在的问题就是,我测试的时候在地址0X08070000上写入"STM32F103 FLASH TEST",但是读出来的只有STM3,后面的内容都没有了,这是什么问题?求大佬解答

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 19:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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