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.

[参考译文] TMS320F28379D:闪存操作问题

Guru**** 2540720 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1303254/tms320f28379d-flash-operations-problem

器件型号:TMS320F28379D

您好!

当文本连续写入和删除到微芯片闪存15-16次时、CCS 会断开与调试屏幕的连接。 我需要切断电源、然后再对电路板重新供电。  

此外、闪存操作示例仅工作一次。 我需要连续写入/擦除几次。  

有什么建议吗?

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

    您能否更详细地介绍一下您如何对闪存进行编程、是通过 CCS 加载还是 CPU 运行调用闪存 API 的代码?  至于操作示例、这只是用于显示用法的不同闪存命令的集合、不应出于任何原因而多次调用闪存编程/擦除功能。

    我相信在此示例中、我们将禁用看门狗计时器、因此不应存在计时超时的风险、但您可以确保在示例顶部调用看门狗禁用功能的情况就是如此。  如果启用 WD 很重要、有一些方法可以保持启用 WD、但您必须使用回调函数在不同闪存操作之间为 WD 提供服务。

    此致!

    马修

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

    Matthew、您好!

    我们有关于通过闪存 API Fapi 库进行闪存编程的问题。

    在本例中,我们需要将应用程序相关变量写入一些非易失性存储器,如外部 EEPROM,并有时将其擦除,但在本例中,我们为此目的使用 MCU 的内部闪存扇区 N 而不是外部 EEPROM (我们的 MCU C2000 f28379d )。

    这些读取、写入和擦除情况不仅仅是一次性的情况、尤其是应用程序需要记录或更新一些应用程序相关变量时、该代码的闪存编程部分需要执行、 例如、我们有32位 x 255个变量、需要每1秒连续记录所有这些变量。

    在代码看门狗始终禁用的情况下、我们不使用看门狗。 我们的代码有一点复杂、我们在闪存和 RAM 部分中执行了若干中断例程。 还有我们无法在 RAM 上执行的代码的闪存读取写入擦除部分(.TI.ramfuncs),它在闪存上运行。 我看到有关 RAM 和闪存部件执行的多个 POST 导致该 fapi 函数相关代码执行出现问题。 我尝试将这个与 fapi 相关的代码放入闪存和 RAM 中、 但对我们的示例并没有太大影响、仍然在记录我们的值、在记录20 25次之后、问题会出现、然后在调试模式下、调试断开连接然后重新连接到电路板一些变量连接到闪存、但有些不是、有时所有变量0xFF。 此问题有点随机。 此外、我试图独立运行而不进行调试、结果是一样的。

    此外、写入扇区 N 有某种顺序、我们不是在写入之前擦除该扇区而写入扇区 N。 是否正确、我们需要在每次写入之前进行擦除?

    此外,我们的系统时钟200MHz,我们正在配置闪存 API 200MHz/206Mhz %3%规则,但不工作,我们配置 fapi inint 120MHz,它的工作在上述有问题的情况下。 为什么不在200MHz 的频率下工作?

    我 共享了代码的闪存编程部分:

    在.cmd 文件中:

    我们添加了

    BufferDataSection :> RAMD1, page = 1, align (8)

    在闪存编程库代码部分中:

    #define  words_in_flash_buffer   0xFF              //编程数据缓冲区,字
    #pragma DATA_SECTION (FlashBuffer,"BufferDataSection");
    unsigned int FlashBuffer[words_in_flash_buffer + 1];
    unsigned long int  * FlashBuffer32 =(UINT32 *) FlashBuffer;
    unsigned int FlashReadBuffer [50]
    t_45100c Flash_Operation_ E_s Flash_Operation_对象

    FlashEraseOperation()
    {
      UINT32 u32Index = 0
      UINT16 I = 0
      Fapi_Status 回退检查
      Volatile Fapi_Flash usType oFlashStatus;
      Fapi_Flash 15.4WordType oFlashStatusWord;

      //  *
      //  *擦除扇区
      //  *
      
      EALLOW;
      DcsmCommonRegs.FLSEM = 0xA501
      EDIS;
      InitFlash()
      //
      //禁用 ECC。
      //
      EALLOW;
      Flash0EccRegs.ECC_ENABLE_bit.enable = 0x0
      //
      //根据系统初始化闪存 API 需要该函数
      //执行任何其他闪存 API 操作之前的频率
      //
      oReturnCheck = Fapi_initializeAPI (F021_CPU0_BASE_ADDRESS、120);
      //
      // Fapi_setActiveFlashBank 函数设置闪存组和 FMC 以进一步
      //将要在组上执行的闪存操作
      //
      oReturnCheck = Fapi_setActiveFlashBank (Fapi_Flash 0);
      //
      //擦除扇区 N
      //
      oReturnCheck = Fapi_issueAsyncCommandWithAddress (
          Fapi_Erase 52,(Uint32*);Bzero_Sector
      //
      //等待 FSM 完成擦除扇区操作
      //
      while (Fapi_checkFsmForReady()!= Fapi_Status_Fsm )
      {
      }
      //
      //验证 SectorL 是否已擦除。  擦除步骤本身会执行
      //按顺序进行验证。  此验证是可以完成的第二个验证。
      //
    /*  oReturnCheck = Fapi_doBlankCheck ((Uint32 *) Bzero_Sector 45i_start、
      Bzero_16KSector_u32长度、
                        oFlashStatusWord);*/
      

      //
      //启用 ECC。
      //
      Flash0EccRegs.ECC_ENABLE_bit.enable = 0xA
      //
      //释放闪存信号量。
      //
      DcsmCommonRegs.FLSEM = 0xA500

      EDIS;

    FlashReadOperation()
    {

      Fapi_doMarginReadByByByByByByByByByByByBybee (uint16_t *) Bzero_Sector _start、FlashReadBuffer、27、Fapi_Normal 境内);
      //已读取变量...

    FlashWriteOperation()
    {
      UINT32 u32Index = 0
      UINT16 I = 0
      Fapi_Status 回退检查
      Volatile Fapi_Flash usType oFlashStatus;
      Fapi_Flash 15.4WordType oFlashStatusWord;

      //*
      //*将变量写入闪存扇区
      //*
      EALLOW;
      DcsmCommonRegs.FLSEM = 0xA501
      EDIS;
      InitFlash()
      //
      //禁用 ECC。
      //
      EALLOW;
      Flash0EccRegs.ECC_ENABLE_bit.enable = 0x0

      //
      //根据系统初始化闪存 API 需要该函数
      //执行任何其他闪存 API 操作之前的频率
      //
      oReturnCheck = Fapi_initializeAPI (F021_CPU0_BASE_ADDRESS、120);

      //
      // Fapi_setActiveFlashBank 函数设置闪存组和 FMC 以进一步
      //将要在组上执行的闪存操作
      //
      oReturnCheck = Fapi_setActiveFlashBank (Fapi_Flash 0);

      //
      //等待 FSM 完成擦除扇区操作。
      //
      while (Fapi_checkFsmForReady()!= Fapi_Status_Fsm )
      {
      }

      FlashBuffer[0]= 0
      FlashBuffer[1]= 0 ;
      FlashBuffer[2]= 0 ;
      FlashBuffer[3]=(UINT16 )(变量);
      FlashBuffer[4]= (UINT16 )(变量);
      FlashBuffer[5]= (UINT16 )(变量);
      FlashBuffer[6]= (UINT16 )(变量);
      FlashBuffer[7]= (UINT16 )(变量);
      FlashBuffer[8]= (UINT16 )(变量);
      FlashBuffer[9]= (UINT16 )(变量);
      FlashBuffer[10]= (UINT16 )(变量);
      FlashBuffer[11]= (UINT16)(变量);
      FlashBuffer[12]= (UINT16 )(变量);
      FlashBuffer[13]= (UINT16 )(变量);
      FlashBuffer[14]= (UINT16)(变量);
      FlashBuffer[15]=(UINT16)( 变量);
      FlashBuffer[16]= (UINT16)(变量);
      FlashBuffer[17]= (UINT16)(变量);
      FlashBuffer[18]= (UINT16 )(变量);
      FlashBuffer[19]= (UINT16 )(变量);
      FlashBuffer[20]= (UINT16 )(变量);
      FlashBuffer[21]= (UINT16 )(变量);
      FlashBuffer[22]= (UINT16 )(变量);
      FlashBuffer[23]= (UINT16 )(变量);
      FlashBuffer[24]= (UINT16 )(变量);
      FlashBuffer[25]= (UINT16 )(变量);
      FlashBuffer[26]= (UINT16 )(变量);


      对于(I = 0u32Index = Bzero_Sector 启动;(u32Index <(Bzero_Sector 启动+ words_in_flash_buffer))和(oReturnCheck = Fapi_Status_Success);i += 8、u32Index += 8)
      {
        //fapi_issueProgrammingCommandForEccAddresses();
        oReturnCheck = Fapi_issueProgrammingCommand ((Uint32 *)u32Index , FlashBuffer + I , 8 , 0 , 0 , Fapi_Auto EccGeneration );

        //
        //等待 FSM 完成编程操作。
        //
        while (Fapi_checkFsmForReady()== Fapi_Status_Fsm 52)
        {
        }

        //
        //读取 FMSTAT 寄存器内容以了解 FSM 的状态,
        //编程命令进行任何调试。
        //
        //oFlashStatus = Fapi_getFsmStatus ();

        //
        //验证编程的值。  "Program"步骤本身进行验证
        //。  此验证是可以完成的第二个验证。
        //
    /*     oReturnCheck = Fapi_doVerify ((UINT32 *) u32Index、4、
                        FlashBuffer32 +(I / 2)、
                        oFlashStatusWord);*/

      }

      //
      //启用 ECC。
      //
      Flash0EccRegs.ECC_ENABLE_bit.enable = 0xA
      //
      //释放闪存信号量。
      //
      DcsmCommonRegs.FLSEM = 0xA500

      EDIS;   

    FlashOperations (空)
    {

      切换器(Flash_Operation_ Flash_Operation_States)
      {
        案例 FLASH_OPERATION_ESHOLD_STATE
          //通过
        中断;

        案例 FLASH_OPERATION_ERASE_STATE
          FlashEraseOperation ();
          Flash_Operation_ Design_Object.Flash= Flash_Operation_States flash_operation_dummy_state

        中断;

        案例 FLASH_OPERATION_READ_STATE
          FlashReadOperation()
          Flash_Operation_ Design_Object.Flash= Flash_Operation_States flash_operation_dummy_state

        中断;

        案例 FLASH_OPERATION_WRITE_STATE
          FlashEraseOperation ();
          FlashWriteOperation()
          Flash_Operation_ Design_Object.Flash= Flash_Operation_States flash_operation_dummy_state

        中断;

        默认值
          //通过
        中断;
      }  
     当 ver 状态为写入、读取或擦除而触发时,此函数 FlashOperations()在 main 中运行。
    有什么想法欢迎您?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    闪存 API 必须从 RAM 或不同的闪存存储体运行。  在该器件上为 CPU1、这意味着 API 必须位于 RAM 中。  如果您使用 CPU1对 CPU2进行编程、则可以在对 CPU2闪存进行编程时将 API 保留在 CPU1的闪存中。  CPU2无法对 CPU1的闪存进行编程、因此这就是我们必须放置在 RAM 中的原因。

    这是因为闪存被破坏、在编程操作期间、其他扇区可能会受到影响。  预取缓冲区可能对我们有所帮助、但我们不建议这样做、我建议将所有 API 都放置在 RAM 中、以确保器件正常运行。

    在频率方面、您提到的裕度与使用内部振荡器作为时钟源有关、因为如果您锁定200MHz 并采用10MHz 源、它的容差变化会导致器件在规格上限之外运行。  闪存操作是基于时间的、这意味着使用了有限延迟、因此对于该操作、运行200MHz 与120MHz 没有优势。

    就 CCS 断开连接而言、OTP 扇区中存在某些安全设置(DCSM)。  如果在闪存编程期间读取这些代码、则可能会导致某些连接问题、如果安全处于活动状态并且代码正在从安全区域执行、则会阻止仿真器连接。  您可以在代码中查看是否激活了安全性等。

    此致!

    马修