大家好、
你好。
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.
大家好、
你好。
我们的客户尝试从头开始构建 GPIO 驱动器,当他通过设置 RCGCTIMER 寄存器上的相应位来处理 GPIO 部分的指令时,该位未设置并转至中断。 可能的问题是什么?
调试器会给他这个注释
"这是处理器收到故障时调用的代码
中断。 这只是进入一个无限循环、从而保持系统状态
供调试器检查。"
谢谢、此致、
艺术
您好!
客户不会使用 TivaWare 外设驱动程序库有什么原因吗? 这是一个经过验证的驱动程序库、 便于客户进行快速的软件开发。 您说过构建 GPIO 驱动程序、然后提到设置 RCGCTIMER 中的位。 RCGCTIMER 是计时器模块的时钟门控寄存器、而不是 GPIO 的时钟门控寄存器。 如果客户的问题是由时钟引起的、RCGCGPIO 寄存器是用来启用 GPIO 模块时钟的寄存器。 同样、我强烈建议客户使用 TivaWare 库进行软件开发。 在 DRM 中编写代码(直接存储器操作)很容易出错。 另请参阅 https://e2e.ti.com/support/microcontrollers/other/f/other-microcontrollers-forum/695568/faq-read-before-posting-tm4c-forum-general-guidelines 中的常见问题解答4 、我们不支持 DRM 编码风格。
您好、Charles、
我已附上客户的文件。 请参阅"GPIO_TEST4.rar"
您可能会在审阅时发现错误。 他仍然遇到同样的问题。
e2e.ti.com/.../GPIO_5F00_TEST4.rar
谢谢、此致、
艺术
您好!
我运行了测试代码、代码卡在 RCC_init 中 、即时钟启动。 当 TivaWare 已经具有完全相同的驱动程序时、重新设计编写时钟初始化例程的轮子实际上没有任何好处。 其余驱动器也是如此。 时钟启动是一个非常复杂的软件序列、我不会推荐任何编写自己的时钟的人。 如果客户必须为其编写自己的驱动程序、我建议他参考 TivaWare SysCtlClcokSet()以了解其完成方式。 我不想粗鲁,但我会再次重申,我不建议从头开始编写时钟启动,我在上一个答复中明确指出,根据常见问题解答,我们不支持 DRM 编码风格。 如果有人必须写入 DRM、请参考 TivaWare 源代码。
void
SysCtlClockSet(uint32_t ui32Config)
{
uint32_t ui32Delay, ui32RCC, ui32RCC2;
//
// Get the current value of the RCC and RCC2 registers.
//
ui32RCC = HWREG(SYSCTL_RCC);
ui32RCC2 = HWREG(SYSCTL_RCC2);
//
// Bypass the PLL and system clock dividers for now.
//
ui32RCC |= SYSCTL_RCC_BYPASS;
ui32RCC &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= SYSCTL_RCC2_BYPASS2;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// See if the oscillator needs to be enabled.
//
if((ui32RCC & SYSCTL_RCC_MOSCDIS) && !(ui32Config & SYSCTL_MAIN_OSC_DIS))
{
//
// Make sure that the required oscillators are enabled. For now, the
// previously enabled oscillators must be enabled along with the newly
// requested oscillators.
//
ui32RCC &= (~SYSCTL_RCC_MOSCDIS | (ui32Config & SYSCTL_MAIN_OSC_DIS));
//
// Clear the MOSC power up raw interrupt status to be sure it is not
// set when waiting below.
//
HWREG(SYSCTL_MISC) = SYSCTL_MISC_MOSCPUPMIS;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
//
// Timeout using the legacy delay value.
//
ui32Delay = 524288;
while((HWREG(SYSCTL_RIS) & SYSCTL_RIS_MOSCPUPRIS) == 0)
{
ui32Delay--;
if(ui32Delay == 0)
{
break;
}
}
//
// If the main oscillator failed to start up then do not switch to
// it and return.
//
if(ui32Delay == 0)
{
return;
}
}
//
// Set the new crystal value and oscillator source. Because the OSCSRC2
// field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a
// special encoding within ui32Config to avoid the overlap.
//
ui32RCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC |= ui32Config & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M);
ui32RCC2 |= ui32Config & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 |= (ui32Config & 0x00000008) << 3;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// Set the PLL configuration.
//
ui32RCC &= ~SYSCTL_RCC_PWRDN;
ui32RCC |= ui32Config & SYSCTL_RCC_PWRDN;
ui32RCC2 &= ~SYSCTL_RCC2_PWRDN2;
ui32RCC2 |= ui32Config & SYSCTL_RCC2_PWRDN2;
//
// Clear the PLL lock interrupt.
//
HWREG(SYSCTL_MISC) = SYSCTL_MISC_PLLLMIS;
//
// Write the new RCC value.
//
if(ui32RCC2 & SYSCTL_RCC2_USERCC2)
{
HWREG(SYSCTL_RCC2) = ui32RCC2;
HWREG(SYSCTL_RCC) = ui32RCC;
}
else
{
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
}
//
// Set the requested system divider and disable the appropriate
// oscillators. This value is not written immediately.
//
ui32RCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC |= ui32Config & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
ui32RCC2 |= ui32Config & SYSCTL_RCC2_SYSDIV2_M;
if(ui32Config & SYSCTL_RCC2_DIV400)
{
ui32RCC |= SYSCTL_RCC_USESYSDIV;
ui32RCC2 &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= ui32Config & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB);
}
else
{
ui32RCC2 &= ~(SYSCTL_RCC2_DIV400);
}
//
// See if the PLL output is being used to clock the system.
//
if(!(ui32Config & SYSCTL_RCC_BYPASS))
{
//
// Wait until the PLL has locked.
//
for(ui32Delay = 32768; ui32Delay > 0; ui32Delay--)
{
if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
{
break;
}
}
//
// Enable use of the PLL.
//
ui32RCC &= ~(SYSCTL_RCC_BYPASS);
ui32RCC2 &= ~(SYSCTL_RCC2_BYPASS2);
}
//
// Write the final RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// Delay for a little bit so that the system divider takes effect.
//
SysCtlDelay(16);
}