本帖最后由 lcczg 于 2024-10-12 09:39 编辑
在AVR D系列芯片中有一个非易失存储区是USERROW,BOOTROW, 可以用来存放终端产品的一些信息,例如校准数据,密钥串码之类的。芯片擦除(erase)时它不受影响,不会被擦。
在调试的时候耗费了一些时间,所以这里和大家分享一下,用到的话可以做一个参考。
我用的硬件是AVR64DU32 Cnano板(https://www.microchip.com/en-us/development-tool/ev59f82a),
IDE是MPLABX 6.20, 编译器XC8 v2.50.
程序里对USERROW操作,先擦再写,再读出来,调试时可以看到写入读出的数据是一致的。
USERROW大小512字节,测试时写入了32字节做验证。工程在附件里,这里直接贴一下代码
#include <xc.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#define USER_ROW_START_ADDRESS 0x1200
#define USER_ROW_SIZE 32
uint8_t read_buf[USER_ROW_SIZE];
uint8_t read_user_row(uint16_t address)
{
return *(uint8_t *) address;
}
void erase_user_row(void) {
while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FLBUSY_bm));
_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc); // Enter erase mode
USERROW_USERROW = 0; // trigger page(512byte) Erase
while (NVMCTRL.STATUS & NVMCTRL_FLBUSY_bm);
_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc); // Leave erase mode
}
void write_user_row(uint8_t *data, uint8_t length) {
// Set up the NVMCTRL to write to the user row
NVMCTRL.ADDR = USER_ROW_START_ADDRESS;
// Write data to the user row
for (uint8_t i = 0; i < length; i++) {
while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FLBUSY_bm));
CCP = CCP_SPM_gc ;
NVMCTRL.CTRLA = 0x02;
*((uint8_t *)(USER_ROW_START_ADDRESS + i)) = data;
}
}
int main(void) {
uint8_t user_data[USER_ROW_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20};
// Erase USERROW
erase_user_row();
// Write the user data to the user row
write_user_row(user_data, USER_ROW_SIZE);
// Read data from the user row
for (uint8_t i = 0; i < USER_ROW_SIZE; i++) {
read_buf = read_user_row(USER_ROW_START_ADDRESS + i);
}
while (1) {
// Main loop
NOP();
}
return 0;
}
烧录运行后,可以读出memory 内容到一个文件,
读出后打开文件,可以看到写入的数据
|