AN1673

AN1673
Using the PIC16F1XXX High-Endurance Flash (HEF) Block
Author:
Lucio Di Jasio
Microchip Technology Inc.
INTRODUCTION
The PIC16F1XXX family of general purpose Flash
microcontrollers features the 8-bit PIC® MCU
enhanced mid-range core. Carefully trading
functionality versus cost, several members of this
family, including the PIC16F14XX, PIC16F15XX and
PIC16F17XX, have made a departure from the usual
set of peripherals found in previous models to achieve
a lower price point while still offering a compelling new
set of features. Among the several new peripherals
introduced, it is worth noting:
• Configurable Logic Cell – a small set of logic
blocks (unlike a small PLD) that can help directly
interconnect various peripherals inputs/outputs
without CPU intervention.
• Complementary Output Generator – the front end
of a traditional PWM module, now decoupled from
the timing generator and, therefore, available for
direct connection to other modules (including
analog comparators).
• Numerically Controlled Oscillator – a frequency
synthesizer that allows linear control of the
frequency output.
• High-Endurance Flash (HEF) Block – replacing
the data EEPROM present on previous models
with a block of Flash memory that is ensured to
provide the same high endurance (100,000 erase/
write cycles).
This application note illustrates the benefits offered by
the high-endurance Flash block and describes a small
C library which allows a simple and safe use of its
capabilities.
 2014 Microchip Technology Inc.
FLASH VS. HIGH-ENDURANCE
FLASH
Like most other PIC microcontrollers in Flash
technology, the PIC16F1XXX series features a
single-voltage self-write Flash program memory array.
This means that, without additional external hardware
support, these devices can modify the contents of their
Flash memory at runtime, under firmware control.
As an example, this capability is conveniently used to
implement boot loaders, enabling embedded
application that can be reprogrammed in the field via a
simple serial connection (UART, SPI, I2C™, USB, etc.)
and without requiring the use of a dedicated in-circuit
programmer/debugger device.
This capability can also be used to store and/or update
calibration data in program memory (obtained at the
end of a production line or after product installation).
However, the main limitation of the self-write Flash
program memory array lies in the relatively small
number of possible erase/write cycles.
For example, the PIC16(L)F1508/9 data sheet
(DS40001609) specifies a minimum of 10K cycles in
the industrial temperature range (-40˚C to +85˚C) (see
http://www.microchip.com/wwwproducts/
Devices.aspx?dDocName=en553471). This is an
order of magnitude smaller than the traditional value
offered by most data EEPROM modules and
stand-alone devices.
The high-endurance block is a block of 128 memory
locations, found at the top of the Flash program
memory that is ensured to provide a superior
endurance, equal to that of a traditional data EEPROM
memory within a given temperature range (0˚C to 60˚C)
(see Table 1 below from the PIC16(L)F1508/9 data
sheet).
DS00001673A-page 1
AN1673
TABLE 1:
MEMORY PROGRAMMING SPECIFICATIONS
Standard Operating Conditions (unless otherwise stated)
Param.
No.
Sym.
Characteristic
Min.
Typ.†
Max.
Units
Conditions
Program Memory
Programming Specifications
D110
VIHH
Voltage on MCLR/VPP pin
8.0
—
9.0
V
D111
IDDP
Supply Current during
Programming
—
—
10
mA
D112
VBE
VDD for Bulk Erase
D113
VPEW
VDD for Write or Row Erase
D114
D115
2.7
—
VDDMAX
V
VDDMIN
—
VDDMAX
V
IPPPGM Current on MCLR/VPP during
Erase/Write
—
1.0
—
mA
IDDPGM Current on VDD during Erase/
Write
—
5.0
—
mA
10K
—
—
E/W
(Note 2)
Program Flash Memory
-40C  TA +85C
(Note 1)
D121
EP
Cell Endurance
D122
VPRW
VDD for Read/Write
VDDMIN
—
VDDMAX
V
D123
TIW
Self-timed Write Cycle Time
—
2
2.5
ms
D124
TRETD
Characteristic Retention
—
40
—
Year
Provided no other
specifications are violated
D125
EHEFC
High-Endurance Flash Cell
100K
—
—
E/W
0°C  TA +60°C, lower
byte last 128 addresses
† Data in “Typ” column is at 3.0V, 25°C unless otherwise stated. These parameters are for design guidance
only and are not tested.
Note 1: Self-write and Block Erase.
2: Required only if single-supply programming is disabled.
Compare parameter D121, EP, Cell Endurance of a
regular Flash program memory cell, to parameter
D125, EHEFC, High-Endurance Flash Cell.
It is also worth noting that each high-endurance cell
can be used only to hold an 8-bit value, whereas the
standard Flash memory will hold 14 bits of information
as per the traditional PIC MCU mid-range program
memory array design.
DS00001673A-page 2
 2014 Microchip Technology Inc.
AN1673
FLASH VS. EEPROM
Stall During Write
Both the high-endurance Flash and the regular Flash
memory arrays differ from a data EEPROM module in
two important ways:
In contrast with the behavior of a data EEPROM, the
MCU is unable to fetch new instructions from the Flash
memory array during a self-write cycle and it is,
therefore, stalled. This means that no other work can
be performed in parallel during an erase or write
operation, nor can the application respond to interrupts.
In fact, these are delayed until the MCU code execution
resumes. The designer must, therefore, take into
account the potentially-introduced additional jitter or
the momentary application freeze during the
nonvolatile memory updates.
a)
b)
Data must be manually erased before a
write and this can be performed only in
blocks (referred to as rows) of a fixed size
determined by the Flash array inner design.
Writing to Flash stalls the MCU for a few
milliseconds (see parameter D123 in
Table 1).
By contrast, true data EEPROMs are designed to allow
byte-by-byte erase and do not stall the MCU execution
during a write cycle, although, for simplicity reasons,
most applications will include a delay loop to ensure a
(byte) write has been completed before the next one
can be initiated.
Note:
Note that the delay duration is independent of the
amount of data actually written in a row, be it a single
byte or the entire row.
Finally, note that no delays or penalties are incurred by
reading the content of the Flash memory arrays.
To speed up the writing process, external
serial EEPROM devices will often include
a page mechanism that is not too
dissimilar in principle to the rows of a
Flash array.
The differences noted above have implications for the
design of the embedded application, which need to be
fully understood whether considering the use of regular
or high-endurance Flash in lieu of a true EEPROM.
Row Erase/Write
Notice that no restrictions exist on the amount of data
fetched during a read operation or its alignment with
row boundaries.
When writing a block of data to a Flash memory, it is
important to ensure alignment with the array row
boundaries. When the data block does not entirely fit
inside a single row, multiple write operations can be
required to store sequential rows, which explains why it
is essential to know the size of the Flash memory array
(row size). The user needs to ensure that the data is
aligned with the row size, especially if data spans more
than one row.
 2014 Microchip Technology Inc.
DS00001673A-page 3
AN1673
A FLASH SUPPORT LIBRARY
The flash.c module has been written to simplify the
use of the self-write Flash memory in embedded
applications written in C (see Listing B-2). It can be
used to operate independently on the normal Flash
array as well as on the high-endurance Flash block.
Five basic functions are prototyped and documented in
flash.h (see Listing B-1).
The first three functions provide read capability (see
Function 1 through Function 3).
FUNCTION 1:
FLASH_read
/**
* Read a word from program Flash memory
*
* @param address source address (absolute
Flash memory address)
* @return
word retrieved from
Flash memory
*/
unsigned FLASH_read (unsigned address);
The FLASH_read function reads a 14-bit word from a
given address in the device program Flash memory. It
can be used to read very large tables of data from
memory.
FUNCTION 2:
FLASH_readConfig
/**
* Read a word from configuration Flash memory
*
* @param address
source address (absolute
Flash memory address)
* @return
word retrieved from
Flash memory
*/
unsigned FLASH_readConfig (unsigned address);
The FLASH_readConfig function is a variant of the
previous function that allows access to addresses
above the 0x8000 threshold where the IDLOC
information, processor Configuration bits and
calibration data are found.
FUNCTION 3:
FLASH_readBlock
/**
* Read a block of words from program Flash memory
*
* @param buffer
destination buffer (must be
sufficiently large)
* @param address
source address (absolute
Flash memory address)
* @param count
number of words to be
retrieved
*/
void FLASH_readBlock (unsigned* buffer, unsigned
address, char count);
The FLASH_readBlock function will perform a read
operation from the main program memory array of the
device transferring a number of 14-bit words (up to
255) into a buffer of 16-bit unsigned integers.
DS00001673A-page 4
The last two functions provide the write and erase
capability (see Function 4 and Function 5).
FUNCTION 4:
FLASH_write
/**
* Write a word of data to Flash memory (latches)
* if parameter latch = 1, data is only latched
and no actual write cycle
* is initiated until a subsequent call with
latch = 0
*
* @param address
destination address (absolute
Flash memory)
* @param data
word of data to be written
(latched)
* @param latch
*/
void FLASH_write (unsigned address, unsigned data,
byte latch);
The FLASH_write function offers the smallest atomic
unit required to perform an actual write operation.
Depending on the value passed as the latch parameter,
it can simply load a latch or initiate a write cycle during
which all values previously loaded in a row get written
at once. Refer to Section 10.0, Flash Program
Memory Control, of the device data sheet for more
details on the low-level sequence of operation required
(see
http://ww1.microchip.com/downloads/en/
DeviceDoc/40001609C.pdf).
Note:
When latching, the function performs a
short unlock sequence which includes the
temporary disabling of interrupts, but no
delay (MCU stall) is incurred. During an
actual write operation, the function
performs the unlock sequence, but it also
stalls the MCU for the self-write cycle
time. Any interrupt event occurring during
such time will be served after execution is
resumed.
FUNCTION 5:
FLASH_erase
/**
* Erase a row of Flash memory
*
* @param address
absolute address in Flash
contained in selected row
*/
void FLASH_erase (unsigned address);
The FLASH_erase function performs the erase of a
single row of the program memory Flash array. The
address provided can be relative to any of the locations
contained in the row. This function performs a brief
unlock sequence and then proceeds to stall the MCU
for the self-write cycle time. Any interrupt event occurring during such time will be served after execution is
resumed.
 2014 Microchip Technology Inc.
AN1673
Note:
It is not necessary to precede each write
operation with a corresponding erase
operation. In fact an erase is necessary
only when a memory location content
update requires a bit presently set to a
logic ‘0’, to return to a logic value of ‘1’.
After an erase, every location contained in
the given memory row will be set to the
value of 0x3FFF (14 bits set to ‘1’).
Write operations can be performed sequentially or
simultaneously on one or more locations within a row
(using the latching mechanism) without any specific
order. Each memory location can be written to several
times, as long as each time, only bit-clear operations
are requested (‘1’’0’).
EEPROM-LIKE USE OF THE HIGHENDURANCE FLASH
Utilizing the five functions presented in the previous
section, it is possible to implement any number of
strategies for the implementation and management of
a nonvolatile storage system on Flash.
Several application notes and articles have already
presented solutions to help emulate a high-endurance
block using multiple locations of (lower endurance)
Flash memory. See AN1095 for use with PIC18, PIC24
and dsPIC33FJ devices (http://ww1.microchip.com/
downloads/en/AppNotes/01095D.pdf).
The “High-Endurance Flash Block” application note will
instead take advantage of the superior characteristics
of the high-endurance Flash array, available on the
current PIC16F1XXX family and its future derivatives.
Since high endurance is already ensured by design,
the approach presented will require no additional Flash
memory space outside of the high-endurance Flash
region and no additional resources.
A simple library module (HEFlash.c, HEFlash.h)
has been prepared to provide the simplest and most
intuitive use of the high-endurance Flash region for
data EEPROM-like nonvolatile storage (admittedly
more similar to a paged data EEPROM use).
For maximum efficiency, the high-endurance Flash
library handles the high-endurance Flash as a small
array of data blocks, mapping each block to a row,
adding up to 128 bytes of total capacity (see Figure 1).
FIGURE 1:
HIGH-ENDURANCE
MEMORY USED AS AN
ARRAY OF FOUR BLOCKS
ON PIC16F1509
Block 0
(row 0x1F80)
0000
SelfǦWrite
Flash
32 bytes
Block 1
(row 0x1FA0)
32 bytes
Block 2
(row 0x1FC0)
32 bytes
Block 3
(row 0x1FE0)
32 bytes
1F80
High Endurance
Flash
1FFF
 2014 Microchip Technology Inc.
DS00001673A-page 5
AN1673
The actual capacity of each data block is dictated by
the dimensions of the high-endurance Flash memory
row in the given microcontroller model:
• PIC16F1XXX models with 4K words of Flash (7K
bytes), or more, have a row size of 32 bytes.
• Smaller devices use a row size of 16 bytes.
This means that 4K words and larger models will offer
only four independent data blocks (32 bytes each) of
nonvolatile storage, while smaller devices will offer
eight independent data blocks (16 bytes each).
Each data block can be modified any number of times
up to the maximum specified endurance of the highendurance Flash memory (100,000 times) without
influencing any of the neighboring data blocks.
FUNCTION 6:
writeBlock()
/ **
* Write a block of data to High Endurance Flash
* the entire block must fit within a row
*
* @param radd
HE Flash block number
(0 - MAXROWS-1)
* @param buffer
source buffer
* @param count
number of bytes to write to
block (< ROWSIZE)
* @return
0 if successful, -1 if
parameter error
*/
char
HEFLASH_writeBlock (char radd,
char* buffer, char count);
The writeBlock() function takes the contents of a
data structure pointed to by buffer and writes it into the
selected high-endurance Flash block. Blocks are
atomically updated. All the contents of a block are
erased first and then written to, even if only a portion of
the block capacity (count<ROWSIZE) is used.
The function will return a parameter error (‘-1’) if any of
the input parameters are out of bounds, such as data
too large or invalid block number. The function will
return a write error (‘1’) if the write sequence failed for
any reason.
FUNCTION 7:
readBlock()
/**
* Read a block of data from HE Flash memory
*
* @param buffer destination buffer (must be
sufficiently large)
* @param radd
source block of HE Flash memory
(0 - MAXROWS-1)
* @param count
number of bytes to be retrieved
(< ROWSZE)
* @return
0 if successful, -1 if parameter
error
*/
char
HEFLASH_readBlock (char* buffer, char radd,
char count);
The readBlock() function matches the functionality
of the writeBlock() function by extracting a block of
data from high-endurance Flash and placing the
contents into a structure pointed to by buffer.
This function will return a parameter error (‘-1’) if any
of the input parameters is out of bounds, such as data
too large or invalid block number (see Function 7).
FUNCTION 8:
readByte()
/**
* Read a byte of data from HE Flash memory
*
* @param radd
source block of HE Flash memory
(0 - MAXROWS-1)
* @param offset offset within the HE block
(0 - ROWSIZE-1)
* @return
byte of data retrieved
*/
char
HEFLASH_readByte (char radd,
char offset);
For further convenience, the readByte() function
provides the ability to read any individual byte
contained in a high-endurance Flash memory by
passing a block number and an offset (see Function 8).
The value zero (‘0’) will be returned in case of success
(see Function 6).
DS00001673A-page 6
 2014 Microchip Technology Inc.
AN1673
RESERVING HIGH-ENDURANCE
FLASH MEMORY
It is important to note that the high-endurance Flash
memory region is normally assumed to be available to
the C compiler for the application code storage. In
order to avoid any possible conflict (overlapping code
and data usage), it is important to reserve the devicespecific memory range by using the --ROM linker
switch in the project configuration.
In the example in Figure 2, the region 0x1F80 to
0x1FFF (high-endurance Flash block for a
PIC16F1509 microcontroller) has been removed from
the default space available for code storage using the
notation:
--ROM=default,-1f80-1fff
This is documented in Section 4.8.50, --ROM: Adjust
ROM Ranges, of the “MPLAB® XC8 C Compiler User’s
Guide” (DS50002053) (see http://ww1.microchip.com/
downloads/en/DeviceDoc/xc8-v1.21-manual.pdf).
Note:
Make sure to use a double dash before
the ROM keyword and a comma
immediately following default.
FIGURE 2:
SETTING THE LINKER OPTIONS TO RESERVE THE HIGH-ENDURANCE FLASH
MEMORY FOR DATA STORAGE
 2014 Microchip Technology Inc.
DS00001673A-page 7
AN1673
Device Configuration
The device Configuration bits WRT<1:0>, contained in
Configuration Word CONFIG2, control the Flash
memory self-write protection. Such protection should
be set to off (‘11’) or limited to the lower portion of the
Flash memory array (‘10’, ‘01’).
An Example of Use
Listing A-1 provides a simple test program that can be
used to validate the library operation using a PICkit™
Low Pin Count Explorer Board (DM164130-9) in
conjunction to a PIC16F1509 device and a PICkit 3
debugger/programmer.
The PIC16F1509 has 8K words of program memory
and a row size of 32 bytes.
The high-endurance Flash memory is managed as four
blocks (0-3) capable of 32 bytes of data each.
Example 1 includes the definition of a simple data
structure called data of type Record.
EXAMPLE 1:
typedef struct{
unsigned ID ;
//
2 bytes
char Name[20]; //
20 bytes
long Amount;
//
4 bytes
} Record;
//
26 bytes total
Record data = {0x1234, "HE Flash", 42};
Once more, the returned value indicates whether the
function accepted the parameters and completed the
requested operation (see Figure 3).
FIGURE 3:
FITTING A DATA RECORD
IN A HIGH-ENDURANCE
FLASH BLOCK
Block: 0..3
ID
Record: unsigned
Offset: 0
Name
char[20]
2
Amount
long
ʹ2
nused
2͸
31
SUMMARY
Members
of
the
PIC16F1XXX
family
of
microcontrollers offer a high-endurance Flash block
that is capable of 100,000 erase/write cycles. The highendurance Flash can be effectively used to provide
nonvolatile storage, with EEPROM-like endurance and
simplicity, to low-cost embedded control applications.
The code provided supports and simplifies the
management of the high-endurance Flash block, as
well as the access to the standard Flash memory array.
This can be saved to a block (‘1’) of the high-endurance
Flash (see Example 2).
EXAMPLE 2:
r = HEFLASH_writeBlock(1,(void*)&data, sizeof
(data));
Note the use of the void* cast to pass the record-type
contents to the write function.
The returned value indicates whether the
writeBlock() function accepted and completed the
requested operation.
The contents of the high-endurance Flash block (‘1’)
can be read back into a record-type variable using the
command in Example 3.
EXAMPLE 3:
r = HEFLASH_readBlock((void*)&data, 1, sizeof
(data));
DS00001673A-page 8
 2014 Microchip Technology Inc.
AN1673
APPENDIX A:
EXAMPLE PROJECT
Software License Agreement
The software supplied herewith by Microchip Technology Incorporated (the “Company”) is intended and supplied to you, the
Company’s customer, for use solely and exclusively with products manufactured by the Company.
The software is owned by the Company and/or its supplier, and is protected under applicable copyright laws. All rights are reserved.
Any use in violation of the foregoing restrictions may subject the user to criminal sanctions under applicable laws, as well as to civil
liability for the breach of the terms and conditions of this license.
THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 2014 Microchip Technology Inc.
DS00001673A-page 9
AN1673
LISTING A-1:
Main.c
/*
* File:
main.c
* Author: Lucio Di Jasio
*
* Created on August 28, 2013
*/
#include "Flash.h"
#include "HEFlash.h"
#include <assert.h>
#include <string.h>
//
Configuration Bit Settings
__IDLOC( 4D8A);
// CONFIG1
#pragma config
#pragma config
#pragma config
#pragma config
#pragma config
FOSC = INTOSC
WDTE = OFF
PWRTE = OFF
MCLRE = ON
CP = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
//# pragma config IESO = ON
//# pragma config FCMEN = ON
//CONFIG2
#pragma config WRT = OFF
#pragma config STVREN = ON
#pragma config BORV = LO
#pragma config LPBOR = OFF
#pragma config LVP = OFF
// Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
// Watchdog Timer Enable (WDT disabled)
// Power-up Timer Enable (PWRT disabled)
// MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
// Flash Program Memory Code Protection
(Program memory code protection is disabled)
// Brown-out Reset Enable (Brown-out Reset enabled)
// Clock Out Enable
(CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
// Internal/External Switchover Mode
(Internal/External Switchover mode is enabled)
// Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// Flash Memory Self-Write Protection (Write protection off)
// Stack Overflow/Underflow Reset Enable
(Stack Overflow or Underflow will cause a Reset)
// Brown-out Reset Voltage Selection
(Brown-out Reset Voltage (VBOR), low trip point selected.)
// Low-Power Brown Out Reset (Low-Power BOR is disabled)
// Low-Voltage Programming Enable
(High-voltage on MCLR/VPP must be used for programming)
void_fassert (int line, const char *file, const char *expr)
{
TRISC = 0xf0;
PORTC = PORTC+1;
} // _fassert
void main(void)
{
unsigned r, i;
unsigned wbuffer[4];
char buffer [FLASH_ROWSIZE];
typedef struct {
unsigned ID;
char
Name[20];
long
Amount;
} Record;
Record data = {0x1234, "HE FLASH", 42};
//testing the FLASH read (word in program memory)
r = FLASH_read(0x0001);
assert (r == 0x3180);
//read the first IDLOC
r = FLASH_readConfig(0x8000);
assert (r == 4);
//testing the HE FLASH read block (bytes in HE Flash)
r = HEFLASH_readBlock (buffer, 1, FLASH_ROWSIZE);
assert (r == 0);
DS00001673A-page 10
 2014 Microchip Technology Inc.
AN1673
LISTING A-1:
Main.c (continued)
//write data to HE row 1
r = HEFLASH_writeBlock(1, (void*)&data, sizeof(data));
assert (r == 0);
//empty the buffer
memset(&data, 0, sizeof(data));
//data.ID = 0;
//data.Name[0] = '\0';
//data.Amount = 0L;
// read back its contents
r = HEFLASH_readBlock((void*)&data, 1, sizeof(data));
assert (r == 0);
//read a single byte
r = HEFLASH_readByte(1, 5);
assert (r == 'F');
while(1)
{
// stop here
}
}
 2014 Microchip Technology Inc.
DS00001673A-page 11
AN1673
APPENDIX B:
FLASH SUPPORT LIBRARY LISTINGS
LISTING B-1:
Flash.h
/*
* Flash.h
*
*/
#include<xc.h>
#if defined(_PIC16F1501_H_)
//1K
#define FLASH_ROWSIZE 16
//size of a row
#define HEFLASH_START
0x0380
//first address in HE Flash memory
#define HEFLASH_END
0x03FF
//last address in HE Flash memory
#elif defined(_PIC16F1503_H_)||defined(_PIC16F1507_H_)||defined(_PIC16F1512_H_)||\
defined(_PIC16F1703_H_)||defined(_PIC16F1707_H_)
//2K
#define FLASH_ROWSIZE 16
//size of a row
#define HEFLASH_START
0x0780
//first address in HE Flash memory
#define HEFLASH_END
0x07FF
//last address in HE Flash memory
#elif defined(_PIC16F1508_H_)||defined(_PIC16F1513_H_)||\
defined(_PIC16F1704_H_)||defined(_PIC16F1708_H_)||defined(_PIC16F1713_H_)
//4K
#define FLASH_ROWSIZE 32
//size of a row
#define HEFLASH_START
0x0F80
//first address in HE Flash memory
#define HEFLASH_END
0x0FFF
//last address in HE Flash memory
#elif defined(_PIC16F1509_H_)||defined(_PIC16F1526_H_)||\
defined(_PIC16F1454_H_)||defined(_PIC16F1455_H_)||defined(_PIC16F1459_H_)||\
defined(_PIC16F1705_H_)||defined(_PIC16F1709_H_)||\
defined(_PIC16F1716_H_)||defined(_PIC16F1717_H_)
//8K
#define FLASH_ROWSIZE 32
//size of a row
#define HEFLASH_START
0x1F80
//first address in HE Flash memory
#define HEFLASH_END
0x1FFF
//last address in HE Flash memory
#elif defined(_PIC16F1518_H)||defined(_PIC16F1519_H)||defined(_PIC16F1527_H_)||\
defined(_PIC16F1718_H_)||defined(_PIC16F1719_H_)
//16K
#define FLASH_ROWSIZE 32
//size of a row
#define HEFLASH_START
0x3F80
//first address in HE Flash memory
#define HEFLASH_END
0x3FFF
//last address in HE Flash memory
#endif
#define FLASH_ROWMASK
FLASH_ROWSIZE-1
/******************************************************************************
* Generic Flash functions
*/
/**
* Read a word from program Flash memory
*
* @param address
source address (absolute Flash memory address)
* @return
word retrieved from Flash memory
*/
unsigned FLASH_read (unsigned address);
/ **
* Read a word from configuration Flash memory
*
* @param address
source address (absolute Flash memory address)
* @return
word retrieved from Flash memory
*/
unsigned FLASH_readConfig (unsigned address);
/ **
* Read a block of words from program Flash memory
*
* @param buffer
destination buffer (must be sufficiently large)
* @param address
source address (absolute Flash memory address)
* @param count
number of words to be retrieved
*/
void
FLASH_readBlock (unsigned* buffer, unsigned address, char count);
DS00001673A-page 12
 2014 Microchip Technology Inc.
AN1673
LISTING B-1:
Flash.h (continued)
/ **
* Write a word of data to Flash memory (latches)
* an actual write is performed only if LWLO = 0, data is latched if LWLO = 1
*
* @param address
destination address (absolute Flash memory)
* @param data
word of data to be written (latched)
* @param latch
1 = latch, 0 = write
*/
void
FLASH_write (unsigned address, unsigned data, char latch);
/ **
* Erase a row of Flash memory
*
* @param address
absolute address in Flash contained in selected row
*/
void
FLASH_erase (unsigned address);
LISTING B-2:
Flash.c
/*
* File: Flash.c
*
* Self-Write Flash support functions
*
* Author: Lucio Di Jasio
*
* Created on August 28, 2013
*/
#include "Flash.h"
/******************************************************************************
* Generic Flash functions
*/
unsigned FLASH_readConfig (unsigned address)
{
// 1. load the address pointers
PMADR = address;
PMCON1bits.CFGS = 1;
//select the configuration Flash address space
PMCON1bits.RD = 1;
//next operation will be a read
NOP();
NOP();
// 2. return value read
return PMDAT;
}// FLASH_config
unsigned FLASH_read (unsigned address)
{
// 1. load the address pointers
PMADR = address;
PMCON1bits.CFGS = 0;
// select the Flash address space
PMCON1bits.RD = 1;
// next operation will be a read
NOP();
NOP();
// 2. return value read
return PMDAT;
} //FLASH_read
void FLASH_readBlock (unsigned *buffer, unsigned address, char count)
{
while (count > 0)
{
*buffer++ = FLASH_read (address++);
count--;
}
}// FLASH_readBLock
 2014 Microchip Technology Inc.
DS00001673A-page 13
AN1673
LISTING B-2:
Flash.c (continued)
/ **
* unlock Flash Sequence
*/
void _unlock (void)
{
#asm
BANKSEL
PMCON2
MOVLW
0x55
MOVWF
PMCON2 & 0x7F
MOVLW
0xAA
MOVWF
PMCON2 & 0x7F
BSF
PMCON1 & 0x7F,1
NOP
NOP
#endasm
}// unlock
; set WR bit
void FLASH_write (unsigned address, unsigned data, char latch)
{
// 1. disable interrupts (remember setting)
char temp = INTCONbits.GIE;
INTCONbits.GIE = 0;
// 2. load the
PMADR = address;
PMDAT = data;
PMCON1bits.LWLO =
PMCON1bits.CFGS =
PMCON1bits.FREE =
PMCON1bits.WREN =
address pointers
latch;
0;
0;
1;
//
//
//
//
1 = latch, 0 = write row
select the Flash address space
next operation will be a write
enable Flash memory write/erase
// 3. perform unlock sequence
_unlock();
// 4. restore interrupts
if (temp)
INTCONbits.GIE = 1;
}//FLASH_write
void FLASH_erase (unsigned address)
{
// 1. disable interrupts (remember setting)
char temp = INTCONbits.GIE;
INTCONbits.GIE = 0;
// 2. load the
PMADR = address;
PMCON1bits.CFGS =
PMCON1bits.FREE =
PMCON1bits.WREN =
address pointers
0;
1;
1;
//
//
//
select the Flash address space
next operation will be an erase
enable Flash memory write/erase
// 3. perform unlock sequence and erase
_unlock();
// 4. disable writes and restore interrupts
PMCON1bits.WREN = 0;
// disable Flash memory write/erase
if (temp)
INTCONbits.GIE = 1;
}//FLASH_erase
DS00001673A-page 14
 2014 Microchip Technology Inc.
AN1673
APPENDIX C:
HIGH-ENDURANCE FLASH SUPPORT LIBRARY LISTINGS
LISTING C-1:
HEFlash.h
/*
* HEFlash.h
*
*/
#include "FLash.h"
#define HEFLASH_MAXROWS
(HEFLASH_END-HEFLASH_START+1)/FLASH_ROWSIZE
/ ******************************************************************************
* High Endurance Flash functions
*/
/ **
* Write a block of data to High Endurance Flash
* the entire block must fit within a row
*
* @param radd
HE Flash block number(0 - MAXROWS-1)
* @param buffer
source buffer
* @param count
number of bytes to write to block (< ROWSIZE)
* @return
0 if successful, -1 if parameter error, 1 if write error
*/
char
HEFLASH_writeBlock (char radd, char* buffer, char count);
/ **
* Read a block of data from HE Flash memory
*
* @param buffer
destination buffer (must be sufficiently large)
* @param radd
source block of HE Flash memory (0 - MAXROWS-1)
* @param count
number of bytes to be retrieved (< ROWSZE)
* @return
0 if successful, -1 if parameter error
*/
char
HEFLASH_readBlock (char* buffer, char radd, char count);
/**
* Read a byte of data from HE Flash memory
*
* @param radd
source block of HE Flash memory (0 - MAXROWS-1)
* @param offset
offset within the HE block (0 - ROWSIZE-1)
* @return
byte of data retrieved
*/
char
HEFLASH_readByte (char radd, char offset);
 2014 Microchip Technology Inc.
DS00001673A-page 15
AN1673
LISTING C-2:
HEFlash.c
/*
* File: HEFlash.c
*
* High Endurance Flash - EEPROM emulation and support routines
*
* Author: Lucio Di Jasio
*
* Created on August 28, 2013
*/
#include "HEFlash.h"
/******************************************************************************
* High Endurance Flash functions
*/
char
{
HEFLASH_writeBlock (char radd, char* data, char count)
// 1. obtain absolute address in HE FLASH row
unsigned add = radd * FLASH_ROWSIZE + HEFLASH_START;
// 2. check input parameters
if ((count > FLASH_ROWSIZE)||(radd >= HEFLASH_MAXROWS))
return -1;//return parameter error
// 3. erase the entire row
FLASH_erase (add);
// 4. fill the latches with data
while (count > 1)
{
//load data in latches without writing
FLASH_write (add++, (unsigned) *data++, 1);
count--;
}
// no delay here!!!
// 5. last byte of data -> write
FLASH_write (add, (unsigned) *data, 0);
// NOTE: 2ms typ. delay here!!!
// 6. return success
return PMCON1bits.WRERR;
// 0 success, 1 = write error
} //HEFLASH_writeBlock
char HEFLASH_readBlock (char *buffer, char radd, char count)
{
// 1. obtain absolute address in HE FLASH row
unsigned add = radd * FLASH_ROWSIZE + HEFLASH_START;
// 2. check input parameters
if ((count > FLASH_ROWSIZE)||(radd >= HEFLASH_MAXROWS))
return -1;
// 3. read content
while (count > 0)
{
*buffer++ = (char) FLASH_read (add++);
count--;
}
// 4. success
return 0;
} //HEFLASH_readBlock
char HEFLASH_readByte (char radd, char offset)
{
// 1. add offset into HE Flash memory
unsigned add = radd * FLASH_ROWSIZE + HEFLASH_START + offset;
// 2. read content
return (char) FLASH_read (add);
} //HEFLASH_read
DS00001673A-page 16
 2014 Microchip Technology Inc.
Note the following details of the code protection feature on Microchip devices:
•
Microchip products meet the specification contained in their particular Microchip Data Sheet.
•
Microchip believes that its family of products is one of the most secure families of its kind on the market today, when used in the
intended manner and under normal conditions.
•
There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our
knowledge, require using the Microchip products in a manner outside the operating specifications contained in Microchip’s Data
Sheets. Most likely, the person doing so is engaged in theft of intellectual property.
•
Microchip is willing to work with the customer who is concerned about the integrity of their code.
•
Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as “unbreakable.”
Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of our
products. Attempts to break Microchip’s code protection feature may be a violation of the Digital Millennium Copyright Act. If such acts
allow unauthorized access to your software or other copyrighted work, you may have a right to sue for relief under that Act.
Information contained in this publication regarding device
applications and the like is provided only for your convenience
and may be superseded by updates. It is your responsibility to
ensure that your application meets with your specifications.
MICROCHIP MAKES NO REPRESENTATIONS OR
WARRANTIES OF ANY KIND WHETHER EXPRESS OR
IMPLIED, WRITTEN OR ORAL, STATUTORY OR
OTHERWISE, RELATED TO THE INFORMATION,
INCLUDING BUT NOT LIMITED TO ITS CONDITION,
QUALITY, PERFORMANCE, MERCHANTABILITY OR
FITNESS FOR PURPOSE. Microchip disclaims all liability
arising from this information and its use. Use of Microchip
devices in life support and/or safety applications is entirely at
the buyer’s risk, and the buyer agrees to defend, indemnify and
hold harmless Microchip from any and all damages, claims,
suits, or expenses resulting from such use. No licenses are
conveyed, implicitly or otherwise, under any Microchip
intellectual property rights.
Trademarks
The Microchip name and logo, the Microchip logo, dsPIC,
FlashFlex, KEELOQ, KEELOQ logo, MPLAB, PIC, PICmicro,
PICSTART, PIC32 logo, rfPIC, SST, SST Logo, SuperFlash
and UNI/O are registered trademarks of Microchip Technology
Incorporated in the U.S.A. and other countries.
FilterLab, Hampshire, HI-TECH C, Linear Active Thermistor,
MTP, SEEVAL and The Embedded Control Solutions
Company are registered trademarks of Microchip Technology
Incorporated in the U.S.A.
Silicon Storage Technology is a registered trademark of
Microchip Technology Inc. in other countries.
Analog-for-the-Digital Age, Application Maestro, BodyCom,
chipKIT, chipKIT logo, CodeGuard, dsPICDEM,
dsPICDEM.net, dsPICworks, dsSPEAK, ECAN,
ECONOMONITOR, FanSense, HI-TIDE, In-Circuit Serial
Programming, ICSP, Mindi, MiWi, MPASM, MPF, MPLAB
Certified logo, MPLIB, MPLINK, mTouch, Omniscient Code
Generation, PICC, PICC-18, PICDEM, PICDEM.net, PICkit,
PICtail, REAL ICE, rfLAB, Select Mode, SQI, Serial Quad I/O,
Total Endurance, TSHARC, UniWinDriver, WiperLock, ZENA
and Z-Scale are trademarks of Microchip Technology
Incorporated in the U.S.A. and other countries.
SQTP is a service mark of Microchip Technology Incorporated
in the U.S.A.
GestIC and ULPP are registered trademarks of Microchip
Technology Germany II GmbH & Co. KG, a subsidiary of
Microchip Technology Inc., in other countries.
All other trademarks mentioned herein are property of their
respective companies.
© 2014, Microchip Technology Incorporated, Printed in the
U.S.A., All Rights Reserved.
Printed on recycled paper.
ISBN: 9781620779033
QUALITY MANAGEMENT SYSTEM
CERTIFIED BY DNV
== ISO/TS 16949 ==
 2014 Microchip Technology Inc.
Microchip received ISO/TS-16949:2009 certification for its worldwide
headquarters, design and wafer fabrication facilities in Chandler and
Tempe, Arizona; Gresham, Oregon and design centers in California
and India. The Company’s quality system processes and procedures
are for its PIC® MCUs and dsPIC® DSCs, KEELOQ® code hopping
devices, Serial EEPROMs, microperipherals, nonvolatile memory and
analog products. In addition, Microchip’s quality system for the design
and manufacture of development systems is ISO 9001:2000 certified.
DS00001673A-page 17
Worldwide Sales and Service
AMERICAS
ASIA/PACIFIC
ASIA/PACIFIC
EUROPE
Corporate Office
2355 West Chandler Blvd.
Chandler, AZ 85224-6199
Tel: 480-792-7200
Fax: 480-792-7277
Technical Support:
http://www.microchip.com/
support
Web Address:
www.microchip.com
Asia Pacific Office
Suites 3707-14, 37th Floor
Tower 6, The Gateway
Harbour City, Kowloon
Hong Kong
Tel: 852-2401-1200
Fax: 852-2401-3431
India - Bangalore
Tel: 91-80-3090-4444
Fax: 91-80-3090-4123
Austria - Wels
Tel: 43-7242-2244-39
Fax: 43-7242-2244-393
Denmark - Copenhagen
Tel: 45-4450-2828
Fax: 45-4485-2829
Atlanta
Duluth, GA
Tel: 678-957-9614
Fax: 678-957-1455
Austin, TX
Tel: 512-257-3370
Boston
Westborough, MA
Tel: 774-760-0087
Fax: 774-760-0088
Chicago
Itasca, IL
Tel: 630-285-0071
Fax: 630-285-0075
Cleveland
Independence, OH
Tel: 216-447-0464
Fax: 216-447-0643
Dallas
Addison, TX
Tel: 972-818-7423
Fax: 972-818-2924
Detroit
Novi, MI
Tel: 248-848-4000
Houston, TX
Tel: 281-894-5983
Indianapolis
Noblesville, IN
Tel: 317-773-8323
Fax: 317-773-5453
Los Angeles
Mission Viejo, CA
Tel: 949-462-9523
Fax: 949-462-9608
New York, NY
Tel: 631-435-6000
San Jose, CA
Tel: 408-735-9110
Canada - Toronto
Tel: 905-673-0699
Fax: 905-673-6509
DS00001673A-page 18
Australia - Sydney
Tel: 61-2-9868-6733
Fax: 61-2-9868-6755
China - Beijing
Tel: 86-10-8569-7000
Fax: 86-10-8528-2104
China - Chengdu
Tel: 86-28-8665-5511
Fax: 86-28-8665-7889
China - Chongqing
Tel: 86-23-8980-9588
Fax: 86-23-8980-9500
China - Hangzhou
Tel: 86-571-2819-3187
Fax: 86-571-2819-3189
China - Hong Kong SAR
Tel: 852-2943-5100
Fax: 852-2401-3431
China - Nanjing
Tel: 86-25-8473-2460
Fax: 86-25-8473-2470
China - Qingdao
Tel: 86-532-8502-7355
Fax: 86-532-8502-7205
China - Shanghai
Tel: 86-21-5407-5533
Fax: 86-21-5407-5066
China - Shenyang
Tel: 86-24-2334-2829
Fax: 86-24-2334-2393
China - Shenzhen
Tel: 86-755-8864-2200
Fax: 86-755-8203-1760
China - Wuhan
Tel: 86-27-5980-5300
Fax: 86-27-5980-5118
China - Xian
Tel: 86-29-8833-7252
Fax: 86-29-8833-7256
India - New Delhi
Tel: 91-11-4160-8631
Fax: 91-11-4160-8632
India - Pune
Tel: 91-20-3019-1500
Japan - Osaka
Tel: 81-6-6152-7160
Fax: 81-6-6152-9310
Japan - Tokyo
Tel: 81-3-6880- 3770
Fax: 81-3-6880-3771
Korea - Daegu
Tel: 82-53-744-4301
Fax: 82-53-744-4302
Korea - Seoul
Tel: 82-2-554-7200
Fax: 82-2-558-5932 or
82-2-558-5934
France - Paris
Tel: 33-1-69-53-63-20
Fax: 33-1-69-30-90-79
Germany - Dusseldorf
Tel: 49-2129-3766400
Germany - Munich
Tel: 49-89-627-144-0
Fax: 49-89-627-144-44
Germany - Pforzheim
Tel: 49-7231-424750
Italy - Milan
Tel: 39-0331-742611
Fax: 39-0331-466781
Italy - Venice
Tel: 39-049-7625286
Malaysia - Kuala Lumpur
Tel: 60-3-6201-9857
Fax: 60-3-6201-9859
Netherlands - Drunen
Tel: 31-416-690399
Fax: 31-416-690340
Malaysia - Penang
Tel: 60-4-227-8870
Fax: 60-4-227-4068
Poland - Warsaw
Tel: 48-22-3325737
Philippines - Manila
Tel: 63-2-634-9065
Fax: 63-2-634-9069
Singapore
Tel: 65-6334-8870
Fax: 65-6334-8850
Taiwan - Hsin Chu
Tel: 886-3-5778-366
Fax: 886-3-5770-955
Spain - Madrid
Tel: 34-91-708-08-90
Fax: 34-91-708-08-91
Sweden - Stockholm
Tel: 46-8-5090-4654
UK - Wokingham
Tel: 44-118-921-5800
Fax: 44-118-921-5820
Taiwan - Kaohsiung
Tel: 886-7-213-7830
Taiwan - Taipei
Tel: 886-2-2508-8600
Fax: 886-2-2508-0102
Thailand - Bangkok
Tel: 66-2-694-1351
Fax: 66-2-694-1350
China - Xiamen
Tel: 86-592-2388138
Fax: 86-592-2388130
China - Zhuhai
Tel: 86-756-3210040
Fax: 86-756-3210049
10/28/13
 2014 Microchip Technology Inc.