这里的第一个问题,谢谢您的耐心配合。
使用StdPeriph库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
指令结果应该是将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
它挂在subs和ands指令中。
顺便说一句,用
RCC->CFGR |= RCC_CFGR_SW_PLL;
代替RCC->CFGR |= RCC_CFGR_SW_HSE;
行可以解决此问题。没有损坏发生,并且main()正确执行。但是现在它正在使用另一个时钟源,不知道这将带来什么影响。有什么方法可以恢复为使用PLL作为主时钟源的默认状态,并避免闪存损坏?
最佳答案
我将问题缩小到SetSysClock函数中的str指令:
这通常意味着您忘记之前设置闪存等待状态。闪存的运行速度相当慢-通常在20 MHz左右即可达到峰值,而无需等待许多MCU的等待状态。尝试运行得太快会导致读取垃圾。
参考手册和数据表应说明您的目标频率需要多少等待状态才能访问闪存。注意:以最大等待状态运行闪光灯是安全的(但较慢)。
关于c - 在STM32F4上,为什么将主时钟源设置为PLL会破坏程序的其余部分?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47673522/