一、stm32标准版的移植操作:
具体的移植操作:
第一步:获取源码:FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions;点击下载-->
在点击下载按钮:
下载完后解压到自己想要指定的文件夹里,文件名最好用英文来命名。
第二步:随便找一个基础工程出来,我已江科大的OLED显示屏的代码为例。我们需要打开OLED代码文件,我们需要在此建立一个freertos文件夹,又在freertos文件夹下建立三个文件(inc,port,src)。
inc,port,src:
第三步:我们需要将下载的源码进行移植:在自己新创建的FreeRTOS文件夹下新创建的port文件夹,然后进入FreeRTOS源码FreeRTOSv9.0.0\FreeRTOS\Source\portable目录下将本目录下的MemMang文件夹与RVDS文件夹复制到工程模板的port文件夹下。
第四步:将源码里的include文件夹下的所有文件进行复制到建立的OLED工程文件里的freertos/inc里
第五步:将源码里的这些文件复制到OLED工程文件里的freertos/src文件里。
第六步:打开源码里的freertos下的Demo文件,找到下面的文件,点开他,找到FreeRTOSConfig.h。复制到OLED工程文件的freertos文件下。
第七步:打开代码程序:
点击魔术棒按钮,点击C/C++
添加头文件路径:
第八步:把你文件夹里的三个src,inc,port组添加进来,并且天就文件files。
src:
inc:其中FreeRTOSConfig.h也要添加到inc的组里。
port:
第九步:修改FreeRTOSConfig.h:
添加三个宏定义:只要在#endif前添加就行。
第十步:将stm32f10x_it.c里的函数注释三个:void SVC_Handler(void) void PendSV_Handler(void)
void SysTick_Handler(void)。 stm32f10x_it.h的也可以注释掉这三个
到此为止也就完成了,编译一下看看会不会报错。
第十一步:测试功能:查看led会不会以500ms的时间进行闪烁。
#include "stm32f10x.h" // Device header
#include "freertos.h"
#include "task.h"
static TaskHandle_t myTaskHandler = NULL;
void myTask(void *arg )
{
while(1)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
vTaskDelay(500);
GPIO_SetBits(GPIOC,GPIO_Pin_13);
vTaskDelay(500);
}
}
int main(void)
{
GPIO_InitTypeDef GPIO_Initstruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Initstruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Initstruct.GPIO_Pin=GPIO_Pin_13;
GPIO_Initstruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_Initstruct);
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
xTaskCreate(myTask,"myTask",512,NULL,2,&myTaskHandler);
vTaskStartScheduler();
while (1)
{
}
}
二、任务的创建和删除(动态方式):
2.1、函数的讲解:
(1)首先讲解一下xTaskCreate()这个函数:
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
{
#动态创建任务的函数:第一个是指向任务函数的指针 (动态任务函数名),
第二个是动态任务的字符串(可以随便起),
第三个是任务堆栈大小,注意字为单位,
第四个是传递给任务函数的参数(一般给NULL)
第五个是任务优先级,范围:0 ~ configMAX_PRIORITIES - 1
第六个是任务句柄,就是任务的任务控制块 。
(2)首先讲解一下vTaskDelete()这个函数:
void vTaskDelete( TaskHandle_t xTaskToDelete )这个参数是动态任务的句柄,你需要删除哪个任务就输入哪个任务的句柄。
(3)vTaskStartScheduler();任务调度器:一般是创建一个任务xTaskCreate()需要开启调度器,才可以使用任务。
(4)TaskHandle_t:创建句柄:static TaskHandle_t myTaskHandler0 ; myTaskHandler0:任务句柄名字,不同任务不同任务句柄(自己可以起。)
(5)vTaskDelay(10):freeRTOS自带的延时函数,参数为毫秒为单位的,你用这个延时函数就可以了,把所有用原来的delay函数都替换掉,用delay会出现一些你编译没有错,但是现象就是不对。
2.2、代码分析:
//#############创建task_demo.c和task_demo.h################
//##########task_demo.c
#include "stm32f10x.h" // Device header
#include "freertos.h"
#include "task.h"
/* 创建任务句柄和按键的变量*/
uint8_t KNum=0;
static TaskHandle_t myTaskHandler0 ;
static TaskHandle_t myTaskHandler1 ;
static TaskHandle_t myTaskHandler2 ;
static TaskHandle_t myTaskHandler3 ;
/* 任务函数的声明*/
void task_begin(void *arg);
void myTask1(void *arg );
void myTask2(void *arg );
void myTask3(void *arg );
/*第一个任务task_begin的创建(其中这个任务包含着另外三个任务创建)*/
void freertos_demo(void)
{
xTaskCreate(task_begin,"task_begin",128,NULL,1,&myTaskHandler0);
vTaskStartScheduler();
}
/*第一个任务task_begin的函数:需要开启进入任务临界区,和退出临界区。
因为程序是一行一行的来的,所以myTask1创建的时候,task1的优先级比task_begin的优先级高,然后再task2优先级高于myTask1,又到myTask2先,3也是如此,执行完后就一直是task3为优先了,所以就不符合从一开始到执行之后的优先级任务体系,应该加上这两句。*/
void task_begin(void *arg)
{
taskENTER_CRITICAL();//进入临界区
xTaskCreate(myTask1,"myTask1",128,NULL,2,&myTaskHandler1);
xTaskCreate(myTask2,"myTask2",128,NULL,3,&myTaskHandler2);
xTaskCreate(myTask3,"myTask3",128,NULL,4,&myTaskHandler3);
vTaskDelete(NULL);
taskEXIT_CRITICAL();//退出临界区
}
/*第二个任务myTask1的函数: LED1灯的500ms亮灭*/
void myTask1(void *arg )
{
while(1)
{
printf("task1正在运行\n");
LED1_Turn();
vTaskDelay(500);
}
}
/*第三个任务myTask2的函数: LED2灯的500ms亮灭*/
void myTask2(void *arg )
{
while(1)
{
printf("task2正在运行\n");
LED2_Turn();
vTaskDelay(500);
}
}
/*第四个任务myTask3的函数:按键按下就删除任务*/
void myTask3(void *arg )
{
while(1)
{
printf("task3正在运行\n");
KNum=Key_GetNum();
if(KNum==1)
{
if(myTaskHandler1!=NULL)
{
printf("删除task1任务\n");
vTaskDelete(myTaskHandler1);
myTaskHandler1=NULL;
}
}
vTaskDelay(10);
}
}
//############task_demo.h##########
#ifndef __TASK_DEMO_H
#define __TASK_DEMO_H
void freertos_demo(void);
void task_begin(void *arg);
void myTask1(void *arg );
void myTask2(void *arg );
void myTask3(void *arg );
#endif
//###########main.c##############
#include "stm32f10x.h" // Device header
#include "freertos.h"
#include "task.h"
#include "LED.h"//都是用江科大的就行
#include "Key.h"//都是用江科大的就行
#include "Serial.h"//都是用江科大的就行(不要用Delay.h喔)
#include "task_demo.h"
int main(void)
{
LED_Init();
Key_Init();
Serial_Init();
freertos_demo();
}
对了,如果你需要打印输出日志用printf(),并且要用到串口通信来打印到电脑的串口助手上,复制江科大的串口发送的代码就可以了。
记得打开魔术棒的下面的Use MicroLIB