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

你好奇STM32Cube LL能高效的原因吗?

[复制链接]
eefishing 发布时间:2019-12-18 20:22

ST的库,有很多巧妙之处,值得大家借鉴。今天就来讲讲STM32Cbue LL库中的一点小知识。


3 ~2 ?/ l) @+ X) O( `, O3 Q3 k" g1写在前面

有些应用要求MCU能高效处理,特别是跑一些算法时,对CPU执行效率这一块有要求。


. |2 _% Z# ?, ^. D

网上有很多文章说STM32Cube HAL执行效率不高,代码量大等问题,导致很多没入门,或初学的朋友产生各种各样的疑惑。

9 V3 x( E& \# N* m1 G0 d

承认,HAL相对来说有这些问题,那么与之对应的STM32Cube LL恰好避免了这样的问题。


2 ~* D3 V3 w3 ]) j: I

7 A1 K$ |5 `+ r6 g4 v2LL能高效的原因

简单总结一下原因:巧妙运用C语言静态的,内联函数直接操作寄存器。


; G7 |7 K$ _/ x6 r" k

当然,这是其中重要的原因,还有一些其它原因,这里不描述。

  ?. O* w6 h5 i  `1 h% f! R

你会在LL库.h文件中发现大量类似,静态,内联函数直接读写寄存器的函数。: t8 g$ d4 d& o' l


  N' \) ~1 I0 }) c# Q; S4 f

比如:读写IO口8 Q4 t. h& h0 G; H% \

__STATIC_INLINE uint32_t LL_GPIO_ReadOutputPort
  e, j# n, D" R  o& {) b; N. O(
' q5 F: L6 {1 T4 v7 ?+ A1 CGPIO_TypeDef *GPIOx. ^/ I7 }* F7 ^" ~* {0 E* T
)
! A# S+ _# ]* J+ l' s; L3 ~{   |0 `& _6 b  l# c# W
return (uint32_t)(READ_REG(GPIOx->ODR));$ A0 F. Q/ s7 Z3 S9 X6 `& c" m
}' _* [9 o+ J8 `& l/ {5 u
7 R5 p$ ~" Z& l- L; |
__STATIC_INLINE void LL_GPIO_SetOutputPin(GPIO_TypeDef *GPIOx, uint32_t PinMask)
9 Q0 x% A' Q* Z$ b6 e/ `3 l! K# J{
* U7 \0 a! O8 m WRITE_REG(GPIOx->BSRR, (PinMask >> GPIO_PIN_MASK_POS) & 0x0000FFFFU);3 Q7 m% }: W" k- E/ R  Q8 b) E
}, b) H# N' ^; f


$ a. E/ h+ n& X- f3 o" i% b7 ?

其中__STATIC_INLINE,就是静态、内联:


  • 4 A8 A' u. k8 \% b4 g
#define __STATIC_INLINE  static __inline

* o6 {) [7 O, l

而读写位的定义:


8 b; l; e9 o/ r4 U9 l. }

1.png


/ n" ^% P7 O: u  D- i

这里面的红定义,在众多外设.h中都在调用。比如使能USART:& y$ i# f/ U- ?2 r  U8 r

1 g' K* b0 d! U  I

LL使能USART:0 g. P% g+ V- ?8 k- _6 j8 Q6 _+ d

  • 9 M0 i- w; s  y/ O/ @
__STATIC_INLINE void LL_USART_Enable(USART_TypeDef *USARTx){  SET_BIT(USARTx->CR1, USART_CR1_UE);}


! f6 w) r' v* Y+ f

标准外设库使能USART:
# z) X/ C, L, R; [/ A- u

void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
. E& i# j5 \" [* H; {{  
3 d5 n4 ^4 e' G2 S/* Check the parameters */ 1 n6 s  U% R/ p. s3 d0 N3 R
assert_param(IS_USART_ALL_PERIPH(USARTx));
" s3 ~2 z9 n7 Y  Q assert_param(IS_FUNCTIONAL_STATE(NewState));
& E. J, J' z" f( ^7 v, g, o   if (NewState != DISABLE) ( W* ?8 W, n# K1 }- X  ^# ^$ D
   {  
% Q# Z+ e9 A! T$ }       /* Enable the selected USART by setting the UE bit in the CR1 register */: z( Z7 q: |6 O$ `4 g
       USARTx->CR1 |= USART_CR1_UE;
6 H. s! o& m& M% ]" u   } : C( c  D# ?! u( I8 F6 a4 J! F! k
  else  8 d/ J+ o+ t9 b3 r8 w  x
    {
5 A# {& G2 D2 }% _( ?      /* Disable the selected USART by clearing the UE bit in the CR1 register */
+ N# H/ x4 u. E; y5 b       USARTx->CR1 &= (uint16_t)~((uint16_t)USART_CR1_UE);  7 N+ @7 p: g8 I& L7 F: z- i  E
    }; Y( w7 }, Y. D8 ~) r# j
}5 r. M  ^3 o3 \" {" s9 Q! d, S
4 U& ~" g. k5 h4 F
你会明显发现:LL库的执行效率更高。
/ A$ w; q# c5 o% S7 b

' }  b' G" H0 B$ e$ T' A! |( @/ J
3拓展:内联函数

写到这里,就顺便复习一下内联函数。

5 {% r; N# G6 d6 [. m/ v

内联函数是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展。---来自百度百科2 c. p! b, `! F6 |1 K+ U, {0 K

8 x0 t. T6 H7 h3 A. |
通常,程序执行时,处理器从内存中读取代码执行。当程序中调用一个函数时,程序跳到存储器中保存函数的位置,开始读取代码执行,执行完后再返回。

# X  }0 B# b7 ?  R

为了提高速度,C语言定义了inline函数,告诉编译器把函数代码在编译时直接拷贝到程序中,这样就不用执行时另外读取函数代码。


9 s- p% K# f: w9 u2 F6 e. {" s

提示:% P; e8 W- u0 @, G: |* i" c

当内联函数很大时,会有相反的作用,因此一般比较小的函数才使用内联函数。

  {* i3 u) z4 E( f" R  e: o! j7 e2 s
% S, _4 W. ~) P" U6 g  a4 z
4拓展:软件框架思维

LL之所以高效,是因为它巧妙运用了一些C语言知识,没有太多封装,直接或间接对寄存器进行操作。

0 ]3 {0 E( ?' k9 Z3 T

而能这样实现,归功于ST开发团队设计了这么一个中间层软件框架。' F3 c- D' Q# s5 k) m; M) E5 `" d


/ J" v$ ^% F# O9 {# i4 {

对于有大型项目开发经验的人来说,一个项目的框架对整个项目影响很大。
8 F: r3 Z  H) c- v5 Z
就好比你建一栋楼,如果楼层框架都没造好,你觉得这栋楼质量会好吗?
( ?- P+ f* }" S
所以,这里就提到,我们编程时,特别项目较大,需要考虑一下软件框架,一个好的框架能让你你的项目达到事半功倍的效果。
8 G% V% ^. N( y

评分

参与人数 1 ST金币 +1 收起 理由
026 + 1 很给力!

查看全部评分

赞 1 收藏 1 评论1 发布时间:2019-12-18 20:22

举报

1个回答
bingsun 回答时间:2019-12-19 11:44:02
使用库我真没法下手,我还是像使用单片机一样,配置时钟,I/O等。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版