【飞思卡尔 MC9S12】内部D-Flash模拟EEPROM
上一篇讲到内部Flash的读写,本篇讲述使用D-Flash模拟EEPROM。其实使用P-Flash也可以模拟,只不过D-Flash的Page更小(擦除复写占用更少时间),而且不会占用代码空间。
最近刚换工作,一直比较忙,更新会比较慢。若是需要源码可自行下载:https://download.csdn.net/download/u010875635/11435913
没有积分可以自己新建工程,下面的代码基本可以直接使用。
本篇关于Flash读写就不在赘述,跟PFlash除了Sector大小和指令不同,其余一致,后面直接贴出代码。
模拟EEPROM其实就是模拟其单字节读写功能,原理就是要修改某个Sector内某个字节的数据时,先读出这个扇区内所有数据(256Bytes)到数组,然后擦除这个Sector,再在RAM中修改那个字节的数据,最后将这个数组写回该扇区。修改多字节数据原理相似。
另外大家可以想一下,若是要往EEPROM中写入跨Sector的数组怎么办?(需要判断数组地址范围)
使用范例:
main.c
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include "Typedefs.h"
#include "gpio.h"
#include "System.h"
#include "flash.h"
#include "EmulationEEPROM.h"
UINT32 m_maincount=0;
void main(void)
{
/* put your own code here */
int result;
UINT32 index = 0;
UINT32 globalDFlashAddr1 = 0x100000,globalDFlashAddr2 = 0x100002,globalDFlashAddr3=0x13F800;
UINT32 globalAddr1 = 0x7F4000,globalAddr2 = 0x7F4002,globalAddr3=0x7db460;
UINT8 datas1[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
UINT8 datas2[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
UINT8 readDatas[100];
McuDrivers_System_Init();
McuDrivers_GPIO_Init();
EnableInterrupts;
//for(index = 0;index<129;index++)
// HDL_Flash_PFlash_ProgramMultiSectors(globalAddr2+index*8,datas,sizeof(datas));
//HDL_Flash_PFlash_EraseOneSector(0x7F4000);
// HDL_Flash_PFlash_EraseMultiSectors(globalAddr2,globalAddr2+1001);
//IFsh1_EraseSector(globalAddr2);
//HDL_Flash_PFlash_ProgramMultiSectors(globalAddr1,datas,sizeof(datas));
//HDL_Flash_PFlash_ProgramMultiSectors(globalAddr3,datas2,sizeof(datas2));
//HDL_Flash_DFlash_EraseMultiSectors(globalDFlashAddr1,globalDFlashAddr1+1000);
//for(index = 0;index<33;index++)
// HDL_Flash_DFlash_ProgramMultiSectors(globalDFlashAddr1+index*16,datas1,sizeof(datas1));
//HDL_Flash_DFlash_EraseMultiSectors(globalDFlashAddr1,globalDFlashAddr1+1000);
//HDL_Flash_DFlash_ProgramMultiSectors(globalDFlashAddr2,datas1,sizeof(datas1));
result = HAL_EEE_ChangeValue(globalDFlashAddr1,datas1,sizeof(datas1));
result = HAL_EEE_ChangeValue(globalDFlashAddr1+10,datas1,sizeof(datas1));
HAL_EEE_GetValue(globalDFlashAddr1,30,readDatas);
for(;;)
{
m_maincount++;
if(m_maincount>100000)
{
m_maincount = 0;
PORTB_PB0 ^=1;
}
_FEED_COP(); /* feeds the dog */
} /* loop forever */
/* please make sure that you never leave main */
}
EmulationEEPROM.h
#ifndef _HAL_EmulationEEPROM_H_
#define _HAL_EmulationEEPROM_H_
#include "Typedefs.h"
//get value
int HAL_EEE_GetValue(UINT32 startGlobalAddr, UINT8 newDataLength, UINT8 * pNewData);
//change value
int HAL_EEE_ChangeValue(UINT32 startGlobalAddr, UINT8 * pNewData,UINT8 newDataLength);
#endif
EmulationEEPROM.c
#include "EmulationEEPROM.h"
#include "flash.h"
#define DFLASH_SECTOR_ADDR_MASK 0xFFFFFF00 //256 bytes
#define DFLASH_SECTOR_SIZE 256U
#define PROGRAM_DFlash_Phrase_SIZE 8U
#define PROGRAM_DFlash_Phrase_MASK 0xFFFFFFF8
//get value
int HAL_EEE_GetValue(UINT32 startGlobalAddr, UINT8 newDataLength, UINT8 * pNewData)
{
UINT16 i;
UINT8 *far readTmpData;
//读取DFlash中内容
for(i=0;i<newDataLength;i++)
{
readTmpData = (UINT8 *far)(startGlobalAddr+i);
pNewData[i] = (*readTmpData);
}
}
//change value
int HAL_EEE_ChangeValue(UINT32 startGlobalAddr, UINT8 * pNewData,UINT8 newDataLength)
{
UINT32 sectorStartAddr = startGlobalAddr&DFLASH_SECTOR_ADDR_MASK;
UINT8 dataContainer[DFLASH_SECTOR_SIZE]={0};
UINT16 *far readTmpData;
UINT16 i;
volatile int result = 0;
//读取DFlash中此扇区内容
for(i=0;i<DFLASH_SECTOR_SIZE;i+=2)
{
readTmpData = (UINT16 *far)(sectorStartAddr+i);
dataContainer[i] = ((*readTmpData)>>8)&0xFF; //高位在前
dataContainer[i+1] = (*readTmpData)&0xFF;
}
//更新要写入的内容
for(i=startGlobalAddr-sectorStartAddr;i<startGlobalAddr-sectorStartAddr+newDataLength;i++)
dataContainer[i] = pNewData[i-startGlobalAddr+sectorStartAddr];
result = HDL_Flash_DFlash_EraseMultiSectors(sectorStartAddr,sectorStartAddr);
result = HDL_Flash_DFlash_ProgramMultiSectors(sectorStartAddr,dataContainer,DFLASH_SECTOR_SIZE);
return result;
}
flash.h
#ifndef _HDL_FLASH_H_
#define _HDL_FLASH_H_
#define FLASH_BOOT_SEQUENCE_ERROR (-2)
#define FLASH_ADDRESS_ERROR (-3)
#define FLASH_ERASE_ERROR (-4)
#define FLASH_PROGRAM_ERROR (-5)
#define FLASH_VERIFICATION_ERROR (-6)
#define FLASH_DATALENGTH_ERROR (-8)
#define FLASH_NOTAVAIL_ERROR (-9)
#define FLASH_PROTECTED_ERROR (-10)
#define FLASH_MGSTAT_ERROR (-11)
#define FLASH_BUSY_ERROR (-12)
#define FLASH_SUCCESS (1)
//erase multiple sector
int HDL_Flash_DFlash_EraseMultiSectors(UINT32 startGlobalAddr, UINT32 endGlobalAddr);
//program multiple phrases
int HDL_Flash_DFlash_ProgramMultiSectors(UINT32 globalAddr, UINT8 * pData,UINT16 dataLength);
//erase multiple sector
int HDL_Flash_PFlash_EraseMultiSectors(UINT32 startGlobalAddr, UINT32 endGlobalAddr);
//program multiple phrases
int HDL_Flash_PFlash_ProgramMultiSectors(UINT32 globalAddr, UINT8 * pData,UINT16 dataLength);
#endif
flash.c
#include <hidef.h> /* common defines and macros */
#include "derivative.h" /* derivative-specific definitions */
#include "Typedefs.h"
#include "flash.h"
#include "string.h"
/*
默认情况下(ROMHM=0 RAMHM=0)Global Memory Map 如下:
0x000000-0x0007FF Registers 2KB
0x000800-0x000FFF 2K RAM , 扩展空间CS3
0x001000-0x0FDFFF 253*4K Paged RAM
0x0FE000-0x0FFFFF 8K RAM(2*4K)
0x100000-0x13FBFF 255*1K Paged EEPROM
0x100000-0x1003FF 1K (EPAGE 0x00)
……
0x103C00-0x103FFF 1K (EPAGE 0x1F)
---
0x13F000-0x13F3FF 1K (EPAGE 0xFC) --
0x13F400-0x13F7FF 1K (EPAGE 0xFD) | RAM Bufferd
0x13F800-0x13FBFF 1K (EPAGE 0xFE) |
0x13FC00-0x13FFFF 1K EEPROM(EPAGE 0xFF) --
0x140000-0x1FFFFF 扩展空间CS2
0x200000-0x3FFFFF 扩展空间CS1
0x400000-0x7F3FFF 253*16K Paged Flash, 扩展空间CS0
0x700000-0x73FFFF B3(256KB)
0x740000-0x77FFFF B2(256KB)
0x780000-0x79FFFF B1S(128KB)
0x7A0000-0x7BFFFF B1N(128KB)
0x7C0000-0x7F3FFF B0(208KB)
0x7F4000-0x7F7FFF 16KB Flash(PPAGE 0xFD)
0x7F4000-0x7F7FFF B0(16KB)
0x7F8000-0x7FBFFF 16KB Flash(PPAGE 0xFE)
0x7F8000-0x7FBFFF B0(16KB)
0x7FC000-0x7FFFFF 16KB Flash(PPAGE 0xFF)
0x7FC000-0x7FFFFF B0(16KB)
*/
/**** P-Flash and D-Flash Commands ****/
#define ERASE_VERIFY_ALL_BLOCKS 0x01
/* Verify that all program and data Flash blocks are erased. */
/* CCOBIX end = 0 */
/* CCOB Params - NONE */
/* MGSTAT set if fault */
#define ERASE_VERIFY_BLOCK 0x02
/* Verify that a Flash block is erased. */
/* CCOBIX end = 0 */
/* CCOB Params - gpage */
/* MGSTAT set if fault */
#define ERASE_ALL_BLOCKS 0x08
/* Erase all program and data Flash blocks.
An erase of all Flash blocks is only possible when the FPLDIS, FPHDIS, and FPOPEN
bits in the FPROT register and the EPDIS and EPOPEN bits in the EPROM register are
set prior to launching the command. */
/* CCOBIX end = 0 */
/* CCOB Params - NONE */
/* MGSTAT set if fault, FPVIOL / ACCERR set where appropriate */
#define UNSECURE_FLASH 0x0B
/*Supports a method of releasing MCU security by erasing all program and data Flash
blocks and verifying that all program and data Flash blocks are erased. */
/* CCOBIX end = 0 */
/* CCOB Params - NONE */
/* MGSTAT set if fault */
#define SET_USER_MARGIN_LEVEL 0x0D
/*Specifies a user margin read level for all program Flash blocks. */
/* CCOBIX end = 1 */
/* CCOB Params - gpage, level setting (0-2) in CCOB[1] */
/* ACCERR set if invalid level */
#define SET_FIELD_MARGIN_LEVEL 0x0E
/*Specifies a field margin read level for all program Flash blocks (special modes only). */
/* CCOBIX end = 1 */
/* CCOB Params - gpage, level setting (0-4) in CCOB[1] */
/* ACCERR set if invalid level */
/*-------------------------------*/
/* **** P-Flash Only Commands ****/
#define ERASE_VERIFY_P_FLASH_SECTION 0x03
/*Verify that a given number of words starting at the address provided are erased. */
/* CCOBIX end = 2 */
/* CCOB Params - global address, number of phrases in CCOB[2]*/
/* MGSTAT set if fault */
#define READ_ONCE 0x04
/* Read a phrase from a dedicated 64 word area in a hidden region of a programFlash block
that was previously programmed using the Program Once command. */
/* CCOBIX end = 1 */
/* CCOB Params - read once index (0-3) in CCOB[1], phrase in CCOB [5:2] */
/* returns phrase in CCOB [4:1] */
#define PROGRAM_P_FLASH 0x06
/* Program a phrase in a program Flash block and any previously loaded phrases for any
other program Flash block (see Load Data Field command). */
/* CCOBIX end = 5 */
/* CCOB Params - global address, phrase in CCOB [5:2] */
/* MGSTAT set if fault, FPVIOL / ACCERR set where appropriate */
#define PROGRAM_ONCE 0x07
/* Program a dedicated 64 word area in a hidden region of a program Flash block that is
allowed to be programmed only once. */
/* CCOBIX end = 5 */
/* CCOB Params - read once index (0-3) in CCOB[1], phrase in CCOB [5:2] */
/* MGSTAT set if fault */
#define ERASE_P_FLASH_BLOCK 0x09
/* Erase a program Flash block.
An erase of the full program Flash block is only possible when FPLDIS, FPHDIS and
FPOPEN bits in the FPROT register are set prior to launching the command. */
/* CCOBIX end = 1 */
/* CCOB Params - global address */
/* MGSTAT set if fault, FPVIOL / ACCERR set where appropriate */
#define ERASE_P_FLASH_SECTOR 0x0A
/* Erase all bytes in a program Flash sector. */
/* CCOBIX end = 1 */
/* CCOB Params - global address */
/* MGSTAT set if fault, FPVIOL / ACCERR set where appropriate */
#define VERIFY_BACKDOOR_ACCESS_KEY 0x0C
/*Supports a method of releasing MCU security by verifying a set of security keys. */
/* CCOBIX end = 4 */
/* CCOB Params - backdoor key in CCOB [1:4] */
/* ACCERR set if not verified */
/*-------------------------------*/
/**** D-Flash Only Commands ****/
#define ERASE_D_FLASH_BLOCK 0x09
/* Erase a program Flash block.
An erase of the full program Flash block is only possible when DPOPEN bit in the DFPROT
register is set prior to launching the command. */
/* CCOBIX end = 1 */
/* CCOB Params - global address */
/* MGSTAT set if fault, FPVIOL / ACCERR set where appropriate */
#define ERASE_VERIFY_D_FLASH_SECTION 0x10
/* Verify that a given number of words starting at the address provided are erased. */
/* CCOBIX end = 2 */
/* CCOB Params - global address of first word, number of words to verify CCOB[2]*/
/* MGSTAT set if fault */
#define PROGRAM_D_FLASH 0x11
/* Program up to four words in the data Flash block (see Load Data Field command). */
/* CCOBIX end = 2 */
/* CCOB Params - global address, up to 4 data words in CCOB [2:5] */
/* MGSTAT set if fault, EPVIOL / ACCERR set where appropriate */
#define ERASE_D_FLASH_SECTOR 0x12
/* Erase all bytes in a data Flash sector. */
/* CCOBIX end = 2 */
/* CCOB Params - global address */
/* MGSTAT set if fault, EPVIOL set where appropriate */
/*--------------------------------*/
#define ENABLE_EEPROM_EMULATION 0x13
// Requests the FTMSM to enable EEPROM emulation.
// CCOBIX end = 0
// CCOB Params - NONE
#define DISABLE_EEPROM_EMULATION 0x14
// Requests the FTMSM to suspend all current erase and program activity related to
// EEPROM emulation but leave current EEE tags set.
// CCOBIX end = 0
// CCOB Params - NONE
#define CANCEL_EEPROM_EMULATION 0x15 /* M22E mask only */
// Requests the FTMSM to suspend all current erase and program activity related to
// EEPROM emulation and clear all outstanding EEE tags.
// CCOBIX end = 0
// CCOB Params - NONE
#define EEPROM_QUERY 0x15 /* M48H mask only */
// Requests EEE status information.
// CCOBIX end = 0
// CCOB Return Params -
// CCOB[1] DFPART - size of D-Flash user partition (x256 bytes)
// CCOB[2] ERPART - size of EEE ram (x256 bytes)
// CCOB[3] ECOUNT - typical number of erase cycles for the EEE sectors
// CCOB[4] Dead sector count / Ready sector count
#define PARTITION_D_FLASH 0x20 /* M48H mask only */
// Partition a section of D-Flash for user access and EEE.
// CCOBIX end = 2
// CCOB Params - number of sectors for D-Flash in CCOB[1], number of sectors for EEE in CCOB[2]
// ACCERR set if fault
#define FULL_PARTITION_D_FLASH 0x0F
// Partition a section of D-Flash for user access and EEE.
// CCOBIX end = 2
// CCOB Params - number of sectors for D-Flash in CCOB[1], number of sectors for EEE in CCOB[2]
// ACCERR set if fault
#define DFLASH_SECTOR_ADDR_MASK 0xFFFFFF00 //256 bytes
#define DFLASH_SECTOR_SIZE 256U
#define PROGRAM_DFlash_Phrase_SIZE 8U
#define PROGRAM_DFlash_Phrase_MASK 0xFFFFFFF8
#define PFLASH_SECTOR_ADDR_MASK 0xFFFFFC00 //1024 bytes
#define PFLASH_SECTOR_SIZE 1024U
#define PROGRAM_PFlash_Phrase_SIZE 8U
#define PROGRAM_PFlash_Phrase_MASK 0xFFFFFFF8
#define TRANSFER_BUFFER_SIZE 1024U
#define ClearFlags() (FSTAT = 0x30U)
typedef struct
{
UINT8 flashCmd;
UINT32 globalAddr;
UINT8 Datas[PROGRAM_PFlash_Phrase_SIZE];
UINT8 dataLength;
}HDL_FLASH_SCM_FCCO_PARA;
/*the function run in ram,
clear CCIF, then wait CCIF to set
*/
/*use CALL for this function*/
//unsigned char HDL_Flash_Burn_And_WaitFinished[10]={0x1C,0x01,0x06,0x80,0x1F,0x01,0x06,0x80,0xFB,0x0A};
/*use JSR for this function*/
unsigned char HDL_Flash_Burn_And_WaitFinished[11]={0xC6,0x80,0x7B,0x01,0x06,0x1F,0x01,0x06,0x80,0xFB,0x3D};
//check the flash operating frequency and ccif and accerr and fpviol
void HDL_Flash_CheckRegisterBeforeOperate(void)
{
//check if the clock for flash is valid, for 16MHz OSC, the divider should be 0x0F, here is 8MHz
if(FCLKDIV_FDIVLD == 0)
{
#ifdef ON_DEVELOP_BOARD
FCLKDIV = 0x0F; //osc=16MHz
#else
FCLKDIV = 0x07; //osc=8MHz
#endif
}
//check and wait for an ongoing flash command
while(FSTAT_CCIF == 0)
{
_asm(nop);
}
//must clear ACCERR or FPVIOL bits before starting any command write sequence
if((FSTAT_ACCERR != 0)||(FSTAT_FPVIOL !=0))
{
FSTAT_ACCERR = 1;
FSTAT_FPVIOL = 1;
}
}
//return 0-busy, return 1=ok
int HDL_Flash_GetFlashState(void)
{
return FSTAT_CCIF;
}
/******************************** D Flash **********************************/
//check the address is whether the phrase start, 8bytes is a phrase
int HDL_DFlash_CheckAddressIsPhraseStart(UINT32 globalAddr)
{
int nRetval = FLASH_SUCCESS;
if(globalAddr%PROGRAM_DFlash_Phrase_SIZE != 0)
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//execute one flash command
int HDL_D_Flash_ExecOneFlashCmd(HDL_FLASH_SCM_FCCO_PARA* pFCCOpara)
{
UINT8 uIndex = FLASH_SUCCESS;
HDL_Flash_CheckRegisterBeforeOperate();
if (FSTAT_CCIF == 0U) /* Is command buffer full ? */
{
//ExitCritical(); /* Exit critical section */
return FLASH_BUSY_ERROR; /* If yes then error */
}
FCCOBIX = 0x00;
FCCOBHI = pFCCOpara->flashCmd;
FCCOBLO = (UINT)((pFCCOpara->globalAddr & 0x00130000) >> 16);
FCCOBIX = 0x01;
FCCOB = (UINT16)(pFCCOpara->globalAddr & 0x0000FFFF) ;
if(pFCCOpara->flashCmd==PROGRAM_D_FLASH)
{
for(uIndex = 0; uIndex < pFCCOpara->dataLength; uIndex++)
{
FCCOBIX = 0x02 + uIndex / 2;
FCCOBHI = * (pFCCOpara->Datas + uIndex);
FCCOBLO = * (pFCCOpara->Datas + uIndex + 1);
uIndex++;
}
}
DisableInterrupts;
//_asm("CALL HDL_Flash_Burn_And_WaitFinished");
_asm("JSR HDL_Flash_Burn_And_WaitFinished");
EnableInterrupts;
if (FSTAT_FPVIOL == 1U)
{ /* Is protection violation detected ? */
return FLASH_PROTECTED_ERROR; /* If yes then error */
}
if (FSTAT_ACCERR == 1U)
{ /* Is acces error detected ? */
return FLASH_NOTAVAIL_ERROR; /* If yes then error */
}
if (FSTAT_MGSTAT)
{ /* Was attempt to write data to the given address errorneous? */
return FLASH_MGSTAT_ERROR; /* If yes then error */
}
return FLASH_SUCCESS; /* Exit critical section */
}
//check the address is whether valid
int HDL_D_Flash_CheckAddressIsValid(UINT32 globalAddr)
{
int nRetval = FLASH_SUCCESS;
if(! (globalAddr >= 0x100000) && (globalAddr <= 0x13FBFF) )
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//erase one sector,1024bytes
int HDL_Flash_DFlash_EraseOneSector(UINT32 sectorAddr)
{
int nRetval = FLASH_SUCCESS;
HDL_FLASH_SCM_FCCO_PARA fccoPara;
if(HDL_D_Flash_CheckAddressIsValid(sectorAddr))
{
fccoPara.flashCmd = ERASE_D_FLASH_SECTOR;
fccoPara.globalAddr = sectorAddr&PROGRAM_DFlash_Phrase_MASK; //erase start address must be phrase start address
fccoPara.dataLength = 0;
nRetval = HDL_D_Flash_ExecOneFlashCmd(&fccoPara);
}
else
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//erase multiple sector
int HDL_Flash_DFlash_EraseMultiSectors(UINT32 startGlobalAddr, UINT32 endGlobalAddr)
{
int nRetval = FLASH_SUCCESS;
if(HDL_D_Flash_CheckAddressIsValid(startGlobalAddr) && HDL_D_Flash_CheckAddressIsValid(endGlobalAddr) && startGlobalAddr<=endGlobalAddr )
{
UINT32 addr = 0;
for(addr = startGlobalAddr; addr <= endGlobalAddr; addr+=DFLASH_SECTOR_SIZE)
{
nRetval = HDL_Flash_DFlash_EraseOneSector(addr);
if(nRetval!=FLASH_SUCCESS)
return nRetval;
}
}
else
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//program one phrase,8bytes
int HDL_Flash_DFlash_ProgramOneSector(UINT32 globalAddr, UINT8 * pData,UINT16 dataLength)
{
int nRetval = FLASH_SUCCESS;
HDL_FLASH_SCM_FCCO_PARA fccoPara;
if(dataLength!=PROGRAM_DFlash_Phrase_SIZE)
return FLASH_DATALENGTH_ERROR;
if(HDL_D_Flash_CheckAddressIsValid(globalAddr) && HDL_DFlash_CheckAddressIsPhraseStart(globalAddr))
{
fccoPara.flashCmd = PROGRAM_D_FLASH;
fccoPara.globalAddr = globalAddr;
fccoPara.dataLength = dataLength;
memcpy(fccoPara.Datas,pData,dataLength);
HDL_D_Flash_ExecOneFlashCmd(&fccoPara);
}
else
nRetval = FLASH_ADDRESS_ERROR;
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//program multiple phrases
int HDL_Flash_DFlash_ProgramMultiSectors(UINT32 globalAddr, UINT8 * pData, UINT16 dataLength)
{
int nRetval = FLASH_SUCCESS;
UINT32 addr = 0, offsetFromPhraseStartAddr = 0, endAddr = 0;
//UINT8 *dataInFlash=&addr;
UINT8 datas[8];
UINT32 phraseStarAddr = globalAddr&PROGRAM_DFlash_Phrase_MASK; //first phrase start address
if (!HDL_D_Flash_CheckAddressIsValid(globalAddr))
return FLASH_ADDRESS_ERROR;
/*************************************************
start
0 1 2 3 4 5 6 7 8 ..... 0 1 2 3 4 5 6 7 8
|offset|<- dataLength ->| no 8 left data
**************************************************/
//the offset of phrase start
offsetFromPhraseStartAddr = globalAddr - phraseStarAddr;
endAddr = globalAddr + dataLength-1;
//首组不对齐
if (offsetFromPhraseStartAddr != 0)
{
//first contain offset area,read offset area data from flash
for (addr = phraseStarAddr; addr<globalAddr; addr++)
{
//dataInFlash = (UINT8 *)addr; //get the maintain value
datas[addr - phraseStarAddr] = 0xff;//*dataInFlash; //0xFF;
}
//first contain offset fill the left with data
for (addr = globalAddr; addr<globalAddr+ PROGRAM_DFlash_Phrase_SIZE - offsetFromPhraseStartAddr; addr++)
datas[addr - phraseStarAddr] = pData[addr - globalAddr];
//program first one phrase
HDL_Flash_DFlash_ProgramOneSector(phraseStarAddr,datas, PROGRAM_DFlash_Phrase_SIZE);
//下一组要偏移一个Phrase
phraseStarAddr += PROGRAM_DFlash_Phrase_SIZE;
}
//other data
for (addr = phraseStarAddr ; addr <= endAddr + 1 - PROGRAM_DFlash_Phrase_SIZE; addr += PROGRAM_DFlash_Phrase_SIZE)
{
//program data
HDL_Flash_DFlash_ProgramOneSector(addr, &pData[addr - globalAddr], PROGRAM_DFlash_Phrase_SIZE);
}
//endaddr phrase start addr
phraseStarAddr = endAddr&PROGRAM_DFlash_Phrase_MASK; //last phrase start address
//endaddr is not the phrase last one
if (endAddr != (phraseStarAddr+ PROGRAM_DFlash_Phrase_SIZE-1))
{
//the last no 8 left data
for (addr = phraseStarAddr; addr <= endAddr; addr++)
datas[addr - phraseStarAddr] = pData[addr - globalAddr];
for (addr = endAddr + 1; addr<8+phraseStarAddr; addr++)
{
//dataInFlash = (UINT8 *)addr; //get the maintain value
datas[addr - phraseStarAddr] = 0xff;//*dataInFlash;//0xFF;
}
//program first one phrase
HDL_Flash_DFlash_ProgramOneSector(phraseStarAddr, datas, PROGRAM_DFlash_Phrase_SIZE);
}
return nRetval;
}
/******************************** P Flash **********************************/
//check the address is whether the phrase start, 8bytes is a phrase
int HDL_PFlash_CheckAddressIsPhraseStart(UINT32 globalAddr)
{
int nRetval = FLASH_SUCCESS;
if(globalAddr%PROGRAM_DFlash_Phrase_SIZE != 0)
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//execute one flash command
int HDL_P_Flash_ExecOneFlashCmd(HDL_FLASH_SCM_FCCO_PARA* pFCCOpara)
{
UINT8 uIndex = FLASH_SUCCESS;
HDL_Flash_CheckRegisterBeforeOperate();
if (FSTAT_CCIF == 0U) /* Is command buffer full ? */
{
//ExitCritical(); /* Exit critical section */
return FLASH_BUSY_ERROR; /* If yes then error */
}
FCCOBIX = 0x00;
FCCOBHI = pFCCOpara->flashCmd;
FCCOBLO = (UINT)((pFCCOpara->globalAddr & 0x007F0000) >> 16);
FCCOBIX = 0x01;
FCCOB = (UINT16)(pFCCOpara->globalAddr & 0x0000FFFF) ;
if(pFCCOpara->flashCmd==PROGRAM_P_FLASH)
{
for(uIndex = 0; uIndex < pFCCOpara->dataLength; uIndex++)
{
FCCOBIX = 0x02 + uIndex / 2;
FCCOBHI = * (pFCCOpara->Datas + uIndex);
FCCOBLO = * (pFCCOpara->Datas + uIndex + 1);
uIndex++;
}
}
DisableInterrupts;
//_asm("CALL HDL_Flash_Burn_And_WaitFinished");
_asm("JSR HDL_Flash_Burn_And_WaitFinished");
EnableInterrupts;
if (FSTAT_FPVIOL == 1U)
{ /* Is protection violation detected ? */
return FLASH_PROTECTED_ERROR; /* If yes then error */
}
if (FSTAT_ACCERR == 1U)
{ /* Is acces error detected ? */
return FLASH_NOTAVAIL_ERROR; /* If yes then error */
}
if (FSTAT_MGSTAT)
{ /* Was attempt to write data to the given address errorneous? */
return FLASH_MGSTAT_ERROR; /* If yes then error */
}
return FLASH_SUCCESS; /* Exit critical section */
}
//check the address is whether valid
int HDL_P_Flash_CheckAddressIsValid(UINT32 globalAddr)
{
int nRetval = FLASH_SUCCESS;
if(! (globalAddr >= 0x700000) && (globalAddr <= 0x7FFFFF) )
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//erase one sector,1024bytes
int HDL_Flash_PFlash_EraseOneSector(UINT32 sectorAddr)
{
int nRetval = FLASH_SUCCESS;
HDL_FLASH_SCM_FCCO_PARA fccoPara;
if(HDL_P_Flash_CheckAddressIsValid(sectorAddr))
{
fccoPara.flashCmd = ERASE_P_FLASH_SECTOR;
fccoPara.globalAddr = sectorAddr&PROGRAM_PFlash_Phrase_MASK; //erase start address must be phrase start address
fccoPara.dataLength = 0;
nRetval = HDL_P_Flash_ExecOneFlashCmd(&fccoPara);
}
else
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//erase multiple sector
int HDL_Flash_PFlash_EraseMultiSectors(UINT32 startGlobalAddr, UINT32 endGlobalAddr)
{
int nRetval = FLASH_SUCCESS;
if(HDL_P_Flash_CheckAddressIsValid(startGlobalAddr) && HDL_P_Flash_CheckAddressIsValid(endGlobalAddr) && startGlobalAddr<=endGlobalAddr )
{
UINT32 addr = 0;
for(addr = startGlobalAddr; addr <= endGlobalAddr; addr+=PFLASH_SECTOR_SIZE)
{
nRetval = HDL_Flash_PFlash_EraseOneSector(addr);
if(nRetval!=FLASH_SUCCESS)
return nRetval;
}
}
else
{
nRetval = FLASH_ADDRESS_ERROR;
}
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//program one phrase,8bytes
int HDL_Flash_PFlash_ProgramOneSector(UINT32 globalAddr, UINT8 * pData,UINT16 dataLength)
{
int nRetval = FLASH_SUCCESS;
HDL_FLASH_SCM_FCCO_PARA fccoPara;
if(dataLength!=PROGRAM_PFlash_Phrase_SIZE)
return FLASH_DATALENGTH_ERROR;
if(HDL_P_Flash_CheckAddressIsValid(globalAddr) && HDL_PFlash_CheckAddressIsPhraseStart(globalAddr))
{
fccoPara.flashCmd = PROGRAM_P_FLASH;
fccoPara.globalAddr = globalAddr;
fccoPara.dataLength = dataLength;
memcpy(fccoPara.Datas,pData,dataLength);
HDL_P_Flash_ExecOneFlashCmd(&fccoPara);
}
else
nRetval = FLASH_ADDRESS_ERROR;
return nRetval;
}
#pragma MESSAGE DISABLE C1420 //result of function call is ignore
//program multiple phrases
int HDL_Flash_PFlash_ProgramMultiSectors(UINT32 globalAddr, UINT8 * pData, UINT16 dataLength)
{
int nRetval = FLASH_SUCCESS;
UINT32 addr = 0, offsetFromPhraseStartAddr = 0, endAddr = 0;
//UINT8 *dataInFlash=&addr;
UINT8 datas[8];
UINT32 phraseStarAddr = globalAddr&PROGRAM_PFlash_Phrase_MASK; //first phrase start address
if (!HDL_P_Flash_CheckAddressIsValid(globalAddr))
return FLASH_ADDRESS_ERROR;
/*************************************************
start
0 1 2 3 4 5 6 7 8 ..... 0 1 2 3 4 5 6 7 8
|offset|<- dataLength ->| no 8 left data
**************************************************/
//the offset of phrase start
offsetFromPhraseStartAddr = globalAddr - phraseStarAddr;
endAddr = globalAddr + dataLength-1;
//首组不对齐
if (offsetFromPhraseStartAddr != 0)
{
//first contain offset area,read offset area data from flash
for (addr = phraseStarAddr; addr<globalAddr; addr++)
{
//dataInFlash = (UINT8 *)addr; //get the maintain value
datas[addr - phraseStarAddr] = 0xff;//*dataInFlash; //0xFF;
}
//first contain offset fill the left with data
for (addr = globalAddr; addr<globalAddr+ PROGRAM_PFlash_Phrase_SIZE - offsetFromPhraseStartAddr; addr++)
datas[addr - phraseStarAddr] = pData[addr - globalAddr];
//program first one phrase
HDL_Flash_PFlash_ProgramOneSector(phraseStarAddr,datas, PROGRAM_PFlash_Phrase_SIZE);
//下一组要偏移一个Phrase
phraseStarAddr += PROGRAM_PFlash_Phrase_SIZE;
}
//other data
for (addr = phraseStarAddr ; addr <= endAddr + 1 - PROGRAM_PFlash_Phrase_SIZE; addr += PROGRAM_PFlash_Phrase_SIZE)
{
//program data
HDL_Flash_PFlash_ProgramOneSector(addr, &pData[addr - globalAddr], PROGRAM_PFlash_Phrase_SIZE);
}
//endaddr phrase start addr
phraseStarAddr = endAddr&PROGRAM_PFlash_Phrase_MASK; //last phrase start address
//endaddr is not the phrase last one
if (endAddr != (phraseStarAddr+ PROGRAM_PFlash_Phrase_SIZE-1))
{
//the last no 8 left data
for (addr = phraseStarAddr; addr <= endAddr; addr++)
datas[addr - phraseStarAddr] = pData[addr - globalAddr];
for (addr = endAddr + 1; addr<8+phraseStarAddr; addr++)
{
//dataInFlash = (UINT8 *)addr; //get the maintain value
datas[addr - phraseStarAddr] = 0xff;//*dataInFlash;//0xFF;
}
//program first one phrase
HDL_Flash_PFlash_ProgramOneSector(phraseStarAddr, datas, PROGRAM_PFlash_Phrase_SIZE);
}
return nRetval;
}
浙公网安备 33010602011771号