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

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

[复制链接]
power568 发布时间:2019-4-16 14:15
本帖最后由 power568 于 2019-4-16 16:07 编辑
! S( q( u# R; n% J! J; y
' z& }" M! L$ H" n& X. q- i       最近在写一个串口通讯的程序,软件、硬件平台如下:( Q5 i+ g9 T! i& C' |: p
硬件: STM32F429ZG
+ S, i3 o, e9 u系统: FreeRtos、HAL库# `, ~8 g8 m  @2 K: d% |5 S2 K
工具:  Iar7.6% m0 c0 a/ w3 N$ f

' H  s) B0 m3 p9 \+ w/ y       计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置
    ; c( V4 E) Z0 ~0 O0 q
  2. HAL_NVIC_EnableIRQ(USART1_IRQn);. {0 F7 o8 U) K  h2 o0 ^( R
  3. . s$ R  r% ~9 ]2 h: e
  4. void USART1_IRQHandler(void)) P' N( u9 {5 s+ o4 y
  5. {
    3 c& U: e& C2 z+ |" ]
  6.         uint32_t                 flag=0;: C' ^; K1 V' H1 l( [6 B* c+ o
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;. G  y7 S2 P, }/ T8 @4 N+ p
  8.         4 P; g' C8 a" @) ^. S+ {
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE); . |; u+ b. M+ }+ L2 B6 o
  10.         if((flag != RESET))
    ( Q" ?! z( h4 x+ b% j
  11.         {
    0 E$ V4 g! `8 j+ a1 O
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);% B7 A2 O" i8 w: o9 x* v" g
  13.                 huart1.Instance->SR;  3 u+ {& k! M. k( r
  14.                 huart1.Instance->DR;8 L/ C! g+ Q& |- d

  15. 3 v+ h! N$ k4 N, L: h7 v7 Z
  16.                 HAL_UART_DMAStop(&huart1);7 N# n7 H; S7 M2 s
  17.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);; M& P" }+ z$ o
  18.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
    , B6 j+ p' u3 N) v: w) b
  19.         }* p! n# x" T6 ?+ K( M& g
  20. }
复制代码

1 M! u" F7 K! L) m3 p8 A
& A- m4 \6 e' i  //// 为什么代码提交后,代码对齐格式变了呢???
! J6 S3 l& g& d7 y$ N( w6 X$ }, V% d8 j' p( W3 `6 n$ P
       调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:
2 }' k, P+ {9 _* u' j$ \
  1. #if( configASSERT_DEFINED == 1 )
    ) H& g: u9 m9 H* Z4 `: u

  2. $ o0 f! x0 k% R  ?$ t
  3.         void vPortValidateInterruptPriority( void )
    ) J4 G9 Z# t8 \
  4.         {7 l7 P1 z  L; J6 w! h
  5.         uint32_t ulCurrentInterrupt;
      h( G: m! ~. L9 n
  6.         uint8_t ucCurrentPriority;# R. i  ]2 L9 R! B2 r8 p

  7. - O& |, D! H6 p' [; C* M
  8.                 /* Obtain the number of the currently executing interrupt. */
    1 M6 W9 m5 x4 f5 J# ]
  9.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
    ' U( R5 a7 [$ N% z4 V5 n) [+ r
  10.                 //// ulCurrentInterrupt 调试显示为532 R4 X' g9 V# c( x/ w
  11. 8 J8 K7 J, T4 L+ r  J
  12.                 /* Is the interrupt number a user defined interrupt? */
    + H! i0 ?$ u  F/ o4 U5 K
  13.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
    6 u5 D+ O* {+ g7 w) d0 L, y4 |
  14.                 {
    0 Z5 c" W" y" z' d
  15.                         /* Look up the interrupt's priority. */
      [' z. c2 B5 {; c* E; d
  16.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];( `/ `( H& z* v" f; S* X; Z: e
  17.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
    9 c1 k$ y# Q  e# e* \4 }' }; j
  18.                         //// 言configASSERT条件值"==0",进而卡住: |, e$ x# V- H" D* X% _0 x# ?1 s
  19.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的
    6 s# Q5 T% z) M
  20.                         //// 宏configASSERT条件值"==1",所以不会卡住
    , A7 d0 n  C( t

  21. 7 c3 J. \( c+ \2 S
  22.                         /* The following assertion will fail if a service routine (ISR) for- c, z3 P, g: n, d9 e) C0 p1 e7 c
  23.                         an interrupt that has been assigned a priority above" E% u' W) ?* u; d" x
  24.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API; x6 k$ B* J  ~* t
  25.                         function.  ISR safe FreeRTOS API functions must *only* be called
    : L- \7 J" E) ], Z
  26.                         from interrupts that have been assigned a priority at or below
    & t+ f  c: p, P
  27.                         configMAX_SYSCALL_INTERRUPT_PRIORITY./ b& c7 }6 I( s8 ?" S4 x- U
  28.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于. W1 o5 |6 B( n5 n
  29.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于
    ) w) f7 K& T. ]6 C+ t6 L
  30.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),/ B! B8 F- ~) |' u8 B+ p2 H7 T
  31.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于& V& _* A0 x* u5 K6 X7 R
  32.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用! A: f8 L, ?: g. O  l# Y
  33.                         
      _, D3 Y+ \8 l8 Y$ t6 a, D2 T% t
  34.                         Numerically low interrupt priority numbers represent logically high
    & [7 X2 J' W7 d2 U/ p/ Y/ V
  35.                         interrupt priorities, therefore the priority of the interrupt must" E# {1 u* n6 O! \+ `; }
  36.                         be set to a value equal to or numerically *higher* than0 F8 X' p4 L" l* e
  37.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.
      n! g* S) R- L% w
  38.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
    ( o  }5 a0 z, S( Y3 Q* z1 y" Z
  39.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大' X, m4 Z" c/ T- @
  40. . n; `7 k* o' Z$ g7 y# a8 S
  41.                         Interrupts that        use the FreeRTOS API must not be left at their; Q2 N8 O8 x: R2 {! \/ f- O
  42.                         default priority of        zero as that is the highest possible priority,4 |9 C$ T# `% z
  43.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,! M& ]" O5 H6 L/ k8 [% L
  44.                         and        therefore also guaranteed to be invalid.
    5 Y7 k9 V& g& Z& H) ?2 d6 K. G
  45.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最
    + [* g" R4 d2 N. S: [
  46.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必1 X$ ^5 L5 x3 l
  47.                         //// 然无效
    6 G3 |& @" I$ ^; D

  48. 7 @, {; p  r3 B* z. p" P1 j3 Y9 i
  49.                         FreeRTOS maintains separate thread and ISR API functions to ensure
    1 e6 B  W( W  B8 L: k: a$ ?
  50.                         interrupt entry is as fast and simple as possible.% _1 s2 p* G% t! F& U2 S4 I$ p" W2 n
  51.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口1 ?6 _* d4 ^. I/ s; R
  52. " H9 j# g  P1 F+ R! ?
  53.                         The following links provide detailed information:, n; |$ s. u" ~5 o3 q
  54.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html
    / a0 }& h3 p5 a: F# P, Q
  55.                         http://www.freertos.org/FAQHelp.html */" n& R/ J4 Q8 m; ^9 {. O
  56.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置. l$ F* m) B: K& H
  57.                         //// ucMaxSysCallPriority值为0x50
    " |! E4 T2 L2 |% _
  58.                 }: M; B0 I' Y, \$ G& d+ B# _
  59. ; x9 b0 M) `: i! D; J+ A& |* n
  60.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits
    . U* R  p& Q$ S6 `% @' A& D5 u$ T
  61.                 that define each interrupt's priority to be split between bits that
    3 `( B; Q) }; i
  62.                 define the interrupt's pre-emption priority bits and bits that define
    8 k6 [. Z% h9 j1 d
  63.                 the interrupt's sub-priority.  For simplicity all bits must be defined
    ' H' }& R& h4 p0 j8 ~* Y
  64.                 to be pre-emption priority bits.  The following assertion will fail if1 U9 i% q, h* M# G+ v
  65.                 this is not the case (if some bits represent a sub-priority).
    ! J$ H0 m3 e+ n9 }4 e

  66. 0 o# p! Z$ F6 x& R2 {
  67.                 If the application only uses CMSIS libraries for interrupt
    ( B* ^' y1 u' j  g1 W
  68.                 configuration then the correct setting can be achieved on all Cortex-M
    0 o. ^4 a9 O# L' h
  69.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the; S) ~, @( ]7 ]  C6 j! z
  70.                 scheduler.  Note however that some vendor specific peripheral libraries
    & Y/ S0 F/ X) W" M/ B& j$ F
  71.                 assume a non-zero priority group setting, in which cases using a value
    / e: J5 G9 _4 h7 L
  72.                 of zero will result in unpredicable behaviour. */
    ( Y* M) T/ |* p
  73.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    ) y  Z  v5 f! y( p$ `% y
  74.         }
    : [( Y5 m) h/ y% `; B; x
  75. & D0 \0 t/ `4 m# @0 R
  76. #endif /* configASSERT_DEFINED */
复制代码
$ ?) W+ z3 n. M6 F" E
       相关宏定义如下:
9 I. C5 E7 R9 ^0 C; [. O' I
  1. #define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )
复制代码
  1. 0 ?' j1 z9 K& d' X& \5 K: r
  2. /* The lowest interrupt priority that can be used in a call to a "set priority": K7 v- i+ P" ~4 a8 q
  3. function. */
    * V1 R% g% }0 a- y+ S, F
  4. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   158 V( ~. }: P4 A6 m

  5. / W9 t3 E2 B4 i% R" R
  6. /* The highest interrupt priority that can be used by any interrupt service
    4 K( e" l; P4 `- c
  7. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL) K& W. I: B7 g$ R* |* l
  8. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    8 Y+ R, Y$ a9 l  c; P
  9. PRIORITY THAN THIS! (higher priorities are lower numeric values. */9 K& t5 R0 X. _, P& y% y1 g
  10. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
    / g2 y  @2 U# r0 f  d

  11. % C$ t3 {, @- y+ z
  12. /* Interrupt priorities used by the kernel port layer itself.  These are generic/ I, S: S1 ]4 e5 D( r( |' C
  13. to all Cortex-M ports, and do not rely on any particular library functions. */
    ' n8 b7 M" r8 Z' b1 d& g
  14. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )) b0 K; a% C4 W" [' t+ o
  15. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!- i* ]* W7 ^4 T& T2 n) i1 i7 W
  16. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. *// b5 i  ~- l8 b/ b
  17. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )" g+ C; l7 s6 l% x/ v

  18. / A5 @: p& L; l6 r  r( T9 w+ W
  19. /* Normal assert() semantics without relying on the provision of an assert.h
    4 Z- C2 K) o# B6 K5 Q: f
  20. header file. */
    : X% I" d8 @5 n
  21. /* USER CODE BEGIN 1 */   
    7 Q8 w1 E) U; s: L6 |' ?- u
  22. #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
    # e5 z5 X; N& e, E- W
  23. /* USER CODE END 1 */
复制代码
  1. #define configPRIO_BITS         4
复制代码

1 I9 ^  x0 F6 z# J/ z& I3 r3 A( Q4 T
' V  Z  V, A$ ?9 x4 o简单总结如下:/ A3 s& Z# t. a7 M, ?6 f8 N
       使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。6 i# D' U1 v* a5 h( @3 g
6 j- Y( w5 a' ^9 P1 c( S

8 D, g9 }" N) F$ `3 D, K7 d4 h/ d; n# q

- y* C6 W8 I2 L! U  {: Y3 i% e& h% D6 I0 c  \0 k0 Q( ~% N
赞 收藏 2 评论1 发布时间:2019-4-16 14:15

举报

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