GeekIMU/2.Firmware/STM32/Firmware/driver/stmflash.c

138 lines
5.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/******************** (C) COPYRIGHT 2020 GEEKIMU *******************************
* File Name : stmflash.c
* Current Version : V2.0 & ST 3.5.0
* Author : zhanli 719901725@qq.com & JustFeng.
* Date of Issued : 2017.1.11 zhanli : Create
* Comments : STM32 模拟Flash驱动
********************************************************************************/
#include "stmflash.h"
#include "delay.h"
#include "usart.h"
#include "stm32f10x_flash.h"
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //字节
#else
#define STM_SECTOR_SIZE 2048
#endif
uint16_t STMFLASH_BUF[STM_SECTOR_SIZE / 2];//最多是2K字节
/**----------------------------------------------------------------------
* Function : STMFLASH_ReadHalfWord
* Description : 读取指定地址的半字(16位数据)
* Input : faddr:读地址(此地址必须为2的倍数)
* Output : 对应16位数据
* Author : zhanli&719901725@qq.com & JustFeng.
* Date : 2015/10/3 zhanli
*---------------------------------------------------------------------**/
uint16_t STMFLASH_ReadHalfWord(uint32_t faddr)
{
return *(uint16_t*)faddr;
}
/**----------------------------------------------------------------------
* Function : STMFLASH_Write_NoCheck
* Description : 不检查的写入
* Input : WriteAddr : 起始地址
pBuffer : 数据指针
NumToWrite : 半字(16位)数
* Output : 对应16位数据
* Author : zhanli&719901725@qq.com & JustFeng.
* Date : 2015/10/3 zhanli
*---------------------------------------------------------------------**/
void STMFLASH_Write_NoCheck(uint32_t WriteAddr,uint16_t *pBuffer,
uint16_t NumToWrite)
{
uint16_t i;
for(i = 0;i < NumToWrite;i++)
{
FLASH_ProgramHalfWord(WriteAddr, pBuffer[i]);
// 地址增加2.
WriteAddr += 2;
}
}
/**----------------------------------------------------------------------
* Function : STMFLASH_Write
* Description : 初始化追踪器的所有校准数据
* Input : 从指定地址开始写入指定长度的数据
WriteAddr:起始地址(此地址必须为2的倍数)
pBuffer:数据指针
从指定地址开始写入指定长度的数据
* Author : zhanli&719901725@qq.com & JustFeng.
* Date : 2015/2/13 zhanli
*---------------------------------------------------------------------**/
void STMFLASH_Write(uint32_t WriteAddr,uint16_t *pBuffer,uint16_t NumToWrite)
{
uint32_t secpos; //扇区地址
uint16_t secoff; //扇区内偏移地址(16位字计算)
uint16_t secremain; //扇区内剩余地址(16位字计算)
uint16_t i;
uint32_t offaddr; //去掉0X08000000后的地址
if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
FLASH_Unlock(); // 解锁
offaddr=WriteAddr-STM32_FLASH_BASE; // 实际偏移地址.
secpos=offaddr/STM_SECTOR_SIZE; // 扇区地址 0~127 for STM32F103RBT6
secoff=(offaddr%STM_SECTOR_SIZE)/2; // 在扇区内的偏移(2个字节为基本单位.)
secremain=STM_SECTOR_SIZE/2-secoff; // 扇区剩余空间大小
if(NumToWrite<=secremain)secremain=NumToWrite; // 不大于该扇区范围
while(1){
// 读出整个扇区的内容
STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
// 校验数据
for(i = 0;i < secremain; i++){
if(STMFLASH_BUF[secoff+i] != 0XFFFF)break;//需要擦除
}
// 需要擦除
if(i < secremain){
// 擦除这个扇区
FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);
// 复制
for(i = 0;i < secremain; i++){
STMFLASH_BUF[i+secoff]=pBuffer[i];
}
// 写入整个扇区
STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);
}else{
// 写已经擦除了的,直接写入扇区剩余区间.
STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);
}
if(NumToWrite == secremain)break;//写入结束了
else//写入未结束
{
secpos++; //扇区地址增1
secoff = 0; //偏移位置为0
pBuffer += secremain; //指针偏移
WriteAddr += secremain; //写地址偏移
NumToWrite -= secremain; //字节(16位)数递减
if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2; //下一个扇区还是写不完
else secremain = NumToWrite; //下一个扇区可以写完了
}
};
FLASH_Lock();//上锁
}
/**----------------------------------------------------------------------
* Function : STMFLASH_Read
* Description : 从指定地址开始读出指定长度的数据
ReadAddr起始地址
pBuffer : 数据指针
NumToWrite半字数
* Author : zhanli&719901725@qq.com & JustFeng.
* Date : 2015/2/13 zhanli
*---------------------------------------------------------------------**/
void STMFLASH_Read(uint32_t ReadAddr,uint16_t *pBuffer,uint16_t NumToRead)
{
uint16_t i;
for(i = 0;i < NumToRead; i++){
// 读取2个字节.
pBuffer[i] = STMFLASH_ReadHalfWord(ReadAddr);
// 读取地址偏移2个字节.
ReadAddr += 2;
}
}