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.
大家好、
为同事发布。
我要做的是:
我正在尝试将一个小数据块写入一个未使用的闪存扇区。 随意地说、我将使用 TI EEPROM 仿真函数、但对于启动器、我一直在尝试使用 API 向闪存写入少量字节、然后通过直接寻址闪存中的存储器的简单函数将其读回。 供参考-我将向闪存写入8个字节、以尝试保持数据边界正确。
问题是什么:
当我执行闪存读取(在闪存写入之后)时、处理器会遇到未配置的中断。 我假定这是“可纠正的错误故障”,但它似乎不是该故障。 当我尝试捕获中断并确定中断的来源时,我看不到任何指向中断来源的标志。
我的假设:
我一直假设我遇到 ECC 错误,但我无法证明。 我的闪存写入代码是根据 controlSUITE 提供的示例进行调整的、因此我假设它写入正确。 但是,我对闪存写法不太了解,所以我甚至不知道在出现什么问题时要问什么问题。 我注意到这个器件的器件勘误表(文档 SPRZ423D)中提到了闪存错误、但是勘误表特别声明只有当错误是由程序提取操作引起的、而不是数据读取引起的时才会发生这种情况。 我正在读取数据、因此我假设这不适用。 此外、供参考的是、我使用的是 TMS rev C 器件。
在 CCS 版本中使用客户硬件:6.1.1.00022。 修改了一个软件示例。 以下代码:
我的项目中有:F021_API_F2837xD_FPU32.lib 文件、我的项目中有 F021_F2837xD_C28.h #included in Fapi_UserDefinedFuncations.c.
void EEPROM_WRITE (void) { uint32 u32Index = 0; uint16 i = 0; Fapi_StatusType o 返回检查; 易失性 Fapi_FlashStatusType o 闪存状态; Fapi_FlashStatusWordType oFlashStatusWord; //禁用 ECC。 ECC 不必被禁用即可执行类似的 FSM 操作 //编程和擦除。 //但是、在 Sonata Rev. 0芯片上、由于 OTP ECC 勘误表、 //禁用 ECC 以避免在使用闪存 API 函数时出现 ECC 错误 //读取 TI-OTP INT_DISABLE; /* EALLOW; Flash0EccRegs.ecc_enable.bit.enable = 0x0; EDIS; * EALLOW; //需要此函数来根据系统初始化闪存 API //频率才能执行任何其他闪存 API 操作 oReturnCheck = Fapi_initializeAPI (F021_CPU0_BASE_ADDRESS、120); if (oReturnCheck!= Fapi_Status_Success) { //检查闪存 API 文档以了解可能的错误 Example_Error (oReturnCheck); } // Fapi_setActiveFlashBank 函数进一步设置闪存组和 FMC //闪存操作将在组上执行 oReturnCheck = Fapi_setActiveFlashBank (Fapi_FlashBank0); if (oReturnCheck!= Fapi_Status_Success) { //检查闪存 API 文档以了解可能的错误 Example_Error (oReturnCheck); } //擦除扇区 B oReturnCheck = Fapi_issueODE19 CommandWithAddress (Fapi_EraseSector、 (uint32 *) bzero_sectorb_start); //等待 FSM 完成擦除扇区操作 while (fapi_checkFsmForReady()!= fapi_Status_FsmReady){} //验证 sectorb 是否被擦除。 "擦除"步骤本身的验证方式为 //可以。 此验证是可以执行的第二次验证。 oReturnCheck = Fapi_doBlankCheck ((uint32 *) Bzero_sectorb_start、 Bzero_16KSector u32length、 oFlashStatusWord (&O); if (oReturnCheck!= Fapi_Status_Success) { //检查闪存 API 文档以了解可能的错误 //如果擦除命令失败,请使用 Fapi_getFsmStatus()函数 //获取 fmstat 寄存器内容 //查看 EV 位、ESUSP 位、STAT 位或 VOLTSTAT 中是否有任何一个 //位被置位(更多细节请参考 API 文档) Example_Error (oReturnCheck); } //最多可向程序函数提供8个字的数据缓冲区。 //每个字都被编程,直到整个缓冲区被编程或 A //发现问题。 但是、要对具有大于8的缓冲区进行编程 //字、程序函数可在循环中调用、以便为编程8个字 //每个循环迭代直到整个缓冲区被编程 。// //示例:使用输出 ECC 对闪存扇区 B 中的0xFF 字节进行编程 //禁用 ECC,以便在读取闪存内容时不生成错误 //无 ECC Flash0EccRegs.ecc_enable.bit.enable = 0x0; * for (i=0;i<=word_in_flash_buffer;i++) { Buffer[i]= i; } 对于(i=0、u32Index = Bzero_sectorb_start; (u32Index <(Bzero_sectorb_start + wors_in_flash_buffer))) &&(oReturnCheck = Fapi_Status_Success);i+= 8、u32Index+= 8) { oReturnCheck = fapi_issueProgrammingCommand ((UINT32 *) u32Index、 Read_flash_buffer + i、 8、 0、 0、 Fapi_AutoEccGeneration); while (fapi_checkFsmForReady ()=fapi_Status_FsmBusy); if (oReturnCheck!= Fapi_Status_Success) { //检查闪存 API 文档以了解可能的错误 Example_Error (oReturnCheck); } //读取 fmstat 寄存器内容以了解 FSM 的状态 //在用于任何调试的程序命令之后 oFlashStatus = fapi_getFsmStatus(); //验证编程的值。 Program 步骤本身会进行验证 //进行。 此验证是可以执行的第二次验证。 oReturnCheck = fapi_doVerify (((uint32 *) u32Index、 4、 Buffer32+(I/2)、 oFlashStatusWord (&O); if (oReturnCheck!= Fapi_Status_Success) { //检查闪存 API 文档以了解可能的错误 Example_Error (oReturnCheck); } } EDIS; INT_ENABLE; } void Example_Error (Fapi_StatusType 状态) { //错误代码将位于状态参数 //中 _asm (" ESTOP0"); } void flash_read (void) { uint16 i; extern UINT16 EEPROM_DATA_LOAD_START; 对于(i=0;i < word_in_flash_buffer;i++) { *(read_flash_buffer + i)=*(&EEPROM_DATA_load_start + i); } flash_pack_struct_from 缓冲区(); //从闪存取值并打包到 EEPROM_DATA_buffer 结构 中} //函数末尾 flash_read() 此代码段来自.cmd 文件,该文件调用闪存中 EEPROM_DATA 的位置。 EEPROM_DATA :LOAD = FLASHB、 load_start (_EEPROM_DATA_LOAD_START)、 load_end (_EEPROM_DATA_LOAD_END)、 PAGE = 0、ALIGN (4)
感谢您的帮助、
不需要
Nate (和 Brett)、您好!
感谢您在此处发布我的问题。 我想补充一点关于失败条件和我对这一问题的想法的信息。
我正在使用上面附加的函数(EEPROM_WRITE())向闪存写入一个小测试模式。 虽然我注意到使用内存浏览器查看闪存时偶尔会出现位翻转、但数据似乎被正确写入闪存。 当我尝试从闪存中读取数据时、我遇到了一个问题。 CPU 进入一个不受支持的中断。 我在确定触发哪个中断时遇到了一些问题。 对于我们不使用的每个中断、我们都有一个"默认 ISR"矢量。 PIE 使能的所有功能都关闭、因此我无法确定为什么调用默认 ISR、除非存在不可屏蔽的中断、例如不可纠正的闪存错误。 我可以使用一些帮助来确定该中断来自何处。
假设 CPU 在发生闪存 ECC 错误时被中断、我的下一个问题是为什么错误首先被写入闪存中。 但我想、在我弄清楚中断是如何触发的之后、我们可以讨论这一点。
谢谢、
Justin
Justin、
1)阅读问题: 好的、您至今提供了两个不同的代码。 您的最新代码使用 Fapi_DataOnly 模式进行程序操作。 此模式不对 ECC 进行编程。 它仅对数据进行编程。 这就是在启用 ECC 的情况下读取时出现 ECC 错误的原因。 这样、我们可以解决您的读取问题吗?
2) 2)遇到新问题[您正在进行编程时收到中断、由于 ECC 已禁用、因此它不是与 ECC 错误相关的中断。 此外、您确认它不是 NMI ]:
A)如果您想轻松了解中断源、可以初始化整个 PIE 矢量表以指向默认 ISR 例程、如下所示(取自 controlSUITE 示例)。
//
//清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
//
Dint;
//
//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 F2807x_PIECTRL.c 文件中。
//
InitPieCtrl();
//
//禁用 CPU 中断并清除所有 CPU 中断标志:
//
IER = 0x0000;
IFR = 0x0000;
//
//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 F2807x_DefaultIsr.c 中找到 shell ISR 例程
//此函数位于 F2807x_PieVect.c 中
//
InitPieVectTable();
//
//启用全局中断和更高优先级的实时调试事件:
//
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM
b)您是否从闪存或 RAM 运行闪存 API 函数? 它们只能从 RAM 中执行。 当一个编程或者擦除操作正在进行中时、闪存不能被访问。 因此、F2807x 的闪存 API 只能从 RAM 中执行、如 TRM 中所述。 如果在 RAM 中加载了闪存 API 并将其设置为从 RAM 执行(通过将其分配给.TI.ramfunc),请检查是否使用 memcopy()将其复制到 RAM。 确保将 Fapi_UserDefinedFuncations.c 文件中的函数以及.TI.ramfunc 分配给 controlSUITE 示例中所示的函数。 检查您是否获得了 ITRAP (ILLEGAL_ISR)。
c) API 不启用任何中断。 另请注意、API 不配置(启用/禁用)看门狗。 您是否检查了是否启用了任何其他中断? 检查 PIECTRL、PIEIERx、PIEIFRx 寄存器。
d)您没有回答我之前关于看门狗的问题。 是启用还是禁用? 如果已启用、您的应用程序是否正在为其提供服务?
3) 3)关于您的与闪存时钟相关的问题: 只要
(i)您可以正确配置 PLL 以获得应用所需的 SYSCLK、以及
(ii)正确配置等待状态、然后
(iii)将该频率值正确传递到 Fapi_initiatizeAPI ()、
闪存时钟将由 API 正确配置。
谢谢、还有 regars、
Vamsi
Vamsi、
我没有意识到旧版本的代码只对数据进行了编程、而不是 ECC。 让我将其更改为对 ECC 进行编程、我将向您介绍它的运行方式。 我还将在下一次答复中回答你的其余问题。
谢谢、
Justin
Vamsi、
首先、我进行了检查以确保从 RAM 调用闪存 API、然后我附加了下面.map 文件的一个片段、显示 EEPROM_write()位于'ramfuncs'中指定的其他函数中。
全局符号:按符号地址排序
页 地址 名称
------ ----
0 00000124 _bootloader_ram_functions_load_end
0 00000124 _bootloader_ram_functions_load_start
0 00000124 _bootloader_ram_functions_run_start
0 00000ce0 _Cla1SoftIntRegs
0 00008000 _inV_loop
0 00008000 _ram_functions_run_start
0 000082ab _pFC_loop
0 000084b8 _EEPROM_WRITE
0 00008527 _EEPROM_UPDATE_PAGE_STATUS
0 00008528 _EEPROM_UPDATE_班 组状态
0 00008529 _EEPROM_GET_VALID 页
0 0000852a _EEPROM_ERASE
0 0000852b _ISR_PFC
0 00008565 _ISR_INV
其次、我验证了当闪存尚未写入时、闪存读取不会导致问题(所有 FFFF)。 当我使用自动 ECC 生成对闪存进行写入时、我仍然会收到意外中断。 按照您的建议输入所有 ISR shell、它会进入 ILLEGAL_ISR。 您是否对这种情况的发生有任何想法?
第三、就看门狗而言、是的、它被启用、是的、它被处理。 我有一个从操作系统的任务调度程序调用的函数 watchdog_reset(),因此它会频繁运行。 我想、当调用闪存 API 时、操作系统可能会挂起、但我还不知道所有操作都需要多长时间。 安全装置复位代码如下:
空安全装置复位(空)
{
EALLOW;
//重置看门狗计数器
WdRegs.WDKEY。ALL = 0x0055;
WdRegs.WDKEY。ALL = 0x00AA;
//重置外部看门狗
GpioDataRegs.GPBSET.bit.GPIO62=1;
asm (" RPT #50 || NOP");
GpioDataRegs.GPBCLEAR.bit.GPIO62=1;
EDIS;
}
-Justin
您好、Vamsi、
我检查了链接器命令文件、认为我正在擦除扇区 B、程序未使用该扇区获取指令。 我应该尝试使用一个远离程序其余部分的闪存扇区吗? 就像现在一样、程序指令存储在扇区 A 和 C 中
如何"确保堆栈不会溢出到其他 RAM 块覆盖代码或数据"?
我是否需要确保我写入的数据在"PAGE 1"与"PAGE 0"中?
-Justin
Justin、
以上不是错误。 这只是说找不到 API 函数的源代码。 这是因为 TI 提供了一个 API 库(您已链接到您的项目)、而不是 API 源。 这不是问题。 在 API 函数调用后保留一个断点、您将无法进入该断点。
谢谢、此致、
Vamsi
Vamsi、
我使用了 controlSUITE v150中的示例代码。 现在、我将查看我拥有的示例的最新版本(V210)。 我仍然看不到任何指定使用#pragma 语句将闪存 API 库复制到 ramfuncs 的位置。 从一开始、我就将调用闪存 API 的函数复制到了 RAM 中、但我不知道如何指定 API 本身驻留在 RAM 中。 请告诉我如何操作?
-Justin
Justin、
请检查示例中使用的链接器命令文件。 您将注意到.TI.ramfunc 段和 API 库被组合在一起、以加载到闪存并从 RAM 运行。 请参阅以下从链接器命令文件获取的片段。
组
{
.TI.ramfunc
{-l F021_API_F2837xD_FPU32.lib}
}负载= FLASHD,
运行 = RAMLS03、
load_start (_RamfuncsLoadStart)、
load_size (_RamfuncsLoadSize)、
load_end (_RamfuncsLoadEnd)、
run_start (_RamfuncsRunStart)、
run_size (_RamfuncsRunSize)、
run_end (_RamfuncsRunEnd)、
PAGE = 0
谢谢、此致、
Vamsi
Justin、
是否在启用 ECC 的情况下验证是否通过了程序?
我强烈建议您首先在启用 ECC 的情况下执行闪存 API 示例、并查看是否通过验证。 完成此步骤后、我将继续为您提供支持。
谢谢、此致、
Vamsi
Vamsi、
请允许我在这里备份一点。 我在上一个帖子中遇到的许多问题可能是由于看门狗服务不正确导致的。 这就是跟踪变量重新初始化的原因、我认为这就是断点行为错误的原因。 我已更正了看门狗问题、现在跟踪变量正在递增、我更好地了解对您之前有关验证阶段是否失败的问题的答案。 答案是"是"、它未通过验证操作。 此测试期间启用 ECC。
我在这里看到的另一件奇怪的事情是、当我运行 EEPROM_WRITE()函数时、我在函数"flash_write_call"顶部具有的跟踪变量会增加18倍、我计数的跟踪变量会失败验证阶段的次数也会增加18倍。 为什么整个函数运行18次? 我只调用它一次。
我将检查 CCS 更新。
-Justin
[引用 user="Vamsi Gudivada"]我记得我在 CCSv6中遇到了断点问题。
Vasmi -我相信您所想到的问题与 ramfunc 相关、如果程序有一个段在运行时加载到闪存并提取到 RAM 中、并且在 RAM 的那个区域中设置了一个(软件)断点、则会发生该问题。 这里发生了什么?
您好、Vamsi、
我撕下一块备用板、将处理器焊接到 PowerPAD 上。
我没有单独运行实际示例项目、但我已经将代码复制/粘贴到程序中、它在启动时运行。 这是可行的、并且已经运行了一段时间。 当我稍后在程序中再次尝试运行闪存编程例程(封装在我的 EEPROM_write()函数中的示例项目)时,会导致问题。
我尚未检查电源轨。 你认为我应该这样做吗?
-Justin
Justin、
1)关于看门狗: 请确保在看门狗服务函数主体的末尾包含一个 EALLOW、以便以后的 API 函数根据需要写入受保护的寄存器。
Fapi_StatusType Fapi_serviceWatchdogTimer (空)
{
/*用户在此处添加自己的看门狗服务代码*/
ServiceDoG();//您自己的函数主体
EALLOW;//添加此 EALLOW
返回(Fapi_Status_Success);
}
2)关于看门狗复位: API 调用此看门狗服务例程的频率可能不足以为看门狗提供服务。 因此、您可能需要增加看门狗失效的时间周期。 但是、由于闪存 API 在此器件上是可中断的、我建议您启用中断并根据计时器中断为看门狗提供服务。 这样、您就可以确定看门狗装置以正确的速度进行处理。 请注意、ISR 应该被复制到 RAM 中、这是因为当一个擦除或编程操作正在进行时、不应该有一个闪存访问。
谢谢、此致、
Vamsi
您好、Vamsi、
是的、它现在可以工作。 从一开始就存在多个问题。 它们是:
*这些函数是从 ISR 调用的函数中调用的。 这显然会导致问题(即使这是它在28069上运行的该固件的先前版本中的工作方式。 我认为这是导致堆栈溢出的原因。
*首先、看门狗未被处理(用户定义的看门狗处理函数为空"。
*然后、我需要在"用户定义的看门狗服务函数"末尾添加一条 EALLOW 语句。
*未指定 API 库从 CMD 文件中的 RAM 运行。
*在调试早期尚未禁用中断。
*在调试的早期、ECC 计算不正确。
由于我已经解决了这些问题、并且能够可靠地写入闪存、因此我一直在实施 TI EEPROM 仿真功能。 由于您似乎不能重写已经被写入的闪存字、所以它们与28075不直接兼容。 例如、组状态字在"空白"时以0xFFFF 开头、在"当前正在使用"时以0xA00A 开头、在"满"时以0x0000开头。 我发现的问题是、我无法重写0xA00A、使其成为0x0000 (我假设 ECC 字节需要更改、并且通常它不仅会将位从1更改为0)。 因此、我必须修改这些函数的操作、以仅处理"空"和"已使用"状态。 "页面状态"也是如此。 此外、不能写入单个闪存字意味着我需要占用闪存中的整个8字行来处理以前作为单个状态字的内容。 因此、与28069中的相同实现方案相比、它还使用更多的存储器。 但我已经使它正常工作了。
感谢你的帮助。
-Justin