描述和提供支持 dsPIC33F/PIC24H 系列 Microchip 数字信号控制器的闪存自写功能的 C 函数。
介绍本页的代码内容开始于一个需要使用 dsPIC33FJ12MC201 的闪存自写功能的程序中。可以找到汇编示例,通常作为引导加载程序的一部分,但当时我无法在 C 中找到示例。最终,我找到了一个代码示例,CE109 17, 在 Microchip 代码示例数据库中,但已经通过查看 XC16 编译器参考文档开发了所需的代码。因为我已经在这里捕获了基本例程,所以我糟糕的搜索技巧是您的收获。包括将数据从程序 FLASH 复制到 RAM 和擦除/写入数据到程序 FLASH 的单独功能。希望这可以作为开发您自己的 FLASH 自写例程的另一个参考点。
FLASH 自写功能示例源代码最初是为了保存几个用户可修改的超时参数而编写的。默认超时数据值从程序闪存加载,并利用程序空间可见性操作模式。此功能将 dsPIC33F/PIC24H 数据存储器地址空间的高 32 KB 映射到任何 16K 字的程序空间页面。这提供了对来自 X 数据空间的存储常量数据的透明访问,而无需使用诸如 TBLRD、TBLWT 之类的特殊指令(有关程序空间可见性的详细信息,请参阅特定器件系列参考手册)。
此外,此源代码依赖于 XC16 C 编译器中可用的内置函数。这些函数在语法上与函数调用类似,但都是编译后的汇编代码,不涉及函数调用或库例程。MPLAB® XC16 C 编译器用户指南的附录 G 中提供了有关内置函数的信息 4和/或16 位 MCU 和 DSC 程序员参考手册的第 6 节 1.
有关 dsPIC33F/PIC24H 程序存储器和闪存编程的更多信息,请分别在系列参考手册第 4 节和第 5 节中找到,可在器件网页上或此处找到:第 04 节。程序存储器——dsPIC33F/PIC24H FRM 5和05. 闪存编程——dsPIC33F/PIC24H FRM 8.
在这种情况下,我选择使用用户管理的 PSV 访问方法将常量存储在用户定义的地址。或者,可以依靠编译器来管理 PSV 空间。详细信息在特定于器件的参考手册的程序存储器部分中提供。包含 PSV 代码以提供在擦除/读/写功能中引用的内存指针。
/********************************************************************************/// Default
timeout limits in FLASH program memoryconst unsigned int Parameters[3] __attribute__((space(psv), address(0x1FF0))) = {10, 20, 30}; // Timeout limits are globalunsigned int timeout1, timeout2, timeout3 = 0;/********************************************************************************/
在程序执行时,PSV 值将在初始化期间映射到数据存储器中。数据值从闪存程序存储器中读取并复制到数据 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;}
以下函数用于擦除默认超时值所在的闪存块,并使用自写功能对新数据进行编程。
/******************************************************************************** * 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 函数负责通过发出解锁序列来启用闪存以进行写入。大多数代码可以用内置函数“__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 17
支持文档MPLAB® XC16 C 编译器用户指南 4
16 位 MCU 和 DSC 程序员参考手册 1
第 04 节程序存储器——dsPIC33F/PIC24H FRM 5
第 05 节闪存编程——dsPIC33F/PIC24H FRM 8