在 FreeRTOS 中,每个执行线程都被称为”任务”。在嵌入式社区中,对此并没有一个公允的术语,但我更喜欢用”任务”而不是”线程”,因为从以前的经验来看,线程具有更多的特定含义。
创建任务的API函数(可以在tasks.c文件中找到)
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
typedef void (*TaskFunction_t)( void * );
typedef long BaseType_t
typedef unsigned long UBaseType_t
typedef void * TaskHandle_t;
参数:
pxTaskCode:自己创建的任务函数的函数名,用于指向需要运行的任务
pcName:任务的名字,字符串型,名称可以随意起,一般与函数名相同
usStackDepth:任务堆栈大小(实际上申请到的是这里的4倍,单位为字, 4 个字节),设的太小任务 可能无法运行!
pvParameters:任务函数的参数,不需要传参设为NULL即可
uxPriority:任务优先级,0~(configMAX_PRIORITIES-1),数值越大优先级越高,0 代表最低优先级
pxCreatedTask:任务句柄,实际是一个指针,也是任务的任务堆栈
返回值:
pdPASS:数值1,任务创建成功,且添加到就绪列表
错误代码:负数,任务创建识别
删除任务的API函数(可以在tasks.c文件中找到)
vTaskDelete( TaskHandle_t xTaskToDelete )
xTaskToDelete:要删除的任务的任务句柄
临界区
临界区就是一段在执行的时候不能被中断的代码段。在多任务操作系统里面,对全局变量的操作不能被打断,不能执行到一半就被其他任务再次操作。一般被打断,原因就是系统调度或外部中断。对临界区的保护控制,归根到底就是对系统中断的使能控制。在使用临界区时,关闭中断响应,对部分优先级的中断进行屏蔽,因此临界区不允许运行时间过长。为了对临界区进行控制,就需要使用信号量通信,实现同步或互斥操作。
FreeRTOS数据类型(可以在portmacro.h文件找到)
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
推荐应用时使用下面这样定义数据类型
typedef int int32_t;
typedef short int16_t;
typedef char int8_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
前缀初识
FreeRTOS 中,定义变量的时候往往会把变量的类型当作前缀,可以一眼知其类型。
char 型变量的前缀是 c
short 型变量的前缀是 s
long 型变量的前缀是 l
复杂的结构体,句柄等定义的变量名的前缀是 x
变量是无符号型的再加前缀 u,是指针变量则加前缀 p
函数名包含了函数返回值的类型、函数所在的文件名和函数的功能,如果是私有的函数则会加一个 prv(private)的前缀。
宏内容是由大写字母表示,前缀是小写字母,表示该宏在哪个头文件定义
任务创建
#include "stm32f10x.h"
#include
#include "FreeRTOS.h"
#include "task.h"
#define START_TASK_PRIO 1 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
TaskHandle_t StartTask_Handler; //任务句柄
void start_task(void *pvParameters);//任务函数
#define LED0_TASK_PRIO 2 //任务优先级
#define LED0_STK_SIZE 50 //任务堆栈大小
TaskHandle_t LED0Task_Handler; //任务句柄
void led0_task(void *p_arg); //任务函数
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //开启时钟
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0; //选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化GPIO
GPIO_SetBits(GPIOC,GPIO_Pin_0); //将LED端口拉高,熄灭LED
}
int main( void )
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组 4
LED_Init(); //初始化 LED
//创建开始任务
xTaskCreate(
(TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler //任务句柄
);
vTaskStartScheduler(); //开启调度
}
//开始任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建 LED0 任务
xTaskCreate(
(TaskFunction_t )led0_task,
(const char* )"led0_task",
(uint16_t )LED0_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED0_TASK_PRIO,
(TaskHandle_t* )&LED0Task_Handler
);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED0 任务函数
void led0_task(void *pvParameters)
{
while(1)
{
if(GPIO_ReadInputDataBit( GPIOC, GPIO_Pin_0))
{
GPIO_ResetBits( GPIOC, GPIO_Pin_0);
}
else
{
GPIO_SetBits( GPIOC, GPIO_Pin_0);
}
vTaskDelay(400);
}
}
--END--
-
嵌入式
+关注
关注
5082文章
19104浏览量
304811 -
FreeRTOS
+关注
关注
12文章
484浏览量
62140 -
线程
+关注
关注
0文章
504浏览量
19675
发布评论请先 登录
相关推荐
评论