PLL寄存器配置生成中断(ARM)

时间:2016-01-15 00:09:17

标签: c assembly arm interrupt-handling

我正在使用英飞凌生产的ARM设备。在配置PLL 时,我似乎无法找到解决方案。当配置保持正常PLL模式的N,P和K值的寄存器时,代码产生中断并且之后不会暂停。这是反汇编程序(Eclipse)中显示的代码:

1333          SCU_PLL->PLLCON1 = (uint32_t)((SCU_PLL->PLLCON1 & ~(SCU_PLL_PLLCON1_NDIV_Msk | SCU_PLL_PLLCON1_K2DIV_Msk |
08000cc8:   ldr r1, [pc, #252]      ; (0x8000dc8 <XMC_SCU_CLOCK_StartSystemPll+400>)
08000cca:   ldr r3, [pc, #252]      ; (0x8000dc8 <XMC_SCU_CLOCK_StartSystemPll+400>)
08000ccc:   ldr r2, [r3, #8]
08000cce:   ldr r3, [pc, #252]      ; (0x8000dcc <XMC_SCU_CLOCK_StartSystemPll+404>)
08000cd0:   ands r3, r2
1334                                         SCU_PLL_PLLCON1_PDIV_Msk)) | ((ndiv - 1UL) << SCU_PLL_PLLCON1_NDIV_Pos) |
08000cd2:   ldr r2, [r7, #4]
08000cd4:   subs r2, #1
08000cd6:   lsls r2, r2, #8
08000cd8:   orrs r2, r3
1335                                         ((kdiv_temp - 1UL) << SCU_PLL_PLLCON1_K2DIV_Pos) |
08000cda:   ldr r3, [r7, #16]
08000cdc:   subs r3, #1
08000cde:   lsls r3, r3, #16
1334                                         SCU_PLL_PLLCON1_PDIV_Msk)) | ((ndiv - 1UL) << SCU_PLL_PLLCON1_NDIV_Pos) |
08000ce0:   orrs r2, r3
1336                                         ((pdiv - 1UL)<< SCU_PLL_PLLCON1_PDIV_Pos));

似乎代码&#34;打破&#34;在以下说明中:

08000cce:   ldr r3, [pc, #252]      ; (0x8000dcc <XMC_SCU_CLOCK_StartSystemPll+404>)

换句话说,如果我使用&#39;步骤进入&#39;功能,它会在转移到&#39; ldr之前跳转到下面的中断。上面的说明。以下是我使用过的N,P和K值的配置。

.syspll_config.n_div = 80U,
.syspll_config.p_div = 2U,
.syspll_config.k_div = 4U,

我被告知处理程序的名称并不重要,但这是Disassembler在程序无法执行08000cce行之后解决的问题。

08000298:   b.n 0x8000298 <VADC0_G3_3_IRQHandler>

此外,这是控制台中显示的内容。

Starting target CPU...
Debugger requested to halt target...
...Target halted (PC = 0x08000298)
/.../
WARNING: Failed to read memory @ address 0xFFFFFFE8
WARNING: Failed to read memory @ address 0xFFFFFFE8

编辑:也许为了完整起见,我会在system.c文件中包含一个代码片段,该代码片段使用默认值初始化PLL模块,正常工作。它与此问题的第一个代码窗格中显示的代码非常相似,可能除了在写入新的P,N和K值之前重置受影响的寄存器值。我将初始化代码分为两部分 - 重置和设置值;似乎代码&#34;打破&#34;在重置阶段。

SCU_PLL->PLLCON1 = ((PLL_NDIV << SCU_PLL_PLLCON1_NDIV_Pos) |
(PLL_K2DIV_24MHZ << SCU_PLL_PLLCON1_K2DIV_Pos) |
(PLL_PDIV << SCU_PLL_PLLCON1_PDIV_Pos));

1 个答案:

答案 0 :(得分:0)

问题最终是由于在将VCO(压控振荡器)与外部振荡器OSC断开连接时产生的陷阱请求(提升为NMI)引起的。断开两个硬件组件的连接对于配置PLL寄存器非常重要,但是,如果失锁时的陷阱请求不是 清除和禁用 ,则会生成以下命令:中断:

/* disconnect Oscillator from PLL */
SCU_PLL->PLLCON0 |= (uint32_t)SCU_PLL_PLLCON0_FINDIS_Msk; 

该命令位于以下行之前,这是我认为最初导致问题的行,因此将其发布在问题中:

SCU_PLL->PLLCON1 = (uint32_t)((SCU_PLL->PLLCON1 & ~(SCU_PLL_PLLCON1_NDIV_Msk | SCU_PLL_PLLCON1_K2DIV_Msk | SCU_PLL_PLLCON1_PDIV_Msk))

请注意,陷阱请求可以帮助解决PLL模块的问题,因此需要再次启用它们。但是,无论uC是否将对其执行操作(仍由启用/禁用位决定),仍会生成陷阱请求。因此,为了再次恢复陷阱功能,需要再次清除然后启用模块,如下所示:

SCU_TRAP->TRAPCLR |= SCU_TRAP_TRAPCLR_SVCOLCKT_Msk;
SCU_TRAP->TRAPDIS &= ~SCU_TRAP_TRAPDIS_SVCOLCKT_Msk;

在此过程中,我发现了这篇有趣的文章,可以帮助任何处理ARM uCs并面临意外中断的人:Debugging and Diagnosing Hard Fault & Other Exceptions.