235 lines
5.1 KiB
C

/*******************************************************************************
* *
* Copyright 2010 Rheinmetall Canada Inc. *
* *
* No part of this document may be reproduced, stored in *
* a retrieval system, or transmitted, in any form or by any means, *
* electronic, mechanical, photocopying, recording, or otherwise, *
* without the prior written permission of Rheinmetall Canada Inc. *
* *
*******************************************************************************/
/*---- example include file ---------------------------------------------------*/
#include "define.h"
#include "FlashInterface.h"
stDataSector_t CurrentDataSector;
void InitFlashInterface(void)
{
}
//see section 5 of PIC32 manual
unsigned int FlashUnlock(unsigned int Operation)
{
//Setup operation to do
NVMCON = Operation;
int i =0;
for(i=0;i<500;i++)
Nop();
//Unlock
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA;
//Execute operation
NVMCONSET = 0x8000;
//Wait for it to finish
while(NVMCON & 0x8000);
Nop();
NVMCONCLR = 0x4000;
//Return NVMERR et LVDERR status bits
return (NVMCON & 0x3000);
}
unsigned int FlashProgramWord(void *Address, unsigned int DataWord)
{
unsigned int res;
//Load Data into NVMDATA register
NVMDATA = DataWord;
//Load Address (Physical address)
NVMADDR = KVA_TO_PA((unsigned int)Address);
//Unlock Flash and init operation
res = FlashUnlock(FLASH_PROGRAM_WORD_CMD);
return res;
}
unsigned int FlashProgramRow(void *Address, void *DataPtr)
{
unsigned int res;
//Load Address (Physical address)
NVMADDR = KVA_TO_PA((unsigned int)Address);
// Set pointer to data buffer
NVMSRCADDR = KVA_TO_PA((unsigned int)DataPtr);
//Unlock Flash and init operation
res = FlashUnlock(FLASH_PROGRAM_ROW_CMD);
return res;
}
unsigned int FlashProgramData(void *FlashStartAddress, unsigned int *DataPtr, unsigned int Size)
{
//The Size parameter is the number of WORDS.
unsigned int SizeInBytes = Size * 4;
void *CurFlashAddress;
unsigned int i;
unsigned int res = 0;
unsigned int curData;
curData = *DataPtr;
CurFlashAddress = FlashStartAddress;
//1 row = 512 bytes --> 0x80. We must always program an entire row (cannot start in the middle).
//if this happens, we must write words individually before and after the rows.
if(Size < FLASH_ROW_SIZE) //if we don't have enough data to fill a row, program words...
{
for(i = 0; i < Size; i++)
{
curData = *DataPtr++;
res |= FlashProgramWord(CurFlashAddress, curData /*DataPtr++*/);
CurFlashAddress+=4;
}
if(res)
return FLASH_STATUS_ERROR;
else
return FLASH_STATUS_OK;
}
else //we have at least 1 row
{
unsigned int NbRow;
NbRow = Size / FLASH_ROW_SIZE;
int ProgramFinished = 0;
do
{
//check if the start address is aligned with a row.
if((unsigned int)CurFlashAddress & 0x1FF) //data is misaligned. Write all words to the next row.
{
do
{
res |= FlashProgramWord(CurFlashAddress, *DataPtr++);
CurFlashAddress+=4;
Size--;
}
while(((unsigned int)CurFlashAddress & 0x1FF) && Size != 0);
}
else //data is aligned with the row.
{
if(Size % FLASH_ROW_SIZE == 0) //we have an integer number of rows. Program all of them and return.
{
for(i = 0; i < NbRow; i++)
{
res |= FlashProgramRow(CurFlashAddress, (void*)DataPtr);
CurFlashAddress += FLASH_ROW_SIZE_IN_BYTES;
DataPtr += FLASH_ROW_SIZE;
}
if(res)
return FLASH_STATUS_ERROR;
else
return FLASH_STATUS_OK;
}
else //non integer number of rows...
{
res |= FlashProgramRow(CurFlashAddress, (void*)DataPtr);
CurFlashAddress += FLASH_ROW_SIZE_IN_BYTES;
DataPtr += FLASH_ROW_SIZE;
Size -= FLASH_ROW_SIZE;
}
}
if(Size < FLASH_ROW_SIZE) //if we don't have enough data to fill a row, program words...
{
for(i = 0; i < Size; i++)
{
res |= FlashProgramWord(CurFlashAddress, *DataPtr++);
CurFlashAddress+=4;
}
if(res)
return FLASH_STATUS_ERROR;
else
return FLASH_STATUS_OK;
}
if(Size == 0)
{
if(res)
return FLASH_STATUS_ERROR;
else
return FLASH_STATUS_OK;
}
}
while(1);
}
}
unsigned int FlashErase(void)
{
unsigned int res = 0;
unsigned int i;
void* PageAddress;
PageAddress = (void*)APPLICATION_FLASH_START_ADDRESS;
for(i = 0; i < FLASH_NB_APPLICATION_PAGES; i++)
{
res |= FlashErasePage(PageAddress);
if(res)
{
int page = PageAddress;
}
PageAddress += FLASH_PAGE_SIZE_IN_BYTES;
}
if(res)
return FLASH_STATUS_ERROR;
else
return FLASH_STATUS_OK;
}
unsigned int FlashErasePage(void *Address)
{
unsigned int res;
NVMADDR = KVA_TO_PA((unsigned int)Address);
res = FlashUnlock(FLASH_PAGE_ERASE_CMD);
return res;
}
//EOF