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

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

[复制链接]
power568 发布时间:2019-4-16 14:15
本帖最后由 power568 于 2019-4-16 16:07 编辑 9 O' n( `1 k" N0 W8 H7 O7 b: s

0 R8 o+ n+ K3 c+ E! F       最近在写一个串口通讯的程序,软件、硬件平台如下:
$ _+ Y$ O5 P! s8 Q硬件: STM32F429ZG
1 E( F& a4 l* c7 \+ ]6 r6 W1 r系统: FreeRtos、HAL库
: m4 Z- t. Q+ f+ o6 ^: U; S工具:  Iar7.6
; N4 h! P/ F5 Y0 X* D7 \# R3 P4 ~* f2 D( z" M$ g& s+ T" r
       计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置+ y( J9 x6 p9 Q! X9 j/ k/ G
  2. HAL_NVIC_EnableIRQ(USART1_IRQn);4 ^* s( S& q& C3 Q+ b" v1 `

  3. , p6 m+ l" ^9 k* A* _3 h/ \& o
  4. void USART1_IRQHandler(void)0 `! h2 r! i9 w& H; y& E
  5. {
    & B2 y9 ~8 i  a7 N: k
  6.         uint32_t                 flag=0;
    ' ?# ?* @5 y4 b6 t2 m
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;+ u+ o+ ?1 G2 x2 I6 U; \
  8.        
    + ~& h5 X. q) `; o& |2 e
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE); 7 B! ?" ~0 j# r  @, }3 O" [
  10.         if((flag != RESET))& S) h3 b5 C& n7 i. D
  11.         {4 }9 \; ?$ N- X7 g5 X& b
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);2 C6 ]# `$ @1 O
  13.                 huart1.Instance->SR;  7 n: R/ [* B' D5 r6 H+ e
  14.                 huart1.Instance->DR;1 ?1 v- F7 O- Z6 S" M
  15. % N% G) Y' I) [6 t. G( P
  16.                 HAL_UART_DMAStop(&huart1);  ~: ]; T3 Q, E' {, O; A- F3 ~
  17.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);: u" z4 f& S: l; o# g+ S: M" `8 Y
  18.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);1 p" @9 U) q8 ^0 r
  19.         }9 J* }$ f0 [" o. t' A4 z
  20. }
复制代码

7 {* }% \+ ?. w  ]( z& K* H! V$ T. ~' `
  //// 为什么代码提交后,代码对齐格式变了呢???
% `" D, L6 o+ v0 ?$ {
/ z9 _1 }' a7 n) S% V       调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:
, v" l8 ^2 @3 s( h
  1. #if( configASSERT_DEFINED == 1 )
    % ^& P8 j) H4 y$ i! Z+ r( ]

  2. % q. g4 m, G  |# V6 x
  3.         void vPortValidateInterruptPriority( void )
    " }- @1 @: @1 ]6 Q
  4.         {
    # T1 M9 T) ?1 {& U; y# X6 x
  5.         uint32_t ulCurrentInterrupt;2 \- _# j, Q/ N# G
  6.         uint8_t ucCurrentPriority;
    % u7 f$ p% F. `4 X* ?- `

  7. ! I2 Y8 j7 L; H+ ]! I3 J% X, p
  8.                 /* Obtain the number of the currently executing interrupt. */
    + g. R4 j  g' Y3 A6 y5 M8 ]
  9.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );5 ?) K) [7 m# {' R8 \: b! [, c! I& M! x
  10.                 //// ulCurrentInterrupt 调试显示为53
    4 _. q9 }& `& ~) P* V( g

  11. ; i& j( M" l& a! C
  12.                 /* Is the interrupt number a user defined interrupt? */
    / r% p- `4 s3 u9 o
  13.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )6 }9 I' X* P7 i/ I" T
  14.                 {
    3 ^  u8 ]. i3 `. v
  15.                         /* Look up the interrupt's priority. */
    ! n$ P8 y1 t% C) Y+ h" ]; f
  16.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];! ^/ }( x1 d; h' Z: T2 s
  17.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
    , h/ [# }# B% f8 E8 Q4 T
  18.                         //// 言configASSERT条件值"==0",进而卡住
    ) n5 A: e, r& V5 N6 J* Q
  19.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的
    2 [8 @) Y; R" Z7 F5 l
  20.                         //// 宏configASSERT条件值"==1",所以不会卡住
    . u. j2 Z6 G8 h4 L% ?

  21. : H: X( ?7 K3 R3 H6 V
  22.                         /* The following assertion will fail if a service routine (ISR) for% Z. M$ ~/ s% i* i: s: E
  23.                         an interrupt that has been assigned a priority above
    1 |: C' [8 L* |8 g; a! w4 x7 I1 Y
  24.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
    ) s' D5 p1 A9 N( c
  25.                         function.  ISR safe FreeRTOS API functions must *only* be called
    ' Z: _7 Y! Y7 r5 {# j
  26.                         from interrupts that have been assigned a priority at or below
    2 [$ Y5 D  G! C" q7 S' O
  27.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.# `3 Z( N- b- l" R: G, l
  28.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
    3 m) W6 m, H- Q5 S, g2 k# p
  29.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于
    * @7 B9 Q1 I4 [& c4 j/ x4 _; N
  30.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),% u# r, ?( n  S# V; C0 }# ]& ~
  31.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于# |( N$ \9 ~# A7 q6 e! s- m  ?
  32.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用) l+ Z6 U6 v* |- f9 k3 g: \% i
  33.                         9 [! |$ V5 R3 v, B0 A/ A. ]# u
  34.                         Numerically low interrupt priority numbers represent logically high
    / O8 @. s$ w: ~4 E* a# ~
  35.                         interrupt priorities, therefore the priority of the interrupt must
    3 F' d& y" ]6 q: I
  36.                         be set to a value equal to or numerically *higher* than
    6 K! H  j/ o0 X2 p6 j) V: \! a1 K
  37.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.( `$ V4 J( }& H/ s8 r. O
  38.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级  X( R! U$ Z6 [  C0 Z( P& a8 [
  39.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
    7 s5 [7 ]6 K2 g1 M" R- a
  40. / _" t% m+ K# P* V
  41.                         Interrupts that        use the FreeRTOS API must not be left at their9 z3 ]4 L" A+ u  K) z' `! \1 b; n9 M
  42.                         default priority of        zero as that is the highest possible priority,( M, q0 w* K! @
  43.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY," T: ?+ ]+ l9 ~2 T
  44.                         and        therefore also guaranteed to be invalid.
    + c; j" p3 Q; i
  45.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最! L- K: D7 @  C( _
  46.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必  I+ m% O) X; d* j7 u8 B# K
  47.                         //// 然无效2 u5 I& d+ f$ v# M$ ]  d

  48. - D# C2 u: U2 E' \; X0 C$ P) z( t
  49.                         FreeRTOS maintains separate thread and ISR API functions to ensure/ p* y, u$ a5 e5 i
  50.                         interrupt entry is as fast and simple as possible.# B8 K- e" s; r& d5 @
  51.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口2 o9 C- w' O4 K

  52. : G- j: K2 @3 E; {) n2 Y
  53.                         The following links provide detailed information:
    ! C. z% h: k) h7 ]
  54.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html
    ! \0 K" q: O& y5 r2 S/ ^' S
  55.                         http://www.freertos.org/FAQHelp.html */
    ! N% O( L1 B: T- O4 Z) @
  56.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置
    9 s" v$ Q/ u3 n
  57.                         //// ucMaxSysCallPriority值为0x50
    / z2 ]) c; M- ^/ L$ `
  58.                 }/ {+ z6 l7 L0 L& d, @! n

  59. 8 ?# Q3 J6 g/ }- |* n# d/ \
  60.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits
    4 R" z5 K3 h/ S! T+ ~
  61.                 that define each interrupt's priority to be split between bits that
    + n. l( `& F3 e1 s  S
  62.                 define the interrupt's pre-emption priority bits and bits that define
    3 |6 G( b2 e) Z
  63.                 the interrupt's sub-priority.  For simplicity all bits must be defined
    2 L3 R, A( q4 |
  64.                 to be pre-emption priority bits.  The following assertion will fail if- U) c, w' ~* c, C; ~
  65.                 this is not the case (if some bits represent a sub-priority).
    ; ]7 Y7 K* p% X! T  S; x5 r
  66. + T( _' N3 j3 U0 @3 k# b) ~
  67.                 If the application only uses CMSIS libraries for interrupt: w' j. ?# `  F- E$ o* C
  68.                 configuration then the correct setting can be achieved on all Cortex-M- y( B7 B3 d$ k; \! J" f
  69.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the* b5 Z+ @' e, P
  70.                 scheduler.  Note however that some vendor specific peripheral libraries
    ; a; N6 Y9 ^5 \3 T
  71.                 assume a non-zero priority group setting, in which cases using a value
    9 Q5 E9 m9 D" e8 j& g
  72.                 of zero will result in unpredicable behaviour. */' ]! @" s9 B, d9 |! e
  73.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    : h, o( u. L) \% g; S! m
  74.         }
    6 x/ P. h9 R. N/ v
  75. 6 a0 m* a* D5 o: u
  76. #endif /* configASSERT_DEFINED */
复制代码
/ p4 P. [8 s$ J0 M/ z
       相关宏定义如下:5 w& k' Y1 v+ [7 J  o4 S" |
  1. #define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )
复制代码

  1. 9 i, F7 O$ Y' l" O! V7 m) E
  2. /* The lowest interrupt priority that can be used in a call to a "set priority"" L+ v  z" K% t8 i
  3. function. */
    ; Q2 f2 U0 M6 g% a. ?/ I+ o
  4. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15; s% _! v; h4 H) l+ }. A
  5. ( {  U" _- p8 \. _% c5 a7 H
  6. /* The highest interrupt priority that can be used by any interrupt service
    / i, J- ?, n- D4 }5 e' ?5 K
  7. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL- q- q, I6 ?% N7 W1 U. u- ~; H
  8. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    ; @4 S3 D' v: `3 `. h, X) j; l0 f$ I
  9. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
    ( G8 L$ [( {" d9 I# K2 d
  10. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 51 V( k, s- z8 c( O1 A- G0 ~8 s

  11. ; A  N9 _' a5 L: Y% c9 U
  12. /* Interrupt priorities used by the kernel port layer itself.  These are generic5 K4 i# S# l% F! }1 k
  13. to all Cortex-M ports, and do not rely on any particular library functions. */9 g! C. H, h* p+ s# X$ j2 T
  14. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    2 T  {! W( D9 M8 P# w& d) t3 u
  15. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
    4 _# q; m  b3 ^( V) U
  16. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. *// F; N. C! V5 N! i+ D" O' n
  17. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    8 d& X) E, [7 B  W

  18. 5 V/ ^- x+ n9 O& X+ {+ |
  19. /* Normal assert() semantics without relying on the provision of an assert.h
    3 Z8 Z: f8 H5 A& d
  20. header file. */
    5 N) U) z5 [; F6 Z$ M
  21. /* USER CODE BEGIN 1 */   
    5 r3 }+ [2 d3 A0 d5 c
  22. #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
    * \6 p' j, w7 o$ A
  23. /* USER CODE END 1 */
复制代码
  1. #define configPRIO_BITS         4
复制代码

( I& u0 _7 F1 y
9 H1 i7 ~, E( v  A! W' U( ~0 |简单总结如下:
# B5 d$ V6 m: x' O$ r8 R! \       使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。- o3 k! [' z, a, R5 x

6 R7 F! a# `/ }# o# x& H6 i3 t
  q/ m2 I2 ?( ?! G1 V; j. p
" {3 f" }& ^5 r8 W
* \( O  {6 Q( M5 W+ [; I
. L/ ?+ o1 T6 a# a' l/ [9 X/ f
收藏 2 评论1 发布时间:2019-4-16 14:15

举报

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

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版