/******************************************************************************* * * * 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