Writing to Flash Memory on a 16-bit PIC® MCU

Overview of Writing to Flash Memory

Flash memory panels on 16-bit PIC® Microcontrollers (MCUs) are divided into pages. Each page consists of a number of rows. Each row has a set of 24-bit program words. Page and row sizes differ among the MCUs. Consult the datasheet to determine the page and row sizes for the PIC MCU you are using.

The implementation details of flash pages and rows are invisible to the application program. Rows and pages have no effect on program control or where the linker places program objects. Pages and rows are only taken into consideration when the application writes to the flash memory at run-time.

Writing to flash consists of loading the data to be written into a holding latch (or series of latches) using Table Write instructions. The flash address to be written to is loaded in the NVM address register. Once the data and address are loaded, a specific sequence of register operations will initiate the writing process. The writing process transfers the data from the holding latches into the Flash memory. During the writing process, the MCU stalls, resuming once the write operation has been completed

All 16-bit PIC MCUs allow the application program to specify individual Flash memory words to be written. Using this word addressed write method, 24-bits of data are loaded into a write latch with a pair of Table Write instructions (TBLWTH and TBLWTL). After the latch is loaded, the applications load the destination address into the NVM address registers. After both sets of registers are loaded, the application sets the control bits, then executes the write sequence on the NVMKEY register. The write sequence causes the data in the latches to be written to the Flash address specified by the NVM address registers.

Some devices provide the ability to program an entire row at one time. To program an entire row, the application loads a series of holding latch registers with repeated Table Write instructions. The applications then load the first address of the row to be written into the NVM address registers. After both sets of registers are loaded, the application executes the write sequence. With row programming, an entire row is written to flash at one time.

Resources used in writing to Flash Memory

Instructions

Assembly Read Instructions
TBLRDL Table_Read_Low Reads the lower 16-bits of a 24-bit flash memory word. The address to be read is designated by the TBLPAG register and a working register passed to this instruction.
TBLRDH Table_Read_High Reads the upper 8- bits of a 24-bit flash memory word. The address to be read is designated by the TBLPAG register and a working register passed to this instruction.

Read Read Flash Memory for more details on table read instructions.

Assembly Write Instructions
TBLWTL Table_Write_Low Loads 16-bits of data into a holding latch. The address of the data latch to be written to is designated by the table page TBLPAG register and a working register. The latch will be written to flash memory when the programming sequence is initiated
TBLWTH Table_Write_High Loads 8-bits of data into a holding latch. The address of the data latch to be written to is designated by the TBLPAG register and a working register. The latch will be written to flash memory when the programming sequence is initiated.
C Language Macros
Macro Description
__builtin_tblpage Returns the page number of the memory address received as a parameter. For table instructions the returned value is placed in TBLPAG
__builtin_tbloffset Returns the "offset" from the base page address for a memory location whose address is passed as a parameter. The return value of this function is passed as a parameter to table read and table write instructions
__builtin_write_NVM Performs the programming sequence on NVMKEY then immediately sets the WR. __builtin_NVM causes the contents of the data latch(es) to be written to flash memory. This macro does NOT disable interrupts.
__builtin_disi Disables interrupts for a set number of instructions. This macro is typically called immediately preceding __builtin_write_NVM
__builtin_tblrdh Returns the upper 8-bits of the memory address specified by TBLPAG and the offset parameter. (Calls TBLRDH instruction)
__builtin_tblrdl Returns the lower 16-bits of the memory address specified by TBLPAG and the offset parameter. (Calls TBLRDL instruction)
__builtin_tblwrth Writes 8-bits of data to a holding latch which will be programmed to flash when the program sequence is initiated. This function receives two parameters: the value to be written and a page offset. This function determines the latch to be programmed using the contents of TBLPAG and the offset parameter. (Calls TBLWRTH instruction)
__builtin_tblwrtl Writes 16-bits of data to a holding latch which will be programmed to flash when the program sequence is initiated. This function receives two parameters: the value to be written and a page offset. This function determines the latch to be programmed using the contents of TBLPAG and the offset parameter. (Calls TBLWRTL instruction)

Registers

TBLPAG Table Page Register - TBLPAG is used by the Table Read and Table Write instructions. This register specifies the upper 8-bits of the address to be accessed by the table instruction. The lower 16-bits of the address are passed to the instruction as a value in a working register. When a Table Read instruction is to be executed this register contains the page address of the word to be read. When a Table Write instruction is to be executed TBLPAG should be loaded with the base address of the holding latch(es) (#FA00 on many 16-bit PIC® MCUs.)

NVMADR/NVMADDRU NVM Address Registers. Holds the address of the flash memory word (or row address) which will be written to when the program sequence is executed. After loading the holding latch(es) the application sets the destination address in NVMADR/NVMADRU before initiating the write sequence. The write sequence causes the data to be copied from the latches into the flash memory location specified by NVMADR/NVMADRU.

NVMCON Non-Volatile Memory Control Register - The register through which the application selects the function to be performed when the program sequence is executed. The options in this register include Erase Page, Write Word, and Write Row. NVMCON also contains the bit to be written to start the write process (WR).

NVMKEY Non-Volatile Memory KeyRegister - To reduce the potential for flash to be modified by a spurious write to NVMCON WR cannot be set unless a specific sequence of data values are written to NVMKEY. This sequence is commonly referred to as the program sequence. Once the sequence is executed WR becomes 'write-able' for 2 instruction cycles.

Program (Unlock) Sequence

The program sequence for a 16-bit PIC® Microcontroller (MCU) is performed by writing specific values, in successive order, to NVMKEY. Writing 0x55, immediately followed by 0xAA, will unlock WR for two instruction cycles. If WR is set within two instruction cycles of the programming sequence, the MCU will perform the flash self-write process.

Interrupts should be disabled during the write program sequence to prevent servicing an interrupt between the two write instructions.

The unlock sequence can be written in C so long as the compiler places the two write instructions in sequential order. The MPLAB® XC16 compiler provides the function builtin-write-NVM to perform this program sequence. After executing the program sequence, builtin-write-NVM sets WR which initiates a flash write.

Using MPLAB® XC16 C Compiler

Using Assembly Language

Algorithm to Self-Program Flash Memory on a 16-bit PIC® MCU

The 16-bit PIC® MCU reference manual advises that a row or word in Flash program memory should not be programmed twice before being erased. Given this erase-before-programming mandate, the following application flow is commonly used:

1

Copy the Page To Be Updated Into Data Memory

  • Load the base address of the Flash memory page into TBLPAG.
  • Using successive TBLRDH and TBLRDL instructions, copy the contents of the Flash page to data RAM. Care should be taken when copying 24-bit wide Flash memory into the 16-bit wide data memory. One word of Flash memory requires two read instructions (TBLRDH and TBLRDL). These two read instructions will return a total of 32 bits of data.

Example of Reading a Page of Flash Memory

2

Update the Page In Data Memory

Pages can only be erased in their entirety. This means that updating even a single word of Flash memory requires the entire page to be read into Random Access Memory (RAM), erased in Flash, then reprogrammed. Unlike most Electrically Erasable Programmable Read-Only Memory (EEPROM) implementations, Flash memory words cannot be individually updated.

3

Erase the Page In Flash Memory

  • Load the base address of the page to be erased into the NVM address registers NVMADR and NVMADDRU. The base address is a modulo of the page size. For MCU's with a page size of 1024, the lowest 10 bits of the address for all page addresses will be '0'. Ensure that the value placed into NVMADR has the correct base address by masking off the appropriate number of lower bits.
  • Set the bits in NVMCON to enable writes and erase the page. The MCU in this example requires the value 0x4003 to set WREN and to erase a page. Check the datasheet for the bits to set in NVMCON of the MCU being used.
  • Disable interrupts for the duration of the write sequence.
  • Perform the program sequence.
  • Ensure WR is set within two instruction cycles of the completion of the programming sequence. __builtin_write_NVM issues the program sequence, then sets WR.

4

Program the New Data Into the Flash Memory

To write Flash, you must first consult the datasheet for the part you are using to determine the base address of the write latches. This information is typically listed in the memory map section rather than the Flash memory section of the datasheet. In this example, 0xFA000 is the base address of the write latches.

Writing a Row of Flash Data

  • Set TBLPAG with bits <11:8> of the base address of the write latches.
  • Using multiple TBLWRTH and TBLWRTL instructions move data from ram into the data latches.
  • Load NVMADR and NVNADDRU with the base address of the Flash row to be written to.
  • Set the Write Enable (WREN) and the bits needed to write a row into NVMCON.
  • Perform the program sequence.
  • Set WR within two cycles of completing the program sequence.

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site 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.