2、FreeRTOS任务相关API函数
1.任务相关的API函数
函数存在于task.c中,主要的函数有:
- xTaskCreate():使用动态的方法创建一个任务;
- xTaskCreatStatic():使用静态的方法创建一个任务(用的非常少);
- xTaskCreateRestricted():创建一个使用MPU进行限制的任务;
- vTaskDelete():删除一个任务;
- vTaskSuspend():挂起一个任务;
- vTaskResume():恢复一个任务的运行;
- vTaskResumeFromISR():中断服务函数中恢复一个任务的运行;
- portENABLE_INTERRUPTS():打开FreeRTOS中断;
- portDISABLE_INTERRUPTS():关闭freeRTOS中断;
2.动态创建任务
- xTaskCreate()函数原型:
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
uint16_t usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pvCreatedTask
); - 动态创建任务:使用前先判断 #if( configSUPPORT_STATIC_ALLOCATION == 1 ) 是否成立,如果不成立需要在FreeRTOSConfig.h 文件中添加;
#include "FreeRTOS.h"
#include "task.h" //start_task 任务
void start_task(void *pvParameters); // 任务函数
#define start_task_zise 50 // 任务堆栈的大小
#define start_task_prio 1 // 任务优先级
TaskHandle_t start_task_handler; // 任务句柄 //led1_task 任务
void led1_task(void *pvParameters); // 任务函数
#define led1_task_zise 50 // 任务堆栈的大小
#define led1_task_prio 2 // 任务优先级
TaskHandle_t led1_task_handler; // 任务句柄
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init();
delay_init();
LED_Init(); // 创建一个任务 xTaskCreate(任务函数, 任务名, 任务堆栈的大小, 传递给任务函数的参数, 任务优先级, 任务句柄);
xTaskCreate( start_task, "start_stask", start_task_zise, NULL, start_task_prio, &start_task_handler); vTaskStartScheduler(); // 开启任务调度
return ;
} void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); // 创建临界区
// 创建led1任务
xTaskCreate(led1_task, "led1_task", start_task_zise, NULL, led1_task_prio, &led1_task_handler); vTaskDelete(start_task_handler); //删除开始任务
taskEXIT_CRITICAL(); // 退出临界区
}
//LED1任务函数
void led1_task( void * pvParameters )
{
for( ;; )
{
LED0 = ~LED0;
vTaskDelay();
}
}
3.静态创建任务
- xTaskCreatStatic()函数原型:
TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint32_t ulStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
StackType_t * const puxStackBuffer,
StaticTask_t * const pxTaskBuffer ) - 静态创建任务:使用前先判断 #if( configSUPPORT_STATIC_ALLOCATION== 1 ) 是否成立,如果不成立需要在FreeRTOSConfig.h 文件中添加;
- 在FreeRTOSConfig.h 文件中添加中添加宏后,编译报错:
.\Objects\freeRTOS_sCreate_task.axf: Error: L6218E: Undefined symbol vApplicationGetIdleTaskMemory(referred from tasks.o).
.\Objects\freeRTOS_sCreate_task.axf: Error: L6218E: Undefined symbol vApplicationGetTimerTaskMemory (referred from timers.o). - 由于把静态创建的宏给打开了,所以这两个数需要我们自己去实现
// 空闲任务
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
static StaticTask_t IdleTaskTCB;
// 定时器任务
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
static StaticTask_t TimerTaskTCB; // 空闲任务所需内存
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &IdleTaskTCB;
*ppxIdleTaskStackBuffer = IdleTaskStack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
// 定时器任务所需内存
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize )
{
*ppxTimerTaskTCBBuffer = &TimerTaskTCB;
*ppxTimerTaskStackBuffer = TimerTaskStack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
} - 静态创建任务
//start_task 任务
void start_task(void *pvParameters); // 任务函数
#define start_task_zise 50 // 任务堆栈的大小
#define start_task_prio 1 // 任务优先级
StackType_t start_task_stack[start_task_zise]; // 任务控制块大小
StaticTask_t start_task_TCB; // 任务堆栈大小
TaskHandle_t start_task_handler; // 任务句柄 //led1_task 任务
void led1_task(void *pvParameters); // 任务函数
#define led1_task_zise 50 // 任务堆栈的大小
#define led1_task_prio 2 // 任务优先级
StackType_t led1_task_stack[start_task_zise]; // 任务控制块大小
StaticTask_t led1_task_TCB; // 任务堆栈大小
TaskHandle_t led1_task_handler; // 任务句柄 //led2_task 任务
void led2_task(void *pvParameters); // 任务函数
#define led2_task_zise 50 // 任务堆栈的大小
#define led2_task_prio 3 // 任务优先级
StackType_t led2_task_stack[start_task_zise]; // 任务控制块大小
StaticTask_t led2_task_TCB; // 任务堆栈大小
TaskHandle_t led2_task_handler; // 任务句柄 int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init();
delay_init();
LED_Init(); // 创建一个开始任务
start_task_handler = xTaskCreateStatic( (TaskFunction_t )start_task,
(char *)"start_task",
(uint32_t )start_task_zise,
(void * )NULL,
(UBaseType_t )start_task_prio,
(StackType_t * )start_task_stack, // 任务控制块大小
(StaticTask_t * )&start_task_TCB ); // 任务堆栈大小 vTaskStartScheduler(); // 开启任务调度
return ;
} void start_task( void * pvParameters )
{
led1_task_handler = xTaskCreateStatic( (TaskFunction_t )led1_task,
(char *)"led1_task",
(uint32_t )led1_task_zise,
(void * )NULL,
(UBaseType_t )led1_task_prio,
(StackType_t * )led1_task_stack, // 任务控制块大小
(StaticTask_t * )&led1_task_TCB ); // 任务堆栈大小 led2_task_handler = xTaskCreateStatic( (TaskFunction_t )led2_task,
(char *)"led2_task",
(uint32_t )led2_task_zise,
(void * )NULL,
(UBaseType_t )led2_task_prio,
(StackType_t * )led2_task_stack, // 任务控制块大小
(StaticTask_t * )&led2_task_TCB ); // 任务堆栈大小
vTaskDelete(start_task_handler);
}
void led1_task( void * pvParameters )
{
for( ;; )
{
LED0 = ~LED0;
vTaskDelay();
}
}
void led2_task( void * pvParameters )
{
for( ;; )
{
LED1 = ~LED1;
vTaskDelay();
}
}
4.删除任务
- void vTaskDelete( TaskHandle_t xTaskToDelete ) PRIVILEGED_FUNCTION;
5.任务挂起
- void vTaskSuspend( TaskHandle_t xTaskToSuspend ) PRIVILEGED_FUNCTION;
6.任务恢复
- void vTaskResume( TaskHandle_t xTaskToResume ) PRIVILEGED_FUNCTION;
- 挂起、恢复代码如下:
//key_task 任务
void key_task(void *pvParameters); // 任务函数
#define key_task_zise 50 // 任务堆栈的大小
#define key_task_prio 4 // 任务优先级
TaskHandle_t key_task_handler; // 任务句柄 void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); // 创建临界区 // 创建按键检查任务
xTaskCreate((TaskFunction_t )key_task,
(const char * )"key_task",
(uint16_t )key_task_zise,
(void * )NULL,
(UBaseType_t )key_task_prio,
(TaskHandle_t * )&key_task_handler);
......
vTaskDelete(start_task_handler); //删除开始任务
taskEXIT_CRITICAL(); // 退出临界区
} //key任务函数
void key_task( void * pvParameters )
{
char key;
for( ;; )
{
key = KEY_Scan();
switch(key)
{
case KEY0_PRES:
vTaskSuspend(led1_task_handler);
printf("led1_task Suspended.\n");
break;
case KEY1_PRES:
vTaskResume(led1_task_handler);
printf("led1_task Resumed.\n");
break;
case KEY2_PRES:
vTaskSuspend(led2_task_handler);
printf("led2_task Suspended.\n");
break;
case WKUP_PRES:
vTaskResume(led2_task_handler);
printf("led2_task Resumed.\n");
break;
}
vTaskDelay(); //延时10ms
}
}
7.FreeRTOS开关中断
- freeRTOS管理的中断优先级为 5~15,这是在freeRTOSConfig.h中设置的。
#ifdef __NVIC_PRIO_BITS
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4
#endif #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15 //中断最低优先级
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5 //系统可管理的最高中断优先级
#define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) - 设置好宏后,低于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断可以安全的调用FreeRTOS的API函数(xxFromISR()函数);
- 高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断不能被FreeRTOS禁止,中断服务函数也不能调用FreeRTOS的API函数。

- 由于高于configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY的优先级不会被FreeRTOS内核屏蔽,因此那些对实时性要求严格的任务可以使用这些优先级(0~4),比如四轴飞行器中的避障检测;
//start_task 任务
void start_task(void *pvParameters); // 任务函数
#define start_task_zise 50 // 任务堆栈的大小
#define start_task_prio 1 // 任务优先级
TaskHandle_t start_task_handler; // 任务句柄 //interrupt_task 任务
void interrupt_task(void *pvParameters); // 任务函数
#define interrupt_task_zise 50 // 任务堆栈的大小
#define interrupt_task_prio 2 // 任务优先级
TaskHandle_t interrupt_task_handler; // 任务句柄 int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init();
delay_init();
LED_Init();
TIM3_Int_Init(-,-); //设置定时器3的抢占优先级为 4
TIM5_Int_Init(-,-); //设置定时器5的抢占优先级为 5 // 创建一个任务
xTaskCreate((TaskFunction_t )start_task, // 任务函数
(const char * )"start_stask", // 任务名
(uint16_t )start_task_zise, // 任务堆栈的大小
(void * )NULL, // 传递给任务函数的参数
(UBaseType_t )start_task_prio, // 任务优先级
(TaskHandle_t * )&start_task_handler); // 任务句柄 vTaskStartScheduler(); // 开启任务调度
return ;
} void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); // 创建临界区
// 创建led1任务
xTaskCreate((TaskFunction_t )interrupt_task,
(const char * )"interrupt_task",
(uint16_t )interrupt_task_zise,
(void * )NULL,
(UBaseType_t )interrupt_task_prio,
(TaskHandle_t * )&interrupt_task_handler); // 创建led2任务 vTaskDelete(start_task_handler); //删除开始任务
taskEXIT_CRITICAL(); // 退出临界区
}
//interrupt任务函数
void interrupt_task( void * pvParameters )
{
int i = ;
for( ;; )
{
if(i == )
{
printf("关闭中断!!!.\n");
portDISABLE_INTERRUPTS();
delay_xms(); // delay_xms执行的时候不会执行任何任务调度
printf("开中断!!!.\n");
portENABLE_INTERRUPTS();
}
printf("interrupt task is %d runing.\n", i);
LED0 = ~LED0;
vTaskDelay();
i++;
}
}
8.临界段
- 临界段是指:那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。FreeRTOS在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。
- FreeRTOS中与临界段有关的函数有4个,定义于task.h中:
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() #define taskEXIT_CRITICAL() portEXIT_CRITICAL()
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )
- taskENTER_CRITICAL():进入任务级的临界区;
- taskEXIT_CRITICAL():退出任务级的临界区;
void start_task( void * pvParameters )
{
taskENTER_CRITICAL(); // 进入临界区
// 创建led1任务
xTaskCreate((TaskFunction_t )interrupt_task,
(const char * )"interrupt_task",
(uint16_t )interrupt_task_zise,
(void * )NULL,
(UBaseType_t )interrupt_task_prio,
(TaskHandle_t * )&interrupt_task_handler); // 创建led2任务 vTaskDelete(start_task_handler); //删除开始任务
taskEXIT_CRITICAL(); // 退出临界区
} - taskEXIT_CRITICAL_FROM_ISR():进入中断级临界区;
- taskENTER_CRITICAL_FROM_ISR():退出中断级临界区;
//定时器3中断服务程序
void TIM3_IRQHandler(void) //TIM3中断
{
int status_value;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
status_value = taskENTER_CRITICAL_FROM_ISR(); //进入临界区
printf("定时器3发生中断.\n");
LED1=!LED1;
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志
taskEXIT_CRITICAL_FROM_ISR(status_value); //退出临界区
}
} //定时器3中断服务程序
void TIM5_IRQHandler(void) //TIM3中断
{
int status_value;
if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) //检查TIM5更新中断发生与否
{
status_value = taskENTER_CRITICAL_FROM_ISR(); //进入临界区
printf("定时器5发生中断.\n");
LED1=!LED1;
TIM_ClearITPendingBit(TIM5, TIM_IT_Update ); //清除TIMx更新中断标志
taskEXIT_CRITICAL_FROM_ISR(status_value); //退出临界区
}
}
2、FreeRTOS任务相关API函数的更多相关文章
- FreeRTOS-05任务相关API函数
根据正点原子FreeRTOS视频整理 单片机:STM32F207VC FreeRTOS源码版本:v10.0.1 任务相关API函数: 1. main.c /* * */ #include " ...
- 串口编程的相关API函数
用户使用函数CreateFile()创建与指定串口相关联的文件,然后可以使用该函数返回的文件句柄进行串口参数设置.• 01 HANDLE hModem; //定义串口句柄02 hModem=Creat ...
- FreeRTOS系列第20篇---FreeRTOS信号量API函数
FreeRTOS的信号量包括二进制信号量.计数信号量.相互排斥信号量(以后简称相互排斥量)和递归相互排斥信号量(以后简称递归相互排斥量).我们能够把相互排斥量和递归相互排斥量看成特殊的信号量. 信号量 ...
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- C#中可直接调用WIN32的API函数--USER32.DLL
Win32的API函数可以直接在C#中直接调用,在做WinForm时还是很有帮助的.有时候直接调用Win32的API,可以很高效的实现想要的效果. using System; using System ...
- Appium常用的API函数
在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...
- mfc 调用Windows的API函数实现同步异步串口通信(源码)
在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- [转]SQLITE3 C语言接口 API 函数简介
SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...
随机推荐
- -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口 区别 多态 包 访问权限 内部类 匿名内部类 == 与 equal
java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型 也就是 ...
- 通过钩子程序跨程序关闭Window
需求: 在实际场景中会有自身程序在调用第三方的动态库过程中,因为第三方的动态库弹框导致线程阻塞,必须手动将弹窗关闭后才能回到自身程序的主线程中. 最简单的场景就是很多自助设备,本身是没有固定操作员的, ...
- 基于.Net进行前端开发的技术栈发展路线(二)
前言 上一篇<我的技能树>文章分享了我的技能成长过程,还未完成,今天继续跟大家分享. 01 我的技能树 我的当前的技能树: 其中,标注为黄色旗帜的是基本掌握,标注为红色旗帜的为使用熟练.未 ...
- Python并发编程之实战异步IO框架:asyncio 下篇(十一)
大家好,并发编程 进入第十一章. 前面两节,我们讲了协程中的单任务和多任务 这节我们将通过一个小实战,来对这些内容进行巩固. 在实战中,将会用到以下知识点: 多线程的基本使用 Queue消息队列的使用 ...
- 【AutoFac】依赖注入和控制反转的使用
在开始之前首先解释一下我认为的依赖注入和控制反转的意思.(新手理解,哪里说得不正确还请指正和见谅) 控制反转:我们向IOC容器发出获取一个对象实例的一个请求,IOC容器便把这个对象实例“注入”到我们的 ...
- 37.QT-QTSingleApplication-程序只运行一个实例
QTSingleApplication由Qt官方提供的,用于实现只启动一个实例,并在启动时可以向向另一个实例通信(依赖于QtNetwork模块) QTSingleApplication下载路径:链接: ...
- jQuery.parseJSON()函数详解
jQuery.parseJSON()函数用于将格式完好的JSON字符串转为与之对应的JavaScript对象. 所谓”格式完好”,就是要求指定的字符串必须符合严格的JSON格式,例如:属性名称必须加双 ...
- Java中的会话Cookie&&Session
会话技术 会话: 一次会话中包含多次请求和响应. 一次会话:浏览器第一次给服务器资源发送请,会话建立,直到有一方断开为止 功能:在一次会话的范围内的多次请求之间共享数据 方式: 客户端会话技术:coo ...
- 升级本地部署的CRM到Dynamics 365及部分新特性介绍。
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复241或者20161226可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- Dynamics 365使用Execute Multiple Request删除系统作业实体记录
摘要: 本人微信公众号:微软动态CRM专家罗勇 ,回复295或者20190112可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me ...