1.准备工作
4 B/ A0 L u+ Q; K; y6 T3 u7 z. |. @( }
2.新建文件夹及复制必要文件# H8 S8 Q! k& N6 A
2.1、新建7个文件夹
& e' y5 d: \) W% ^5 i7 q* |6 i* I5 [; y/ O+ {& n/ z( ~
.\freeRTOS# N4 Q- E3 a# d# R$ X. W8 V! a
1 [5 f) N6 j( X0 v3 S/ v
.\freeRTOS\include
6 v6 O& x) { E6 j$ p# X' E* b5 T) K; T- L3 c7 W& Q p
.\freeRTOS\port- t+ ^. M# f1 e6 I
5 e9 A$ `: z; f. T( \4 U
.\freeRTOS\src
+ |% X9 U: r) U+ M; e- L' M4 c7 |! B: e! V( u6 n8 [/ }
.\Library
+ K! R$ s1 z6 J2 I/ E) b7 P7 }3 Q d% T+ ?) g8 x- P
.\Project
s% o8 U* J$ Y9 x3 c: J9 p3 \) h$ ~7 ?
.\User9 n- n# I" H/ Y. B+ i0 f' e- I7 h$ Q
9 j" E& Y0 D E
2.2、把源码FreeRTOSv9.0.0\FreeRTOS\Source\include中的文件全部复制到新建的include文件夹 `. r8 k+ }$ @# K
2 p! H: r% }+ F7 y* f
2.3、把源码FreeRTOSv9.0.0\FreeRTOS\Source\portable中MemMang文件夹复制到新建的port文件夹中# B+ `: o6 F' A4 ?: g' a% p( B/ U
9 u* [( q! v+ z# ^) ~7 p2.4、把源码portable\RVDS中的ARM_CM3复制到port文件夹中
1 N' D; r! d$ x# m" ?& `2 m4 \" A6 |3 d" _5 K
2.5、把源码FreeRTOSv9.0.0\FreeRTOS\Source文件夹中的*.c文件全部复制到新建的src文件夹中+ Z8 h7 U8 Y5 X+ \) r" r
' q- \# j9 }% a* t4 O
2.6、把CMSIS和FWlib文件夹复制到新建Library文件夹中$ A* ~6 T Z/ |, }% U, L
3 t3 S. i6 p( P- b8 `0 ^
2.7、User文件中新建一个main.c,然后复制标准库中的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h文件到User文件夹中+ O0 d/ }" T W8 b, \( M
" n+ i( S. g' l3 ]4 L. ?1 Y5 s2.8、把FreeRTOSv9.0.0\FreeRTOS\Demo\CORTEX_STM32F103_Keil中FreeRTOSConfig.h复制到include文件夹中
' R! F T% E+ e( d! t: Q5 z
- E8 [3 [/ L! ~# j8 i/ g3.添加c文件
7 H1 }3 \& E4 S, R3 g9 w5 z; S/ {3.1、打开Keil uVision5新建工程,Project-NEW uVision project,选中Project文件夹,输入工程名称,保存。
: H5 s5 t: z1 Z9 ~) f" s5 P
4 ?) G4 C/ f8 f& {3.2、芯片选择STM32F103C8,确定,再确定。, v- Y9 N4 x% D* R2 c* P
& a$ G& A1 n4 m3 ?6 i' a7 J3.3、打开管理工程项目,分别新建freeRTOS/port、freeRTOS/src、CMSIS、FWLIB、USER% W3 S7 d: d/ }# j, c" s; T
3 r: }% v2 k. R8 a, ^2 z8 Y. o
, |+ I1 k4 v0 H' V
5 U. X7 Q- {% s6 Z/ m+ H3.4、freeRTOS/port中分别添加ARM_CM3\port.c和MemMang\heap_4.c两个文件
; I0 N% M2 {! ?& b
1 d" C3 V/ \. V# z3 C4 m
& L0 v3 {" n, i# J* S$ U
* H7 |0 C" \. V6 h
3.5、freeRTOS/src添加freeRTOS\src文件夹下的所有c文件
7 Q5 [0 y$ a6 ^- i3 x5 F1 o5 {
7 `2 M' w2 G" Z4 ?! E
+ k: J* V$ G* d$ V7 j7 Z/ x% Q
) {+ P; {5 U$ j3.6、CMSIS添加Library\CMSIS\startup\startup_stm32f10x_md.s、Library\CMSIS\core_cm3.c、Library\CMSIS\system_stm32f10x.c三个文件% D# J2 V, `; i& G( ]3 v9 J3 l
3 j9 t% C- v: g: Y* p* s
; q: r6 q! Y) k0 m; K$ d% e+ G, } C3 ^/ j: G/ h
3.7、FWLIB添加Library\FWlib\src文件夹下所有的*.c文件
4 A, q( W9 }4 P% Y9 I
; y3 M$ q* t4 o6 w
3 t4 ]: A2 F% y8 u0 W- o
: `5 X' I5 L$ E a+ f3 p5 P3.8、USER添加main.c、stm32f10x_it.c,如果这里有其他自己编写的代码,也可以放再这里。比如LED,KEY,USART相关代码4 F6 V$ I& E* W8 l
1 W( W7 ]6 |2 K8 t8 a% U' u
# }$ g& c2 Z! o9 I4 e* n4 [7 X+ ~
0 K/ s' K" G7 v4.配置运行环境' ?: T6 _( G: \* w
4.1、在C/C++选项卡,Define输入:STM32F10X_MD,USE_STDPERIPH_DRIVER
" u }( _; Y0 a9 \5 ]; J* U, h1 J; _7 w
4.2、在C/C++中,包含include路径:freeRTOS\include、freeRTOS\port\ARM_CM3、Library\CMSIS、Library\FWlib\inc、User4 F( F8 [" _2 }& q
6 b6 N3 |2 N( Z! Y. ^4 k
如果还有自己编写的其他头文件,也一起包含在里面。如LED,KEY,USART
9 K( w \ q1 ^* A+ ]3 r
1 J0 ^, ?, ]. ~& F7 i3 ^, E6 C
0 Z; n4 H) t3 j) O
( K6 k7 x9 ]; I; `& q$ m8 u4.3、使用MicroLIB库,# F3 ?& ^0 i7 l8 Y; ^9 ^
( a+ D5 y8 ]4 b. t3 R
2 q9 v$ H( U# _' Z; _; `) V# P5 }2 d, G! \2 U4 i8 |
, p+ S! m8 q% A
0 D3 G& _/ x3 [! s c
5.代码修改
5 ` h- }' c3 F% O b1 E5.1、在freeRTOS中,已经为用户实现了SVC_Handle()和PendSV_Handler()函数,需要注释掉,修改stm32f10x_it.c文件
! h. v+ v' X5 ?! |# B4 T. { Q6 ^7 r* O
- *& X/ ]! n7 ^& r3 k$ W6 ]# }" d
- //void SVC_Handler(void)2 \3 W! c n5 s2 T/ {: G# Q+ l
- //{
4 ^% u" n2 w2 g% v - //}
, U+ F/ o% Q9 a Z- K- G p - *
: F) h! [4 e8 R+ c) h$ c* a& ` - //void PendSV_Handler(void)' `0 {; _, E% y* h' D) g
- //{ U$ ?/ L6 J8 R' ~
- //}
# F0 U+ W$ x6 i2 q; F7 q; U9 M - *8 l/ E5 O% P5 M; A& C; y
- /*在c文件中添加如下代码*/ e& N1 w1 i: b+ ~. {8 j2 e
- /*freeRTOS中的systick中断函数*/
# k; j L; K8 i2 j2 s! y - extern void xPortSysTickHandler(void);8 h7 X6 A5 G2 D$ z5 T: w
- void SysTick_Handler(void)) w* J, k7 _- L+ Z
- {% A" j! I0 u5 N8 R B
- #if(INCLUDE_xTaskGetSchedulerState==1)
3 r8 x w0 \7 [) o# S) [! M6 |0 r - if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED){7 Y7 ?) j4 j: R
- #endif
$ Y+ `5 V, z- V7 }- X8 O3 O - xPortSysTickHandler();2 N) z% s3 _7 d8 Q; h W! Q
- #if (INCLUDE_xTaskGetSchedulerState==1) & Z* z' u* F, I+ f
- }
+ O# x2 S1 @7 G+ e" I) ~5 c) r - #endif1 R5 D- z$ C# |/ K8 e
- }. I% h B$ y3 E; e: ^0 h
复制代码
8 \% f) {# F d/ P, @# G1 @/ ~5.2、修改一下"FreeRTOSConfig.h",这里我使用软件定时器,需要打开对应宏定义,还要配置FreeRTOS与中断服务函数有关定义
: A# S5 l0 h7 i6 ^/ D6 \' z1 S: y. Y/ K% N" B
- /*FreeRTOS与中断服务函数的配置选项*/3 y1 v7 S, `' b: [
- #define xPortPendSVHandler PendSV_Handler
m% Q* M( c& u# u4 j; @1 H - #define vPortSVCHandler SVC_Handler
% g m# V* n t3 e: b$ A' R. c - , e/ g' |5 W4 B" n& t1 s
- /*启用软件定时器相关宏定义*/* u: d4 W! y3 a' Y( ]/ s5 h
- #define configUSE_TIMERS 1 D2 C1 z4 Z* o
- #define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
$ k) j4 f9 S$ |( Z% Z& F& X - #define configTIMER_QUEUE_LENGTH 10
) y$ c2 E1 x( k5 t - #define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)
复制代码 . W L2 C) @- m5 z9 R. \
5.3、最后就是添加外设初始化代码,主函数里面添加任务代码。main.c代码如下
, N; f$ b( x7 e% G
4 k. i ^8 `' S/ T O9 E- #include "FreeRTOS.h"$ g( j7 x3 [7 V4 S6 p
- #include "task.h"$ V3 r7 O; H3 G9 `0 y0 a, l0 v1 m
- #include "bsp_led.h"
) v' N$ x0 z& b$ Z1 d" ]: w3 i4 x% s - #include "bsp_usart.h") t0 @" E8 g& z! v
- #include "bsp_key.h") l8 V* ?- M0 V% k
- #include "queue.h"5 a7 o2 D, i6 Y& B+ g
- #include "semphr.h"( _ _: u( D5 q5 O7 d R; J% d+ a
- #include "event_groups.h"4 Y0 _' c1 {; W: w
- #include "timers.h"
- Y: C, u6 Q0 `% ^% d
+ Q& h5 k$ b1 |9 d t
4 q) w: f3 R- E& `" b- /*Function definition*/
9 W {, t! o \4 d' W5 H3 [ - static void BSP_Init(void);/ v: a* Y5 R) d" n
- 9 O0 a9 R- s( H; x9 J) Z2 {
- static void Send_Task(void* pvParameters);- ]' ~6 H! W" _
- static void Callback_LEDTOGGLE(void* pvParameters);6 c7 h3 ^5 B% {6 H& U1 p5 `
- + j$ m* b1 z+ {
- static void AppTaskCreate(void);
9 t B& t+ [: u - 5 E7 N" D* L( b+ m4 q9 G
3 s; ]& f/ ]/ {; x- /*Task Handle*/
) K6 l/ a: C8 E8 p4 Q& M, \ - static TaskHandle_t AppTaskCreate_Handle=NULL;
; y* I2 _4 ]3 i! t% c - static TaskHandle_t Send_Task_Handle=NULL; //PRO:36 |. C5 p) T! z) u7 Y
- / i3 B1 i) f1 l/ G& V& g8 _
6 L' u; c+ d/ \# z- /*Timer handle*/4 K. f. c, d. b4 Z( x
- static TimerHandle_t Timer1=NULL;+ u% s# R- d- h
6 V' n o2 S0 D2 S3 f- static void Callback_LEDTOGGLE(void* pvParameters)! q: g7 ^+ z- S, C% |8 _& ?
- {& b+ U6 ^, s+ f4 h, }
- LED1_TOGGLE;$ {8 h9 g3 E* ~& R
- printf("TickValue=%d\n",(TickType_t)xTaskGetTickCount());6 o+ K0 A# A" C7 M) F6 B
- }
' C: G; f$ C" \& x8 V3 ?; P' y4 y
6 j1 t& W8 \' q% [4 x; n: k- + p1 D, e! B% d0 U: e( t
- int main(void)
6 y& P: [3 W( h4 X" ?. [- Z - {
( y0 I: r' t F& Q8 A# h3 R# K - BaseType_t xReturn =pdPASS;
- }& U! Y# s5 @9 d+ E' V5 J
: h" ]" n; q! ]1 ?2 a5 E- BSP_Init();
; H' y W0 Z0 t& A/ C - . o9 {9 M2 ] ~, Z: a o# [
- printf("FreeRTOS creates tasks dynamically!\r\n");
) ]0 g- l: _; b - 8 ?; A- U1 w9 L; l5 }8 v
- xReturn=xTaskCreate((TaskFunction_t)AppTaskCreate,\2 d3 f4 B& k6 G4 `1 V
- (const char *)"APPTASKCREATE",\
: y j8 F6 c# X5 J; ^" z" `# u3 H( ^ - (uint16_t)512,(void*)NULL,(UBaseType_t)1,\6 y. ?- K5 N1 T! J/ A
- (TaskHandle_t*)&AppTaskCreate_Handle);' m/ K" k# r g+ n2 C
- if(pdPASS==xReturn)5 o$ ~5 v0 z- H7 E7 d0 o5 ]
- vTaskStartScheduler();$ [8 J6 V2 A+ X6 Q" a
- else3 K; D/ i5 W" n8 b
- return -1;
7 P4 y5 I4 g6 k4 a - while(1);
8 B- e, ~8 `* S" G9 o9 K6 ]* n - }
* @5 x3 h4 q) ~5 k/ Z - ! b. [, k9 m; \9 i* u
- ! h, k) o9 k& L% H& @
- /*Hardware initialization*/
7 u. c. t6 n- g - static void BSP_Init(void)$ X2 _3 g9 a* M) c" F
- {
( Z7 E" {' F6 D2 R! T, x - /*Use this priority grouping uniformly, never group again
6 U$ h" v0 R; x9 m. M3 v: g) C- t - * 4 bits for pre-emption priority3 w6 L$ w9 @. W7 M' p7 k
- */! k- G3 U$ M0 L4 M* _0 W$ D
+ ^: }- E1 }9 E9 ?7 b7 L& ^: P- /*led initialization*/
, `* B3 ]4 G' z9 x& @1 u+ K - LED_GPIO_Config();
( { x' _, W' Q - 2 `/ E3 X. `/ W
- /*Serial port initialization*/7 u! G1 r: N2 `+ N1 H
- USART_Config();) U% F8 s/ h) }9 m8 g
, c# D8 m% ]/ {3 S5 y- /*Key initialization*/4 j2 u1 C6 v( e' |, n: j" \
- Key_GPIO_Config();
h, a1 |6 M5 V - }* T% C3 H7 V+ w, ]) F7 x1 a+ v: C5 Q
7 @; p @, [2 @$ f' X5 z1 h- /***********- g( D; a$ v# q# `0 z8 l
- *@Function name:SEND_Task
0 t% v$ G; ]$ d/ ` - *@description:SEND_Task body, ?" k, p7 n9 f9 |8 L
- *@Parameter:None7 K5 s: |* P4 M
- *@return:None; P- B, z' r6 n2 o6 V( Y- p
- *************/
; w4 D( L1 I0 U7 g5 R7 z+ T" C1 M - static void Send_Task(void* pvParameters)
$ y2 p8 z1 G0 @, X - {- e7 v% `1 D% W* ]$ V. `
3 H+ J& q. l5 d* m- w- while(1)% L. U5 |: @) z3 j
- {
! i! e) D1 p# `' `- p' r& ]7 t - vTaskDelay(100); //只是为了演示任务切换2 D1 H& c! y4 p
- }+ e/ }" V# ?2 b$ a
- }0 Y! t6 R' x8 \0 F' V6 i. e) A' b
/ i* A3 S1 o& C: N+ O- static void AppTaskCreate(void)* T$ y) z1 n- a. s% s+ A( V
- {
4 Y' L" d+ j5 y# J4 r) w1 q0 Q - BaseType_t xReturn=pdPASS;- d/ w. `+ _; Z" x+ H- l1 T: K
- taskENTER_CRITICAL();
! h! d/ B, }6 V! U) b& J
$ Z7 l' K( k5 l2 C: T0 v- /* Create Timer1 Handle*/
2 U$ G' I: r1 U. }$ E; H9 F( d, i - Timer1=xTimerCreate((const char*)"1sec-toggle",(TickType_t)pdMS_TO_TICKS(1000),\
/ Q; U6 M7 }, p, m6 ]/ p7 w" o' T - (UBaseType_t)pdTRUE,(void*)1,(TimerCallbackFunction_t)Callback_LEDTOGGLE);5 }* S2 @$ R% ^
- if(NULL!=Timer1)
- a/ n( z. g) P8 ]/ d1 O - printf("Timer1 created successfully.\r\n");
0 C- Q( n. S$ { K - xTimerStart(Timer1,0);; s2 e5 v/ m. `. w! L. B6 ?4 F
- P7 [; O$ [3 ~- /*SEND task*/7 ]. _0 y6 \/ n0 A, \
- xReturn=xTaskCreate((TaskFunction_t)Send_Task,\$ S: A d+ b0 g6 H4 x
- (const char*)"SEND_TASK",\6 Q U/ j1 a* S% O
- (uint16_t)512,(void*)NULL,(UBaseType_t)3,\
# n' Z) o$ _+ q" b1 D1 l' I - (TaskHandle_t)&Send_Task_Handle);: \, e, H( b% X/ u
- if(pdPASS==xReturn)
t# B3 _) b5 |& g0 L - printf("\r\nCreate Send_Task success!\r\n");4 z3 H- ~& f) _; i0 }" F/ W. L
- - ?! F( X6 I& j/ h3 D: H6 b
- vTaskDelete(AppTaskCreate_Handle);
" R, \2 ]1 l, |" R - taskEXIT_CRITICAL();
" s: N0 [0 m- D' _# z+ ~3 T - }
# t! d$ Z4 ?/ U6 Z8 @+ b - " O0 f. N6 m5 n
- /*********************************************END OF FILE**********************/
复制代码 , b. L, F( m2 p: q" e+ ?
0 M& T& I+ D; |; S9 a" `
————————————————/ E% c6 f9 o' s( H7 q* X, P+ l
版权声明:SCCELE
2 Y% V% e3 K# @/ Z" }% d9 c. |
; {/ c0 T& b, y7 { |