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

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

[复制链接]
power568 发布时间:2019-4-16 14:15
本帖最后由 power568 于 2019-4-16 16:07 编辑
6 M  a, l" a8 a% @' B# H3 {, q
; w+ H; O( f4 G0 _       最近在写一个串口通讯的程序,软件、硬件平台如下:$ m: u3 N  p# i
硬件: STM32F429ZG4 W  I& h  k. _2 k9 y2 {+ a1 R
系统: FreeRtos、HAL库8 T; g5 S" _5 o& b3 C- L- j
工具:  Iar7.6
* s% h% v% J0 `
9 |% }  D6 H7 w7 w: n       计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:
  1. HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置
    ) E9 z* L8 [; F3 d
  2. HAL_NVIC_EnableIRQ(USART1_IRQn);
    ( j9 B1 g& u! F" R9 `

  3. ' S3 S# i0 v- c$ b- j4 L7 E
  4. void USART1_IRQHandler(void)
    ; E$ K& ^9 L4 c! }; l& f' c$ e
  5. {* |+ P  q6 D, r
  6.         uint32_t                 flag=0;7 \0 q6 q1 |* H$ k  ?
  7.         BaseType_t        pHigherPriorityTaskWoken = pdFALSE;$ [4 h8 g4 b' x* [
  8.         1 S- z) C; t/ E
  9.         flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
    " R4 N) }1 Z) J
  10.         if((flag != RESET))* b& [  q7 [5 v; a$ C
  11.         {
    ! b( B' R* V3 b% p; N/ ^. Z
  12.                 __HAL_UART_CLEAR_IDLEFLAG(&huart1);- R3 B% Q. _0 g( d' Y( X
  13.                 huart1.Instance->SR;  
    7 o# ?4 B6 R+ U0 ^1 K: I7 r2 @
  14.                 huart1.Instance->DR;2 u4 j0 ?8 K8 b- n
  15. * q9 f+ Y' P9 |  X6 b, z2 D
  16.                 HAL_UART_DMAStop(&huart1);
    , E  k7 n- _. k2 w5 Q
  17.                 xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);
    . e, V, r. @4 q2 R0 r2 J$ r
  18.                 portYIELD_FROM_ISR(pHigherPriorityTaskWoken);+ D3 J, i6 A6 F1 V8 |7 f% s
  19.         }
      D" j6 \4 H, L; C( }, j( ?
  20. }
复制代码
" d# e* c3 o6 g8 Z. S

3 q1 h) m- C% V3 o2 t* ~1 ~  //// 为什么代码提交后,代码对齐格式变了呢???
/ C( `6 W7 c' c* J" I$ G2 I' ^( t8 V: M& D; \; ]7 }
       调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:/ d! x- w* }: r- x+ o  I
  1. #if( configASSERT_DEFINED == 1 )
    ( D" X+ p/ c8 ?4 I
  2. . j$ }# A" ]$ c7 B: A
  3.         void vPortValidateInterruptPriority( void )- p0 `" v- r0 h4 }6 u
  4.         {
    + q0 Y5 Q; k$ X8 S. y8 m  q
  5.         uint32_t ulCurrentInterrupt;5 S* T' S7 t' e; I4 m% E7 d
  6.         uint8_t ucCurrentPriority;9 Y- I  o# Z+ u. e

  7. 7 \( i) |( k) F) I' j/ ]
  8.                 /* Obtain the number of the currently executing interrupt. */: a% l" q) |, X: g1 E/ `/ v
  9.                 __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
    , g6 J6 a' A, E1 _, j* }
  10.                 //// ulCurrentInterrupt 调试显示为53$ ]$ O$ W/ K0 `0 X5 W

  11. 8 m- E( t& Z. v- o
  12.                 /* Is the interrupt number a user defined interrupt? */
    2 _- C/ K/ N: z& D3 G( a+ Y& n+ C
  13.                 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
    ! o3 O- J/ T0 ^* Z1 X. r0 F; i$ {
  14.                 {2 V. A- q# [3 S( U, o
  15.                         /* Look up the interrupt's priority. */
    3 z+ m; I  d$ Y9 u
  16.                         ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
    3 Y+ l( C) A: X, B# ~" ]' L
  17.                         //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
    ( I% D5 i0 z0 v' V; C5 \
  18.                         //// 言configASSERT条件值"==0",进而卡住
    ! G) {) m! S# C
  19.                         //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的3 g5 P% @& k- q7 W' g" h: b
  20.                         //// 宏configASSERT条件值"==1",所以不会卡住, x8 S! J% j* O) L9 \  |
  21. 7 R' g; _: p7 C# Y
  22.                         /* The following assertion will fail if a service routine (ISR) for% i- V, ~0 c$ y
  23.                         an interrupt that has been assigned a priority above. @3 N$ e% u2 C8 H% f9 c/ C
  24.                         configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API/ @* E4 w( Z3 _8 _) h9 e
  25.                         function.  ISR safe FreeRTOS API functions must *only* be called
    : Y. g- T* V; p" X3 G  e8 w' i( W( H6 s
  26.                         from interrupts that have been assigned a priority at or below
    $ n) e3 v7 ]3 c! C3 o% k
  27.                         configMAX_SYSCALL_INTERRUPT_PRIORITY.' p2 s$ C& ~! q/ }! |" {& [* N( t
  28.                         //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
    . ^, ^& y/ z% ~8 Z0 L5 w
  29.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于9 L( U( L: G9 p6 m) ^
  30.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),
    9 t6 V) m- b3 `
  31.                         //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于
      x7 X' X) F) ?6 N; b, ?- Z) B
  32.                         //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用4 @# J. v5 \+ {2 Q2 h
  33.                         
    7 I2 b" D# Z" }' ?  R# k
  34.                         Numerically low interrupt priority numbers represent logically high
    : h8 [2 A0 w) \) P1 C" D0 N
  35.                         interrupt priorities, therefore the priority of the interrupt must- D& K9 G& ^4 {/ k7 T; F" c3 S; `
  36.                         be set to a value equal to or numerically *higher* than$ \* J. M. A( C- C
  37.                         configMAX_SYSCALL_INTERRUPT_PRIORITY." J* O/ N2 H2 `, N( U4 }# ]
  38.                         //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
    * O2 M% p! t5 I3 s0 b  J$ {+ {" F3 Y
  39.                         //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
    0 w% g. Q2 p' B: _
  40. ! O9 V0 x) S) C2 R* L
  41.                         Interrupts that        use the FreeRTOS API must not be left at their. n0 N( ?( J9 l* V
  42.                         default priority of        zero as that is the highest possible priority,
    ! E% l* h2 P& V
  43.                         which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,) V( F' Y' q4 g1 a/ z
  44.                         and        therefore also guaranteed to be invalid.4 Z9 g1 Y" ~# g( q
  45.                         //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最* H" s# ?+ W. _& a
  46.                         //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必5 y' m9 S  q5 n! r7 y8 }
  47.                         //// 然无效1 r6 ]8 N/ i- q' N: S" L
  48. 9 W+ q* }+ m7 r
  49.                         FreeRTOS maintains separate thread and ISR API functions to ensure7 O' Z3 z9 A! E% T
  50.                         interrupt entry is as fast and simple as possible.
    4 f1 Z, u0 G' D) O7 r' u
  51.                         //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口
    1 V7 e+ L4 Z, ^6 d& k' Y# O) x5 K
  52. $ j' I4 N0 r: W  o0 l
  53.                         The following links provide detailed information:
    5 k# ]* B( ~$ D5 Q) s
  54.                         http://www.freertos.org/RTOS-Cortex-M3-M4.html
    5 e* v: z: Z8 r7 K9 ?! J. A5 c
  55.                         http://www.freertos.org/FAQHelp.html */
    5 F9 D4 X" b$ w2 L
  56.                         configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置! M  n) ?- F0 \& e6 Z8 M
  57.                         //// ucMaxSysCallPriority值为0x50
    ' W- R) r2 A* V! l# |; T
  58.                 }
    : {- `5 ]" J2 _3 p( x

  59. 0 V& @4 i8 E: d
  60.                 /* Priority grouping:  The interrupt controller (NVIC) allows the bits8 N1 U# T2 L# `9 f) E6 H* ]
  61.                 that define each interrupt's priority to be split between bits that5 S5 @. r7 K6 @; {
  62.                 define the interrupt's pre-emption priority bits and bits that define6 D4 l  K0 T" Q' w+ W
  63.                 the interrupt's sub-priority.  For simplicity all bits must be defined+ W1 W8 [  d3 W, d/ h, z) ?
  64.                 to be pre-emption priority bits.  The following assertion will fail if, U2 {! J2 m+ g& ]/ ?
  65.                 this is not the case (if some bits represent a sub-priority).
    : v3 J5 w7 t2 i. d3 x# K

  66. / W; A5 E8 ?' V4 N9 T" o2 h
  67.                 If the application only uses CMSIS libraries for interrupt. P  W1 `3 R, c- Y& @3 A
  68.                 configuration then the correct setting can be achieved on all Cortex-M
    # ^9 S4 f0 Q- V1 u! o
  69.                 devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
    7 u5 C- [( i6 A' }4 f
  70.                 scheduler.  Note however that some vendor specific peripheral libraries9 n- ?# N: Z+ m! |& y+ o
  71.                 assume a non-zero priority group setting, in which cases using a value
    2 q8 @9 `7 S. _: w
  72.                 of zero will result in unpredicable behaviour. */
    ' T) h3 W7 H9 ]4 Z8 n9 W
  73.                 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
    2 P# a; [# f* _4 R" q( ~
  74.         }
    0 A+ ]( d, U' d! h4 N. B2 A8 f
  75. : r7 R% G. M7 i" ~1 v
  76. #endif /* configASSERT_DEFINED */
复制代码

* Y' j/ ~, F* X+ T. a( f0 u       相关宏定义如下:
% _# M1 R6 ?- H0 ?8 B8 ~& D
  1. #define portFIRST_USER_INTERRUPT_NUMBER                ( 16 )
复制代码
  1. - K5 ^( `/ }# o6 A! n- M8 \. P5 p
  2. /* The lowest interrupt priority that can be used in a call to a "set priority"6 h. [6 t9 N8 _3 E6 Q
  3. function. */
    4 I5 y1 o7 ]. W2 |4 M* l+ W' y3 v
  4. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15
    # P( s& ]5 i  X; K& t7 p2 |5 ^( A
  5. / k  G4 ?4 w+ {5 Z8 J0 z) ~
  6. /* The highest interrupt priority that can be used by any interrupt service& O1 ]' ]1 u& L: Z1 l3 [! k! ^) m
  7. routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
    ' J6 S5 {. r+ _
  8. INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
    $ a+ n. `) j& a3 [
  9. PRIORITY THAN THIS! (higher priorities are lower numeric values. */6 w) @) Z# G6 T7 m
  10. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5! W0 H5 G3 U/ A: P3 i7 L

  11.   ?* P' ?9 F! a; {0 o
  12. /* Interrupt priorities used by the kernel port layer itself.  These are generic
    0 |' D) r7 N/ d8 t0 O, U
  13. to all Cortex-M ports, and do not rely on any particular library functions. */# z5 i9 t2 A; X0 q8 t2 t: c5 `
  14. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )8 c, l. K& @1 k- A7 p+ F; X
  15. /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!$ J( h0 W4 Y1 E7 W' Y
  16. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */" m: B3 u( W$ d
  17. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
    * Y2 X" W0 Y/ i

  18. 7 W# X) l0 l7 N( N* o  e
  19. /* Normal assert() semantics without relying on the provision of an assert.h
    # X& E  d: K/ w4 i. O5 M2 Z
  20. header file. */8 p  T( |% B/ o9 j" v  w4 Z. W* J! Y
  21. /* USER CODE BEGIN 1 */   
    + p$ c+ B5 V5 D! o: {4 {, E
  22. #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} 9 f/ q5 X& x! M
  23. /* USER CODE END 1 */
复制代码
  1. #define configPRIO_BITS         4
复制代码

8 z1 u! X  g, j+ E0 d
$ x, ^+ G6 y* |+ r简单总结如下:
# H  r: p( q/ z. ~1 {0 f: Q       使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。
+ a2 D, r7 v* \  E& t# h3 h  k5 e, }% U1 J8 d
9 X5 P+ Z" Q8 L) T2 G) q
. J, L% O$ K& S3 e2 }9 {9 w
- @+ j( O1 j; q/ t7 L
3 m# a" b6 k5 {
收藏 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 手机版