FLASH Self Write Microchip dsPIC33F, PIC24H

Created by Kevin Culkins, last modified on Jul 31, 2015

The purpose of this page is to describe and provide C functions supporting the FLASH Self Write capability of the dsPIC33F/PIC24H family of Microchip Digital Signal Controllers.

Introduction

The code content of this page began life in a program that required use of the FLASH Self Write capability of the dsPIC33FJ12MC201. Assembly examples can be found, typically as part of a bootloader, but at the time, I was unable to find examples in C. Eventually, I found a code example, CE109, in the Microchip code example database, but had already developed the code required through review of the XC16 compiler reference documents. My poor search skills are your gain as I’ve captured the basic routines here. The separate functions to copy data from program FLASH to RAM and erase/write data to program FLASH are included. Hopefully, this can serve as another point of reference in developing your own FLASH selfwrite routines.

FLASH Self Write Functions

The example source code was originally written to save several user modifiable timeout parameters. The default timeout data values are loaded from program FLASH, and take advantage of the Program Space Visibility mode of operation. This feature maps the upper 32 Kbytes of dsPIC33F/PIC24H data memory address space into any 16K word program space page. This provides transparent access of stored constant data from X data space without the need to use special instructions such as TBLRD, TBLWT (refer to the specific device family reference manual for details on program space visibility).

Also, this source code relies on the built-in functions available in the XC16 C compiler. These functions are coded syntactically like function calls, but are compiled assembly code, and do not involve function calls or library routines. Information on the built-in functions is available in Appendix G of the MPLAB® XC16 C Compiler User’s Guide and/or Section 6 of the 16-bit MCU and DSC Programmer’s Reference Manual.

Additional information on the dsPIC33F/PIC24H Program Memory and Flash Programming can be found in the Family Reference Manual Sections 4 and 5 respectively, available on the device webpage or here: Section 04. Program Memory – dsPIC33F/PIC24H FRM and Section 05. Flash Programming – dsPIC33F/PIC24H FRM.

In this case, I’ve chosen to use the User Managed PSV access method to store the constants at a user defined address. Alternatively, one can rely on the compiler to manage the PSV space. Details are provided in the device specific Reference Manual, Program Memory Section. The PSV code is included to supply the memory pointers that are referenced in the erase/read/write functions.

/********************************************************************************/
// Default timeout limits in FLASH program memory
const unsigned int Parameters[3] __attribute__((space(psv), address(0x1FF0))) = {10, 20, 30};
 
// Timeout limits are global
unsigned int timeout1, timeout2, timeout3 = 0;
/********************************************************************************/

Upon program execution, the PSV values will be mapped into data memory during initialization. The data values are read from FLASH program memory and copied to data RAM.

/********************************************************************************
 *  initParameters()
 *
 *  Prototype: (void) initParameters(void)
 *  Passed arguments: none
 *  Return value: none
 *  Dependencies: none
 *
 *  Description:  Read the timeout parameters from the Program Space
 *  Visibility area and copy to RAM.
 ********************************************************************************/
void initParameters(void)
{
    int memptrtemp;
    // User Managed PSV
    memptrtemp = PSVPAG;    // Save the auto_psv page
    PSVPAG = __builtin_psvpage(&iParameters);   // get address
    CORCONbits.PSV = 1;                         // Set PSV enable
    timeout1 = Parameters[0];              // Read parameters and assign to variables
    timeout2 = Parameters[1];
    timeout3 = Parameters[2];
    PSVPAG = memptrtemp;    // Restore auto_psv page
 
 
    return;
}

The following functions are used to erase a block of FLASH memory, where the default timeout values reside, and use the selfwrite capability to program the new data.

/********************************************************************************
 *  programParameters()
 *
 *  Prototype: int programParameters(unsigned int, unsigned int, unsigned int)
 *  Passed arguments: unsigned int param1, unsigned int param2, unsigned int param3
 *  Return value: none
 *  Dependencies: INTERRUPTS MUST be DISABLED prior to calling this routine.
 *
 *  Description:  Erase block of NVM and write data to FLASH memory
 ********************************************************************************/
void programParameters(unsigned int param1, unsigned int param2, unsigned int param3)
{
    unsigned int tbloffset;
 
    //Erase one page of FLASH memory
    NVMCON = 0x4042;   // Setup NVMCON for Block Erase operation (512 instructions)
    TBLPAG = __builtin_tblpage(&iParameters[0]);  // Load upper FLASH address
    tbloffset = __builtin_tbloffset(&iParameters[0]);  // Offset within page
    __builtin_tblwtl(tbloffset, 0xFFFF);  // Dummy write to select the page
    FLASHWrite();        // low level erase/write command sequence
 
    // write single word, param1, to FLASH
    // In this case the Page hasn't changed so don't have to load the table
    // page register again.
    tbloffset = __builtin_tbloffset(&iParameters[0]);  // offset within page
    __builtin_tblwtl(tbloffset, param1);  // load the write buffer
    NVMCON = 0x4003;     // Setup NVMCON for Single Word Write operation
    FLASHWrite();        // low level erase/write command sequence
 
    // write single word, param2, to FLASH
    tbloffset = __builtin_tbloffset(&iParameters[1]);  // offset within page
    __builtin_tblwtl(tbloffset, param2);  // load the write buffer
    NVMCON = 0x4003;     // Setup NVMCON for Single Word Write operation
    FLASHWrite();        // low level erase/write command sequence
 
    // write single word, param3, to FLASH
    tbloffset = __builtin_tbloffset(&iParameters[2]);  // offset within page
    __builtin_tblwtl(tbloffset, param3);  // load the write buffer
    NVMCON = 0x4003;     // Setup NVMCON for Single Word Write operation
    FLASHWrite();        // low level erase/write command sequence
 
    return;
}

The FLASHWrite function takes care of enabling Flash for writing by issuing the unlock sequence. Most of the code could be replaced with the builtin function “__builtin_write_NVM”. Why didn’t I do that in the first place? At the time of development I didn’t know there was a builtin function available to unlock the Flash for writing. Reference the aforementioned C User Guide or Programmers Ref Manual for builtin function information.

/********************************************************************************
 *  FLASHWrite()
 *
 *  Prototype: (void) FLASHWrite(void)
 *  Passed arguments: none
 *  Return value: none
 *  Dependencies: Must have NVMCOM, TBLPAG, and table write buffer initialized
 *                prior to calling this routine.  NVMCOM must have the erase
 *                or write enable bits correctly set.
 *  Description:  Provides the low level FLASH erase/write command sequence
 *                required to erase a page of FLASH, or write a row of data in
 *                FLASH, or write a single word in FLASH.  It clears the
 *                NVMCOM WR bit before returning to calling function.
 ********************************************************************************/
void FLASHWrite()
{
    __builtin_disi(5);      // Disable interrupts for 5 cycles
    NVMKEY = 0x55;          // Write requisite KEY values for FLASH access
    NVMKEY = 0xAA;
    NVMCONbits.WR = 1;      // Activate the erase action
    __builtin_nop();        // Requires two nops for time delay
    __builtin_nop();
    NVMCONbits.WR = 0;      // Clear the write action bit
 
    return;
}

CONCLUSION

I think you’ll agree that it isn’t difficult to take advantage of the FLASH self-write capability of the Microchip dsPIC33 family of controllers, and hope these code examples will save time as you develop your own FLASH self-write routines.

Supporting Files

Source Code

eewiki_FLASH_selfwrite_funcs.zip (1.5 KB)

CE109

Supporting Documentation

MPLAB® XC16 C Compiler User’s Guide

16-bit MCU and DSC Programmer’s Reference Manual

Section 04. Program Memory – dsPIC33F/PIC24H FRM

Section 05. Flash Programming – dsPIC33F/PIC24H FRM

Questions/Comments

We welcome comments, feedback, suggestions, and questions. Please go to the DigiKey TechForum

A post was split to a new topic: FLASH Self Write Question