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

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

[复制链接]
power568 发布时间:2019-4-16 14:15
本帖最后由 power568 于 2019-4-16 16:07 编辑
2 K" w( {6 Y, [. H& T/ ]- y' i: v; }
       最近在写一个串口通讯的程序,软件、硬件平台如下:3 K) \1 I  R/ e; X( |4 }& s
硬件: STM32F429ZG
! P8 q3 y! o) ^+ Y7 \系统: FreeRtos、HAL库* T: v( g9 [- X
工具:  Iar7.6
, x( {, T& D& l3 Z0 X
0 l# W9 t3 ~+ T9 v2 F. F       计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置+ ?& b5 ]+ z( D( _5 `$ M% v; L
  2. HAL_NVIC_EnableIRQ(USART1_IRQn);" u6 Q, p1 B+ P$ O

  3. 7 X$ D' s% I0 F& S
  4. void USART1_IRQHandler(void); v, p9 }, p3 D1 ]! ?
  5. {  h- @4 i- B- t5 e
  6.         uint32_t                 flag=0;7 ?# Z) f0 b  x) o/ W' Z& ?1 X
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;* q3 E/ Y5 R! @6 j& T
  8.        
    8 d; `5 t& h4 Q! H$ i, j! [
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
    ) c, ~4 L  d( X
  10.         if((flag != RESET))& P! E8 i, i) i3 c" A  `
  11.         {8 f& Q' Q  U% E7 F& b# C6 j
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);6 N3 p/ Z' V+ f$ D/ E5 K2 X( _6 R+ j
  13.                 huart1.Instance->SR;  ' c/ j- W! T$ ?. @0 |" D, s
  14.                 huart1.Instance->DR;* z7 n" j+ q; ~6 X6 C6 l$ g7 z4 C+ x
  15. 1 _4 c) f, B- m, e! J
  16.                 HAL_UART_DMAStop(&huart1);; [5 C( M  ]8 x7 y' s" K
  17.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);
    * Y7 o( l+ d& J$ N' E6 B3 ~
  18.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
    * A& T: d1 ?- k- \
  19.         }
    - d% m9 j( ?0 H" N$ Z
  20. }
复制代码
' d- E1 I- k' i0 x

% k" o) q/ s, Z, Q$ g, }7 [: s  //// 为什么代码提交后,代码对齐格式变了呢???* O1 |1 g$ i! ~  l# \: B$ n& W" L+ r
" j( y# V* y$ o- G3 D. f
       调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:
1 c  ?. j' G! h1 N  D' F0 ~
  1. #if( configASSERT_DEFINED == 1 )
    2 g0 d& r- ?  ?9 M+ \3 B; P6 U6 D7 F
  2. 4 J; J6 }" {% y
  3.         void vPortValidateInterruptPriority( void )
    $ J, z3 p$ N: f9 I* G+ a
  4.         {
    2 f" w* T# s" h1 g9 g4 J; C
  5.         uint32_t ulCurrentInterrupt;
    7 x2 l1 T7 H$ |6 T
  6.         uint8_t ucCurrentPriority;
    ( W5 U$ b/ _1 P) w# h7 y! e

  7. 0 q2 r: x8 i; `% [  Z- z
  8.                 /* Obtain the number of the currently executing interrupt. */- [# c/ v8 X0 V& ]  g7 o+ r
  9.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );, E2 a. z' |2 {+ W
  10.                 //// ulCurrentInterrupt 调试显示为537 e) O0 {, o/ e" j
  11. 3 D; W: U- m' i2 u
  12.                 /* Is the interrupt number a user defined interrupt? */
    + _/ n7 ?. l5 f. l7 U3 J
  13.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
    - h5 K! n9 |" X' g  U- z
  14.                 {) }7 E* I8 n( ^. n
  15.                         /* Look up the interrupt's priority. */
    ! q& z4 |+ G' k' w, f1 C
  16.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
    . A  t, [0 d  x/ ?
  17.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
    + c) J7 Q' M, g" A! |$ k- F* v4 n4 @
  18.                         //// 言configASSERT条件值"==0",进而卡住
    8 U' l' {4 A1 M$ {
  19.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的  s$ y: d* k% @  U- g
  20.                         //// 宏configASSERT条件值"==1",所以不会卡住
    ; n7 z# _+ i1 a4 g7 G' S2 u

  21. + J) z: r: j- p0 q8 w6 B" g  m+ ^9 b
  22.                         /* The following assertion will fail if a service routine (ISR) for1 X) U9 i# i( i$ g  L$ v. P7 s
  23.                         an interrupt that has been assigned a priority above
    8 K3 I* N: \* q7 Y1 T) z( _+ o! O
  24.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
    " V9 A8 t: z1 S* v: G* b# B: r
  25.                         function.  ISR safe FreeRTOS API functions must *only* be called& n4 M& n" {( o2 C$ N! t8 b" N
  26.                         from interrupts that have been assigned a priority at or below
    . N5 c* e  e: X4 s/ K- R, X
  27.                         configMAX_SYSCALL_INTERRUPT_PRIORITY./ N7 L% t( b  A/ `; O
  28.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于+ M) Q" u/ o- m% _
  29.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于
    , y( B! ?9 A$ V% {/ G& ~
  30.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),) K, R0 Y- n4 u- E  e0 E
  31.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于
    8 t5 O( l& K. R; y0 l* K" \3 {; R
  32.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用& f  P# \9 g% ^3 ?* Y
  33.                         
    , P( n1 R! b' z: L
  34.                         Numerically low interrupt priority numbers represent logically high
    1 H8 w) G) n& k! _; a
  35.                         interrupt priorities, therefore the priority of the interrupt must# r6 z$ Z5 g9 @' u/ w
  36.                         be set to a value equal to or numerically *higher* than# y" o7 r  R" g8 Y& r# ~
  37.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.
    ( V9 g2 k* }3 M( k! D$ ~2 u8 C
  38.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级! n# F9 m- [+ J8 j( s
  39.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
    , l4 p" m. Z9 m6 P: ]3 |" v

  40. 5 I, k/ x$ X7 T; k7 }$ g2 N# S
  41.                         Interrupts that        use the FreeRTOS API must not be left at their; `; c) a; l" R& B% t9 G8 {
  42.                         default priority of        zero as that is the highest possible priority,
    9 Y, }) Z! U) z; K, W3 C
  43.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,7 z- y: j6 D8 b# V
  44.                         and        therefore also guaranteed to be invalid.3 ~, P: b0 t# G8 v# A1 w3 h' v7 H
  45.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最) y3 M3 U- a% x, M. n" c
  46.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必0 e" O' J! \& F: ^; Q5 E$ W3 A
  47.                         //// 然无效, [& n2 ^5 q. v' u  N% X2 p5 M5 l  L

  48. & z4 N2 F; \$ f8 B# e' K
  49.                         FreeRTOS maintains separate thread and ISR API functions to ensure
    & K/ X5 O) \7 e2 u
  50.                         interrupt entry is as fast and simple as possible.3 ~5 P+ }% ~$ K# x, k: A. G3 U
  51.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口
    ! x, ]" R6 g) l& _
  52. 1 y" Q& }3 d, r, @+ y, x
  53.                         The following links provide detailed information:
    % |" V: Q$ o$ d! I8 S  J
  54.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html& N, Z  N% i0 h& G
  55.                         http://www.freertos.org/FAQHelp.html */3 N- e8 q* A' Y7 g
  56.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置+ b0 e4 I' P/ m  c+ [1 i
  57.                         //// ucMaxSysCallPriority值为0x50
    , Y  H6 E% T2 w
  58.                 }; }/ r" l6 C5 X; X

  59. 5 D6 S9 x# M/ x/ Y8 N7 S: S* R; R
  60.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits" i) w, o+ m1 `0 \) Q
  61.                 that define each interrupt's priority to be split between bits that4 w0 p# e  p: f; s) }
  62.                 define the interrupt's pre-emption priority bits and bits that define
    5 B4 p& T7 I+ a( D! S' N# n
  63.                 the interrupt's sub-priority.  For simplicity all bits must be defined
    1 x, O$ P, ]+ i4 {3 a
  64.                 to be pre-emption priority bits.  The following assertion will fail if
    + ], Q  z( J. W6 w  z
  65.                 this is not the case (if some bits represent a sub-priority).: j) j: t/ Q$ x" U% E
  66. ) o; l1 S3 P) _
  67.                 If the application only uses CMSIS libraries for interrupt/ B; R6 B# ^; w4 @5 Z8 _3 h
  68.                 configuration then the correct setting can be achieved on all Cortex-M& `& J1 I: k* M6 F
  69.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the8 k$ R. P$ z2 L% i/ s5 y5 F8 |# U
  70.                 scheduler.  Note however that some vendor specific peripheral libraries
    6 ?! X* D6 g1 B' G: R, ]; V
  71.                 assume a non-zero priority group setting, in which cases using a value
    . j6 g$ Z7 [6 g
  72.                 of zero will result in unpredicable behaviour. */
    # b; n1 O1 f* o! D  l8 e$ F
  73.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    ; }- ~" X- f! k5 x0 _7 O% F
  74.         }9 h( P  f1 B0 A" W

  75. & W0 w! ]% k+ t) q- X- a( e
  76. #endif /* configASSERT_DEFINED */
复制代码
0 x. `7 {5 E; _& X9 k2 x5 z  H
       相关宏定义如下:4 g5 r% N7 s: J$ J1 V
  1. #define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )
复制代码

  1. ! h) _- h! x6 ?/ K" E: t# D
  2. /* The lowest interrupt priority that can be used in a call to a "set priority"6 E) X2 U* Y. ~* ?6 D9 B6 G
  3. function. */0 \" f% L! p! h8 B8 x
  4. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
    6 H6 z; b* R, L- k9 s" |" l
  5. 3 l3 P1 q* K* s7 n$ u, y3 p7 f+ Z
  6. /* The highest interrupt priority that can be used by any interrupt service
    5 W9 m( H8 i4 t$ M& j& x
  7. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
    6 w2 y- Y# b- y9 t
  8. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    . ~- G5 D; _9 i3 D( Z+ c
  9. PRIORITY THAN THIS! (higher priorities are lower numeric values. */
    . z1 c" g! X0 ]! U  u
  10. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
    ( G' i9 k% A1 N  F3 d

  11. 2 {3 P0 E* C4 |0 n$ ?8 D1 `
  12. /* Interrupt priorities used by the kernel port layer itself.  These are generic1 O" A' l  b/ X' d+ W& J
  13. to all Cortex-M ports, and do not rely on any particular library functions. */
    - Q6 c7 t# \5 I3 J
  14. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )0 Q$ m! ^+ {5 T
  15. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
    ; h6 P) u: n5 [8 f! h
  16. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */+ C5 s! [. @! [8 d
  17. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )4 A, U9 @- ~* U# b5 V5 _

  18. ; ?0 T1 Y& l4 e% ^8 N
  19. /* Normal assert() semantics without relying on the provision of an assert.h
    5 f/ w9 A* M0 p  X: H
  20. header file. */
    4 u. q: m5 L0 j4 E
  21. /* USER CODE BEGIN 1 */   + q9 P  u: `/ D# K+ J' Q3 d/ I
  22. #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
    6 O1 k- `6 r: Q0 x( Y
  23. /* USER CODE END 1 */
复制代码
  1. #define configPRIO_BITS         4
复制代码

0 m  c) \& @/ k0 F$ M' |3 d& @
8 k2 H5 k6 J% h; ^/ B- T* j简单总结如下:& [4 ~9 c  e1 u! g# n
       使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。
& x- w8 X) H) n, N4 T) T
! B! s4 V# B' `) N8 o5 D, P+ j2 x2 a

% A4 N, f$ y  Y1 g7 O
. s. V* y- ^3 r/ \& X- H1 a/ n+ ?% Y3 ?- A, G& Y/ O$ w- p( l; v
收藏 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 手机版