ShipCentralControl/Loader_DTU/User/fmc_flash.c

249 lines
7.4 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];
// 将地址按4字节对齐
#define ALIGN_DWORD_SIZE(addr) ((addr) & 0xFFFFFFFCul)
/* Base address of the Flash sectors */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base address of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base address of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base address of Sector10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base address of Sector11, 128 Kbytes */
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base address of Sector12, 128 Kbytes */
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08120000) /* Base address of Sector13, 128 Kbytes */
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08140000) /* Base address of Sector14, 128 Kbytes */
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x08160000) /* Base address of Sector15, 128 Kbytes */
/**
* @brief Gets the sector of a given address
* @param None
* @retval The sector of a given address
*/
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_SECTOR_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_SECTOR_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_SECTOR_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_SECTOR_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_SECTOR_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_SECTOR_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_SECTOR_6;
}
else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_7) */
{
sector = FLASH_SECTOR_7;
}
return sector;
}
/**
* @brief Gets sector Size
* @param None
* @retval The size of a given sector
*/
static uint32_t GetSectorSize(uint32_t Sector)
{
uint32_t sectorsize = 0x00;
if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) || (Sector == FLASH_SECTOR_3))
{
sectorsize = 16 * 1024;
}
else if(Sector == FLASH_SECTOR_4)
{
sectorsize = 64 * 1024;
}
else
{
sectorsize = 128 * 1024;
}
return sectorsize;
}
/**
* @brief Gets sector start Address
* @param None
* @retval The start address of a given sector
*/
static uint32_t GetSectorAddr(uint32_t Sector)
{
uint32_t sectoraddr = 0x00;
if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) || (Sector == FLASH_SECTOR_3))
{
sectoraddr = ADDR_FLASH_SECTOR_0 + 16 * 1024 * (Sector - FLASH_SECTOR_0);
}
else if(Sector == FLASH_SECTOR_4)
{
sectoraddr = ADDR_FLASH_SECTOR_0 + 64 * 1024;
}
else
{
sectoraddr = ADDR_FLASH_SECTOR_0 + 128 * 1024 * (Sector - FLASH_SECTOR_5);
}
return sectoraddr;
}
// 校验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_EraseSector(uint32_t Addr)
{
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t PAGEError = 0;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = GetSector(Addr);
EraseInitStruct.NbSectors = 1;
HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
}
// 写入一页Addr为首地址
void Flash_SectorWrite(uint32_t Addr, uint8_t *buf, uint32_t count)
{
unsigned long *buf32 = (unsigned long *) buf;
uint32_t i = 0;
while(i < count)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Addr + i, *buf32++);
i += 4;
}
}
void Flash_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes)
{
uint32_t count, offset;
uint32_t sector, sectorSize, sectorAddr;
// 第1页Bootloader不允许擦除
static uint8_t sectorErased[16] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
while(nbytes > 0)
{
sector = GetSector(Addr);
sectorSize = GetSectorSize(sector);
sectorAddr = GetSectorAddr(sector);
// 计算页内偏移只有第一页有可能非0
offset = Addr - sectorAddr;
// 计算一页内写入字节数
count = sectorSize - offset;
if(count > nbytes)
count = nbytes;
// 如果第一次写入某个扇区,则擦除
if(!sectorErased[sector])
{
// 擦除本页
Flash_EraseSector(Addr);
sectorErased[sector] = 1;
}
// 写入本页数据
Flash_SectorWrite(Addr, buf, count);
// 计算下一页
Addr += count;
buf += count;
nbytes -= count;
}
}