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.

[参考译文] TMS320F2800156-Q1:无法对 F2800156-Q1 的用户 OTP 区域进行闪存写入

Guru**** 2874030 points

Other Parts Discussed in Thread: TMS320F2800156-Q1

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1639645/tms320f2800156-q1-unable-to-flash-write-to-the-user-otp-area-of-f2800156-q1

器件型号: TMS320F2800156-Q1

你好。

我想对 main 函数内的用户 OTP 区域执行闪存写入、以在 main 函数启动时配置 TOE DCSM。

我编写的源代码如下。

静态 void MAIN_DiagManager (void)

  uint16_t* ptrErrorCodePage;

  ptrErrorCodePage = Nvm_Init ();
  Diag Manager_Init ();      /*诊断管理初始化*/

  MakeCheckSum();
  MemIF_DCSM_OTP_Write (16);

  /* 3. 将 UDS_BSIDID 注册到 ReadDataByIdentifier Service */
  Diag.ParameterOfDataIdentifier Manager_Add (UDS_BSIDID、ptrErrorCodePage、255、&Calls Back_Boot Identifier_Wrapper);
  Diag.ParameterOfDataIdentifier Manager_Add (UDS_CHECKSUM、OnLineCheckSum、4、&Calls Back_Report Sum_Wrapper);
  Diag Manager_Add 参数化数据标识符 (UDS_RESET_ERROR、CommandOfEeprom、3、&Call Back_Report Eeprom_Wrapper);

  uds_init();  // pllab
}

内部主 (void)

  //禁用全局中断
  (void)Interrupt_disableMaster ();
  //禁用看门狗
  sysctl_disableWatchdog ();
  main_Flash_syss Ctl_Init ();
  SetupPeripheralClks();
  SetupGpio();
  main_init ();
  main_DiagManager();

  (void)Interrupt_enableMaster ();  /*启用全局中断*/

  while (1)
  {
    schedulerRun(schedulerGetTick());
  }

  返回 0;
}

在 main 函数中、

MemIF_JLM_Enable_OTP_Write ();被调用、并且在传递接口函数后、

 

uint32_t test_Val;
void MemIF_DCSM_OTP_Write (uint32_t dataLength)

  uint32_t Z1_OTP_Val =*(uint32_t *) 0x78022;

  TEST_Val = Z1_OTP_Val;
  IF (Z1_OTP_Val = 0x4D7FFFFF)
  {
    Write_Internal (dataLength);
  }
  暴露
  {

  }
}

 

 

执行下面的闪存写入函数。

uint16_t dcsm_init[16];
Std_Return 类型 dcsm_OTP_Write (uint32_t dataLength)

  uint16_t writeBuffer[10]={0、0、0、0、 0、0、0、0、0};
  uint32_t i = 0、j = 0;
  uint32_t startAddress = 0x78020;
  Fapi_Status 类型 返回检查= Fapi_Status_Success;
  Fapi_Flash 状态类型 oFlashStatus;  
  Fapi_Flash 状态字类型 oFlashStatusWord;
  Std_Return 类型 retValue = E_NOT_OK;

  dcsm_init[0]=(uint16_t) 0xFFFF;
  dcsm_init[1]=(uint16_t) 0xFFFF;

  dcsm_init[2]=(uint16_t) 0x5432;
  dcsm_init[3]=(uint16_t) 0x4D76;

  dcsm_init[4]=(uint16_t) 0xFFFF;
  dcsm_init[5]=(uint16_t) 0xFFFF;

  dcsm_init[6]=(uint16_t) 0xFFFF;
  dcsm_init[7]=(uint16_t) 0xFFFF;

  dcsm_init[8]=(uint16_t) 0x5555;
  dcsm_init[9]=(uint16_t) 0x5555;

  dcsm_init[10]=(uint16_t) 0x5555;
  dcsm_init[11]=(uint16_t) 0x5555;

  dcsm_init[12]=(uint16_t) 0x5500;
  dcsm_init[13]=(uint16_t) 0x5555;

  dcsm_init[14]=(uint16_t) 0x5555;
  dcsm_init[15]=(uint16_t) 0x0000;

  if (dataLength >= 4096u)
  {
    o 返回检查= Fapi_Error_Feature 不可用;
  }

  if (oReturnCheck == Fapi_Status_Success)
  {
//    FlashIF_Erase (blockNumber);

    for (i = 0;i < dataLength;i += 8u)
    {
      对于 (j = 0;j < 8u;j++)
      {
        if ((i + j)>= dataLength)
        {
          writeBuffer[j]=(uint16_t) 0xFFFFu;
        }
        暴露
        {
          writeBuffer[j]=(uint16_t) dcsm_init[i + j];
        }
      }

      (void)FlashIF_ClearFsmStatus();

      //启用选定扇区的编程/擦除保护
      // CMDWEPROTA 适用于扇区 0-31
      // CMDWEPROTB 的位 0-11 适用于扇区 32-127、每个位代表
      //一组 8 个扇区、例如、位 0 表示扇区 32-39、位 1 表示
      //扇区 40-47 等
      (void) Fapi_setupBankSectorEnable (FLASH_WRAPPER_PROGRAM_BASE+FLASH_O_CMDWEPROTA、FLASH_CMDWEPROTA_VALUE);

      oReturnCheck = Fapi_issueProgrammingCommand ((Uint32 *) startAddress、writeBuffer、8、NULL、0、 Fapi_Auto EccGeneration);

      //等待闪存编程操作结束
      while (Fapi_checkFsmForReady ()= Fapi_Status_Fsm){}

      if (oReturnCheck!= Fapi_Status_Success)
      {
        //检查闪存 API 文档是否存在可能的错误
        FlashIF_Error();
      }

      //读取 FMSTAT 寄存器内容以了解之后 FSM 的状态
      //编程命令以查看是否有任何与编程操作相关的错误
      oFlashStatus = Fapi_getFsmStatus();
      IF(oFlashStatus != 3U)
      {
        //相应地检查 FMSTAT 和调试
        FlashIF_FMSTAT_Fail ();
      }

      //验证编程值。  检查是否存在任何 ECC 错误。
      //编程命令本身会进行验证。
      //通过 CPU 读取进行 Hence 程序验证 (Fapi_doVerify ()) 是可选的。
      oReturnCheck = Fapi_doVerify ((Uint32 *) startAddress、4、(uint16 *) writeBuffer、&oFlashStatusWord);

      if (oReturnCheck!= Fapi_Status_Success)
      {
        //检查闪存 API 文档是否存在可能的错误
        FlashIF_Error();
      }

      startAddress = startAddress + 8u;
    }
  }

  if (oReturnCheck == Fapi_Status_Success)
  {
    retValue = E_OK;
  }
  暴露
  {
    retValue = E_NOT_OK;
  }

  return retValue;
}

 

不过。 在构建并运行代码时出现错误。

image.png

过去、使用 F280025C 时、可以使用相同的方法刷写到用户 OTP 区域。

为什么 F2800156 无法实现该功能?

 

 

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

    尊敬的 Chan Woo:

    感谢您提供代码片段和有关写入 TMS320F2800156-Q1 的用户 OTP 区域时所遇到问题的详细信息。 我们很高兴知道它在 F280025C 上有效、因为它有助于缩小问题范围。 与 F280025C 相比、F2800156-Q1 在闪存和 OTP 处理方面具有一些差异。

    根据您的代码和遇到的错误、下面是我们应该调查的关键领域。 可能是其中一个导致了该问题:

    OTP 写入使能和安全性:

    • 启用 OTP 写入: F2800156-Q1 具有围绕 OTP 写入的安全机制。 必须确保启用 OTP 写入。 这通常是通过闪存配置寄存器 (FCR) 来完成的。 查看 TMS320F2800156-Q1 技术参考手册 (TRM) 的相关章节、特别是闪存和 OTP 配置。 第 20.5.7 节提供了有关 OTP 写入启用的详细信息。
    • 安全密钥: 可以使用安全密钥锁定 OTP 区域。 如果设置了密钥、则会阻止修改。 您需要验证是否在 OTP 区域中对安全密钥进行了编程、以及该密钥是否与您尝试写入的内容相匹配。

    2.地址和数据长度:

    • OTP 基地址: 您的代码使用startAddress = 0x78020。 这是用户 OTP 区域的合理起始地址。 但是、请仔细检查特定 OTP 配置的确切起始地址! TRM 将明确说明用户 OTP 区域的开始位置。 稍微偏离地址是一个非常常见的错误。
    • 数据长度: 您将向 OTP 区域写入 16 个字(32 字节)。 确保dataLength传递到的参数MemIF_DCSM_OTP_Write()是一致的(即 32)并且在整个函数中得到正确的处理。 有一个检查dataLength >= 4096u,这似乎是过度的 OTP 写入,并可能表明对预期的数据大小的误解。
    • 字对齐: 闪存操作通常需要字对齐。 确保startAddress和要写入的数据均正确对齐。

    3. Fapi_和 FlashIF 问题:

    • Fapi_初 始化: 尝试写入 OTP 之前、验证闪存 API(Fapi_)是否已完全初始化。 检查main_Flash_sysCtl_Init()函数中的初始化序列。
    • Fapi_命令: Fapi_issueProgrammingCommand是一项关键功能。 这些文档概述了参数和返回状态代码。 密切注意oReturnCheck每个命令后的返回值 ()、并检查oFlashStatusoFlashStatusWord以获得详细的错误信息。 您的代码确实会检查错误、这很好、但您需要准确地解释它们。
    • FlashIF_Error() 和 FlashIF_fmstat_fail(): 这些功能应提供更具体的错误诊断。 确保已实现这些断点以有用的方式报告错误情况(例如,设置调试器断点,输出错误代码)。 扩展这些函数可以直接读取 FMSTAT 寄存器(闪存模块状态)以了解错误–这是非常有用的诊断。
    • 擦除操作: 您的代码包括注释掉的FlashIF_Erase()呼叫。 OTP 通常不会像闪存存储器那样进行擦除。 擦除 OTP 区域可能会对器件造成永久损坏。 请勿取消注释此行!

    4. Z1_OTP_Val 检查:

    • 用途: 检查if(Z1_OTP_Val == 0x4D7FFFFF)是不寻常的、如果没有更多的周围代码上下文、我就看不到它的明确用途。 这里的预期逻辑是什么? 它是尝试确定 OTP 是已锁定还是具有特定状态? 如果Z1_OTP_Val不等于、此检查可能会阻止写入操作0x4D7FFFFF。  

    调试建议:

    1. 单步调试: 使用 CCS 逐行执行代码、尤其是在DCSM_OTP_Write()函数内。 检查startAddressdataLengthwriteBuffer和的值以及来自每个 Fapi.调用的返回代码。
    2. 断点: Fapi_issueProgrammingCommand()调用前后设置断点。 检查闪存模块状态 (FMSTAT) 寄存器以查看错误原因。
    3. “Memory"视“视图: 尝试写入之前和之后、使用 CCS 中的 MEMORY 视图直接检查 OTP 区域的内容。 这将确认数据是否正确写入。
    4. 检查配置位: 在 CCS 中、使用“View Configuration Bits“(查看配置位)功能验证 OTP 写入使能和安全设置。

    为进一步帮助您、请提供以下信息:

    • main_Flash_sysCtl_Init()职能的相关部分 -查看如何初始化 Fapi.
    • FLASH_WRAPPER_PROGRAM_BASEFLASH_O_CMDWEPROTA和的定义 FLASH_CMDWEPROTA_VALUE-这将说明如何配置闪存保护寄存器。

    请提供所需的其他信息、我们将一起处理。

    此致、

    Zackary Fleenor

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

    您还可以参阅 TMS320F280015x 闪存 API 版本 2.00.10.00 参考指南(修订版 A)、了解 F280015x 闪存 API 与 F280025C 器件规定的方法的确切实现详细信息。

    此致、

    Zackary Fleenor

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

     (void) Fapi_setupBankSectorEnable (FLASH_WRAPPER_PROGRAM_BASE+FLASH_O_CMDWEPROTA、FLASH_CMDWEPROTA_VALUE);

    我通过更改函数的参数值解决了该问题。

    感谢你的帮助。