dsPIC33 Flash Erase broken



当涉及到dsPIC33EP64GP503上的闪光擦除时,我遇到了很多麻烦,我希望这里有人能帮助我。

我想在设备的闪存程序存储器中存储一个数据结构。我有麻烦,当谈到消除闪光灯。当数据发生变化时,我需要擦除并重新写入。

我正在用0填充页面的其余部分,以便可以安全地擦除。

可以写入结构体的相同内存位置。当做一个flash写入到结构的开始,byStructValid变成0x11(我知道这是非常糟糕的,因为它是写双字。但我只是想让闪存操作工作第一),然而,当我做一个擦除什么都没有发生。有人能指出我做错了什么吗?

我用0xFF初始化结构并尝试执行闪存写入。这是成功的,因为我收到的CAN消息显示数据从0xFF更改为0x11。

然后我试着做一个flash擦除,但什么也没发生。设备正常运行。我无法访问调试,所以很难完全理解在这段时间里发生了什么。

我已经尝试移动结构体的位置,使它是在一个"偶数"页面边界(如数据表中指定),但这也没有工作。我还尝试使用数据表提供的擦除功能的汇编版本,这也不起作用。设备就像没有flash擦除命令一样运行。

下面是我一直在使用的一些代码片段:

任何帮助都将非常感激,谢谢。

注意:我无法使用调试器。我使用CAN消息定期发送"调试"消息,其中包含从闪存位置读取的数据。这样我就可以看到写/擦除是否在工作。

#define MEMORY_USER_CALIBRATION_LOC 0x006000
typedef struct
{
byte byStructValid;
byte abyStructData[3];
}stFlashStruct_t;
volatile const __prog__ stFlashStruct_t stFlashStruct __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) =
{   
.byStructValid = 0xFF,  
.abyStructData = {50, 10, 20},
};
const byte padding[_FLASH_PAGE*2 - sizeof(stFlashStruct_t)] __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC + sizeof(stFlashStruct_t)))) = {0};
//FLASH Write
void FLASH_WriteDoubleWord(dword address, dword data[2])
{
word INTCON2Save;
word i;

//set WREN and ERASE settings for operation
NVMCON = 0x4001;
TBLPAG = 0xFA;

//set address to erase
NVMADR = address & 0xFFFF; 
NVMADRU = (address >> 16) & 0x3F; 

for (i = 0; i < 2; i++)
{
__builtin_tblwtl(i*2, data[i] & 0xFFFF);
__builtin_tblwth(i*2, (data[i] >> 16) & 0xFF);
}
//save the interrupt register
INTCON2Save = INTCON2;

// Disable interrupts for NVM unlock 
__builtin_disable_interrupts(); 
__builtin_write_NVM();

// Start write cycle 
while(NVMCONbits.WR == 1); 

//restore interrupts
INTCON2 = INTCON2Save;
}
//FLASH Erase
void FLASH_ErasePageC(dword dwAddress)
{
word INTCON2Save;

//set WREN and ERASE settings for operation
NVMCON = 0x4003;

//set address to erase
NVMADRU = (dwAddress >> 16) & 0x3F; 
NVMADR = dwAddress & 0xFFFF; 

//save the interrupt register
INTCON2Save = INTCON2;

__builtin_disable_interrupts(); 

// Disable interrupts for NVM unlock 
__builtin_write_NVM();

// Start write cycle 
while(NVMCONbits.WR == 1); 

//restore interrupts
INTCON2 = INTCON2Save;
}
byte temp_flash_write(void)
{
dword new_data[2] = {0x1111, 0x1111};

FLASH_WriteDoubleWord(&stCustomerCalibration, new_data);
return 0;
}

Your "dsPIC33 Flash Erase "问题是不理解Microchip dsPIC33EP64GP503数据表和系列参考手册中描述的运行时Flash编程(RTFP)方法有多糟糕。

这篇文章不会解释这些是如何工作的。它确实有效,但真的很难理解。

对你来说困难的是程序flash字在擦除后只能写入一次。第二次写入同一个程序flash字会损坏它,下次读取它时将断言一个ECC陷阱错误。

附件是分配地址为0x6000的1024指令字页的示例代码。在该页的开头声明一个结构,大小为2个指令字。然后,该代码擦除该页,然后将不同的数据写入该页中的前两个指令字。

/*
* File:   main.c
* Author: Dan1138
*
* Description:
*  Example for Run Time Self Programming (RTSP).
*  This is very limited, useful as a test bench but not much more.
* 
* Created on December 10, 2022, 2:05 PM
*/
/* Define the system oscillator frequency this code must configure */
#define FSYS (7372800ul)
#define FCY  (FSYS/2ul)
// DSPIC33EP64GP503 Configuration Bit Settings
// 'C' source line config statements
// FICD
#pragma config ICS = PGD1               // ICD Communication Channel Select bits (Communicate on PGEC1 and PGED1)
#pragma config JTAGEN = OFF             // JTAG Enable bit (JTAG is disabled)
// FPOR
#pragma config ALTI2C1 = OFF            // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF            // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25           // Watchdog Window Select bits (WDT Window is 25% of WDT period)
// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128           // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON              // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)
// FOSC
#pragma config POSCMD = NONE            // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON            // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin)
#pragma config IOL1WAY = OFF            // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD           // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)
// FOSCSEL
#pragma config FNOSC = FRC              // Oscillator Source Selection (Internal Fast RC (FRC))
#pragma config IESO = ON                // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)
// FGS
#pragma config GWRP = OFF               // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF                // General Segment Code-Protect bit (General Segment Code protect is Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <libpic30.h>
#define MEMORY_USER_CALIBRATION_LOC (_FLASH_PAGE * 24)
typedef struct
{
uint8_t byStructValid;
uint8_t abyStructData[3];
} stFlashStruct_t;
volatile const __prog__ __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) union 
{
uint16_t words[_FLASH_PAGE];    /* reserve the entire erase page. Note only the low 16-bits of the instruction word can be accessed with this method. */
struct {
stFlashStruct_t stFlashStruct;  /* calibration structure */
};
} CalSpace =
{   
.stFlashStruct.byStructValid = 0xFF,  
.stFlashStruct.abyStructData = {50, 10, 20},
};
int main(void) 
{
volatile stFlashStruct_t ReadBack;

/*
* application initialization
*/
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint();  /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();

/* Erase 1024 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4003;
NVMADR = __builtin_tbloffset(&CalSpace);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_disi(5);                          // Disable interrupts for NVM unlock
__builtin_write_NVM();                      // Start write cycle
while(NVMCONbits.WR == 1);    
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint();  /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();

/* Update data in structure to be written */
ReadBack.byStructValid = 1;
ReadBack.abyStructData[0] = 2;
ReadBack.abyStructData[1] = 3;
ReadBack.abyStructData[2] = 4;
/* Write 2 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4001; // Set WREN and word program mode
TBLPAG = 0xFA; // write latch upper address
NVMADR = __builtin_tbloffset(&CalSpace.stFlashStruct);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_tblwtl(0,*((uint16_t *)(&ReadBack)+0));   // load low 16-bits of first instruction word
__builtin_tblwth(0,0x00);                           // make high 8-bits of first instruction word zero
__builtin_tblwtl(2,*((uint16_t *)(&ReadBack)+1));   // load low 16-bits of second instruction word
__builtin_tblwth(2,0x00);                           // make high 8-bits of second instruction word zero
__builtin_disi(5); // Disable interrupts for NVM unlock sequence
__builtin_write_NVM(); // initiate write
while(NVMCONbits.WR == 1);

ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint();  /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/*
* Application process loop
*/
for(;;)
{
Nop();
Nop();
Nop();
__delay_ms(100);
}
}

相关内容

  • 没有找到相关文章

最新更新