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:使用 F021 API 时的 ITRAP

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/957576/tms320f28379d-itrap-when-using-f021-api

器件型号:TMS320F28379D
主题中讨论的其他器件:C2000WARE

您好!

我可以使用一些提示、想法和建议。 我正在编写一个引导加载程序、该加载程序位于第一个闪存扇区中、应通过 CAN 接受固件并将其存储在其余扇区中。 引导加载程序擦除为固件保留的闪存扇区、然后使用来自 CAN 总线的数据刷写固件。 这非常好!

我使用 make (CMake)构建软件、并将生成的具有 CSS 和 XDS200的 bootloader.out 文件加载到 TMS320F28379D 的第一个 CPU 中(所有其他 CPU 都空闲)。 我启动软件、一切正常。

当我现在关闭硬件并再次打开电源时、软件崩溃、并执行非法操作。 到目前为止、崩溃似乎是从返回包含对 F021 API (驻留在 RAM 中)调用的函数开始的。 如果我注释掉对 F021 API 函数的调用、引导加载程序不会崩溃。 当我单步执行代码时、API 调用不会崩溃、但从 RAM 驻留调用函数返回到闪存中的函数似乎是问题所在。 (函数正忙等待 Fapi_checkFsmForReady()返回 Fapi_Status_FsmReady)。

在我看来、bootloader.out 文件的加载确实具有一些必要的副作用、但在对软件进行电源复位时不会发生这种副作用。 我尝试设置范围规避设置:0x00-0x80000、0x82000-0xffffffff、以防止调试探针(XDS200)写入引导加载程序闪存扇区之外的任何内容。 但这并没有改变任何东西。

有什么东西、我可以用来查看调试探针写入的存储器范围吗?

此致、

Torsten

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

    Torsten、

    当一个擦除或编程操作正在进行中时、不应该有任何来自闪存组/OTP 的读取或提取存取。 因此、闪存 API 函数、调用闪存 API 函数的用户应用程序函数以及任何 ISR (中断服务例程)都必须从 RAM 中执行。 例如、下面显示的整个代码片段应该从 RAM 执行、而不仅仅是闪存 API 函数。 原因是 Fapi_issueODE19 CommandWithAddress()函数向 FSM 发出擦除命令,但不会等到擦除操作结束。 只要 FSM 忙于当前操作、就不应进行闪存访问。

    //

    //擦除扇区

    //

    oReturnCheck = Fapi_issueODE19 CommandWithAddress (Fapi_EraseSector、(uint32*) 0x0080000);

    //

    //等待擦除操作结束

    //

    while (fapi_checkFsmForReady()!= fapi_Status_FsmReady){}

     

    谢谢、此致、
    Vamsi

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

    [引用 user="Vamsi Gudivada"]

    当一个擦除或编程操作正在进行中时、不应该有任何来自闪存组/OTP 的读取或提取存取。 因此、闪存 API 函数、调用闪存 API 函数的用户应用程序函数以及任何 ISR (中断服务例程)都必须从 RAM 中执行。

    [/报价]

    是的、就是这样。 否则、如果通过 CCS 加载后执行、代码甚至不会正确执行。 第二个想到的错误源是缺少 F021库代码和从闪存调用此代码到 RAM 的代码的副本。 但我想、如果缺少该复制、当我尝试调用其中一个 F021库函数时、代码就会崩溃。

    这是我的代码:

    #pragma FUNCTION_OPTIONS (flash_memory_words、"-opt_level=0);
    RAMFUNC bool flash_memory_words (uint16_t* buffer、uint16_t size、uint32_t addr)
    {
    EALLOW;
    
    bool 结果= true;
    
    对于(;大小!=0 &&结果;)
    {
    //闪存中的0xffff 也会设置闪存的 ECC 部分、
    //然后不能更改
    如果(!empty_s部份(buffer、flash_s部份))
    {
    结果= fapi_issueProgrammingCommand()
    (uint32 *) addr、
    (uint16*)缓冲器、
    FLASH_SAFLET_REGLE、0、0、
    Fapi_AutoEccGeneration)=Fapi_Status_Success;
    
    while (fapi_checkFsmForReady()!= fapi_Status_FsmReady)
    ;
    
    结果=结果&& Fapi_getFsmStatus()= 0;
    }
    
    ADDR += FLASH_SAGE;
    buffer += flash_s部份;
    size -= flash_seg;
    }
    
    EDIS;
    
    返回结果;
    }
    

    故障在返回后发生。 非常有趣、我无法在该函数中设置断点、但我必须在之前设置它、然后单步执行该函数。 但这可能只是一个 CCS 调试器问题。 我曾观察到调用此函数后地址的闪存内容、其中全为零:

    08088e:56BF02C1 MOVB *+XAR1[0]、#0x02、UNC
    267 返回 FLASH_MEMORY_WORD (block_buffer、max_data_block_word_size、block_address - block_address % MAX_data_block_size);
    080890:060A MOVL ACC、@0xA
    080891:8F00C200 MOVL XAR4、#0x00c200
    080893:D580 MOVB XAR5、#0x80
    080894:18A9FF00和 @AL、#0x0000
    080896:76408729 LCR FLASH_MEMORY_Cwords
    268}
    C$L11:
    080898:0000 ITRAP0
    080899:0000 ITRAP0
    08089a:0000 ITRAP0
    339. {
    DEVICE_CONFIGureTMXAnalogTrim (): 

    这将是完全合理的,因为这将导致一项《国际贸易行动计划》。 但无法再次观察到这一点、因此我认为这也是调试器问题。 有趣的是、擦除闪存存储器(固件应刷写到该存储器)可以正常工作。

     TI.ramfunc 包含所有根据映射文件指定的 Fapi_xxx 函数、以及所有调用该 API 函数的函数以及所有相关 ISR:

    .TI.ramfunc
    * 0 00081528 000009dd 运行 ADDR = 00008000
    00081528 00000259 F021_API_F2837xD_FPU32.lib:FlashStateMachine.obj (.text:__Fapi_setupFlashStateMachine)
    00081781 0000019d :program.obj (.text:_fapi_issueProgrammingCommand)
    0008191e 00000088 :read.obj (.text:__Fapi_loopRegionForValue)
    000819a6 00000042 :BlankCheck.obj (.text:_Fapi_doBlankCheck)
    000819e8 00000034 :Init.obj (.text:_Fapi_initializeAPI)
    00081a1c 0000002e :utilities.obj (.text:_Fapi_calculateFletcherChecksum)
    00081a4a 0000002d :FlashStateMachine.obj (.text:__Fapi_issueFsmCommand)
    00081a77 0000002c :utilities.obj (.text:__Fapi_divedUnsignedLong)
    00081aa3 00000025 :FlashStateMachine.obj (.text:_Fapi_setActiveFlashBank)
    00081ac8 00000022 :FlashStateMachine.obj (.text:_Fapi_isAddressEcc)
    00081aea 00000022 :FlashStateMachine.obj (.text:__Fapi_setupSectorsForWrite)
    00081b0c 00000020 :ASYNC.obj (.text:_Fapi_issueCommand19预扣地址)
    00081b2c 0000001a :utilities.obj (.text:_Fapi_waitDelay)
    00081b46 00000016 :read.obj (.text:_fapi_flushPipeline)
    00081b5c 0000000d :utilities.obj (.text:__Fapi_scaleCycles)
    00081b69 00000001 --hole --[填充= 0]
    00081b6a 0000000c :Init.obj (.ebss)[填充= 0]
    00081b76 0000000b :utilities.obj (.text:__fapi_calculateOtpChecksum)
    00081b81 0000000a :FlashStateMachine.obj (.text:_Fapi_checkFsmForReady)
    00081b8b 00000006 :FlashStateMachine.obj (.text:_Fapi_getFsmStatus)
    00081b91 00000077 Fapi_UserDefinedFunctions.c.obj (.TI.ramfunc:_Fapi_setupEepromSectorEnable)
    00081c08 00000076 CAN_ADAPTER.c.obj (.TI.ramfunc:_CAN_INTERRUPT)
    00081c7e 00000064 main.c.obj (.TI.ramfunc:_bootloader_timer_ISR)
    00081ce2 0000005c flash_driver.c.obj (.TI.ramfunc:_flash_memory_words)
    00081d3E 0000004b flash_driver.c.obj (.TI.ramfunc:_flash_write_and_check_meta_data)
    00081d89 00000043 libc2000ware.A:flash.c.obj (.TI.ramfunc:_Flash_initModule)
    00081dcc 0000002f Fapi_UserDefinedFuncations.c.obj (.TI.ramfunc:_Fapi_setupBankSectorEnable)
    00081dfb 0000002d libc2000ware.A:flash.c.obj (.TI.ramfunc:_Flash_setBankPowerMode)
    00081e28 00000026 :flash.c.obj (.TI.ramfunc:_Flash_setWaitstates)
    00081e4e 0000001e :flash.c.obj (.TI.ramfunc:_Flash_setPumpPowerMode)
    00081e6c 0000001a :flash.c.obj (.TI.ramfunc:_Flash_disableCache)
    00081e86 0000001a :flash.c.obj (.TI.ramfunc:_Flash_disablePrefetch)
    00081ea0 00000019 :flash.c.obj (.TI.ramfunc:_Flash_enableCache)
    00081eb9 00000019 :flash.c.obj (.TI.ramfunc:_Flash_enablePrefetch)
    00081ed2 00000017 :flash.c.obj (.TI.ramfunc:_Flash_enableECC)
    00081ee9 00000016 FLASH_DRIVER.c.obj (.TI.ramfunc:_ERASE_Sector)
    00081eff 00000004 libc2000ware.A:sysctl.c.obj (.TI.ramfunc)
    00081f03 00000002 Fapi_UserDefinedFunctions.c.obj (.TI.ramfunc:_Fapi_serviceWatchdogTimer)
    

    将该段从加载地址复制到运行地址的代码如下所示:

    memcpy (&RamfuncsRunStart、&RamfuncsLoadStart、(size_t)&RamfuncsLoadSize);
    

    链接器脚本的相应片段如下所示:

    组
    {
    .TI.ramfunc
    /* F021 API 中的所有函数均从 RAM 运行*/
    
    # ifdef target_MC_family_F2837xD
    {-l F021_API_F2837xD_FPU32.lib}
    # Elif 定义了 TARGET_MC_family_F2837xS
    {-l F021_API_F2837xS_FPU32.lib}
    # 否则
    # 错误"不支持的设备!"
    编号 endif
    
    } LOAD =闪存、
    运行= RAMLS0_1、
    load_start (_RamfuncsLoadStart)、
    load_size (_RamfuncsLoadSize)、
    load_end (_RamfuncsLoadEnd)、
    run_start (_RamfuncsRunStart)、
    run_size (_RamfuncsRunSize)、
    run_end (_RamfuncsRunEnd)、
    PAGE = 0、ALIGN (8)
    

    但我认为映射或复制是正确的、否则应用程序在从调试器加载后不应运行。 我认为可能有一些问题、调试器正在初始化正常的引导过程、但没有执行。 由于在 POR 之后计时器 ISR 在我看到 LED 闪烁时正确执行、因此将代码复制到 RAM 已完成。

    有什么想法吗?

    此致、

    Torsten

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

    Torsten、

    1.您是否正在擦除闪存、以使 RAM 函数在完成此函数的执行后返回到哪个位置?

    2.当应用程序返回到闪存时,您是否在该闪存位置看到有效的代码?   

    3.根据映射文件,flash_memory_words ()的加载和运行地址是什么?

    4.看门狗在您的应用程序中是否被禁用,或者您是否在应用程序中定期进行维护? 在调试器情况下、GEL 文件会禁用它。

    5.当应用程序处于非法 ISR 中时,您是否也注意到闪存 ECC 错误?   

    6.在共享的快照中,地址0x80898显示为全0。  这是预期吗?   

    谢谢、此致、
    Vamsi

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

    1) 1)否 我现在多次调试了这种情况。 在源代码级别进行调试后、从上述函数返回时、我会收到 ITRAP。 如果我尝试在汇编器代码级别从该函数返回、我不会遇到 ITRAP。 它要么是 Heisenbug、要么与时序相关。 我尝试通过汇编器代码进行调试的速度非常快、但在汇编器中进行调试时无法导致 ITRAP (汇编器步骤到)。

    2) 2)是的。

    3) 0x00081ce2和0x000087ba

    4) 4)禁用看门狗。

    5) 5)我不这么认为。 请查看随附的 FLASH_ECC_regs 寄存器的屏幕截图

    6) 6)我仅观察过一次。 我从未观察到过它。 根据预期的程序流程、不会出现这种情况。 但如果我观察到这种可重现性、那么这可能是我要寻找的罪魁祸首。 我想这是 CCS 中的一个干扰。

    我还观察到:由于闪存未被擦除、闪存失败。 引导加载程序应已擦除闪存。 为此、针对固件闪存范围的所有扇区调用以下函数:

    RAMFUNC bool ERASE_SECTOR (uint32_t START_ADDRESS)
    {
    bool 结果= Fapi_issue190xCommandWithAddress (Fapi_EraseSector、(uint32*) start_address)=Fapi_Status_Success;
    
    while (fapi_checkFsmForReady()!= fapi_Status_FsmReady)
    ;
    
    Fapi_FlashStatusType 状态= Fapi_getFsmStatus();
    结果=结果&&状态= 0;
    
    返回结果;
    }
    

    调用该函数并不报告错误(Fapi_getFsmStatus()返回0)。 但它不会擦除给定的扇区! 再说一次、这仅在引导加载程序从 POR 运行时发生。 如果引导加载程序在将 bootloader.out 文件加载到目标后运行、一切都正常。

    我是否有可能获得 F021库的源代码?

    除了调用 Fapi_initiatizeAPI ()和 Fapi_setActiveFlashBank()之外、是否还有其他需要初始化 F021库的东西?

    还有什么想法、我可以调查吗?

    此致、

    Torsten

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

    进一步研究引导加载程序 POW 案例中的故障闪存擦除:

    将 bootloader.out 加载到目标后在 CCS 中运行引导加载程序时。  Fapi_getFsmStatus()在 Fapi_issueCommandWithAddress()之后返回0,无论引导加载程序的闪存区域是否已被擦除。

    当我对目标进行电源复位并使用调试器连接到目标时,我可以观察 到,当 闪存区域不为空时,Fapi_getFsmStatus()返回0xC10, 当闪存为空时返回0x810。 两个错误代码都设置了位11、该位根据 SPRUHM8I 中的表3-327进行保留、2019年9月修订。

     

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

    Torsten、

    感谢您提供了擦除失败的更新。

    1. 在 https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/951668?-FAQ-FAQ-on-Flash-API-usage-for-C2000-devices 上的闪存 API 使用 wiki 中 、请搜索以下问题、并告诉我它是否有助于解决擦除问题。 特别是在擦除前检查是否调用 EALLOW。
      • 当闪存 API 无法擦除或编程时、我们可以考虑哪些常见的调试提示?
      • 完成扇区擦除操作后、Fapi_issueAppeApphexCommandAddress (Fapi_EraseSector、xx)函数调用是否返回?
      • 如果 Fapi_issueAppiCommandWithAddress (Fapi_EraseSector、xx)没有等待擦除操作完成、我们如何知道擦除操作是否成功?
    2. 您是否在 CPU1或 CPU2上遇到此问题?
    3. 您是否能够从 C2000ware 成功执行闪存 API 示例? 示例位于:C2000Ware_3_03_00_00\device_support\f2837xd\examples\dual\flash_programming

    关于闪存 API 源代码:请参阅 https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/780927?-FAQ-F05-Flash-Does-TI-distribute-the-API-source-code-

    关于 fmstat 保留位: 这告诉我擦除没有成功。  请尝试上述常见问题解答建议、然后我们可以根据您的回复进一步分析。

    谢谢、此致、
    Vamsi

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

    您好、 Vamsi、

    看起来我在  Fapi_initiataleAPI ()和 Fapi_setActiveFlashBank()前面缺少 EALLOW。 这对您来说有道理吗? 我是说它在从 CCS 加载后执行时起作用、但在 POR 之后不起作用。

    总之:非常感谢、祝您度过愉快的周末、

    Torsten

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

    Torsten、

    很高兴它帮助解决了问题。 是的、有道理。  

    在 CCS 中将代码加载到闪存后、如果您在调试器中执行重置/重新启动(有助于在通过闪存插件加载代码后使器件进入重置状态)、然后执行应用程序、您也会注意到调试器的情况相同。

    周末愉快!  我将关闭此帖子。

    谢谢、此致、
    Vamsi

x 出现错误。请重试或与管理员联系。