STM32_WGY/User/fmc_flash.c

168 lines
4.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* 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;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
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);
HAL_FLASH_Lock();
}
// 写入一页Addr为页首地址
void Flash_PageWrite(uint32_t Addr, uint8_t *buf)
{
unsigned long long *buf64 = (unsigned long long *) buf;
uint32_t i = Addr;
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
while(i < Addr + FLASH_ERASE_SIZE)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, i, *buf64++);
i += 8;
}
HAL_FLASH_Lock();
}
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;
}
}