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.

[参考译文] MSPM0G3507:存储变量

Guru**** 2031750 points
Other Parts Discussed in Thread: MSPM0G3507, SYSCONFIG
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1459721/mspm0g3507-storing-variables

器件型号:MSPM0G3507
主题中讨论的其他器件: SysConfig

工具与软件:

您好!

我想问一下如何最好地将数据保存到闪存中。 
我需要使用,例如,序列号,版本和其他变量等特定的内存地址。
但我希望某些值​​是只读的、其他值也是 R/W
例如、这些更改随后不能被代码覆盖。
有人可以建议吗?

谢谢你。
1月



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    其他人对此有更多的经验,但这里是我所做的。

    首先更改链接器文件以留出一些存储器。 闪存下部具有更多的读取/写入寿命:

    (这是我的 mspm0G3507.cmd 文件。 userconfig 是我为我的变量预留的内存。)

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    接下来定义存储器地址:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 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};
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    在主初始化代码中、如果已重新编程、请设置初始值-这会擦除所有保存的值:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 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);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    最后、如果需要、请将新信息写入闪存。 请注意,我总是写*一切*闪存,但你可能不需要

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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,
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    访问闪存非常简单:

    Fullscreen
    1
    void GoToMark(int mark) { GoPosition(*(int32_t *)Mark[mark]); }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    我想你必须做一些事情,以使用你的.cmd 文件的首选项,但我目前找不到它。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、Jan、Hi Keith、

    此过程几乎涵盖了该范围。

    若要确保使用的是定制的.cmd 文件、而不是 SysConfig 自动为您生成的文件、请转至 SysConfig 文件、转至工程配置选项卡、然后禁用链接器文件生成。 然后需要手动将链接器添加到顶层项目目录中。 最简单的方法是生成链接器、然后禁用生成并在再次编译之前将生成的链接器复制到顶层目录。 然后保存更改并重建。

    如果您想更进一步、您可以通过静态写操作来保护包含版本号和其他信息的内存区域、但根据您的描述、似乎您只是想确保您不会意外地刷写此内存、因此上述过程应该没问题。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    非常感谢您的答复。 Keith、您能否仍然发送 GoPosition ()和 GetPosition ()函数的样子? 谢谢你

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我可以这么做、但这实际上特定于我的步进电机驱动应用、重点是向您展示如何访问闪存:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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;
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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;
    }
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX