在STM32F4上,为什么将主时钟源设置为PLL会破坏程序的其余部分?

时间:2017-12-06 11:45:58

标签: c assembly arm corruption stm32f4

第一个问题,感谢您的耐心等待。

使用StdPeriph库v1.8.0,我遇到了基于STM32F446VET6的电路板(STMicroelectronics的ST-B96B-F446VE)的问题。我已将问题缩小到SetSysClock函数中的str指令:

;722          RCC->CFGR |= RCC_CFGR_SW_PLL;
; RCC->CFGR = 0x9400
; RCC_CFGR_SW_PLL = 0x02
ldr r2, [pc, #36]   ; (0x80005a8 <SetSysClock+284>)
ldr r3, [pc, #36]   ; (0x80005a8 <SetSysClock+284>)
ldr r3, [r3, #8]
orr.w   r3, r3, #2
str r3, [r2, #8]    ; r2 = 0x40023800, r3 = 0x9402

指令结果应该是RCC-> CFGR(SW1)的第二位设置为1,以便将PLL设置为主时钟源。

相反,该位保持为0,并且将覆盖超过0x08000000(在闪存中)的大量代码。例如,SystemInit()中的这一行:

; SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
ldr     r3, [pc, #12]   ; (0x8000484 <SystemInit+96>)
mov.w   r2, #134217728  ; 0x8000000
str     r2, [r3, #8]

最终改写为:

; SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
bic.w   r3, r3, #262144 ; 0x40000
str     r3, [r2, #0]
ldr     r3, [pc, #24]   ; (0x8000494 <SetSysClock+8>)

让程序在这种状态下运行并再次暂停它会显示更多的覆盖事件再次发生在同一行:

; SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
b.n     0x8000476 <SystemInit+86>
subs    r0, #0
ands    r2, r0

它挂在sub和ands指令中。

顺便说一句,用RCC->CFGR |= RCC_CFGR_SW_PLL;替换行RCC->CFGR |= RCC_CFGR_SW_HSE;可以解决问题。没有发生损坏,并且main()正确执行。但现在它正在使用另一个时钟源,不知道它带来了什么影响。

有没有办法恢复到使用PLL作为主时钟源的默认状态,并避免闪存损坏?

1 个答案:

答案 0 :(得分:1)

  

我已将问题缩小到SetSysClock函数中的str指令:

这通常意味着您之前忘记设置闪存等待状态。闪存速度相当慢 - 它通常在20 MHz左右,没有许多MCU的等待状态。试图快速运行会导致读取垃圾。

参考手册和数据表应说明目标频率闪存访问所需的等待状态数。注意:以最大等待状态运行闪存是安全的(但速度较慢)。