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.

[参考译文] TMS320F280037C:正确的闪存写入流程

Guru**** 2512495 points
Other Parts Discussed in Thread: SYSBIOS

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1324782/tms320f280037c-proper-flash-write-flow

器件型号:TMS320F280037C
Thread 中讨论的其他器件:SYSBIOS

您好!

我正在开发一个闪存管理器、它将写入一些重要数据、例如 CAN 网络的测试结果和节点 ID。 我想知道如何在闪存地址管理方面添加此内容。

目前、要保存的变量是应在生命周期中运行一次的测试结果、以及可能在生命周期中多次更改的节点 ID 值。 我来问了三个问题,我想和你分享。

首先、关于我只想擦除部分扇区以写入新数据、我想知道与保存要在另一个扇区中擦除的扇区相比、是否有更好的写入闪存的方法、 擦除并复制包含新数据的内容。 其次、我想知道将调用闪存 API 的函数是否也需要放入 RAM 中、或者只要待擦除的扇区不包含代码执行、我就可以将它们保留在闪存中。 最后,我想知道,最佳做法是保留一个部门,填充此类变量,还是将其分散在不同部门,甚至放在代码运行所在的相同部门。

此致、

大卫

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

    尊敬的 David:

    该器件闪存存储体中的最小可擦除单元是一个扇区-不可能仅擦除部分扇区。

    如果您想知道是否有更好的闪存写入方法、则需要知道 计划写入扇区的数据大小是多少?  这会占领整个行业吗?  如果不是、您可以将多个此类数据条目编程到扇区中、直到它变满、然后将该数据切换到新  扇区、以便可以擦除以前填充的扇区。  这意味着、您不必在每次更新数据时擦除扇区。   我们确实有一个适用于 TMS320F28P65x 的 EEPROM 仿真示例- https://www.ti.com/lit/pdf/sprade8。 另外、我们 计划在3月发布基于 F28003x 的 EEPROM 示例。   

    可以在您对另一个闪存组进行编程/擦除的同时从一个闪存组执行闪存 API (不过、请考虑此勘误表: https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1320238/faq-tms320f280039x-tms320f28004x-flash-api-usage-advisory-errata)。  但是、无法从计划对其执行擦除/编程操作以存储数据的同一个闪存存储体中执行闪存 API。

    最佳做法是保留几个部门,开始填补一个部门,并在第一个部门已满时转到另一部门。

    谢谢。此致、
    瓦姆西

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

    您好 Vamsi、

    目前数据的大小将是32位变量、因此目前扇区太大、无法满足我们的需求。 此外、IS 未展示此器件:

    f not ,您可以将多个此类数据条目编程到扇区中,直到它变满,然后将该数据切换到新  扇区,这样您就可以擦除以前填充的扇区。

    您是指使用相同的变量对整个闪存扇区进行编程、直到该扇区被占用? 为什么此目的比仅对变量进行一次编程更好?

    阅读了应用手册后,我仍然相信这种方法。 使用 EEPROM 仿真的要点是、每次请求值更新时、我可以查看不同闪存地址中同一变量的多个实例? 然后、是否应该将在 EEPROM 中找到的最后一个值读取为实际值?

    此致、

    大卫

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

    此外、我对链接器文件.cmd 有另一个问题。 如果将两个不同的代码段分配到同一个 lfash 组、会发生什么情况? 我有任何问题吗?

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

    尊敬的 David:

    我可以在一两天内查看并与您联系。

    谢谢。此致、
    瓦姆西

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

    您好 Vamsi、

    感谢你的帮助。 此外,是否有可能看看我在尝试将库集成到我们的项目中时遇到的这个错误?

    错误出现在来自 C2000安装的文件中、我不知道如何能够获取该错误。 我在添加文件 F021_F28003x_C28x.h 时会遇到这些错误。

    我正在使用的.cmd 如下所示:

    内存
    {
      begin             :origin = 0x00080000、length = 0x00000002
      BOOT_RSVD      :origin = 0x00000002、length = 0x00000126

      RAMM0             :origin = 0x00000128、length = 0x000002D8
      RAMM1           :origin = 0x00000400,length = 0x00000380    /*片上 RAM 块 M1 */
      BOOT_RSVD_SYSBIOS:origin = 0x00000780、length = 0x00000080

    /* RAMLS0          :origin = 0x00008000、length = 0x00000800
      RAMLS1          :origin = 0x00008800、length = 0x00000800
      RAMLS2          :origin = 0x00009000、length = 0x00000800
      RAMLS3          :origin = 0x00009800、length = 0x00000800
      RAMLS4          :origin = 0x0000A000、length = 0x00000800 */
      RAMLS04         :origin = 0x00008000、length = 0x00002800
      RAMLS5          :origin = 0x0000A800、length = 0x00000800
      RAMLS6          :origin = 0x0000B000、length = 0x00000800
      RAMLS7          :origin = 0x0000B800、length = 0x00000800
      
      RAMGS0          :origin = 0x0000C000、length = 0x00001000
      RAMGS1          :origin = 0x0000D000、length = 0x00001000
      RAMGS2          :origin = 0x0000E000、length = 0x00001000
      RAMGS3          :origin = 0x0000F000、length = 0x00001000

      BootROM         :origin = 0x003F8000、length = 0x00007FC0
      SECURE_ROM      :origin = 0x003F2000、length = 0x00006000

      复位           :origin = 0x003FFFC0、length = 0x00000002

      /*闪存扇区*/
      /*组0 */
      FLASH_BANK0_SEC0 :origin = 0x080002、length = 0x000FFE
      FLASH_BANK0_SEC1 :origin = 0x081000、length = 0x001000
      FLASH_BANK0_sec2 :origin = 0x082000、length = 0x001000
      FLASH_BANK0_SEC3 :origin = 0x083000、length = 0x001000
      FLASH_BANK0_SEC4 :origin = 0x084000、length = 0x001000
      FLASH_BANK0_SEC5 :origin = 0x085000、length = 0x001000
      FLASH_BANK0_SEC6 :origin = 0x086000、length = 0x001000
      FLASH_BANK0_sec7 :origin = 0x087000、length = 0x001000
      FLASH_BANK0_SEC8 :origin = 0x088000、length = 0x001000
      FLASH_BANK0_SEC9 :origin = 0x089000、length = 0x001000
      FLASH_BANK0_SEC10:origin = 0x08A000、length = 0x001000
      FLASH_BANK0_SEC11:origin = 0x08B000、length = 0x001000
      FLASH_BANK0_SEC12:origin = 0x08C000、length = 0x001000
      FLASH_BANK0_SEC13:origin = 0x08D000、length = 0x001000
      FLASH_BANK0_SEC14:origin = 0x08E000、length = 0x001000
      FLASH_BANK0_SEC15:origin = 0x08F000、length = 0x001000

      /*组1 */
      FLASH_BANK1_SEC0 :origin = 0x090000、length = 0x001000
      FLASH_BANK1_SEC1 :origin = 0x091000、length = 0x001000
      FLASH_BANK1_SEC2 :origin = 0x092000、length = 0x001000
      FLASH_BANK1_SEC3 :origin = 0x093000、length = 0x001000
      FLASH_BANK1_SEC4 :origin = 0x094000、length = 0x001000
      FLASH_BANK1_SEC5_6 :origin = 0x095000、length = 0x002000
      //FLASH_BANK1_SEC5 :origin = 0x095000、length = 0x001000
      //FLASH_BANK1_SEC6 :origin = 0x096000、length = 0x001000
      FLASH_BANK1_SEC7 :origin = 0x097000、length = 0x001000
      FLASH_BANK1_SEC8 :origin = 0x098000、length = 0x001000
      FLASH_BANK1_SEC9 :origin = 0x099000、length = 0x001000
      FLASH_BANK1_SEC10:origin = 0x09A000、length = 0x001000
      FLASH_BANK1_SEC11:origin = 0x09B000、length = 0x001000
      FLASH_BANK1_SEC12:origin = 0x09C000、length = 0x001000
      FLASH_BANK1_SEC13:origin = 0x09D000、length = 0x001000
      FLASH_BANK1_SEC14:origin = 0x09E000、length = 0x001000
      FLASH_BANK1_SEC15:origin = 0x09F000、length = 0x001000

     /*组2 */
      FLASH_BANK2_SEC0 :origin = 0x0A0000、length = 0x001000
      FLASH_BANK2_SEC1 :origin = 0x0A1000、length = 0x001000
      FLASH_BANK2_sec2 :origin = 0x0A2000、length = 0x001000
      FLASH_BANK2_SEC3 :origin = 0x0A3000、length = 0x001000
      FLASH_BANK2_SEC4 :origin = 0x0A4000、length = 0x001000
      FLASH_BANK2_SEC5 :origin = 0x0A5000、length = 0x001000
      FLASH_BANK2_SEC6 :origin = 0x0A6000、length = 0x001000
      FLASH_BANK2_sec7 :origin = 0x0A7000、length = 0x001000
      FLASH_BANK2_SEC8 :origin = 0x0A8000、length = 0x001000
      FLASH_BANK2_SEC9 :origin = 0x0A9000、length = 0x001000
      FLASH_BANK2_SEC10:origin = 0x0AA000、length = 0x001000
      FLASH_BANK2_SEC11:origin = 0x0AB000、length = 0x001000
      FLASH_BANK2_SEC12:origin = 0x0AC000、length = 0x001000
      FLASH_BANK2_SEC13:origin = 0x0AD000、length = 0x001000
      FLASH_BANK2_SEC14:origin = 0x0AE000、length = 0x001000
      FLASH_BANK2_SEC15:origin = 0x0AF000、length = 0x001000





    部分
    {
      codestart       :> beging, align (8)
      .text           :>> FLASH_BANK0_sec2 | FLASH_BANK0_SEC3 | FLASH_BANK0_SEC4 | FLASH_BANK0_SEC5 | FLASH_BANK0_SEC6 | FLASH_BANK0_SEC7 | FLASH_BANK0_SEC8、ALIGN  (8)
      .cinit          :> FLASH_BANK0_SEC1、 align (8)
      .switch         :> FLASH_BANK0_SEC1、ALIGN (8)
      .reset          :> reset,                 type = DSECT /*未使用,*/

      .stack          :> RAMM1

    #if defined (__TI_EABI __)
      .init_array     :> FLASH_BANK0_SEC1、ALIGN (8)
      .bss            :> RAMLS5
      .bss:输出:     > RAMLS04
      bss:CIO:        > RAMLS04
      .data           :> RAMLS5
      .sysmem         :> RAMLS5
      .const          :> FLASH_BANK1_SEC5_6、ALIGN (8)
    #else
      .pinit          :> FLASH_BANK0_SEC1、ALIGN (8)
      .ebss           :>> RAMLS5 | RAMLS6
      .esysmem        :> RAMLS5
      CIO            :> RAMLS04
      econst         :> FLASH_BANK0_SEC9、ALIGN (8)
    #endif

       ramgs0:> RAMGS0
       ramgs1 :> rammGS0

       /* 分配 IQ 数学领域:*/
      IQMath          :> FLASH_BANK0_SEC1、ALIGN (8)
      IQmathTables    :> FLASH_BANK0_sec2, ALIGN (8)

     组
      {
          .TI.ramfunc
          {-l FAPI_F28003x_COFF_v1.58.01.lib}

      } LOAD = FLASH_BANK0_SEC1、
         RUN = RAMLS04、
         Load_start (_RamfuncsLoadStart)、
         Load_Size (_RamfuncsLoadSize)、
         Load_End (_RamfuncsLoadEnd)、
         RUN_START (_RamfuncsRunStart)、
         RUN_SIZE (_RamfuncsRunSize)、
         RUN_END (_RamfuncsRunEnd)、
         对齐(8)

       /* TBD las variables que se usaran */

       DataBufferSection :> RAMM1, ALIGN(8)

    最后、链接器和文件的包含选项:

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

    尊敬的 David:

    请为每一个新问题打开新帖子-这将帮助我们的团队为您提供良好的支持。  我们可以在该主题中讨论原始问题。

    谢谢。此致、
    瓦姆西

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

    David:

    关于我建议的有关 EEPROM 模型的问题:  

    • 1) 1)您不需要通过扇区对相同的变量进行编程。  您可以从扇区的第一个位置开始对所选变量的第一个值进行编程。  只要有想要编程的更新值、就可以在下一个可用地址中对其进行编程。  然后继续操作、直到扇区(EEPROM 组/页)填满。
    • 2) 2)是的、您会读取最后的编程数据。  EEPROM 驱动程序中有一个函数可用于读取最后一个编程数据。 请通读本指南、如果您有任何具体问题、请告诉我们。   

    关于代码段映射到闪存组:在将两个不同的代码段映射到链接器命令文件中的给定闪存条目时没有任何问题。  链接器不会在闪存存储体中的相同地址分配两个段。  链接器将为这些代码段分配不同的地址范围。  编译后可以查看映射文件、以了解链接器将每个段放置在何处。

    谢谢。此致、

    瓦姆西

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

    您好 Vamsi、

    感谢您的答复。 我理解了行为。 现在、我将尝试实现 EEPROM 仿真。 非常感谢您的帮助。

    此致、

    大卫