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

笔记---FreeRtos系统中外设中断优先级设置的要点

[复制链接]
power568 发布时间:2019-4-16 14:15
本帖最后由 power568 于 2019-4-16 16:07 编辑 # {0 y- W) I" v* [8 T8 K' a

9 R' H8 I! w9 {. I* M       最近在写一个串口通讯的程序,软件、硬件平台如下:6 \- x3 z; N7 `, I/ g  G3 C: i
硬件: STM32F429ZG
8 w5 g. h& G' y; z系统: FreeRtos、HAL库8 R! w) P% c) |6 B* G; p
工具:  Iar7.6" u0 h$ k8 b8 @& @

! H3 e2 L& b1 |  y4 Y1 h# s+ `       计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置* i" F0 s' k$ E$ s
  2. HAL_NVIC_EnableIRQ(USART1_IRQn);
    & ?/ b9 g  U* Y" B2 f
  3. + Q6 a7 k/ z$ B! b6 \$ M( P: \: J
  4. void USART1_IRQHandler(void)
    9 U" B6 I& u# K# M4 Q6 M
  5. {
    6 N; V; V' Y8 i9 S3 c, E) W
  6.         uint32_t                 flag=0;' w/ `% Z  M# m) R- S: V* g+ H
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;. T% u6 U6 V; k5 W9 y6 w3 V; m
  8.         ! Q% I+ b  R. e* i
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
    1 p  i, s: M6 l/ u9 |$ q9 O( ]1 K
  10.         if((flag != RESET))/ }5 t7 i7 t. g% g
  11.         {3 l1 F- }( Z7 n: p9 H% W
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);( F0 z4 D8 S- B
  13.                 huart1.Instance->SR;  
    & k4 {. }) ?( k+ p8 p' `8 a
  14.                 huart1.Instance->DR;) r/ n+ `! _& o+ _8 c9 M* ?- }

  15. 3 P/ e5 K) U' v: J# T" j/ H' ]: p
  16.                 HAL_UART_DMAStop(&huart1);& }' y5 S6 `5 X. \' l' k
  17.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);5 o  i, g" Q" Y9 S
  18.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
    ' \) W& u, Q9 F2 I1 b; u: b' k
  19.         }
    ) H0 P* l; T9 i% h
  20. }
复制代码
* ^7 w, L) P" i! ]+ q4 B

9 l* J: i7 T8 k- v$ U1 i  //// 为什么代码提交后,代码对齐格式变了呢???
- v  t' W3 N9 T6 D& E' t; K" R
% @: M6 b6 b  S* m3 _, p) g4 A1 F       调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:3 o* H- Z( }2 `+ o6 Z9 l2 v
  1. #if( configASSERT_DEFINED == 1 )
    0 G% }8 G' ~1 z, t% ?
  2. : z2 u5 G/ r# U9 j6 E5 R
  3.         void vPortValidateInterruptPriority( void )4 y, U! S4 V/ o+ \
  4.         {
    : p+ g: |/ j7 G4 L
  5.         uint32_t ulCurrentInterrupt;
    & I5 M% n* _" i3 {" F
  6.         uint8_t ucCurrentPriority;
    $ F* r' j- C. u. E: S' a
  7. ) ~8 B0 R$ d- o& o# b
  8.                 /* Obtain the number of the currently executing interrupt. */
    5 M- F. P/ w( L) i% _. S8 T7 P
  9.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );2 H" o! _% P, x! R3 T
  10.                 //// ulCurrentInterrupt 调试显示为53/ p- `) ]' [4 e/ O4 _- k+ C2 A

  11. ' [' q1 k  j! h# c9 W
  12.                 /* Is the interrupt number a user defined interrupt? */
    ( S6 u9 d! ~. B/ K
  13.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )+ p# h6 B% ~; [/ E0 R
  14.                 {3 l4 g/ u# ~# n0 {' p* t; l/ [  w% v
  15.                         /* Look up the interrupt's priority. */% W! S1 n8 S  Z0 _# i
  16.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
    & E& s, H' Y, T* h+ x1 F
  17.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断' [" i* @, s/ i" ~5 l
  18.                         //// 言configASSERT条件值"==0",进而卡住
    & g* R  U) O8 X* m* \
  19.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的1 p( q7 m2 E  c7 S2 f) V/ A
  20.                         //// 宏configASSERT条件值"==1",所以不会卡住
    $ V" J: T1 E  p
  21. . K9 Z* o$ {+ I7 s9 N, y: i7 A
  22.                         /* The following assertion will fail if a service routine (ISR) for" V* o3 e' q9 p7 ^' I5 q/ ^% Q
  23.                         an interrupt that has been assigned a priority above# |* G  O+ R/ f
  24.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API: C, |% v4 @2 `& @  B% a; ]2 e
  25.                         function.  ISR safe FreeRTOS API functions must *only* be called, V8 Q, d: [: B5 m
  26.                         from interrupts that have been assigned a priority at or below
    # r/ w+ k% d% [# }7 k) O/ r
  27.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.0 F; G6 n) j0 }3 |* a
  28.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
    8 l6 x/ M" I( V% N# ?# O' `  T+ ]
  29.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于; q  p) F# k, h& G
  30.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),4 q) Q  B) [8 S2 d; ], R, l
  31.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于: i% R9 M' A/ a' _- O/ P3 [3 m! [
  32.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用) {- }4 w: i4 S8 O* X, k: [
  33.                         / g' ?% y- z$ K! ^
  34.                         Numerically low interrupt priority numbers represent logically high
    ) O8 O* m2 \6 r7 m
  35.                         interrupt priorities, therefore the priority of the interrupt must
    * F& X) o, n, Y( g9 j7 e) G, T
  36.                         be set to a value equal to or numerically *higher* than, {" L  h1 r+ S5 {" j
  37.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.
    7 [. b, O1 s$ l! W" V
  38.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
    - M. I* E/ e7 E  g! e  {/ o
  39.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
    2 d; J6 S+ s. G
  40. . g' a8 J$ t# K/ `' v
  41.                         Interrupts that        use the FreeRTOS API must not be left at their4 n: P: a2 s7 u0 B$ S# t+ V: M% K
  42.                         default priority of        zero as that is the highest possible priority,
    " ?, l9 P, A  v8 F9 u# s
  43.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,7 o2 V* C7 `. K: M' k* ?. ^
  44.                         and        therefore also guaranteed to be invalid.4 n$ c8 p6 l% F. R6 ]
  45.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最. `7 ^0 l0 a6 ?* }. C
  46.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必+ I) o: [( ^! G7 w! E
  47.                         //// 然无效6 Q9 E" I* x1 v' A8 H
  48. . t8 E, ?6 P, U$ i0 T# A! m- d: C
  49.                         FreeRTOS maintains separate thread and ISR API functions to ensure
    & I( d9 ]. n3 y& S. l) F) ~8 S* L
  50.                         interrupt entry is as fast and simple as possible.
    1 q# J9 A. k% B  `+ ~# \( ?
  51.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口, O% W0 m' V/ D6 U4 F! L: k! i

  52. / b5 w. V( A0 X  h( q& A  C
  53.                         The following links provide detailed information:/ X% Q- r" K, Z7 J2 E4 {
  54.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html4 S  h' O+ }8 p) R& ?9 B- \- l4 G9 K
  55.                         http://www.freertos.org/FAQHelp.html */
    # O: O! u$ Q! |3 F, P- o  k8 N
  56.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置
    * G8 l2 _1 `/ D
  57.                         //// ucMaxSysCallPriority值为0x50$ u" }/ D  S. \/ v
  58.                 }
    * U5 H) O. }1 S' l0 W2 E2 Y+ p$ P
  59. & w/ s0 B/ N# p, B' d
  60.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits
    ( v" T; F8 H( y7 I3 R$ U1 k
  61.                 that define each interrupt's priority to be split between bits that
    , x$ ~: t# w4 U3 s9 H0 z5 ^
  62.                 define the interrupt's pre-emption priority bits and bits that define" q$ F$ ~" {  E* V) x3 {
  63.                 the interrupt's sub-priority.  For simplicity all bits must be defined0 u3 |1 S1 n" N' a
  64.                 to be pre-emption priority bits.  The following assertion will fail if* F* ~8 F% G* @6 t% z9 i7 ~
  65.                 this is not the case (if some bits represent a sub-priority).
    - |* k) @( K) c
  66. 0 ^; \& h3 f8 X# }, A& x4 b1 u, r3 \
  67.                 If the application only uses CMSIS libraries for interrupt6 v0 z4 F% N* B$ y: x
  68.                 configuration then the correct setting can be achieved on all Cortex-M- W  z! `' N! X) @2 Q
  69.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the/ E2 m+ v. n9 p7 \9 M
  70.                 scheduler.  Note however that some vendor specific peripheral libraries* `9 I4 I$ G# E- {
  71.                 assume a non-zero priority group setting, in which cases using a value7 R0 }; S2 Y/ C& w1 ~6 o' J( d) n; a
  72.                 of zero will result in unpredicable behaviour. */
    & x4 [5 M% E1 a( x9 S
  73.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    1 T9 K: `2 u5 [5 {$ t/ [
  74.         }
    % X  [( V$ v3 @1 g6 C- q
  75. % ~' e' {$ `2 s6 J$ z
  76. #endif /* configASSERT_DEFINED */
复制代码
9 J" U: M' |- }7 x/ {  Y
       相关宏定义如下:
7 Z# F3 y& y) g
  1. #define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )
复制代码

  1. 6 ^, h: J. M, T2 W. p
  2. /* The lowest interrupt priority that can be used in a call to a "set priority"
    1 I9 S  D1 R, W& t4 M; J* g; Q( H  c
  3. function. */
    : {8 Z5 ~" I, ^# @- X$ c% X" Z
  4. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
    6 \# V3 s% a% q/ C! _4 f. G
  5. & I# w( |7 O; `3 U% w
  6. /* The highest interrupt priority that can be used by any interrupt service* }2 C1 |* ~+ n6 H* r+ E: g) r
  7. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL" d$ p* w( t8 c2 U. ^+ T/ h4 Q
  8. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    ( O  `+ V5 C+ f0 _' y. S6 _# _
  9. PRIORITY THAN THIS! (higher priorities are lower numeric values. */& y& o. H- j% q; Z2 M( c
  10. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
    : Q' r4 W% F! L  [

  11. 2 a: I3 p1 n& C
  12. /* Interrupt priorities used by the kernel port layer itself.  These are generic% x# }3 J% f9 G9 V1 [' c5 D& m! t
  13. to all Cortex-M ports, and do not rely on any particular library functions. */
    + _4 x6 t6 o$ H) a
  14. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    0 j( o7 f; R! M0 h' ^
  15. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!# \: _- ]8 x% X0 @; X0 @
  16. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
    % Q7 S9 I$ X+ S% y- O0 _! Z: N
  17. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )3 f6 w0 c; I' i# x  U, c* R: B

  18. # ]5 d& b1 e* C, E5 d6 X% O
  19. /* Normal assert() semantics without relying on the provision of an assert.h
    2 Q# y- D! y, [* r( `5 |! T
  20. header file. */
    . v! \) R# i$ j
  21. /* USER CODE BEGIN 1 */   0 `$ [$ R" X+ J* `0 F
  22. #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
    7 z3 W6 {5 X! b; T# Z- B0 t, V, w
  23. /* USER CODE END 1 */
复制代码
  1. #define configPRIO_BITS         4
复制代码

$ ?& L* F+ S! o5 K, b4 J
, W4 ~: d. P& T8 J7 a1 [' m3 Z简单总结如下:  d* a  h2 J3 }, R* O/ L- X& A
       使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。0 T4 J% t) [* d* b0 O

+ ~/ d& C3 s! l9 t5 O2 d& N3 [
. P: H' ?% e' H2 E; [. D) b

: }0 P$ `0 L! U4 |5 Y; t& E$ `2 ?. o8 k- o
收藏 2 评论1 发布时间:2019-4-16 14:15

举报

1个回答
Kevin_G 回答时间:2019-4-16 15:50:42
收藏

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版