158 lines
4.2 KiB
C
158 lines
4.2 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* IAR Development Kits
|
||
* on the
|
||
*
|
||
* M451
|
||
*
|
||
* Filename : fmc_flash.h
|
||
* Version : V1.00
|
||
* Programmer(s) : Qian Xianghong
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INCLUDE FILES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#include "includes.h"
|
||
|
||
// 读Flash全局缓冲
|
||
uint8_t Flash_rdBuf[FLASH_ERASE_SIZE];
|
||
// 写Flash缓冲
|
||
uint8_t Flash_wtBuf[FLASH_ERASE_SIZE];
|
||
|
||
// 将地址按4字节对齐
|
||
#define ALIGN_DWORD_SIZE(addr) ((addr) & 0xFFFFFFFCul)
|
||
// 将地址按FLASH_ERASE_SIZE字节对齐
|
||
#define ALIGN_PAGE_SIZE(addr) ((addr) & 0xFFFFF800ul)
|
||
|
||
static uint32_t GetPage(uint32_t Addr)
|
||
{
|
||
uint32_t page = 0;
|
||
|
||
if (Addr < (FLASH_BASE + FLASH_BANK_SIZE))
|
||
{
|
||
/* Bank 1 */
|
||
page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;
|
||
}
|
||
else
|
||
{
|
||
/* Bank 2 */
|
||
page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
|
||
}
|
||
|
||
return page;
|
||
}
|
||
|
||
// 校验flash内容
|
||
uint8_t Flash_BufferVerify(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
// 将地址按4字节对齐
|
||
uint32_t Addr4Start = ALIGN_DWORD_SIZE(Addr);
|
||
uint32_t Addr4End = ALIGN_DWORD_SIZE(Addr + nbytes + 3);
|
||
uint32_t u32Data, i, j = 0;
|
||
|
||
for(i = Addr4Start; i < Addr4End; i += 4)
|
||
{
|
||
u32Data = *(__IO uint32_t *)(i);
|
||
if(i >= Addr && i < Addr + nbytes && buf[j++] != (u32Data & 0xFF))
|
||
return 0;
|
||
if(i + 1 >= Addr && i + 1 < Addr + nbytes && buf[j++] != ((u32Data >> 8) & 0xFF))
|
||
return 0;
|
||
if(i + 2 >= Addr && i + 2 < Addr + nbytes && buf[j++] != ((u32Data >> 16) & 0xFF))
|
||
return 0;
|
||
if(i + 3 >= Addr && i + 3 < Addr + nbytes && buf[j++] != (u32Data >> 24))
|
||
return 0;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
// 将flash内容读入缓冲区
|
||
void Flash_BufferRead(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
// 将地址按4字节对齐
|
||
uint32_t Addr4Start = ALIGN_DWORD_SIZE(Addr);
|
||
uint32_t Addr4End = ALIGN_DWORD_SIZE(Addr + nbytes + 3);
|
||
uint32_t u32Data, i, j = 0;
|
||
|
||
for(i = Addr4Start; i < Addr4End; i += 4)
|
||
{
|
||
u32Data = *(__IO uint32_t *)(i);
|
||
|
||
if(i >= Addr && i < Addr + nbytes)
|
||
buf[j++] = (u32Data & 0xFF);
|
||
if(i + 1 >= Addr && i + 1 < Addr + nbytes)
|
||
buf[j++] = ((u32Data >> 8) & 0xFF);
|
||
if(i + 2 >= Addr && i + 2 < Addr + nbytes)
|
||
buf[j++] = ((u32Data >> 16) & 0xFF);
|
||
if(i + 3 >= Addr && i + 3 < Addr + nbytes)
|
||
buf[j++] = (u32Data >> 24);
|
||
}
|
||
}
|
||
|
||
// 擦除一页
|
||
void Flash_ErasePage(uint32_t Addr)
|
||
{
|
||
static FLASH_EraseInitTypeDef EraseInitStruct;
|
||
uint32_t PAGEError = 0;
|
||
|
||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
||
EraseInitStruct.Banks = FLASH_BANK_1;
|
||
EraseInitStruct.Page = GetPage(ALIGN_PAGE_SIZE(Addr));
|
||
EraseInitStruct.NbPages = 1;
|
||
HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
|
||
}
|
||
|
||
// 写入一页,Addr为页首地址
|
||
void Flash_PageWrite(uint32_t Addr, uint8_t *buf)
|
||
{
|
||
unsigned long long *buf64 = (unsigned long long *) buf;
|
||
uint32_t i = Addr;
|
||
|
||
while(i < Addr + FLASH_ERASE_SIZE)
|
||
{
|
||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, i, *buf64++);
|
||
i += 8;
|
||
}
|
||
}
|
||
|
||
void Flash_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
|
||
{
|
||
uint32_t count, offset;
|
||
|
||
while(nbytes > 0)
|
||
{
|
||
// 计算页内偏移(只有第一页有可能非0)
|
||
offset = Addr % FLASH_ERASE_SIZE;
|
||
|
||
// 计算一页内写入字节数
|
||
count = FLASH_ERASE_SIZE - offset;
|
||
if(count > nbytes)
|
||
count = nbytes;
|
||
|
||
// 页对齐
|
||
Addr = ALIGN_PAGE_SIZE(Addr);
|
||
// 读本页内数据
|
||
Flash_BufferRead(Addr, Flash_wtBuf, FLASH_ERASE_SIZE);
|
||
// 如果数据一致,不用写
|
||
if(memcmp(Flash_wtBuf + offset, buf, count) != 0)
|
||
{
|
||
// 擦除本页
|
||
Flash_ErasePage(Addr);
|
||
// 修改数据
|
||
memcpy(Flash_wtBuf + offset, buf, count);
|
||
// 写入本页数据
|
||
Flash_PageWrite(Addr, Flash_wtBuf);
|
||
}
|
||
|
||
// 计算下一页
|
||
Addr += FLASH_ERASE_SIZE;
|
||
buf += count;
|
||
nbytes -= count;
|
||
}
|
||
}
|