前言/ g( g. [% Y5 x1 r1 i/ D* ?% K
简单介绍一下如何使用FreeRtos的中断配置和临界段。
" }4 T; z; v3 z: g) ~9 f0 d. o3 _5 [/ J$ I- q- Z
一、stm32的NVIC 分组配置. o! z; x+ S9 i# c
STM32最多有 5 种优先级分组设置,这 5 个分组在 msic.h 中有定义。因为FreeRTOS 的中断配置没有处理亚优先级这种情况,所以我们只能配置中断优先级分组为 4,直接就 16 个主优先级,使用起来也简单!
0 Q& P9 V& x6 }. T6 ?7 E
' v4 d7 x6 ^8 V K; a9 L4 m9 C J- #define NVIC_PriorityGroup_0 ((uint32_t)0x700)
2 |1 D3 A0 o$ j* U% H! J" _ - /*!< 0 bits for pre-emption priority4 bits for subpriority */* ^7 c4 r. l! F' d9 K3 B
- #define NVIC_PriorityGroup_1 ((uint32_t)0x600)
- V3 b. z# g, ~% c) p/ j7 a - /*!< 1 bits for pre-emption priority3 bits for subpriority */
1 C$ I2 F& ~+ ~ - #define NVIC_PriorityGroup_2 ((uint32_t)0x500)
/ a+ u+ Q: \2 `% R- [ - /*!< 2 bits for pre-emption priority2 bits for subpriority */
6 X# }" T: d4 a7 g' d/ t6 }9 q$ l - #define NVIC_PriorityGroup_3 ((uint32_t)0x400) 3 ~; } I3 [; c! {
- /*!< 3 bits for pre-emption priority1 bits for subpriority */8 ~/ E6 C: ~* ^8 w9 g1 l+ {
- #define NVIC_PriorityGroup_4 ((uint32_t)0x300); J% j3 z3 y4 t* {6 r/ @1 G% z) X- w
- /*!< 4 bits for pre-emption priority0 bits for subpriority */
复制代码
i% ^* h* |8 T2 n$ h9 w2 U$ p二、FreeRTOS 相关API函数+ K: l/ p, [8 E4 s
1.开关中断
3 H% Y$ Y l8 _2 EFreeRTOS 打开中断 :portENABLE_INTERRUPTS (), T& `. T5 l0 p1 c; a9 t7 _
FreeRTOS 关闭中断函数为: portDISABLE_INTERRUPTS()。
+ [. C) m8 t& z' k8 f. @利用他们可以打开或屏蔽FreeRTOSConfig.h中指定优先级的中断。( ^& Z' y( A# g7 q8 D
备注:
; b# X# G* x7 m) x7 P在FreeRTOSConfig.h文件中宏定义了freerots可以管理的优先级
( ~! j* l5 _) k% U7 R#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级4 R- c+ G' J9 p; c
当用户中断优先级高于这个宏定义的优先级则关闭中断只会关闭低于或等于此宏定义设置的优先级
. m8 w5 E1 Q3 Y `6 F( B9 W6 O
( Y$ ^( Q* ^+ b8 M2.临界段代码
" F$ F$ G" f( _; p- 临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,
9 F% v9 |9 h8 b! Z5 z - 比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。4 l0 w! I& B3 o ~1 n- {* G
- FreeRTOS 在进入临界段代码的时候需要关闭中断,当处理完临界段代码1 w3 j+ n& ?7 N2 x; P4 F/ }9 D3 q; E7 m
- 以后再打开中断。FreeRTOS 系统本身就有很多的临界段代码,这些代码. d& V8 P, |+ V& Q' p* @# y
- 都加了临界段代码保护,我们在写自己的用户程序的时候有些地方也需要
+ r; M4 B4 h. x- ~2 _ - 添加临界段代码保护。
复制代码- FreeRTOS 与 临 界 段 代 码 保 护 有 关 的 函 数 有 4 个 :
3 x/ j5 {# e( P' @ - taskENTER_CRITICAL() //进入代码临界区/ {6 k) l' _0 m+ Y) T7 r- U+ [1 }
- taskEXIT_CRITICAL() //退出代码临界区
* O5 X% ~3 H2 q5 H - taskENTER_CRITICAL_FROM_ISR() //进入中断级代码临界区
4 a1 H7 l8 B* q- ~: v. H - taskEXIT_CRITICAL_FROM_ISR()。//退出中断级代码临界区
复制代码
8 z- m. P) }; d: S1、taskENTER_CRITICAL()和 taskEXIT_CRITICAL()任务级临界代码保护使用方法如下:- 2 S; T F6 @9 C" x
- void taskcritical_test(void)
2 Q8 g' Q0 b- W4 ] - {! o& c* h3 C6 R T" P* v M& H" m I
- while(1)
, C4 ]2 x; M D$ v' Y% C - {
: w6 \" Y1 y8 `4 X8 F0 V - taskENTER_CRITICAL(); ' A% k' I9 R2 ]$ K: e
- total_num+=0.01f;
5 D' s; G' k( }, c4 { W) M4 W8 W - printf("total_num 的值为: %.4f\r\n",total_num);
2 T& |0 T0 ^* {0 M' ` - taskEXIT_CRITICAL();3 ~0 ?( Q3 \! h( R
- vTaskDelay(1000);, Q- ~0 }- U: s9 t5 k, h W* K8 v
- } 4 ^' L, |) d/ e: O
- }
& f/ Q0 Y$ _! ?/ ` L2 { - ( |6 H5 G8 u8 g# y) R. T
复制代码
: r( ?! n9 M/ _7 P' m
% x, h6 R) X% o3 E8 R; z, B: k9 j2. taskENTER_CRITICAL_FROM_ISR()和 taskEXIT_CRITICAL_FROM_ISR()中断级临界段代码保护中断级临界代码保护使用方法如下:
G( b3 V" m. W1 f//定时器 3 中断服务函数# m6 ]; J+ _' l; |
- void TIM3_IRQHandler(void)2 }/ V, U! z9 D3 J* G; i; O" U7 U
- {* B% I8 J$ f9 e+ ?' [
- if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断1 Y2 z* r! I& G2 P+ r
- {' n) J( a5 J' Z, M* ^( a
- status_value=taskENTER_CRITICAL_FROM_ISR(); 8 n. c( |, ^, S. X$ k: c0 h* A
- total_num+=1;: d5 H) l" ~' K a, S0 C; F
- printf("float_num 的值为: %d\r\n",total_num);
# P9 G5 d0 @/ Y1 y5 {: G# J) C! H - taskEXIT_CRITICAL_FROM_ISR(status_value);) w$ w3 P O/ ?- N( [3 X& e
- }
$ T7 V. a8 t$ i# T* F - TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
5 u" d0 q$ J5 U& v! z" x' V. A - }
复制代码 % ~* E4 K$ y9 H* a
备注:askENTER_CRITICAL_FROM_ISR()和 taskEXIT_CRITICAL_FROM_ISR()中断级别临界段代码保护,是用在中断服务程序中的,而且这个中断的优先级一定要低于configMAX_SYSCALL_INTERRUPT_PRIORITY,因为高于这个优先级的中断服务函数不能调用 FreeRTOS 的 API 函数6 e. ^! W# {6 y8 ~; t
0 y7 s" j$ `% B4 E5 w1 ?( I7 a0 M: j' D" V0 G
- M- G4 o2 s, ^0 I2 ^8 |! D6 [
2 G, i' R4 h( f1 U% Y |