This is the content of the file in which there are the funtions of
reading and writing:
#define CUR_BLOCK_SIZE 256
#define FLASH_SECTOR_FOR_DATA 7 // Highest Flash sector
number in LPC1114
#define START_OF_FLASH_SECTOR 0x00007000 // Start address of
FLASH_SECTOR_FOR_DATA
#define END_OF_FLASH_SECTOR 0x00008000 // End address of
FLASH_SECTOR_FOR_DATA
#define IAP_FLASH_CMD_PREPARE_SECTOR 50
#define IAP_FLASH_CMD_COPY_RAM2FLASH 51
#define IAP_FLASH_CMD_ERASE_SECTOR 52
#define IAP_LOCATION 0x1FFF1FF1
typedef void (*IAP)(unsigned int *pcommand, unsigned int *presult);
typedef struct versiont_
{
uint16_t major;
uint16_t minor;
} version_t;
typedef struct nvmlayout_t_
{
version_t version;
uint8_t data[CUR_BLOCK_SIZE - sizeof(version_t)];
} nvm_layout_t;
/*******************************************************************************
******************************************************************************/
nvm_layout_t nvm_storage; //static
/*******************************************************************************
******************************************************************************/
static void erase_flash_sector(void)
{
uint32_t command[5];
uint32_t result[4];
IAP iap_entry = (IAP)IAP_LOCATION;
__disable_irq();
command[0] = IAP_FLASH_CMD_PREPARE_SECTOR;
command[1] = FLASH_SECTOR_FOR_DATA;
command[2] = FLASH_SECTOR_FOR_DATA; // Only 1 sector, so end
sector # is start sector #
iap_entry(command, result);
if (result[0] == 0)
{
command[0] = IAP_FLASH_CMD_ERASE_SECTOR;
command[1] = FLASH_SECTOR_FOR_DATA;
command[2] = FLASH_SECTOR_FOR_DATA; // Only 1 sector, so end
sector # is start sector #
command[3] = SystemCoreClock / 1000;
iap_entry(command, result);
}
__enable_irq();
}
static void program_flash_sector(uint32_t * pDest, uint32_t * pSrc,
uint32_t size)
{
uint32_t command[5];
uint32_t result[4];
IAP iap_entry = (IAP)IAP_LOCATION;
__disable_irq();
command[0] = IAP_FLASH_CMD_PREPARE_SECTOR;
command[1] = FLASH_SECTOR_FOR_DATA;
command[2] = FLASH_SECTOR_FOR_DATA; // Only 1 sector, so end
sector # is start sector #
iap_entry(command, result);
if (result[0] == 0)
{
command[0] = IAP_FLASH_CMD_COPY_RAM2FLASH;
command[1] = (uint32_t)pDest;
command[2] = (uint32_t)pSrc;
command[3] = size;
command[4] = SystemCoreClock / 1000;
iap_entry(command, result);
}
__enable_irq();
}
/*******************************************************************************
******************************************************************************/
bool NVM_read(void * pData, uint32_t data_size)
{
bool erase = false;
bool found = false;
uint32_t * fl_ptr;
nvm_layout_t * flash_nvm_ptr;
if (data_size > sizeof(nvm_storage.data))
{
return false;
}
// check if last block in Flash is empty
fl_ptr = (uint32_t *)(END_OF_FLASH_SECTOR - CUR_BLOCK_SIZE);
if (*fl_ptr != 0xFFFFFFFF)
{
// last block in Flash is not empty.
// so the Data storage in Flash is full.
erase = true;
}
// Try to find the most recent data in the NVM Flash sector.
// We search backward (highest address) to the first non empty
block that we
// find, since the NVM Flash sector is filled from the lowest
address upwards.
while (!found && (fl_ptr >= (uint32_t *)START_OF_FLASH_SECTOR))
{
flash_nvm_ptr = (nvm_layout_t *)fl_ptr;
if ((flash_nvm_ptr->version.major ==
MAJOR_FIRMWARE_VERSION_NUMBER) &&
(flash_nvm_ptr->version.minor ==
MINOR_FIRMWARE_VERSION_NUMBER))
{
found = true;
memcpy(pData, &flash_nvm_ptr->data[0], data_size);
}
else
{
fl_ptr -= (CUR_BLOCK_SIZE / sizeof(uint32_t)); // skip to
previous block
}
}
if (erase)
{
// Data storage will be cleaned up now,
// so that there is room in Flash when the next power down
takes place.
erase_flash_sector();
if (found)
{
// write back to Flash the most recent data
NVM_write(pData, data_size);
}
}
return found;
}
void NVM_write(void * pData, uint32_t data_size)
{
bool found = false;
uint32_t * pDest = (uint32_t *)START_OF_FLASH_SECTOR;
if (data_size > sizeof(nvm_storage.data))
{
return;
}
while (!found && (pDest < (uint32_t *)END_OF_FLASH_SECTOR))
{
// check if pDest points to an empty block
if (*pDest == 0xFFFFFFFF)
{
found = true;
}
else
{
pDest += (CUR_BLOCK_SIZE / sizeof(uint32_t)); // skip to
next block
}
}
if (!found)
{
erase_flash_sector();
pDest = (uint32_t *)START_OF_FLASH_SECTOR;
}
nvm_storage.version.major = MAJOR_FIRMWARE_VERSION_NUMBER;
nvm_storage.version.minor = MINOR_FIRMWARE_VERSION_NUMBER;
memcpy(&nvm_storage.data[0], pData, data_size);
program_flash_sector(pDest, (uint32_t *)&nvm_storage, CUR_BLOCK_SIZE);
}
/* End Of File */
Il 05/01/2017 09:38, kerryzhou ha scritto:
>
NXP Community
<https://community.freescale.com/resources/statics/1000/35400-NXP-Community-Email-banner-600x75.jpg>
>
Re: IAP flash writing problem
reply from Kerry Zhou
<https://community.nxp.com/people/kerryzhou?et=watches.email.thread>
in /LPC/ - View the full discussion
<https://community.nxp.com/message/865663?commentID=865663&et=watches.email.thread#comment-865663>
>