主题中讨论的其他器件: SysConfig
工具与软件:
您好!
我想问一下如何最好地将数据保存到闪存中。
我需要使用,例如,序列号,版本和其他变量等特定的内存地址。
但我希望某些值是只读的、其他值也是 R/W
例如、这些更改随后不能被代码覆盖。
有人可以建议吗?
谢谢你。
1月
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具与软件:
您好!
我想问一下如何最好地将数据保存到闪存中。
我需要使用,例如,序列号,版本和其他变量等特定的内存地址。
但我希望某些值是只读的、其他值也是 R/W
例如、这些更改随后不能被代码覆盖。
有人可以建议吗?
谢谢你。
1月
其他人对此有更多的经验,但这里是我所做的。
首先更改链接器文件以留出一些存储器。 闪存下部具有更多的读取/写入寿命:
(这是我的 mspm0G3507.cmd 文件。 userconfig 是我为我的变量预留的内存。)
Modified for persistant flash storage: Keith Barkley Feb 2024
*****************************************************************************/
-uinterruptVectors
--stack_size=512
MEMORY
{
IntVectors (RW) : origin = 0x00000000, length = 0x00000400
USERCONFIG (RW) : origin = 0x00000400, length = 0x00000400
FLASH (RX) : origin = 0x00000800, length = 0x0001F800
SRAM (RWX) : origin = 0x20200000, length = 0x00008000
BCR_CONFIG (R) : origin = 0x41C00000, length = 0x00000080
BSL_CONFIG (R) : origin = 0x41C00100, length = 0x00000080
}
SECTIONS
{
.intvecs: > 0x00000000
.text : palign(8) {} > FLASH
.const : palign(8) {} > FLASH
.cinit : palign(8) {} > FLASH
.pinit : palign(8) {} > FLASH
.rodata : palign(8) {} > FLASH
.ARM.exidx : palign(8) {} > FLASH
.init_array : palign(8) {} > FLASH
.binit : palign(8) {} > FLASH
.TI.ramfunc : load = FLASH, palign(8), run=SRAM, table(BINIT)
.vtable : > SRAM
.args : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.BCRConfig : {} > BCR_CONFIG
.BSLConfig : {} > BSL_CONFIG
}
接下来定义存储器地址:
// Mark Flash Addresses
#define MAIN_BASE_ADDRESS (0x00000400)
#define MAGIC_ADDRESS (MAIN_BASE_ADDRESS)
#define MARK0_ADDRESS (MAIN_BASE_ADDRESS + 8)
#define MARK1_ADDRESS (MAIN_BASE_ADDRESS + 16)
#define MARK2_ADDRESS (MAIN_BASE_ADDRESS + 24)
#define MAGIC_VALUE (0xDEADBEEF)
int32_t Mark[3] = {MARK0_ADDRESS, MARK1_ADDRESS, MARK2_ADDRESS};
在主初始化代码中、如果已重新编程、请设置初始值-这会擦除所有保存的值:
// If necessary, init the mark flash values
// Note if there are problems writing to flash, we may trigger an ECC error
// and NMI.
tmp = *(uint32_t *)MAGIC_ADDRESS;
if (tmp != MAGIC_VALUE) {
// initial setup of flash, set the marks to zero.
// First erase our sector
/* Unprotect sector in main memory with ECC generated by hardware */
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
/* Erase sector in main memory */
cmdstatus = DL_FlashCTL_eraseMemoryFromRAM(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_COMMAND_SIZE_SECTOR);
// Write Magic
tmp = MAGIC_VALUE;
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MAGIC_ADDRESS, &tmp);
// Write Mark0
tmp = 0;
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK0_ADDRESS, &tmp);
// Write Mark1
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK1_ADDRESS, &tmp);
// Write Mark2
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK2_ADDRESS, &tmp);
}
最后、如果需要、请将新信息写入闪存。 请注意,我总是写*一切*闪存,但你可能不需要
void WriteMarkToFlash() {
bool done;
DL_FLASHCTL_COMMAND_STATUS cmdstatus;
int32_t position = GetPosition();
// since we have to erase the flash to write it, stash all the flash
// note if the flash has gone bad, we may get an NMI...
uint32_t magic = *(uint32_t *)MAGIC_ADDRESS;
int32_t mark0 = (CurrentMark == 0) ? (position) : (*(int32_t *)MARK0_ADDRESS);
int32_t mark1 = (CurrentMark == 1) ? (position) : (*(int32_t *)MARK1_ADDRESS);
int32_t mark2 = (CurrentMark == 2) ? (position) : (*(int32_t *)MARK2_ADDRESS);
/* Unprotect sector in main memory with ECC generated by hardware */
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
/* Erase sector in main memory */
cmdstatus = DL_FlashCTL_eraseMemoryFromRAM(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_COMMAND_SIZE_SECTOR);
// Write Magic
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MAGIC_ADDRESS, &magic);
// Write Mark0
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK0_ADDRESS, (uint32_t *)&mark0);
// Write Mark1
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK1_ADDRESS, (uint32_t *)&mark1);
// Write Mark2
DL_FlashCTL_unprotectSector(FLASHCTL, MAIN_BASE_ADDRESS,
DL_FLASHCTL_REGION_SELECT_MAIN);
cmdstatus = DL_FlashCTL_programMemoryFromRAM32WithECCGenerated(
FLASHCTL, MARK2_ADDRESS, (uint32_t *)&mark2);
}
访问闪存非常简单:
void GoToMark(int mark) { GoPosition(*(int32_t *)Mark[mark]); }
我想你必须做一些事情,以使用你的.cmd 文件的首选项,但我目前找不到它。
大家好、Jan、Hi Keith、
此过程几乎涵盖了该范围。
若要确保使用的是定制的.cmd 文件、而不是 SysConfig 自动为您生成的文件、请转至 SysConfig 文件、转至工程配置选项卡、然后禁用链接器文件生成。 然后需要手动将链接器添加到顶层项目目录中。 最简单的方法是生成链接器、然后禁用生成并在再次编译之前将生成的链接器复制到顶层目录。 然后保存更改并重建。
如果您想更进一步、您可以通过静态写操作来保护包含版本号和其他信息的内存区域、但根据您的描述、似乎您只是想确保您不会意外地刷写此内存、因此上述过程应该没问题。
我可以这么做、但这实际上特定于我的步进电机驱动应用、重点是向您展示如何访问闪存:
int32_t GetPosition() {
int32_t tmp;
/// Safe way to get position even while running
NVIC_DisableIRQ(TIMER_0_INST_INT_IRQN);
tmp = StepCount;
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
return tmp;
}void GoPosition(int pos) {
int32_t distance;
Stop();
// Find out how far
distance = pos - StepCount;
DoAccel = true;
CurrentSpeed = SLOWSPEED;
if (distance > 0) {
StepDir = FWD_DIR;
DL_GPIO_clearPins(GPIO_STEPPER_PORT, GPIO_STEPPER_PIN_DIR_PIN);
CurrentStep = 0;
NumSteps = distance;
} else if (distance < 0) {
StepDir = REV_DIR;
DL_GPIO_setPins(GPIO_STEPPER_PORT, GPIO_STEPPER_PIN_DIR_PIN);
CurrentStep = 0;
NumSteps = -distance;
}
DisplayPos();
}
int32_t GetPosition() {
int32_t tmp;
/// Safe way to get position even while running
NVIC_DisableIRQ(TIMER_0_INST_INT_IRQN);
tmp = StepCount;
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
return tmp;
}