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

C 在STM32F4上,为什么将主时钟源设置为PLL会损坏程序的其余部分?,c,assembly,arm,corruption,stm32f4,C,Assembly,Arm,Corruption,Stm32f4,第一个问题,谢谢你的耐心 我在使用StdPeriph library v1.8.0时遇到了一个基于STM32F446VET6的电路板(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 <S

第一个问题,谢谢你的耐心

我在使用StdPeriph library v1.8.0时遇到了一个基于STM32F446VET6的电路板(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
;722 RCC->CFGR |=RCC_CFGR_SW_PLL;
; RCC->CFGR=0x9400
; RCC\u CFGR\u SW\u PLL=0x02
ldr r2,[pc,#36];(0x80005a8)
ldr r3,[pc,#36];(0x80005a8)
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;/*内部FLASH中的向量表重定位*/
ldr r3,[pc,#12];(0x8000484)
第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;/*内部FLASH中的向量表重定位*/
比克w r3,r3,#262144;0x40000
str r3[r2,#0]
ldr r3,[pc,#24];(0x8000494)
让程序在此状态下运行并再次暂停,会显示在相同的行中发生了更多的覆盖:

; SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
b.n     0x8000476 <SystemInit+86>
subs    r0, #0
ands    r2, r0
;SCB->VTOR=FLASH_BASE|VECT_TAB_OFFSET;/*内部FLASH中的向量表重定位*/
b、 n 0x8000476
潜艇r0#0
r2,r0
它挂在潜艇和防空指令上

顺便提一下,替换线路
RCC->CFGR |=RCC_CFGR_SW_PLL
RCC->CFGR |=RCC_CFGR_SW_HSE解决该问题。不会发生损坏,main()会正确执行。但现在它使用另一个时钟源,不知道这意味着什么


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

我已将问题缩小到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
这通常意味着您以前忘记设置闪存等待状态。闪存速度相当慢——它的最高频率通常在20兆赫左右,许多MCU都没有等待状态。试图运行得太快会导致读取垃圾


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

如果在重置后的第一条指令(通常是称为
reset\u Handler
的程序集标签)处中断,并检查闪存,则在发生此情况后的下一次运行中,闪存是否仍然损坏?如果没有(我强烈怀疑),这将指向某个运行时错误,该错误只会使闪存看起来损坏,即闪存读取失败。当您切换到PLL时,它的频率是多少?是稳定的吗?另外,请考虑切换到Cube。注意,当调试器改变时钟源时,许多调试器无法适应。只是这样做。事实上,闪光灯看起来不再损坏。这是什么原因造成的?是闪光灯跟不上PLL的频率吗?我尝试过将Flash等待状态从6个周期提高到11个周期,但没有成功。如何测试PLL稳定性?我将研究多维数据集。目前的主要问题不是调试器问题:在没有调试器的情况下运行程序,如果选择PLL作为主时钟源,处理器不会进入main()。使用HSE,main()可以正常运行,并且LED会在我编程时闪烁。尽管如此,我还是会记住你的话。这个特殊的部分显然指定了零等待状态的最大时钟30MHz,并提供3.3V。(手册第6.3.1章表17)时钟源和闪存延迟在system_stm32f4xx.c中设置,我还没有编写。断层线上方两行,震源显示:
FLASH->ACR=FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS我尝试使用
FLASH\u ACR\u LATENCY\u 15WS
,但没有效果。