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

STM32超低功耗平台上的RTOS培训 -- 实验2 中断和任务同步(信....

[复制链接]
TLLED 发布时间:2018-4-17 10:26
接上篇:STM32超低功耗平台上的RTOS培训 -- 实验1 任务创建$ R' {3 {! F7 ]9 b' a, S( v. T

; K9 N4 o( e' ]- Z3 Q+ t" e& L" x8 o, ^( y
: b3 J9 b; l& Q8 u% U6 N6 Q& I
FreeRTOS中断方式的二值信号量是实现中断函数与任务之间的同步。
8 Z& P0 j/ x2 M: ]. D9 ~
. K1 G1 h4 \/ B! l/ \0 e$ j
& U. H1 c2 u) h/ O$ w
    程序任务框图:7 U- @# ^: P' g% z! U, ^8 n
    下面是本程序实现中断函数与任务之间同步的框图:9 y) f  s: v* M0 d, ~
      1.jpg
, P# n' a( b, n6 l( `9 I$ Q0 h' p
5 H/ F) s9 I, L7 x, D1 o/ r5 ]; @% k* J+ ?1 o; A; N: D6 D
     程序执行的条件:. i. b+ W. K4 l  C
    > 创建两个任务:一个任务vAppStartTask()用于LED2指示灯闪烁;
2 I6 V- Z1 D/ V; j( u" C  }                              一个任务prvAppButtonTask()用与等待中断后,通过串口发送按键次数;: N! Q2 Z9 a+ g, S" p; Z1 b
    > 二值信号量的初始值为0,按键中断调用xSemaphoreGiveFromISR();函数释放信号量。任务prvAppButtonTask()调用xSemaphoreTake()函数获取信号量资源。
  \( n3 l0 _7 H* R$ l   执行过程描述:
% B$ O# |1 P$ S3 }% N' y    > 任务vAppStartTask()用于LED2指示灯闪烁,和信号量之前没有关联;
3 G% Z+ k: S$ `    > 任务prvAppButtonTask()运行过程中调用xSemaphoreTake()函数,由于信号量的初始值为0,没有信号量资源可用,任务prvAppButtonTask()由运行态进入到阻塞态,串口无数据输出。
- M) c" S( S& h( U& k    > 按键后,发生外部中断,中断发生,中断程序中调用xSemaphoreGiveFromISR()函数,释放信号量资源,信号量数值加1,此时信号量计数值为1,任务prvAppButtonTask()由阻塞态进入就绪态,在调度器的作用下由就绪态进入到运行态。任务prvAppButtonTask()获得信号量后,信号量数值减1,此时信号量值又变成0。
! o; O) i; g. R- w- Z- S    > 再次循环执,任务prvAppButtonTask()由于没有信号量资源可用,再次进入阻塞态重复执行。% v4 s7 ^' v) P" Q2 j

* ]0 N- X  l0 i/ B, X: t    程序执行:
8 w4 M" @5 R  L( o3 n& I) b        > 板子上LD2闪烁
' V5 x, M' _/ i: h7 x        > 串口输出数据: 按一下板子上B1 USER按键,串口输出一帧数据。
* y/ D1 e; `( ^8 a5 ?; o    2.jpg
" ]- Z" N6 O  J' C" L& k  c
2 ]) w6 q) L+ \4 Z) L1 W    程序相关的代码:为了便于查看有关信号量相关的函数位置,只截取程序中相关函数。
; m* u2 j: J5 w: g2 g6 b2 f1 U, ?
int main(void)
$ W9 w) ^% V7 M! w* n{
% V. D" N) T' ^' t) l        HAL_Init();
* u* a& K# j, G4 c. r. B0 y        SystemClock_Config();" m6 I/ F$ V# y% K9 O
        __HAL_RCC_PWR_CLK_ENABLE(); //Modified by ST MCU China Team, Added by JWR 2018.01.29+ C7 F0 C/ E2 Y3 C
        
; D5 Q) U/ Z) X8 M/ F" ~        /* Initialize LED */
4 a$ B  ?1 X3 Z7 s5 S        BSP_LED_Init(LED1);
4 d1 Z" }2 x5 a        BSP_LED_Init(LED2);
) Z8 l- u- A  J2 f6 y        
- x6 n# I8 ~7 M) B( e. p; g        /* Initialize buttons */
8 S3 _3 P1 ~7 \/ |/ O        BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);% L6 l6 r7 n$ \' Q+ I/ {
        
7 z  k. q1 h2 z' S9 c6 a2 w9 W        /* Configure  Uart */% s5 I+ d) e7 ]+ ^
        BSP_Uart_Init();0 w1 l" Y- `: C( A+ F3 N; o" U% Q
        
" H" h6 n, u- w" D& z! x9 ]        
1 ]# @7 S" p7 d        //vSemaphoreCreateBinary( xTestSemaphore );
3 x* w  g7 \1 ]) ~        xTestSemaphore = xSemaphoreCreateBinary();   //创建二值信号量,首次创建信号量计数值为0' ]/ z: a4 `: T4 x- R7 d/ F  o
        xTaskCreate( 8 Y# ~  [: k& r; g
                     vAppStartTask,
9 c$ ]9 U! X" E1 f) n                     "Start", # z* h; ~: T- f- @  @/ z
                     configMINIMAL_STACK_SIZE,   h. |  B2 _; g' K, Q' l6 b
                     NULL, : u7 v$ e& i1 A5 {& l
                     Start_TASK_PRIORITY, : D/ ]/ X9 V# Q+ T( v; J1 S
                     ( TaskHandle_t * ) NULL ; S- z7 ?3 [) c) A) c( b5 C3 K0 d
                    );8 P/ y4 L% O. V- h6 d: P
        
% Z) |7 B/ _* L3 }: }$ }* F        xTaskCreate(
* \( L+ c* V3 y* w+ ~                      prvAppButtonTask,
5 Q3 P0 Z: X2 n( X/ e                      "ButTest", 7 C/ x. l( I$ X7 f: B8 }
                      configMINIMAL_STACK_SIZE, 2 X3 S+ ^+ v. \! Q) y. X
                      ( void * ) NULL,
0 I/ P5 f8 @% P0 }3 l/ Q                      But_TEST_PRIORITY, ) G7 O0 b5 j9 r$ n: e5 t
                      NULL . k, S( {) K" ?: @% n) V# A
                   );
1 H) ^- P# J$ f  Z% F. c) g        * N9 A7 y$ ~  n/ ^% N/ k- J
        vTaskStartScheduler();; g' a! n& H  W
        for (;;);
9 q' B+ B3 Y& R}
* X. O4 f! ]: T* p* E! E3 N( n3 E: a
/**& |# {; D1 s, R0 n' o- \: \
* @brief  Start a Task.3 E0 S, d% Q/ u9 n+ c
* @param  argument: Not used2 Y* t$ o3 c5 t1 T; q# n
* @retval None. c% b9 O5 s7 g7 }* ~0 ]- z7 K, X
*/
8 x' r) n, R. A9 n/ R% L. I. A7 T) e6 Astatic void vAppStartTask( void *pvParameters )' b6 I6 I! `- r# c, J2 z. Y1 n5 Q
{
' T- V9 b6 C4 w2 O8 H9 V: Q        (void) pvParameters;' Q! I: }+ o/ n: k8 o
        
$ |$ }4 ]' B( n; q0 z) r" s        for(;;)
. k; B7 t! x3 K/ l- G  t# Z        {, z# e  ^9 c9 }: I  g
                BSP_LED_Toggle(LED2);) F; h% e6 T+ B7 F8 y
                vTaskDelay(200);
  o: k2 L4 L$ ~% N6 p        }
5 L/ y! s" A1 e* ?' i- T' ~: g}$ S0 p5 {, x; ^2 W9 G" Y7 F% a  i# M
" F  y& {1 e6 V
/**. Q. Z0 B- \& h$ c9 z, \# |
* @brief  Button Task.$ Y' j) n8 o4 Q
* @param  argument: Not used
+ |0 C, n5 }% A. N& d7 C# j* @retval None+ V9 g+ P1 C2 Z4 R
*/6 [! k+ j. ]+ p# q$ N' u
static void prvAppButtonTask( void *pvParameters )
4 _5 p# H: p1 j3 O{
& F' }0 m+ ^0 B* J        configASSERT( xTestSemaphore ); // The assert 函数确定信号量是否有效
8 |9 v1 a1 |7 V4 R; _2 @3 D. ^        
% U! O# n* S5 _2 s$ J: _        //获取信号量,等待时间为0,则xSemaphoreTake()在信号量无效时会立刻返回& s- j1 x- y  ~) t( H
        xSemaphoreTake( xTestSemaphore, mainDONT_BLOCK );3 R# S) T2 d5 [6 a6 q  i* s
        
; P3 D0 ]( i/ v        for( ;; )
8 ?# ^  f4 q, l7 l        {
; F& Y" K# J+ t$ I: Q                xSemaphoreTake( xTestSemaphore, portMAX_DELAY ); //获取信号量,超时时间为portMAX_DELAY值  S0 E5 c" M9 z& h8 J# ^9 K
                ulButtonPressCounts++;
) J0 k- H! b1 A, ^# p5 F* I6 r                printf("Button Press Counts:%d\r\n",ulButtonPressCounts);
; w: C# |' s4 J5 x# x. ^* q  y        }
5 |2 e9 `6 b7 \}
: B, M6 C  {) T; Y3 k7 `! A
, E) J: S2 P3 c  P, y/**
3 u4 Q- x4 J% ^' }- @: n( V: A3 I' L* @brief EXTI line detection callback." j8 P9 A3 ^1 E3 n: F
* @param GPIO_Pin: Specifies the pins connected EXTI line
$ u5 j- c% v4 q7 i  I, U0 z) F5 Q3 U* @retval None  C' m' `/ B2 S( L
*/* K- ]8 g( c. J# n1 D. U4 S
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)' c4 `9 T% R/ c9 s
{  Y" Q$ |  W- d
        if(GPIO_Pin == KEY_BUTTON_PIN)  N4 e1 d3 v% {6 F# b+ U, D2 a
        {6 M' g3 h+ Q! _( X; v- U8 w6 D$ Q/ \8 v
                if (uwIncrementState == 0)
0 _5 \! x7 H0 v; o                {/ L. ?, I$ J1 e  a8 l4 l2 V0 q
                        /* Change the Push button state */
( Q; F+ o6 o& E' ~: b: X% a' M                        uwIncrementState = 1;
" I0 ^: Q' y. @! ~+ J5 `+ y                }  A/ c) M0 b& v
                else% m2 k) u3 o; S0 d+ }6 L8 t
                {0 W: \1 ^' l9 p* h
                        /* Change the Push button state */' Q3 R$ v- c" Q
                        uwIncrementState = 0;& B% K# O: Z2 U) I: A
                }
5 t6 M; ^2 O6 q  g- l        }  " P7 Y  y/ O3 ?! y1 y7 ?1 u4 P4 K" b
}$ j( Q& U; \2 E8 P4 P+ m/ t' F  r

$ a) V9 l7 N0 X/ q; l/**
0 s" j/ e" C" R* k" d* @brief  EXTI15_10 IRQ# @( r$ y9 N# z. a/ A
* @param  None+ Y. O$ i: }+ W; F; G
* @retval None  c3 T- p7 t/ W3 ~
*/- C& ?( V# T8 n- }& t
void EXTI15_10_IRQHandler(void), v! }0 N( m, z' ~3 f5 b0 |( F
{
$ H3 z* m8 N/ j) O+ X        
8 F- ^) [  V5 C: F        static BaseType_t xHigherPriorityTaskWoken;  //高优先级任务是否被唤醒的状态保存                    ; X9 L  F3 T: |7 g
        
( @, d5 x& G+ t- r' |# h1 E$ U        HAL_GPIO_EXTI_IRQHandler(KEY_BUTTON_PIN);    //中断消息处理                             - c) j$ {4 A6 T3 `1 W
       : r4 ^6 _& P" ?3 c: v5 ^4 ^
        if (utime_tick >= 200)
" a  I1 Z; q9 p4 u        {, x8 L* o% \$ x$ K$ c" N! l
                /* The second parameter of the send sync signal is used to save
- F( g" u( S# u3 s# [3 Z- b+ T" _                whether a high-priority task is ready.*/) ~8 ?) l/ W& S; T. P$ ?. [  u; P
                xSemaphoreGiveFromISR( xTestSemaphore, &xHigherPriorityTaskWoken );        
* P8 J0 L+ `  @8 B                utime_tick = 0;
4 t5 p; ^& j1 v6 s  Y! h! S. k        }; D) z6 p6 N( h7 [
        //如果 xHigherPriorityTaskWoken = pdTRUE,则切换到当前最高任务执行,然后退出中断 1 X. a/ d2 Q9 B0 E: G# S
        portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );# p" O' v1 Q$ l3 k; U2 i
}
6 H  r$ u' M$ l, J* w2 K/ K, P3 S3 }% w! X  P7 ^2 J
) H# [9 q% W7 d& d/ i9 {6 W2 w
/**, H' x9 v' `3 x7 X3 O1 t0 W( A. R0 d# \
* @brief  FreeRTOS Tick Hook FUNC" e3 Y3 w' W' w: }& F! s9 \- z
* @param  None
# h  u+ h: S' q4 B0 `: r9 |* @retval None' r$ t) K& B6 R% @
*/- L7 p* ^6 B6 p$ x0 z
void vApplicationTickHook()0 \+ ?: ^, `0 @0 }0 Y; a) g- I' W# A
{
/ x, V. J8 R3 o! }( i        utime_tick++;        /*Use for button glitch filter,It's not for the freertos kernel*/0 a! j+ M/ S5 a$ ^
        if (utime_tick >= 65535)
# {1 k  ]' y6 v5 }        {
- X3 V0 F" P2 O1 E+ L                utime_tick = 200;. S* n' q, x) v" V( j. D8 M( w3 C
        }, `4 D! G; k8 i6 ~
}" }& D/ H  w$ T& n% k
: x! D6 u3 Y' Z3 N

/ d2 X. A6 i' s6 v: Z; r2 I: d4 h, ?/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
0 s6 X; b4 `% X  p( @% j( u. i) I6 v. n* Y
1 P5 C, `% n  Y" {# ]$ `

* B8 l; V; T6 [& \* d0 h6 z* G( q! j
- y( B5 l- F9 \: b4 i3 |
( H* d5 g0 s9 B8 @0 \

' O0 G# g" L# I  c: i& x/ P3 {: }
% N1 B0 q: M8 Z- w7 D, D6 N! l$ f' K+ B

) q; `5 c8 [8 ]  R
赞 收藏 1 评论2 发布时间:2018-4-17 10:26

举报

2个回答
zero99 回答时间:2018-4-17 14:53:16
支持下
蓝夜 回答时间:2018-7-21 10:48:13
写的很好,突出了重点
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版