本帖最后由 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如下:- HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置
) E9 z* L8 [; F3 d - HAL_NVIC_EnableIRQ(USART1_IRQn);
( j9 B1 g& u! F" R9 `
' S3 S# i0 v- c$ b- j4 L7 E- void USART1_IRQHandler(void)
; E$ K& ^9 L4 c! }; l& f' c$ e - {* |+ P q6 D, r
- uint32_t flag=0;7 \0 q6 q1 |* H$ k ?
- BaseType_t pHigherPriorityTaskWoken = pdFALSE;$ [4 h8 g4 b' x* [
- 1 S- z) C; t/ E
- flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
" R4 N) }1 Z) J - if((flag != RESET))* b& [ q7 [5 v; a$ C
- {
! b( B' R* V3 b% p; N/ ^. Z - __HAL_UART_CLEAR_IDLEFLAG(&huart1);- R3 B% Q. _0 g( d' Y( X
- huart1.Instance->SR;
7 o# ?4 B6 R+ U0 ^1 K: I7 r2 @ - huart1.Instance->DR;2 u4 j0 ?8 K8 b- n
- * q9 f+ Y' P9 | X6 b, z2 D
- HAL_UART_DMAStop(&huart1);
, E k7 n- _. k2 w5 Q - xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);
. e, V, r. @4 q2 R0 r2 J$ r - portYIELD_FROM_ISR(pHigherPriorityTaskWoken);+ D3 J, i6 A6 F1 V8 |7 f% s
- }
D" j6 \4 H, L; C( }, j( ? - }
复制代码 " 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
- #if( configASSERT_DEFINED == 1 )
( D" X+ p/ c8 ?4 I - . j$ }# A" ]$ c7 B: A
- void vPortValidateInterruptPriority( void )- p0 `" v- r0 h4 }6 u
- {
+ q0 Y5 Q; k$ X8 S. y8 m q - uint32_t ulCurrentInterrupt;5 S* T' S7 t' e; I4 m% E7 d
- uint8_t ucCurrentPriority;9 Y- I o# Z+ u. e
7 \( i) |( k) F) I' j/ ]- /* Obtain the number of the currently executing interrupt. */: a% l" q) |, X: g1 E/ `/ v
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
, g6 J6 a' A, E1 _, j* } - //// ulCurrentInterrupt 调试显示为53$ ]$ O$ W/ K0 `0 X5 W
8 m- E( t& Z. v- o- /* Is the interrupt number a user defined interrupt? */
2 _- C/ K/ N: z& D3 G( a+ Y& n+ C - if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
! o3 O- J/ T0 ^* Z1 X. r0 F; i$ { - {2 V. A- q# [3 S( U, o
- /* Look up the interrupt's priority. */
3 z+ m; I d$ Y9 u - ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
3 Y+ l( C) A: X, B# ~" ]' L - //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断
( I% D5 i0 z0 v' V; C5 \ - //// 言configASSERT条件值"==0",进而卡住
! G) {) m! S# C - //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的3 g5 P% @& k- q7 W' g" h: b
- //// 宏configASSERT条件值"==1",所以不会卡住, x8 S! J% j* O) L9 \ |
- 7 R' g; _: p7 C# Y
- /* The following assertion will fail if a service routine (ISR) for% i- V, ~0 c$ y
- an interrupt that has been assigned a priority above. @3 N$ e% u2 C8 H% f9 c/ C
- configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API/ @* E4 w( Z3 _8 _) h9 e
- function. ISR safe FreeRTOS API functions must *only* be called
: Y. g- T* V; p" X3 G e8 w' i( W( H6 s - from interrupts that have been assigned a priority at or below
$ n) e3 v7 ]3 c! C3 o% k - configMAX_SYSCALL_INTERRUPT_PRIORITY.' p2 s$ C& ~! q/ }! |" {& [* N( t
- //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
. ^, ^& y/ z% ~8 Z0 L5 w - //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于9 L( U( L: G9 p6 m) ^
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),
9 t6 V) m- b3 ` - //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于
x7 X' X) F) ?6 N; b, ?- Z) B - //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用4 @# J. v5 \+ {2 Q2 h
-
7 I2 b" D# Z" }' ? R# k - Numerically low interrupt priority numbers represent logically high
: h8 [2 A0 w) \) P1 C" D0 N - interrupt priorities, therefore the priority of the interrupt must- D& K9 G& ^4 {/ k7 T; F" c3 S; `
- be set to a value equal to or numerically *higher* than$ \* J. M. A( C- C
- configMAX_SYSCALL_INTERRUPT_PRIORITY." J* O/ N2 H2 `, N( U4 }# ]
- //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
* O2 M% p! t5 I3 s0 b J$ {+ {" F3 Y - //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
0 w% g. Q2 p' B: _ - ! O9 V0 x) S) C2 R* L
- Interrupts that use the FreeRTOS API must not be left at their. n0 N( ?( J9 l* V
- default priority of zero as that is the highest possible priority,
! E% l* h2 P& V - which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,) V( F' Y' q4 g1 a/ z
- and therefore also guaranteed to be invalid.4 Z9 g1 Y" ~# g( q
- //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最* H" s# ?+ W. _& a
- //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必5 y' m9 S q5 n! r7 y8 }
- //// 然无效1 r6 ]8 N/ i- q' N: S" L
- 9 W+ q* }+ m7 r
- FreeRTOS maintains separate thread and ISR API functions to ensure7 O' Z3 z9 A! E% T
- interrupt entry is as fast and simple as possible.
4 f1 Z, u0 G' D) O7 r' u - //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口
1 V7 e+ L4 Z, ^6 d& k' Y# O) x5 K - $ j' I4 N0 r: W o0 l
- The following links provide detailed information:
5 k# ]* B( ~$ D5 Q) s - http://www.freertos.org/RTOS-Cortex-M3-M4.html
5 e* v: z: Z8 r7 K9 ?! J. A5 c - http://www.freertos.org/FAQHelp.html */
5 F9 D4 X" b$ w2 L - configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置! M n) ?- F0 \& e6 Z8 M
- //// ucMaxSysCallPriority值为0x50
' W- R) r2 A* V! l# |; T - }
: {- `5 ]" J2 _3 p( x
0 V& @4 i8 E: d- /* Priority grouping: The interrupt controller (NVIC) allows the bits8 N1 U# T2 L# `9 f) E6 H* ]
- that define each interrupt's priority to be split between bits that5 S5 @. r7 K6 @; {
- define the interrupt's pre-emption priority bits and bits that define6 D4 l K0 T" Q' w+ W
- the interrupt's sub-priority. For simplicity all bits must be defined+ W1 W8 [ d3 W, d/ h, z) ?
- to be pre-emption priority bits. The following assertion will fail if, U2 {! J2 m+ g& ]/ ?
- this is not the case (if some bits represent a sub-priority).
: v3 J5 w7 t2 i. d3 x# K
/ W; A5 E8 ?' V4 N9 T" o2 h- If the application only uses CMSIS libraries for interrupt. P W1 `3 R, c- Y& @3 A
- configuration then the correct setting can be achieved on all Cortex-M
# ^9 S4 f0 Q- V1 u! o - devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
7 u5 C- [( i6 A' }4 f - scheduler. Note however that some vendor specific peripheral libraries9 n- ?# N: Z+ m! |& y+ o
- assume a non-zero priority group setting, in which cases using a value
2 q8 @9 `7 S. _: w - of zero will result in unpredicable behaviour. */
' T) h3 W7 H9 ]4 Z8 n9 W - configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
2 P# a; [# f* _4 R" q( ~ - }
0 A+ ]( d, U' d! h4 N. B2 A8 f - : r7 R% G. M7 i" ~1 v
- #endif /* configASSERT_DEFINED */
复制代码
* Y' j/ ~, F* X+ T. a( f0 u 相关宏定义如下:
% _# M1 R6 ?- H0 ?8 B8 ~& D- #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
复制代码- - K5 ^( `/ }# o6 A! n- M8 \. P5 p
- /* The lowest interrupt priority that can be used in a call to a "set priority"6 h. [6 t9 N8 _3 E6 Q
- function. */
4 I5 y1 o7 ]. W2 |4 M* l+ W' y3 v - #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
# P( s& ]5 i X; K& t7 p2 |5 ^( A - / k G4 ?4 w+ {5 Z8 J0 z) ~
- /* The highest interrupt priority that can be used by any interrupt service& O1 ]' ]1 u& L: Z1 l3 [! k! ^) m
- routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
' J6 S5 {. r+ _ - INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
$ a+ n. `) j& a3 [ - PRIORITY THAN THIS! (higher priorities are lower numeric values. */6 w) @) Z# G6 T7 m
- #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5! W0 H5 G3 U/ A: P3 i7 L
?* P' ?9 F! a; {0 o- /* Interrupt priorities used by the kernel port layer itself. These are generic
0 |' D) r7 N/ d8 t0 O, U - to all Cortex-M ports, and do not rely on any particular library functions. */# z5 i9 t2 A; X0 q8 t2 t: c5 `
- #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )8 c, l. K& @1 k- A7 p+ F; X
- /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!$ J( h0 W4 Y1 E7 W' Y
- See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */" m: B3 u( W$ d
- #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
* Y2 X" W0 Y/ i
7 W# X) l0 l7 N( N* o e- /* Normal assert() semantics without relying on the provision of an assert.h
# X& E d: K/ w4 i. O5 M2 Z - header file. */8 p T( |% B/ o9 j" v w4 Z. W* J! Y
- /* USER CODE BEGIN 1 */
+ p$ c+ B5 V5 D! o: {4 {, E - #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} 9 f/ q5 X& x! M
- /* USER CODE END 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 {
|