主题中讨论的其他器件:TM4C1294NCPDT
您好!
寻求有关使用 MOSC (外部25MHz xtal)配置 PLL 以驱动 SYSCLK 的说明、并对数据表中的步骤有一些疑问。
在2014年6月18日 TM4C1294NCPDT 数据表第5.3节(第246页) PLL 配置的修订版中、第4步说明将 RSCLKCFG 寄存器中的 OSCSRC 域设置为0x3 = MOSC、但它并未说明如何将 PLLSRC 域设置为 MOSC、 这对于配置 PLL 而言似乎很重要。 在 SysCtlClockFreqSet()的 TivaWare 实现中、它将 OSCSRC 和 PLLSRC 设置为0x3 = MOSC、但随后它会恢复 OSCSRC 以在退出前使用 PIOSC。 第一和第二个问题是:
第4步是正确的、还是应该改为将 PLLSRC 字段设置为0x3? 如果您的唯一目的是使能 PLL 来驱动 SYSCLK、那么在配置期间是否有任何理由将 OSCSRC 和 PLLSRC 都设置为 MOSC?
数据表中也没有提到如何设置 MOSCTL 中的 OSCRNG 位。 我不确定在使用 PLL 或 OSC (PLL 被绕过)或两者时是否需要这个、但 SysCtlClockFreqSet 实现确实将其置位。 第三个问题:
使用 PLL (频率> 10MHz)时、是否应设置 OSCRNG?
更重要的是步骤7 (写入 MEMTIME0)和8 (等待 PLLSTAT)是否必须按该顺序执行。 似乎可以在 PLL 锁定后、但在设置 MEMTIU 之前设置 MEMTIME0 (以启用新的 EPROM 和闪存时序)。 最后一个问题是:
在 PLL 状态变为锁定状态之前、是否有理由写入 MEMTIME0?
我已经能够使用下面的代码配置 PLL 以将 SYSCLK 成功驱动至120MHz、使 OSCSRC = 0x0 PIOSC、到目前为止一切似乎都正常。 我将其分解为三个主要步骤。 感谢您提供任何反馈/更正。
// 加电复位(POR)后、CPU 将使用精确内部 // 运行频率为16MHz 的振荡器(PIOSC)。 //有三个主要步骤 初始化/使用 PLL: // 1) 1)启用主振荡器(MOSC)。 // 2) 2)配置和启用 PLL。 // 3) 3)重新配置 SYSCLK 以使用 PLL 作为其源。 // 每个主步骤都有一个或多个子步骤、涉及直接寄存器访问。 // void PLL_Init120MHz (void) { // //步骤1:启用 MOSC // //同时应用子步骤1-3以保留当前 MOSCCTL 位值。 uint32_t mosc = sysctl_MOSCCTL_R; // 1)通过清除"no crystal"位来为 MOSC (主振荡器)加电。 // EK-TM4C1294XL 电路板上的晶振为25MHz 并连接到 OSC0和 OSC1。 mosc &=~SYSCTL_MOSCCTL_NOXTAL; // 2)通过清除断电位来启用主振荡器的电源。 mosc &=~SYSCTL_MOSCCTL_PWRDN; // 3)指定高振荡器范围(>=10MHz)。 //此子步由 SysCtlClockFreqSet 执行、其表述为"增加 // 10MHz 及以上 MOSC 的驱动强度"。 Valvano 不使用它 //或数据表配置中提到的。 mosc |= SYSCTL_MOSCCTL_OSCRNG; // 3)设置并等待 MOSC 经过足够的时间到达 晶体的预期25MHz 频率//。 得到的 MOSCCTL 值将为0x10。 SYSCTL_MOSCCTL_R = mosc; //这将检查加电屏蔽的中断状态位。 while (((SYSCTL_RIS_R & SYSCTL_RIS_MOSCPUPRIS)==0){} // //步骤2:配置和启用 PLL // // 5)清除 PLL 输入时钟源并将其设置为 MOSC。 //由于拼写错误(?)、数据表中似乎未提及此子步骤 也就是这样 //改为设置 OSCSRC 字段。 SysCtlClockFreqSet 和 Valvano 都设置了 PLLSRC、 //但它们也设置了 OSCSRC。 SysCtlClockFreqSet 在之后恢复 OSCSRC //启用 PLL,但 Valvano 没有。 似乎没有必要设置给定的 OSCSRC // PLL 不会被旁路(?)。 数据表中没有说明原因 //必须将 OSCCRC 配置为在 PLL 配置时临时使用 MOSC、以此类推 //跳过这里。 SYSCTL_RSCLKCFG_R =(SYSCTL_RSCLKCFG_R &~SYSCTL_RSCLKCFG_PLLSRC_M)| SYSCTL_RSCLKCFG_PLLSRC_MOSC; //步骤6-8在数据表中进行了说明(pgs.237-238) //= 1 (dfin + 1) /(dfin = 1)/(1)/(dfin = 1)/(dfin + 1)/(1)/(dtin = 1)/(dtin + 1)/(dtin = 1)/fin + 1) 对于 fxtal= 25MHz、设置 Q = 0、N = 4 => fin = 25MHz/((0+1)(4+1))= 5MHz SYSCTL_PLLFREQ1_R = 0x4; // 7)设置 M分数= 0 SYSCTL_PLLFREQ0_R &&~SYSCTL_PLLFREQ0_MFRAC_M; // 8)设置 Mint = 96 = 0x60 => fvco =(5MHz * 96)= 480MHz SYSCTL_PLLFREQ0_R =(SYSCTL_PLL_PLQ0_R )| 0_Rp =(SYSCTL_PLQ0_PLLVM_R_Rp)| 0_Rp =(SYSC0_PLQ0_PLQ0)+ 0_Rp =) 0 ~0_Rp + 0)/0 + 稳定并锁定请求的频率需要一些时间。 SYSCTL_PLLFREQ0_R |= SYSCTL_PLLFREQ0_PLLPWR; // 10)等待 PLL 上电并锁定。 while ((SYSCTL_PLLSTAT_R & SYSCTL_PLLSTAT_LOCK)==0){} // //步骤3:重新配置 SYSCLK 以使用 PLL。 // // 11)设置主闪存和 EEPROM 存储器的时序参数。 //这些设置将在下面设置 MEMTIU 位后生效。 //因此,清除相关的字段位,确保保留的位保持不变。 //对于 CPU 频率100MHz < f <= 120MHz: // EBCHT = FBCHT = 0x6 // EBCE = FBCE = 0 // FWS = EWS = 0x5; //由于保留的位20和4显示为0x1,因此得到的 MEMTIME0值应为:0x01950195 UINT32_t timim0 = SYSCTL_MEMOR_0; memtim0 &=~(SYSCTL_MEMTIME0_EBCHT_M | SYSCTL_MEMTIME0_EBCE | SYSCTL_MEMTIME0_EWS_M | SYSCTL_MEMTIME0_FBCHT_M | SYSCTL_MEMTIME0_FBCE | SYSCTL_MEMTIME0_FWS_M); memtim0 ||(SYSCTL_MEMTIME0_EBCHT_3_5 | SYSCTL_MEMTIME0_FBWS_3_5 |(0x5 < SYSCTL_MEMOR_0 | )= SYSCT14_MEMTR0 | SYSCTTR_MEMCTL_0 |(0x5 < 0x5)+ SYSCTR_MEMCTL_MEMOR_MEMOR_MEMOR_0 =同时应用 SYSCTR0)。 uint32_t rsclkcfg = SYSCTL_RSCLKCFG_R; // 12)设置 PLL 系统时钟分频值= 3 => SYSCLK = 480MHz /(1+3)= 120MHz。 rsclkcfg =(rsclkcfg &~sysctl_RSCLKCFG_PSYSDIV_M)| 0x3; // 13)使用 PLL 作为系统时钟源 rssclkcfg |= sysctl_RSCLKCFG_USEPLL; // 14)应用 MEMTIMEU 寄存器值并在设置的内存时序中更新。 rsclkcfg |= SYSCTL_RSCLKCFG_MEMTIU; SYSCTL_RSCLKCFG_R = rsclkcfg; }
谢谢!