{
//
//将 PLL 的时钟设置为以80MHz 运行。
//
SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |
SYSCTL_OSC_MAIN |
SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480)、SYSTEM_CLOCK);
SysCtlDelay (10*system_delay_ms);//延迟10ms
{
}
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.
您好、Gavin、
这是我第一次在调用 SysCtlClockFreqSet 时看到一个硬故障报告。 也许我需要更好地理解这个问题。
TM4C129有许多 TivaWare 示例。 您能不能尝试其中任何一个(即闪烁示例)、并看到您在调用 SysCtlClockFreqSet 时会遇到硬故障。 每个示例将调用 SysCtlClockFreqSet 来设置系统时钟。
当您仍 在应用程序中时或者在它已经跳转到引导加载程序之后调用 SysCtlClockFreqSet 时、是否会出现硬故障?
在返回到引导加载程序之前、您需要再次设置系统时钟的原因是什么。 通常情况下、引导加载程序会设置自己的时钟、对吧?
您尝试设置为80MHz。 如果您选择120MHz 或与引导加载程序本身匹配的频率等其他频率、会有什么不同?
你(们)好,查尔斯
感谢您的回复、请参阅以下我的评论:
TM4C129有很多 TivaWare 示例。 您能不能尝试其中任何一个(即闪烁示例)、并看到您在调用 SysCtlClockFreqSet 时会遇到硬故障。 每个示例将调用 SysCtlClockFreqSet 来设置系统时钟。
[Gavin]是的、我可以尝试样本。
2.当您 在应用程序中或者已经跳转到引导加载程序时调用 SysCtlClockFreqSet 时、是否会出现硬故障?
[Gavin]我之前已经检查过这个问题、硬件故障在 应用程序中使 SysCtlClockFreqSet 中的 CPU 粘滞。
3.在返回引导加载程序之前、您需要再次设置系统时钟的原因是什么。 通常情况下、引导加载程序会设置自己的时钟、对吧?
[Gavin]不、在跳转到引导加载程序之前、我没有再次设置时钟。 实际上、顺序是在引导加载程序中设置时钟、并在应用程序中再次设置时钟。
我设置时钟两次以解决时钟设置问题。
4.您尝试设置80MHz。 如果您选择120MHz 或与引导加载程序本身匹配的频率等其他频率、会有什么不同?
[Gavin]不、我没有尝试不同的频率。 但我在引导加载程序和应用程序中设置了相同的时钟(80MHz)。
另一方面、由于我在 SysCtlClockFreqSet 中检查了硬故障、所以我简化了应力代码作为 POST。
是否可以正确注释应力代码以进行测试?
我还研究了外部晶体在发生硬故障时的状态、外部晶体正常工作。
如果您对此问题有任何想法、请与我分享。
谢谢
Gavin
你(们)好,查尔斯
我发现在 SysCtlClockFreqSet ()中的类似行发生了硬故障、请参考所附的屏幕
我还为您的测试附加了测试程序、您可以将其直接闪存到 LaunchPad 中。
在我的测试中、我加载引导加载程序(地址:0x0000)和应用程序(0x8000)、 从引导加载程序发送的一条 CAN 消息作为记录、并且跳转操作保持运行、直到发生硬故障。
e2e.ti.com/.../TM4C129_5F00_hard_5F00_fault_5F00_reproduce.7z
谢谢
Gavin
您好、Gavin、
我似乎无法再现您的问题。 如您所见,我在 UIUpgrade()放置了一个断点,它会运行到它。 这意味着它运行在 SysCtlClockFreqSet() Fine 中。 请参阅下面的内容。
我注意到的一点是、我看到您的程序映像 SysCtlClockFreqSet()与我的不同。 您确定使用的是最新的 TivaWare 库。 您能否下载最新的 TivaWare 库并与当前库进行比较。
查看您的 sysctl.c 文件的第一个黄色突出显示行、并与我的 sysctl.c 的第一个黄色突出显示行进行比较、您会发现在您除以变量时、我有2分频。
您的以下文件:
下面是我的 sysctl.c 文件:
以下是最新 TivaWare 库中 SysCtlClockFreqSet()的源代码。
// // //! 配置系统时钟。 //! //! \param ui32Config 是器件计时的所需配置。 //! \param ui32SysClock 是请求的处理器频率。 //! //! 此函数用于配置器件的主系统时钟。 //! 输入频率、振荡器源、是否启用 PLL、和 //! 系统时钟分频器均使用此功能进行配置。 此 //! 函数将系统频率配置为最接近的可用除数 //! Ui32Config //!中提供的固定 PLL VCO 设置之一 参数。 调用方设置\e ui32SysClock 参数以请求 //! 系统时钟频率、然后此函数尝试使用 //! ui32Config 参数中提供的值。 如果此函数 //! 无法完全匹配请求的频率、它会选择最接近 的//! 低于请求频率的频率。 ui32Config //! 参数使用一组 //! 定义为几个不同值的逻辑 OR、其中许多 //! 被分组为只能选择其中一个集合的集合。 此 //! 函数返回可能与 //! 请求的频率。 //! //! 如果应用使用外部晶振、则频率为 //! 使用以下值之一进行设置: //! b SYSCTL_XTAL_5MHZ、\b SYSCTL_XTAL_6MHZ、\b SYSCTL_XTAL_8MHZ、 //! b SYSCTL_XTAL_10MHz、\bSYSCTL_XTAL_12MHz、\bSYSCTL_XTAL_16MHz、 //! b SYSCTL_XTAL_18MHz、\bSYSCTL_XTAL_20MHz、\bSYSCTL_XTAL_24MHZ 或 //! b SYSCTL_XTAL_25MHz。 //! //! 振荡器源选择如下值之一: //! //! -\b SYSCTL_OSC_MAIN 使用外部晶体或振荡器。 //! -\b SYSCTL_OSC_INT 以使用16MHz 精密内部振荡器。 //! -\b SYSCTL_OSC_INT30以使用内部低频振荡器。 //! -\b SYSCTL_OSC_EXT32以使用休眠模块32.786kHz 振荡器。 //! 此选项仅在包含休眠 //!的器件上可用 模块。 //! //! 系统时钟源的选择值如下: //! //! -\b SYSCTL_USE_PLL 用于选择 PLL 输出作为系统时钟。 //! -\b SYSCTL_USE_OSC 被用来选择一个振荡器作为 //! 系统时钟。 //! //! PLL VCO 频率由以下值之一选择: //! //! -\b SYSCTL_CFG_VCO_480将 PLL VCO 输出设置为480MHz //! -\b SYSCTL_CFG_VCO_320以将 PLL VCO 输出设置为320MHz //! //! 示例:使用320MHz PLL 将系统时钟配置为40MHz //! 使用16MHz 内部振荡器进行设置。 //! //! 逐字记录 //! SysCtlClockFreqSet (SYSCTL_OSC_INT | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_320、 //! 40000000); //! \end逐 字记录 //! //! 注意此函数不能用于 TM4C123器件。 对于 TM4C123 //! 器件使用 SysCtlClockSet()函数。 //! //! \如果 //! 由于参数错误或 PLL 锁定失败、无法更改值。 //// ***************** uint32_t SysCtlClockFreqSet (uint32_t ui32Config、uint32_t ui32SysClock) { int32_t i32Timeout、i32VCOIdx、i32XtalIdx; uint32_t ui32MOSCCTL; uint32_t ui32Delay; uint32_t ui32SysDiv、ui32Osc、ui32OscSelect、ui32RSClkConfig; // // TM4C123器件不应使用此函数。 // if (class_in_TM4C123) { 返回(0); } // //从 ui32Config 参数中获取晶体的索引。 // i32XtalIdx = SysCtlXtalCfgToIndex (ui32Config); // //确定选择了哪个非 PLL 源。 // if ((ui32Config & 0x38)=sysctl_OSC_INT) { // //使用 PIOSC 振荡器的标称频率并设置 //晶体选择。 // ui32Osc = 16000000; ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC; ui32OscSelect |= SYSCTL_RSCLKCFG_PLLSRC_PIOSC; // //强制晶体索引为16MHz 的值。 // i32XtalIdx = SysCtlXtalCfgToIndex (SYSCTL_XTAL_16MHz); } 否则、if (((ui32Config & 0x38)=sysctl_OSC_INT30) { // //使用低频振荡器的标称频率。 // ui32Osc = 30000; ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_LFIOSC; } 否则 if (((ui32Config & 0x38)==(SYSCTL_OSC_EXT32 & 0x38)) { // //使用 RTC 频率。 // ui32Osc = 32768; ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_RTC; } 否则、if (((ui32Config & 0x38)== SYSCTL_OSC_main) { // // Bounds 检查主振荡器的源频率。 是 //因为 g_pppui32XTALtoVCO 结构范围中的 PLL 表 //从5MHz 到25MHz。 // if (((i32XtalIdx >(SysCtlXtalCfgToIndex (SYSCTL_XTAL_25MHz))))|| (i32XtalIdx <(SysCtlXtalCfgToIndex (SYSCTL_XTAL_5MHZ)))) { 返回(0); } ui32Osc = g_pui32Xtals[i32XtalIdx]; // //将 PLL 源选择设置为 MOSC。 // ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_MOSC; ui32振荡器选择|= SYSCTL_RSCLKCFG_PLLSRC_MOSC; // //清除 MOSC 断电、高振荡器范围设置、且无晶振 //当前设置。 // ui32MOSCCTL = HWREG (SYSCTL_MOSCCTL)& ~(SYSCTL_MOSCCTL_OSCRNG | SYSCTL_MOSCCTL_PWRDN | SYSCTL_MOSCCTL_NOXTAL); // //增加10MHz 及以上 MOSC 的驱动强度。 // if (i32XtalIdx >=(SysCtlXtalCfgToIndex (SYSCTL_XTAL_10MHz)- (SysCtlXtalCfgToIndex (SYSCTL_XTAL_5MHZ))) { ui32MOSCCTL |= SYSCTL_MOSCCTL_OSCRNG; } HWREG (SYSCTL_MOSCCTL)= ui32MOSCCTL; // //使用传统延迟值超时。 // ui32Delay = 524288; while ((HWREG (SYSCTL_RIS)& SYSCTL_RIS_MOSCPUPRIS)==0) { ui32 Delay--; if (ui32Delay = 0) { 中断; } } // //如果主振荡器启动失败,则不要切换到 //它并返回。 // if (ui32Delay = 0) { 返回(0); } } 其他 { // //这是一个无效的请求,因为没有振荡器源 //已指明。 // ui32Osc = 0; ui32OscSelect = SYSCTL_RSCLKCFG_OSCSRC_PIOSC; } // //检查是否请求了启用 PLL 的运行。 // if (((ui32Config & sysctl_use_OSC)== sysctl_use_pll) { // // ui32Config 必须是 SYSCTL_OSC_main 或 SYSCTL_OSC_INT。 // if ((((ui32Config & 0x38)!= SYSCTL_OSC_main)&& ((ui32Config & 0x38)!= SYSCTL_OSC_INT) { 返回(0); } // //从 ui32Config 参数中获取 VCO 索引。 // i32VCOIdx =(ui32Config >> 24)和7; // //检查 VCO 索引是否超出范围。 // 断言(i32VCOIdx < MAX_VCO_ENTRIEOINTRIES[i32VCOIdx < MAX_VCO // //为自以来的最大外部频率设置存储器时序 //这可以是到 PIOSC 的切换,也可以是到 MOSC 的切换 //高达25MHz。 // HWREG (SYSCTL_MEMTIME0)=_SysCtlMemTimingGet (25000000); // //清除旧的 PLL 分频器和源,以防它被设置。 // ui32RSClkConfig = HWREG (SYSCTL_RSCLKCFG)& ~(SYSCTL_RSCLKCFG_PSYSDIV_M | SYSCTL_RSCLKCFG_OSCSRC_M | SYSCTL_RSCLKCFG_PLLSRC_M | SYSCTL_RSCLKCFG_USEPLL); // //更新存储器时序以匹配从 PIOSC 运行。 // ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIU; // //更新时钟配置以切换回 PIOSC。 // HWREG (SYSCTL_RSCLKCFG)= ui32RSClkConfig; // //表从5MHz 开始,因此修改索引以匹配此值。 // i32XtalIdx = SysCtlXtalCfgToIndex (SYSCTL_XTAL_5MHZ); // //计算系统分频器,这样我们得到的频率就是 //最接近请求的频率而不会发生变化。 // ui32SysDiv =(g_pui32VCOF 所需时间[i32VCOIdx]+ ui32SysClock - 1)/ ui32SysClock; // //设置振荡器源。 // HWREG (SYSCTL_RSCLKCFG)|= ui32振荡器选择; // //设置表中提供的 M、N 和 Q 值并保留 //主 PLL 的电源状态。 // HWREG (SYSCTL_PLLFREQ1)= G_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][1]; HWREG (SYSCTL_PLLFREQ1)|= PLL_Q_TO_REG (ui32SysDiv); HWREG (SYSCTL_PLLFREQ0)= (G_pppui32XTALtoVCO[i32VCOIdx][i32XtalIdx][0]| (HWREG (SYSCTL_PLLFREQ0)和 SYSCTL_PLLFREQ0_PLLPWR)); // //计算实际系统时钟、因为 PSYSDIV 始终为2分频。 // ui32SysClock =_SysCtl频率 Get (ui32Osc)/ 2; // //设置闪存和 EEPROM 时序值。 // HWREG (SYSCTL_MEMTIME0)=_SysCtlMemTimingGet (ui32SysClock); // //检查 PLL 是否已加电。 // IF (HWREG (SYSCTL_PLLFREQ0)和 SYSCTL_PLLFREQ0_PLLPWR) { // //触发 PLL 以锁定到新频率。 // HWREG (SYSCTL_RSCLKCFG)|= SYSCTL_RSCLKCFG_NEWFREQ; } 其他 { // //为 PLL 加电。 // HWREG (SYSCTL_PLLFREQ0)|= SYSCTL_PLLFREQ0_PLLPWR; } // //等待 PLL 锁定。 // for (i32Timeout = 32768;i32Timeout > 0;i32Timeout--) { if ((HWREG (SYSCTL_PLLSTAT)& SYSCTL_PLLSTAT_LOCK)) { 中断; } } // //如果上面的环路没有超时,则切换到 PLL // if (i32超时) { ui32RSClkConfig = HWREG (SYSCTL_RSCLKCFG); ui32RSClkConfig |=(1 << SYSCTL_RSCLKCFG_PSYSDIV_S)| ui32OscSelect | SYSCTL_RSCLKCFG_USEPLL; ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIU; // //设置新的时钟配置。 // HWREG (SYSCTL_RSCLKCFG)= ui32RSClkConfig; } 其他 { ui32SysClock = 0; } } 其他 { // //设置 PIOSC 的闪存和 EEPROM 时序值。 // HWREG (SYSCTL_MEMTIME0)=_SysCtlMemTimingGet (16000000); // //确保 PLL 掉电是因为它没有被使用。 // HWREG (SYSCTL_PLLFREQ0)&=~SYSCTL_PLLFREQ0_PLLPWR; // //清除旧的 PLL 分频器和源,以防它被设置。 // ui32RSClkConfig = HWREG (SYSCTL_RSCLKCFG); ui32RSClkConfig &=~(SYSCTL_RSCLKCFG_OSYSDIV_M | SYSCTL_RSCLKCFG_OSCSRC_M | SYSCTL_RSCLKCFG_USEPLL); // //更新内存时序。 // ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIU; // //设置新的时钟配置。 // HWREG (SYSCTL_RSCLKCFG)= ui32RSClkConfig; // //如果系统时钟为零,则默认为1分频。 // if (ui32SysClock =0) { ui32SysDiv = 0; } 其他 { // //根据请求的计算系统分频器 //频率。 // ui32SysDiv = ui32Osc / ui32SysClock; // //如果系统除数尚未为零,则减去1 //在需要值的寄存器中设置值 //为 n-1。 // if (ui32SysDiv!= 0) { ui32SysDiv -= 1; } // //计算系统时钟。 // ui32SysClock = ui32Osc /(ui32SysDiv + 1); } // //设置新系统时钟的存储器时序值。 // HWREG (SYSCTL_MEMTIME0)=_SysCtlMemTimingGet (ui32SysClock); // //设置新的系统时钟值。 // ui32RSClkConfig = HWREG (SYSCTL_RSCLKCFG); ui32RSClkConfig |=(ui32SysDiv << SYSCTL_RSCLKCFG_OSYSDIV_S)| ui32振荡器选择; // //更新内存时序。 // ui32RSClkConfig |= SYSCTL_RSCLKCFG_MEMTIU; // //设置新的时钟配置。 // HWREG (SYSCTL_RSCLKCFG)= ui32RSClkConfig; } // //最后将 OSCSRC 改回 PIOSC // HWREG (SYSCTL_RSCLKCFG)&=~(SYSCTL_RSCLKCFG_OSCSRC_M); return (ui32SysClock); }
最后一点是、如果您只需运行简单的 hello 或 blinky 或任何 TivaWare 示例。 您看到问题了吗?
你(们)好,查尔斯
首先、这个问题并不是每次 SysCtlClockFreqSet()发生的、它需要运行一段时间。
如果可能、您可以尝试让它运行一段时间、直至出现问题吗?
其次、 SysCtlClockFreqSet()的不同内容是权变措施、它与您的团队一起处理时钟分频设置问题。
第三、我将运行简单的 hello 样本、但我认为我的应力代码比 hello 更简单。 如果我得到结果、我将更新为您。
如果您有更多的顾虑需要澄清、请告诉我、我可以尝试从我的身边获取。
谢谢
Gavin
您好、Gavin、
我有几个问题。
1.我在当前 TivaWare 版本中对 sysctl.c 与本地目录中的 SYSCTL.c 进行了比较、发现了相当大的差异。 如果 您自己进行了更改或从 TI 获得了更改、请您发表评论。
2.如果您从 TI 获得了权变措施更改、您是否在发送给您的内容之上进行了任何修改?
3.你什么时候得到了变化?
4. 您能否使用链接到的 driverlib.lib 来运行您的项目 driverlib/ccs/Debug/driverlib.lib。 而不是本地目录? 您会看到差异吗?
5、如前所述、您能否运行一个简单的 TivaWare 示例、例如 blinky 或 hello、此示例中的 driverlib 链接到 TivaWare_Installation 或您本地重建的目录? 这两种情况是否都发生故障、或者只有一种情况发生故障、或者两者都将通过?
6.我在 Launchpad 上运行了您的项目。 我没有 CAN 消息。 但是、我看到项目将进入应用程序。 因此、我假设此项目不需要 CAN 消息即可工作、对吧? 我只需通过 JTAG 闪存引导加载程序和应用程序。 这是可以的吗?
7.您的应用程序将在结尾写入 while (1) 一旦我通过 SysCtlClockFreqSet、我就在旋转。 除非执行复位、否则我不能仅运行一段时间来发生硬故障。
你(们)好,查尔斯
请参阅我的回答:
1./ 2./3。
[Gavin]是的、这种差异是在两年前来自 TI 团队的。 修改解决了复位情况下的异常系统时钟设置和 USB 时钟(在系统时钟80MHz 下)问题。
我们尝试促使 TI 将修改作为正式版本(文档和 SDK)进行、但至今尚未更新。
4./5。
[Gavin]我可以在得到结果后立即更新给您。
6./7.
[Gavin] CAN 消息只是一条记录、让我知道测试仍在运行、这不是必需的。 刷写引导加载程序和应用程序后、应运行测试。
我想您在刷写应用程序时擦除了引导加载程序。 您可以转储闪存进行确认。
我还有一些更新:
我尝试禁用编译器优化、但仍然发生硬故障。
2.当发生硬件故障时,我在异常帧转储中检查 LR,它似乎在发生故障
//
//设置闪存和 EEPROM 时序值。
//
HWREG (SYSCTL_MEMTIME0)=_SysCtlMemTimingGet (ui32SysClock);
但我不知道为什么它至今造成了严重的错误、我尝试找出 可能的原因。
如果您有一些建议、请与我分享一下吗?
谢谢
Gavin
您好、Gavin、
由于您已经解决了一年多的问题、在此期间您是否遇到过类似的问题? 我只是想知道为什么突然出现了硬故障。 您是否有任何产品实施了该变通办法并正在工作? 如果是这种情况、您是否知道曾经使用过权变措施的产品与当前项目之间的区别是什么?
我想知道频率是否超出导致硬故障的规格? 您能否通过将频率设置为较低的值来尝试实验? 例如、尝试40MHz。 这会产生影响吗?
Gavin、您好!
我查看了您发送的 sysctl 文件、它的起始地址为2.1.0。 此后、我们进行了多次更新、包括由于勘误表而导致硬件故障(未反映在您的软件中)的关键更新。 请使用 2.1.4中的最新文件。 您可能会发现所需的更改也会被烘烤到其中、但会更干净、更紧凑。
请参阅 在2.1.3及更新版本中寻址的勘误项 sysctl#22和 sysctl#23: http://www.ti.com/lit/er/spmz850g/spmz850g.pdf