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 文件、转至工程配置选项卡、然后禁用链接器文件生成。 然后需要手动将链接器添加到顶层项目目录中。 最简单的方法是生成链接器、然后禁用生成并在再次编译之前将生成的链接器复制到顶层目录。 然后保存更改并重建。
如果您想更进一步、您可以通过静态写操作来保护包含版本号和其他信息的内存区域、但根据您的描述、似乎您只是想确保您不会意外地刷写此内存、因此上述过程应该没问题。
非常感谢您的答复。 Keith、您能否仍然发送 GoPosition ()和 GetPosition ()函数的样子? 谢谢你
我可以这么做、但这实际上特定于我的步进电机驱动应用、重点是向您展示如何访问闪存:
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; }