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**** 2538950 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 是我为我的变量预留的内存。)

    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;
    }