Microchip dsPIC33F, PIC24HのFLASH自己書き込み

Kevin Culkins執筆、最終校正2015年7月31日

このページでは、MicrochipのデジタルシグナルコントローラdsPIC33F/PIC24HファミリのFLASH自己書き込み機能(Self Write capability)をサポートするC関数を説明します。

はじめに

このページのコードは、dsPIC33FJ12MC201のFLASH自己書き込み機能を使用する必要があるプログラムで生まれました。アセンブリの例は、通常ブートローダの一部として見つけることができますが、当時、私はC言語の例を見つけることができませんでした。最終的に、Microchipコード例データベースでサンプルコードCE109を見つけましたが、XC16コンパイラリファレンスドキュメントを確認して、必要なコードは既に開発していましたので、基本的なルーチンはここに収めました。私の検索能力が低かったせいで開発することになったコードがお役に立てればと思います。プログラムFLASHからRAMにデータをコピーする関数と、プログラムFLASHにデータを消去したり書き込む関数は別々に含まれています。FLASHの自己書き込みルーチンを独自に開発する際の参考資料としていただければ幸いです。

FLASH自己書き込み機能

このソースコード例は、もともとユーザーが変更可能ないくつかのタイムアウトパラメータを保存するために書かれたものです。デフォルトのタイムアウトデータ値は、FLASHプログラムからロードされ、Program Space Visibilityモードを利用しています。この機能は、dsPIC33F/PIC24Hのデータメモリアドレス空間の上位32Kバイトを、任意の16Kワードのプログラム空間ページにマッピングするものです。これにより、TBLRD、TBLWTのような特別な命令を使用することなく、Xデータ空間に保存された定数データに透過的にアクセスできます(プログラム空間の可視性の詳細については、個々のデバイスファミリのリファレンスマニュアルを参照してください)。

また、このソースコードは、XC16 Cコンパイラで利用可能な組み込み関数に依存しています。これらの関数は、構文的には関数呼び出しのようにコード化されていますが、コンパイルされたアセンブリコードであり、関数呼び出しやライブラリルーチンを含みません。ビルトイン関数に関する情報は、MPLAB® XC16 C Compiler User’s GuideのAppendix Gおよび16-bit MCU and DSC Programmer’s Reference ManualのSection 6に掲載されています。

dsPIC33F/PIC24HのプログラムメモリとFLASHプログラミングに関する追加情報は、ファミリ・リファレンスマニュアルのセクション4と5にそれぞれ記載されています。これらは、デバイスのウェブページまたはこちらから入手できます。セクション 4. プログラムメモリ – dsPIC33F/PIC24H FRM、およびセクション 5. フラッシュ プログラミング – dsPIC33F/PIC24H FRM

このケースでは、ユーザー管理のPSVアクセス方法を使用して、定数をユーザー定義のアドレスに格納することにしました。または、コンパイラがPSV空間を管理することも可能です。詳細は、デバイス個別のリファレンスマニュアル、プログラムメモリセクションに記載されています。消去/読み取り/書き込み関数で参照されるメモリポインタを供給するために、PSVコードが含まれています。

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

プログラム実行時、PSVの値は初期化中にデータメモリにマッピングされます。データ値は、FLASHプログラムメモリから読み出され、データ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;
}

次の関数は、デフォルトのタイムアウト値が存在するFLASHメモリブロックを消去し、自己書き込み機能を使用して新しいデータをプログラムするために使用されます。

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

FLASHWrite関数は、アンロックシーケンスを発行して、書き込み用にFLASHを有効にする処理を行います。このコードのほとんどは、ビルトイン関数「__builtin_write_NVM」で置き換えることができます。なぜ最初にそうしなかったのでしょうか?開発当時は、FLASHの書き込みを解除するための組み込み関数が用意されていることを知りませんでした。ビルトイン関数の情報は、前述のC言語ユーザーガイドまたはプログラマーズリファレンスマニュアルを参照してください。

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

結論

MicrochipのdsPIC33ファミリコントローラのFLASH自己書き込み機能を利用することは難しくないということが分かっていただけたと思います。これらのコード例が、独自のFLASH自己書き込みルーチンを開発する際の時間短縮につながることを願っています。

サポートファイル

ソースコード

eewiki_FLASH_selfwrite_funcs.zip (1.5 KB)

CE109

サポートドキュメント

MPLAB® XC16 C Compiler User’s Guide

16-bit MCU and DSC Programmer’s Reference Manual

セクション 4. プログラムメモリ – dsPIC33F/PIC24H FRM

セクション 5. フラッシュ プログラミング – dsPIC33F/PIC24H FRM

質問/コメント

コメント、フィードバック、提案、質問などをお待ちしています。DigiKeyのTechForumにアクセスしてください。




オリジナル・ソース(English)