/******************** (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+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; } }