235 lines
5.1 KiB
C
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
|
|
|
|
|