赞
踩
## 驱动代码
#ifndef STM32F103VET6_PROJECT_BSP_FLASH_H #define STM32F103VET6_PROJECT_BSP_FLASH_H #include "sys.h" //FLASH起始地址 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define STM32_FLASH_BASE 0x08000000 //STM32 FLASH的起始地址 #define STM32_FLASH_END 0x0807FFFFUL #define FLASH_WAITETIME 50000 //FLASH等待超时时间 //FLASH 扇区的起始地址 #define ADDR_FLASH_SECTOR_0 ((u32)0x08000000) //扇区0起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_1 ((u32)0x08004000) //扇区1起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_2 ((u32)0x08008000) //扇区2起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_3 ((u32)0x0800C000) //扇区3起始地址, 16 Kbytes #define ADDR_FLASH_SECTOR_4 ((u32)0x08010000) //扇区4起始地址, 64 Kbytes #define ADDR_FLASH_SECTOR_5 ((u32)0x08020000) //扇区5起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_6 ((u32)0x08040000) //扇区6起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_7 ((u32)0x08060000) //扇区7起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_8 ((u32)0x08080000) //扇区8起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_9 ((u32)0x080A0000) //扇区9起始地址, 128 Kbytes #define ADDR_FLASH_SECTOR_10 ((u32)0x080C0000) //扇区10起始地址,128 Kbytes #define ADDR_FLASH_SECTOR_11 ((u32)0x080E0000) //扇区11起始地址,128 Kbytes typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; typedef int8_t s8; typedef int16_t s16; typedef int32_t s32; typedef volatile uint32_t vu32; typedef volatile uint16_t vu16; typedef volatile uint8_t vu8; u32 STMFLASH_ReadBase(u32 Address, void *Buffer, u32 Size); bool STMFLASH_WriteBase(u32 TypeProgram, u32 WriteAddr, void *pBuffer, u16 byteNum); bool STMFLASH_Write_u8(u32 WriteAddr, u8 *pBuffer, u16 Size); bool STMFLASH_Write_u16(u32 WriteAddr, u16 *pBuffer, u16 Size); bool STMFLASH_Write_u32(u32 WriteAddr, u32 *pBuffer, u16 Size); bool STMFLASH_Write_u64(u32 WriteAddr, u64 *pBuffer, u16 Size); #endif //STM32F103VET6_PROJECT_BSP_FLASH_H
#include "bsp_flash.h" static HAL_StatusTypeDef p_Status; //读取指定地址的字(32位数据) //faddr:读地址 //返回值:对应数据. u32 STM32_FLASH_ReadWord(u32 faddr) { return *(vu32 *) faddr; } //获取某个地址所在的flash扇区 //addr:flash地址 //返回值:0~11,即addr所在的扇区 u8 STM32_FLASH_GetFlashSector(u32 addr) { if (addr < ADDR_FLASH_SECTOR_1)return FLASH_SECTOR_0; else if (addr < ADDR_FLASH_SECTOR_2)return FLASH_SECTOR_1; else if (addr < ADDR_FLASH_SECTOR_3)return FLASH_SECTOR_2; else if (addr < ADDR_FLASH_SECTOR_4)return FLASH_SECTOR_3; else if (addr < ADDR_FLASH_SECTOR_5)return FLASH_SECTOR_4; else if (addr < ADDR_FLASH_SECTOR_6)return FLASH_SECTOR_5; else if (addr < ADDR_FLASH_SECTOR_7)return FLASH_SECTOR_6; else if (addr < ADDR_FLASH_SECTOR_8)return FLASH_SECTOR_7; else if (addr < ADDR_FLASH_SECTOR_9)return FLASH_SECTOR_8; else if (addr < ADDR_FLASH_SECTOR_10)return FLASH_SECTOR_9; else if (addr < ADDR_FLASH_SECTOR_11)return FLASH_SECTOR_10; return FLASH_SECTOR_11; } /** * 获取地址递增数 * @param TypeProgram * @return */ static inline u8 GetIncreasingCnt(uint32_t TypeProgram) { switch (TypeProgram) { case FLASH_TYPEPROGRAM_BYTE: return 1; case FLASH_TYPEPROGRAM_HALFWORD: return 3; case FLASH_TYPEPROGRAM_WORD: return 4; default: return 8; } } /********************************************************************************** * 函数功能:不检查的写入 * 输入参数: WriteAddr:起始地址、pBuffer:数据指针、NumToWrite:半字(16位)数 * 返 回 值: 无 * 说 明: */ HAL_StatusTypeDef write_no_check(uint32_t TypeProgram, uint32_t WriteAddr, void *pBuffer, uint16_t NumToWrite) { uint8_t cnt = GetIncreasingCnt(TypeProgram); for (uint16_t i = 0; i < NumToWrite; i++) { switch (TypeProgram) { case FLASH_TYPEPROGRAM_BYTE: p_Status = HAL_FLASH_Program(TypeProgram, WriteAddr, ((u8 *) pBuffer)[i]); break; case FLASH_TYPEPROGRAM_HALFWORD: p_Status = HAL_FLASH_Program(TypeProgram, WriteAddr, ((u16 *) pBuffer)[i]); break; case FLASH_TYPEPROGRAM_WORD: p_Status = HAL_FLASH_Program(TypeProgram, WriteAddr, ((u32 *) pBuffer)[i]); break; default: p_Status = HAL_FLASH_Program(TypeProgram, WriteAddr, ((u64 *) pBuffer)[i]); break; } if (p_Status != HAL_OK) { return p_Status; } WriteAddr += cnt; //地址增加cnt. } return HAL_OK; } /** * 读FLASH * @param Address 地址 * @param Buffer 存放读取的数据 * @param Size 要读取的数据大小,单位字节 * @return 读出成功的字节数 */ u32 STMFLASH_ReadBase(u32 Address, void *Buffer, u32 Size) { u32 nread = Size; vu8 *d = (vu8 *) Buffer; const vu8 *s = (const vu8 *) Address; if (!Buffer || Address < STM32_FLASH_BASE || Address >= STM32_FLASH_END) return 0; while (nread >= sizeof(uint32_t) && (((uint32_t) s) <= (STM32_FLASH_END - 4))) { *(vu32 *) d = *(vu32 *) s; d += sizeof(uint32_t); s += sizeof(uint32_t); nread -= sizeof(uint32_t); } while (nread && (((vu32) s) < STM32_FLASH_END)) { *d++ = *s++; nread--; } return Size - nread; } //从指定地址开始写入指定长度的数据 //特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数 // 写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以 // 写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里 // 没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写. //该函数对OTP区域也有效!可以用来写OTP区! //OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(注意:最后16字节,用于OTP数据块锁定,别乱写!!) bool STMFLASH_WriteBase(u32 TypeProgram, u32 WriteAddr, void *pBuffer, u16 byteNum) { FLASH_EraseInitTypeDef FlashEraseInit; HAL_StatusTypeDef FlashStatus; u32 SectorError = 0; u32 addrx = 0; u32 endAddr = 0; if (WriteAddr < STM32_FLASH_BASE || WriteAddr % 4)return false; //非法地址 HAL_FLASH_Unlock(); //解锁 addrx = WriteAddr; //写入的起始地址 endAddr = WriteAddr + byteNum; //写入的结束地址 if (addrx < 0X1FFF0000) { uint8_t cnt = GetIncreasingCnt(TypeProgram); while (addrx < endAddr) //扫清一切障碍.(对非FFFFFFFF的地方,先擦除) { if (STM32_FLASH_ReadWord(addrx) != 0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区 { FlashEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; //擦除类型,扇区擦除 FlashEraseInit.Sector = STM32_FLASH_GetFlashSector(addrx); //要擦除的扇区 FlashEraseInit.NbSectors = 1; //一次只擦除一个扇区 FlashEraseInit.VoltageRange = FLASH_VOLTAGE_RANGE_3; //电压范围,VCC=2.7~3.6V之间!! if (HAL_FLASHEx_Erase(&FlashEraseInit, &SectorError) != HAL_OK) { break;//发生错误了 } } else addrx += cnt; FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成 } } FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成 if (FlashStatus == HAL_OK) { FlashStatus = write_no_check(TypeProgram, WriteAddr, pBuffer, byteNum); } HAL_FLASH_Lock(); //上锁 return FlashStatus == HAL_OK; } bool STMFLASH_Write_u8(u32 WriteAddr, u8 *pBuffer, u16 Size) { return STMFLASH_WriteBase(FLASH_TYPEPROGRAM_BYTE, WriteAddr, pBuffer, Size); } bool STMFLASH_Write_u16(u32 WriteAddr, u16 *pBuffer, u16 Size) { return STMFLASH_WriteBase(FLASH_TYPEPROGRAM_HALFWORD, WriteAddr, pBuffer, Size); } bool STMFLASH_Write_u32(u32 WriteAddr, u32 *pBuffer, u16 Size) { return STMFLASH_WriteBase(FLASH_TYPEPROGRAM_WORD, WriteAddr, pBuffer, Size); } bool STMFLASH_Write_u64(u32 WriteAddr, u64 *pBuffer, u16 Size) { return STMFLASH_WriteBase(FLASH_TYPEPROGRAM_DOUBLEWORD, WriteAddr, pBuffer, Size); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。