本帖最后由 power568 于 2019-4-16 16:07 编辑 # {0 y- W) I" v* [8 T8 K' a
9 R' H8 I! w9 {. I* M 最近在写一个串口通讯的程序,软件、硬件平台如下:6 \- x3 z; N7 `, I/ g G3 C: i
硬件: STM32F429ZG
8 w5 g. h& G' y; z系统: FreeRtos、HAL库8 R! w) P% c) |6 B* G; p
工具: Iar7.6" u0 h$ k8 b8 @& @
! H3 e2 L& b1 | y4 Y1 h# s+ ` 计划是利用串口DMA+IDLE空闲中断的方式接收数据,在中断内将接收到的数据通过队列的方式发送出去,在任务内部等待接收队列,串口中断配置及ISR如下:- HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);//// 中断配置,优先级大小不能乱配置* i" F0 s' k$ E$ s
- HAL_NVIC_EnableIRQ(USART1_IRQn);
& ?/ b9 g U* Y" B2 f - + Q6 a7 k/ z$ B! b6 \$ M( P: \: J
- void USART1_IRQHandler(void)
9 U" B6 I& u# K# M4 Q6 M - {
6 N; V; V' Y8 i9 S3 c, E) W - uint32_t flag=0;' w/ `% Z M# m) R- S: V* g+ H
- BaseType_t pHigherPriorityTaskWoken = pdFALSE;. T% u6 U6 V; k5 W9 y6 w3 V; m
- ! Q% I+ b R. e* i
- flag = __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE);
1 p i, s: M6 l/ u9 |$ q9 O( ]1 K - if((flag != RESET))/ }5 t7 i7 t. g% g
- {3 l1 F- }( Z7 n: p9 H% W
- __HAL_UART_CLEAR_IDLEFLAG(&huart1);( F0 z4 D8 S- B
- huart1.Instance->SR;
& k4 {. }) ?( k+ p8 p' `8 a - huart1.Instance->DR;) r/ n+ `! _& o+ _8 c9 M* ?- }
3 P/ e5 K) U' v: J# T" j/ H' ]: p- HAL_UART_DMAStop(&huart1);& }' y5 S6 `5 X. \' l' k
- xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken);5 o i, g" Q" Y9 S
- portYIELD_FROM_ISR(pHigherPriorityTaskWoken);
' \) W& u, Q9 F2 I1 b; u: b' k - }
) H0 P* l; T9 i% h - }
复制代码 * ^7 w, L) P" i! ]+ q4 B
9 l* J: i7 T8 k- v$ U1 i //// 为什么代码提交后,代码对齐格式变了呢???
- v t' W3 N9 T6 D& E' t; K" R
% @: M6 b6 b S* m3 _, p) g4 A1 F 调试发现进入中断后,程序卡在了函数xQueueSendFromISR(UrtK125RcvQueue, DrvUsartRcvBuf, &pHigherPriorityTaskWoken)内部configASSERT( ucCurrentPriority >= ucMaxSysCallPriority )处,具体为:3 o* H- Z( }2 `+ o6 Z9 l2 v
- #if( configASSERT_DEFINED == 1 )
0 G% }8 G' ~1 z, t% ? - : z2 u5 G/ r# U9 j6 E5 R
- void vPortValidateInterruptPriority( void )4 y, U! S4 V/ o+ \
- {
: p+ g: |/ j7 G4 L - uint32_t ulCurrentInterrupt;
& I5 M% n* _" i3 {" F - uint8_t ucCurrentPriority;
$ F* r' j- C. u. E: S' a - ) ~8 B0 R$ d- o& o# b
- /* Obtain the number of the currently executing interrupt. */
5 M- F. P/ w( L) i% _. S8 T7 P - __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );2 H" o! _% P, x! R3 T
- //// ulCurrentInterrupt 调试显示为53/ p- `) ]' [4 e/ O4 _- k+ C2 A
' [' q1 k j! h# c9 W- /* Is the interrupt number a user defined interrupt? */
( S6 u9 d! ~. B/ K - if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )+ p# h6 B% ~; [/ E0 R
- {3 l4 g/ u# ~# n0 {' p* t; l/ [ w% v
- /* Look up the interrupt's priority. */% W! S1 n8 S Z0 _# i
- ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
& E& s, H' Y, T* h+ x1 F - //// 当串口优先级设置小于5时,ucCurrentPriority的值小于0x50,导致下面的宏断' [" i* @, s/ i" ~5 l
- //// 言configASSERT条件值"==0",进而卡住
& g* R U) O8 X* m* \ - //// 当串口优先级设置大于等于5时,ucCurrentPriority的值大于等于0x50,下面的1 p( q7 m2 E c7 S2 f) V/ A
- //// 宏configASSERT条件值"==1",所以不会卡住
$ V" J: T1 E p - . K9 Z* o$ {+ I7 s9 N, y: i7 A
- /* The following assertion will fail if a service routine (ISR) for" V* o3 e' q9 p7 ^' I5 q/ ^% Q
- an interrupt that has been assigned a priority above# |* G O+ R/ f
- configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API: C, |% v4 @2 `& @ B% a; ]2 e
- function. ISR safe FreeRTOS API functions must *only* be called, V8 Q, d: [: B5 m
- from interrupts that have been assigned a priority at or below
# r/ w+ k% d% [# }7 k) O/ r - configMAX_SYSCALL_INTERRUPT_PRIORITY.0 F; G6 n) j0 }3 |* a
- //// 如果一个调用FreeRtos安全ISR API接口的中断ISR优先级分配大于
8 l6 x/ M" I( V% N# ?# O' ` T+ ] - //// configMAX_SYSCALL_INTERRUPT_PRIORITY(即中断优先级值小于; q p) F# k, h& G
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY,因为FreeRtos中值越小优先级越高),4 q) Q B) [8 S2 d; ], R, l
- //// 下面的断言就会失败。FreeRtos安全ISR API接口必须只能在优先级分配大于: i% R9 M' A/ a' _- O/ P3 [3 m! [
- //// configMAX_SYSCALL_INTERRUPT_PRIORITY的中断ISR中调用) {- }4 w: i4 S8 O* X, k: [
- / g' ?% y- z$ K! ^
- Numerically low interrupt priority numbers represent logically high
) O8 O* m2 \6 r7 m - interrupt priorities, therefore the priority of the interrupt must
* F& X) o, n, Y( g9 j7 e) G, T - be set to a value equal to or numerically *higher* than, {" L h1 r+ S5 {" j
- configMAX_SYSCALL_INTERRUPT_PRIORITY.
7 [. b, O1 s$ l! W" V - //// 数值小的中断优先级逻辑上具有高的中断有限权,因此设置时,中断的优先级
- M. I* E/ e7 E g! e {/ o - //// 值必须必configMAX_SYSCALL_INTERRUPT_PRIORITY大
2 d; J6 S+ s. G - . g' a8 J$ t# K/ `' v
- Interrupts that use the FreeRTOS API must not be left at their4 n: P: a2 s7 u0 B$ S# t+ V: M% K
- default priority of zero as that is the highest possible priority,
" ?, l9 P, A v8 F9 u# s - which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,7 o2 V* C7 `. K: M' k* ?. ^
- and therefore also guaranteed to be invalid.4 n$ c8 p6 l% F. R6 ]
- //// 使用FreeRTOS API的中断的优先级禁止使用其0的认值,因为此时中断优先级最. `7 ^0 l0 a6 ?* }. C
- //// 高,0值的优先级必然大于configMAX_SYSCALL_INTERRUPT_PRIORITY,因此也必+ I) o: [( ^! G7 w! E
- //// 然无效6 Q9 E" I* x1 v' A8 H
- . t8 E, ?6 P, U$ i0 T# A! m- d: C
- FreeRTOS maintains separate thread and ISR API functions to ensure
& I( d9 ]. n3 y& S. l) F) ~8 S* L - interrupt entry is as fast and simple as possible.
1 q# J9 A. k% B `+ ~# \( ? - //// FreeRTOS为了确保中断入口尽可能的快和简单,因此分离了线程ISR API接口, O% W0 m' V/ D6 U4 F! L: k! i
/ b5 w. V( A0 X h( q& A C- The following links provide detailed information:/ X% Q- r" K, Z7 J2 E4 {
- http://www.freertos.org/RTOS-Cortex-M3-M4.html4 S h' O+ }8 p) R& ?9 B- \- l4 G9 K
- http://www.freertos.org/FAQHelp.html */
# O: O! u$ Q! |3 F, P- o k8 N - configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); //// 程序卡住位置
* G8 l2 _1 `/ D - //// ucMaxSysCallPriority值为0x50$ u" }/ D S. \/ v
- }
* U5 H) O. }1 S' l0 W2 E2 Y+ p$ P - & w/ s0 B/ N# p, B' d
- /* Priority grouping: The interrupt controller (NVIC) allows the bits
( v" T; F8 H( y7 I3 R$ U1 k - that define each interrupt's priority to be split between bits that
, x$ ~: t# w4 U3 s9 H0 z5 ^ - define the interrupt's pre-emption priority bits and bits that define" q$ F$ ~" { E* V) x3 {
- the interrupt's sub-priority. For simplicity all bits must be defined0 u3 |1 S1 n" N' a
- to be pre-emption priority bits. The following assertion will fail if* F* ~8 F% G* @6 t% z9 i7 ~
- this is not the case (if some bits represent a sub-priority).
- |* k) @( K) c - 0 ^; \& h3 f8 X# }, A& x4 b1 u, r3 \
- If the application only uses CMSIS libraries for interrupt6 v0 z4 F% N* B$ y: x
- configuration then the correct setting can be achieved on all Cortex-M- W z! `' N! X) @2 Q
- devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the/ E2 m+ v. n9 p7 \9 M
- scheduler. Note however that some vendor specific peripheral libraries* `9 I4 I$ G# E- {
- assume a non-zero priority group setting, in which cases using a value7 R0 }; S2 Y/ C& w1 ~6 o' J( d) n; a
- of zero will result in unpredicable behaviour. */
& x4 [5 M% E1 a( x9 S - configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
1 T9 K: `2 u5 [5 {$ t/ [ - }
% X [( V$ v3 @1 g6 C- q - % ~' e' {$ `2 s6 J$ z
- #endif /* configASSERT_DEFINED */
复制代码 9 J" U: M' |- }7 x/ { Y
相关宏定义如下:
7 Z# F3 y& y) g- #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
复制代码
6 ^, h: J. M, T2 W. p- /* The lowest interrupt priority that can be used in a call to a "set priority"
1 I9 S D1 R, W& t4 M; J* g; Q( H c - function. */
: {8 Z5 ~" I, ^# @- X$ c% X" Z - #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
6 \# V3 s% a% q/ C! _4 f. G - & I# w( |7 O; `3 U% w
- /* The highest interrupt priority that can be used by any interrupt service* }2 C1 |* ~+ n6 H* r+ E: g) r
- routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL" d$ p* w( t8 c2 U. ^+ T/ h4 Q
- INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
( O `+ V5 C+ f0 _' y. S6 _# _ - PRIORITY THAN THIS! (higher priorities are lower numeric values. */& y& o. H- j% q; Z2 M( c
- #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
: Q' r4 W% F! L [
2 a: I3 p1 n& C- /* Interrupt priorities used by the kernel port layer itself. These are generic% x# }3 J% f9 G9 V1 [' c5 D& m! t
- to all Cortex-M ports, and do not rely on any particular library functions. */
+ _4 x6 t6 o$ H) a - #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
0 j( o7 f; R! M0 h' ^ - /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!# \: _- ]8 x% X0 @; X0 @
- See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
% Q7 S9 I$ X+ S% y- O0 _! Z: N - #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )3 f6 w0 c; I' i# x U, c* R: B
# ]5 d& b1 e* C, E5 d6 X% O- /* Normal assert() semantics without relying on the provision of an assert.h
2 Q# y- D! y, [* r( `5 |! T - header file. */
. v! \) R# i$ j - /* USER CODE BEGIN 1 */ 0 `$ [$ R" X+ J* `0 F
- #define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );}
7 z3 W6 {5 X! b; T# Z- B0 t, V, w - /* USER CODE END 1 */
复制代码- #define configPRIO_BITS 4
复制代码
$ ?& L* F+ S! o5 K, b4 J
, W4 ~: d. P& T8 J7 a1 [' m3 Z简单总结如下: d* a h2 J3 }, R* O/ L- X& A
使用了FreeRtos操作系统后,外设中断优先级值不能设置小于configMAX_SYSCALL_INTERRUPT_PRIORITY,否则会导致了宏configASSERT的条件成立,进而卡住了。0 T4 J% t) [* d* b0 O
+ ~/ d& C3 s! l9 t5 O2 d& N3 [
. P: H' ?% e' H2 E; [. D) b
: }0 P$ `0 L! U4 |5 Y; t& E$ `2 ?. o8 k- o
|