关于带有dspic33ep512mu810的闪存,我有一些问题。我知道该如何做:为地址、锁存等设置所有寄存器,然后执行顺序来启动写过程或调用builtins函数。
但是我发现在我的经历和DOC中的东西之间有一些小的区别。
int varWord1L = 0xXXXX;int varWord1H = 0x00XX;int varWord2L = 0xXXXX;int varWord2H = 0x00XX;int TargetWriteAddressL;// bits<15:0> int TargetWriteAddressH;// bits<22:16> NVMCON = 0x4001;// set WREN和word程序模式TBLPAG = 0xFA;// write闩锁上层地址NVMADR = TargetWriteAddressL;//设置目标写入地址NVMADRU = TargetWriteAddressH;__builtin_tblwtl(0,varWord1L);//加载写闩锁__builtin_tblwth(0,varWord1H);__builtin_tblwtl(0x2,varWord2L);__builtin_tblwth(0x2,varWord1H);__builtin_disi(5);//禁用NVM解锁序列__builtin_write_NVM()的中断;//启动写时(NVMCONbits.WR == 1);
但根据我想写的地址,这段代码不起作用。我找到了写一个字的办法,但我不能在我想写的地方写两个字。我把所有东西都存储在aux内存中,所以上面的地址(NVMADRU)对我来说总是0x7F。NVMADR是我可以更改的地址。我看到的是,如果我想要写模块4的地址不是0,那么我必须把我的值放在最后的两个锁存中,否则我必须把这个值放在第一个锁存中。
如果地址模块4不是零,它的工作方式不像文档代码(上面)。地址上的值将是第二组闩锁中的值。我把它修正为一次只写一个字:
if(Address % 4)
{
__builtin_tblwtl(0, 0xFFFF);
__builtin_tblwth(0, 0x00FF);
__builtin_tblwtl(2, ValueL);
__builtin_tblwth(2, ValueH);
}
else
{
__builtin_tblwtl(0, ValueL);
__builtin_tblwth(0, ValueH);
__builtin_tblwtl(2, 0xFFFF);
__builtin_tblwth(2, 0x00FF);
}我想知道为什么我会看到这种行为?
2)我也想写一整行。这似乎也不适合我,我也不知道为什么,因为我在做DOC的事情。我尝试了一个简单的写行代码,最后我只读取了我编写的第一个3或4个元素,看看它是否有效:
NVMCON = 0x4002; //set for row programming
TBLPAG = 0x00FA; //set address for the write latches
NVMADRU = 0x007F; //upper address of the aux memory
NVMADR = 0xE7FA;
int latchoffset;
latchoffset = 0;
__builtin_tblwtl(latchoffset, 0);
__builtin_tblwth(latchoffset, 0); //current = 0, available = 1
latchoffset+=2;
__builtin_tblwtl(latchoffset, 1);
__builtin_tblwth(latchoffset, 1); //current = 0, available = 1
latchoffset+=2;
.
. all the way to 127(I know I could have done it in a loop)
.
__builtin_tblwtl(latchoffset, 127);
__builtin_tblwth(latchoffset, 127);
INTCON2bits.GIE = 0; //stop interrupt
__builtin_write_NVM();
while(NVMCONbits.WR == 1);
INTCON2bits.GIE = 1; //start interrupt
int testaddress;
testaddress = 0xE7FA;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);
testaddress += 2;
status = NVMemReadIntH(testaddress);
status = NVMemReadIntL(testaddress);我看到的是存储在地址0xE7FA中的值是125,在0xE7FC中是126,在0xE7FE中是127。其余的都是0xFFFF。为什么它只取最后3个锁存,并将它们写在前3个地址中?
提前感谢你们的帮助。
发布于 2022-03-21 13:30:27
dsPIC33程序内存空间被视为24位宽,更合适的做法是将程序内存的每个地址看作一个上下字,而上层单词的上字节未实现。

每两个程序单词就有一个幻影字节。
你的代码
if(Address % 4)
{
__builtin_tblwtl(0, 0xFFFF);
__builtin_tblwth(0, 0x00FF);
__builtin_tblwtl(2, ValueL);
__builtin_tblwth(2, ValueH);
}
else
{
__builtin_tblwtl(0, ValueL);
__builtin_tblwth(0, ValueH);
__builtin_tblwtl(2, 0xFFFF);
__builtin_tblwth(2, 0x00FF);
}如果从有效的Intel文件生成值,则...will可以编写引导加载程序,但并不能简化数据结构的存储,因为没有考虑到幻影字节。
如果您创建一个uint32_t变量并查看已编译的HEX文件,您会注意到它实际上耗尽了两个24位程序单词中最不重要的单词。也就是说,32位值被放置在64位范围内,但64位中只有48位是可编程的,其余的是幻影字节(或零)。留下三个字节,每个地址模块4,实际上是可编程的。
如果写数据的话,我倾向于做的是保持32位对齐,并和编译器一样。
写作:
UINT32 value = ....;
:
__builtin_tblwtl(0, value.word.word_L); // least significant word of 32-bit value placed here
__builtin_tblwth(0, 0x00); // phantom byte + unused byte
__builtin_tblwtl(2, value.word.word_H); // most significant word of 32-bit value placed here
__builtin_tblwth(2, 0x00); // phantom byte + unused byte 阅读:
UINT32 *value
:
value->word.word_L = __builtin_tblrdl(offset);
value->word.word_H = __builtin_tblrdl(offset+2);UINT32结构:
typedef union _UINT32 {
uint32_t val32;
struct {
uint16_t word_L;
uint16_t word_H;
} word;
uint8_t bytes[4];
} UINT32;https://stackoverflow.com/questions/68763839
复制相似问题