你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法

[复制链接]
STMCU小助手 发布时间:2022-4-10 16:48
现象复现
/ H% z' o& {! J7 `; X" n7 B1 u9 @项目中一个是IAP程序,另一个是APP程序,两个程序都是使用STM32CubeIDE生成,当程序跳转到APP中并且执行到函数SystemClock_Config中的时候,在初始化锁相环调用HAL_RCC_OscConfig函数的时候返回HAL_ERROR或者直接卡死在里面。
, ?- b4 v- Y* a$ K7 w! l7 |2 p- i6 L! [. M/ L
为什么在IAP中可以初始化通过,但是在APP中却通不过,查阅STM32F4xx参考手册发现这么一段话:
% W  ^7 g8 V8 Q' [' @1 m" H% Z% K7 K. a0 @1 f) x
C5)Z[0`UUDFGQYX0P2KB{@E.png & o. @+ J  ~# \2 b* t

! ?8 }) }" w( g1 \7 y6 u那么出现这个问题的原因也就清楚了,因为在IAP中已经初始化了PLL,在APP中再次初始化就不成功。6 c8 a' z1 Y9 T7 I) L1 p  p9 c6 l
( j( `8 U& i7 a
解决办法
4 d, ~8 U4 {- K* K- N我查找ST官方HAL固件库中对重复配置RCC时钟的时候,发现他是这么做的:
: Q8 T9 l% r2 v+ O1.先将时钟源选择为内部时钟- z- r& [! n6 G; b
2.初始化锁相环! _% Z4 k9 ?% Q5 Z. s2 a% `: Q! }: c
3.将时钟源在切换回外部时钟源7 D7 p/ W! G# ]: W( f
4.禁用内部高速时钟(可选步骤,如果内部高速时钟不用的话,建议禁掉)
9 x( X- n! N. k" C4 B, C/ _+ k6 K% f# ]1 X$ K
官方代码如下:
  R. z1 E% G0 T/ S- G* u
8 U  j, p+ M' d/ @2 D' z CWW59K4%$L~GB`~][c1EN.png
" Z0 L+ I, z4 Z1 C
7 _$ }$ D% w2 g) D以下是我的示例代码:  u3 A+ l- S( v9 L( E" I

1 O9 M% Y6 }8 Z& J4 W
  1. void SystemClock_Config(void), R7 N! T/ H- b3 S1 N! q1 b
  2. {5 m: ^' |, n, F$ {. m" ?
  3.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    ( z# g, l6 \& Z1 f3 O. s( g( z
  4.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};8 m& N. m8 M- ^
  5. " T& h2 J4 i: O: f3 K
  6.   /** Configure the main internal regulator output voltage
    0 q8 ^, T5 N/ }1 }* s2 _
  7.   */+ ?  Z: F2 B3 b# }, I( p
  8.   __HAL_RCC_PWR_CLK_ENABLE();; w" X# u2 R0 w% S0 m" p5 B" N
  9.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    0 E9 ]& I# M) T
  10. & W4 b: u  \- C" z2 H3 |5 F7 ?' d- {
  11.   // 先将时钟源选择为内部时钟
    " L' m  y7 I6 S/ p! S# ~9 H
  12.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;% h. e& v1 w, }. M7 D6 @. }1 L
  13.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    9 f3 ]# X2 {5 D0 T4 d* \
  14.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
      |' H! D  f, P- Y2 f' z( f
  15.   {
    0 Z& \  j! i' l, e* D
  16.     Error_Handler();
    2 x1 F8 ~! B7 {: V# o' a; h% J8 ?# f4 A
  17.   }
    7 X# p5 {! B# f6 x; R+ \) n

  18. * R( B: m) F! o+ ]  Y; [
  19.   // 初始化锁相环
    / o5 i* `$ ?- g' p' R( Q1 ]' v+ X) X; W
  20.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    ! e8 \2 S1 b) l- O. X. w9 t
  21.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;! t/ k* z/ l! [
  22.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;( b# |  R! {; ~* K1 _( x/ y) @
  23.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;% s2 }7 R4 b' |
  24.   RCC_OscInitStruct.PLL.PLLM = 4;3 G. M6 j/ W: W' |& v$ J
  25.   RCC_OscInitStruct.PLL.PLLN = 168;
    2 I% P. n, F# e/ w! O  ?
  26.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;* i+ ~$ ]) O0 i! Q- ]; a# o% P
  27.   RCC_OscInitStruct.PLL.PLLQ = 4;
    ! Y2 V- F( B  o, R# {
  28.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    ' a# O! N# G0 w+ k
  29.   {
    # y5 o  @7 b* |8 p* I# v0 |
  30.     Error_Handler();, c$ M$ G: s. L$ ~& J
  31.   }
    4 H0 ~; v/ y$ K

  32. ) E0 B# ]# }' e# m) f
  33.   // 锁相环已经初始化完毕了,将时钟源在切换回外部时钟源; A( T! u( O2 U9 y2 w7 t/ P
  34.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK0 V( M8 u& I' `: ?2 |; Z4 ]
  35.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    + H- f8 ?$ r3 u; A& T
  36.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    & N. a6 u, D, Q& y# ]
  37.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;3 z& g6 v$ J4 b
  38.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;% e0 ^$ Z& x- [- G6 C
  39.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    6 k. G) [5 s) `; d
  40.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
    / ~! ?: {: V, s4 r. d
  41.   {
    8 a6 L& |5 H2 z
  42.     Error_Handler();
    0 B8 Z& Q0 w1 F  z  o& ]# w
  43.   }' e& M6 e& Z" B4 o6 i' v+ T

  44. 5 H; y2 Y8 @3 m0 e$ q
  45.         // 禁用内部高速时钟+ Y& T2 S+ q# E4 A
  46.         RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    5 P  x, R3 X7 e5 r
  47.         RCC_OscInitStruct.HSIState = RCC_HSI_OFF;& p0 B0 |4 N- Q6 i& ~
  48.         RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;: k5 s: h  u) H( u# i! h5 o
  49.         if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    8 _- _' @+ F1 w" F& ~- c* F
  50.         {
    ( f8 ?( V! C0 e! t5 k! t7 q# ]
  51.           Error_Handler();7 i9 H  |5 g* M! R& i# v  k
  52.         }
      {8 Z8 [8 |. z3 x) h
  53. }
复制代码
4 ~  e  M1 u- H4 w, t, @
通过以上操作后,问题成功解决!) h1 W! {* l4 y: }$ y7 E5 N

- D+ p$ v1 j9 Q; }! |; c解决F4系列这个问题之后,我又去看F1系列的参考手册,发现:
* g' w9 \, y; y+ o' U
& I5 E7 D4 D% U$ } Z~BM4E0%XV9CHOD)9M{EA`A.png ; s. t( o; g( f/ ?; O" x
1 J+ w: {3 M1 O9 L, v) W
同样的也是需要在使能PLL之前完成时钟配置,不过在实际中发现,F1系列的IAP跳转到APP中并没有卡死在HAL_RCC_OscConfig函数中。
: P& ?7 r* J$ ~, }9 O& Z4 Q! m: j9 S9 c8 S8 ^$ a
还有一个更快捷方便的办法,就是在IAP中不使用PLL,直接使用HSE或HSI的8M晶振作为系统时钟,如下图时钟的配置:
+ q0 o& S1 I: G0 j0 m% B
3 r3 y2 a; a* a+ l H0$`KI_NV8G756SU`T6(}]H.png , O  q9 r/ m/ }1 [
( I- i- {, \& l! X) T9 i% K
7 [9 D6 F* _  b- J' \) b

- h1 v5 W( m" g. }3 y2 n
赞 收藏 评论0 发布时间:2022-4-10 16:48

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版