/************************************************************************
*
* Emulating Data EEPROM for PIC24 Microcontrollers and
* dsPIC Digital Signal Controllers
*
* This application note provides a standard interface to an efficient
* Data EEPROM emulation algorithm and uses available program memory.
* It is designed for Microchip Technology 16-bit PIC and dsPIC J devices
* which currently include PIC24F, PIC24H and dsPIC33 products. The
* project is initially configured to use PIC24FJ128GA010 on the Explorer
* 16 Development Board. To use different device, simply select new device
* in MPLAB, replace C30 linker script and rebuild.
* User must select number pages of program memory, erase/write limit and
* emulated DEE size. These are defined in "DEE Emulation 16-bit.h".
* At build-time, the linker reserves pages in the next available
* locations in program memory. Compiler error occurs if more than 255
* DEE locations are declared, less than 2 pages of program memory is
* reserved, greater than 65,535 erase/write cycles specified or if
* insufficient program memory is available.
* Call initialization routine and clear status flags before attempting
* any other DEE operation.
*
*************************************************************************
* FileName: DEE Emulation 16-bit.c
* Dependencies: Flash Operations.s
* DEE Emulation 16-bit.h
* Compiler: MPLAB C30, v2.01 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* Copyright � 2007 Microchip Technology Inc. All rights reserved.
*
* Microchip licenses to you the right to use, modify, copy and distribute
* Software only when embedded on a Microchip microcontroller or digital
* signal controller, which is integrated into your product or third party
* product (pursuant to the sublicense terms in the accompanying license
* agreement).
*
* You should refer to the license agreement accompanying this Software for
* additional information regarding your rights and obligations.
*
* SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE
* LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY,
* CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY
* DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY
* INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST
* PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY,
* SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO
* ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
*
* Author Date Comment
*************************************************************************
* D. Otten 2007/05/01 Version 1.0.0 - Initial Release
* D. Otten 2007/05/15 Version 1.0.1 - First publication release
* Pradeep Budagutta 2008/04/02 Version 1.1.0 - Multi EEPROM banks included
* Pradeep Budagutta 2008/05/05 Version 1.1.1 - TBLPAG page boundary problem solved
************************************************************************/
#if defined (__dsPIC33F__)
#include <p33Fxxxx.h>
#elif defined (__PIC24H__)
#include <p24Hxxxx.h>
#elif defined (__PIC24F__)
#include <p24Fxxxx.h>
#else
#error Selected processor not supported
#endif
#include "DEE Emulation 16-bit.h"
// User constant validation
#if DATA_EE_BANKS == 0
#error Minimum data EE banks is 1
#endif
#if DATA_EE_SIZE > 255
#error Maximum data EE size is 255
#endif
#if NUM_DATA_EE_PAGES < 2
#error Minimum number of program memory pages is 2
#endif
#if ERASE_WRITE_CYCLE_MAX > 65535
#error Maximum number of erase/write cycles is 65,535
#endif
DATA_EE_FLAGS dataEEFlags;
//Data EE info stored in PM in following format
// Status in first two locations of PM page,
// 8-bit DEE Address (odd address, low byte) 16-bit DEE data (even address)
unsigned char emulationPages[DATA_EE_BANKS * NUM_DATA_EE_PAGES][NUMBER_OF_INSTRUCTIONS_IN_PAGE * 2]
__attribute__ ((space(psv), aligned(NUMBER_OF_INSTRUCTIONS_IN_PAGE * 2), noload));
#define DEE_BANK_SIZE (sizeof(emulationPages[0])*NUM_DATA_EE_PAGES)
#define DEE_PAGE_SIZE (sizeof(emulationPages[0]))
#define DEE_PAGE_TBL(bank, page) ((__builtin_tbladdress(&emulationPages) + (DEE_BANK_SIZE * (bank)) + (DEE_PAGE_SIZE * (page))) >> 16)
#define DEE_PAGE_OFFSET(bank, page) ((__builtin_tbladdress(&emulationPages) + (DEE_BANK_SIZE * (bank)) + (DEE_PAGE_SIZE * (page))) & 0xFFFF)
/************************************************************************
UnlockWrite
This routine saves the current CPU priority and sets it the highest
user level of 7. It calls an assembly routine to perform an unlock
sequence and sets the WR bit in NVMCON. The WR bit is polled until it
clears indicating the flash operation is complete. The previous CPU
priority is restored.
Parameters: None
Return: None
Side Effects: None
************************************************************************/
void UnlockWrite(void)
{
unsigned int sh_SR;
SET_AND_SAVE_CPU_IPL(sh_SR, 7);
UnlockPM();
RESTORE_CPU_IPL(sh_SR);
return;
}
/************************************************************************
GetPageStatus
This routine returns the page status for the selected page for the
selected field. The return value is right shifted into LSb position.
Parameters: Page number, Status Field
Return: Right justified bit value representing selected Status
Field value
Side Effects: None
************************************************************************/
int GetPageStatus(unsigned char bank, unsigned char page, unsigned char field)
{
unsigned int statusOffset;
unsigned char statusByte;
unsigned char status;
int savedTBLPAG; //Context save of TBLPAG value. Current and packed page are on same page.
savedTBLPAG = TBLPAG;
// Point to proper TBLPAG and offset
TBLPAG = DEE_PAGE_TBL(bank, page);
statusOffset = DEE_PAGE_OFFSET(bank, page);
statusByte = (ReadPMHigh(statusOffset) & 0xFF);
switch(field)
{
case STATUS_AVAILABLE:
status = ((statusByte & 4) >> 2);
break;
case STATUS_CURRENT:
status = ((statusByte & 8) >> 3);
break;
case STATUS_EXPIRED:
status = ((statusByte & 16) >> 4);
break;
default:
status = 0;
break;
}
TBLPAG = savedTBLPAG;
return(status);
}
/************************************************************************
ErasePage
This routine erases the selected page.
Parameters: Page number
Return: None
Side Effects: Loads NVCOM with erase opcode
************************************************************************/
void ErasePage(unsigned char bank, unsigned char page)
{
unsigned int pmOffset; //Current array (page) offset of selected element (PM 16-bit word)
int savedTBLPAG; //Context save of TBLPAG value. Current and packed page are on same page.
savedTBLPAG = TBLPAG;
// Point to proper TBLPAG and offset
TBLPAG = DEE_PAGE_TBL(bank, page);
NVMCON = ERASE;
pmOffset = DEE_PAGE_OFFSET(bank, page);
WritePMLow(pmOffset, pmOffset);
UnlockWrite();
TBLPAG = savedTBLPAG;
return;
}
/************************************************************************
GetNextAvailCount
This routine finds the active page and performs a backward search to find
the first available location. The available location is determined by
reading an LSB (odd