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.
您好!
我可以使用一些提示、想法和建议。 我正在编写一个引导加载程序、该加载程序位于第一个闪存扇区中、应通过 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、
感谢您提供了擦除失败的更新。
关于闪存 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