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函数的更多相关文章

  1. FreeRTOS-05任务相关API函数

    根据正点原子FreeRTOS视频整理 单片机:STM32F207VC FreeRTOS源码版本:v10.0.1 任务相关API函数: 1. main.c /* * */ #include " ...

  2. 串口编程的相关API函数

    用户使用函数CreateFile()创建与指定串口相关联的文件,然后可以使用该函数返回的文件句柄进行串口参数设置.• 01 HANDLE hModem; //定义串口句柄02 hModem=Creat ...

  3. FreeRTOS系列第20篇---FreeRTOS信号量API函数

    FreeRTOS的信号量包括二进制信号量.计数信号量.相互排斥信号量(以后简称相互排斥量)和递归相互排斥信号量(以后简称递归相互排斥量).我们能够把相互排斥量和递归相互排斥量看成特殊的信号量. 信号量 ...

  4. Windows API 函数列表 附帮助手册

    所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...

  5. C#中可直接调用WIN32的API函数--USER32.DLL

    Win32的API函数可以直接在C#中直接调用,在做WinForm时还是很有帮助的.有时候直接调用Win32的API,可以很高效的实现想要的效果. using System; using System ...

  6. Appium常用的API函数

    在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...

  7. mfc 调用Windows的API函数实现同步异步串口通信(源码)

    在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信.串口通信方便易行,应用广泛. 一般情况下,工控机和各智能仪表通过RS485总线进行通信.RS485的通信方式是半 ...

  8. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

  9. [转]SQLITE3 C语言接口 API 函数简介

    SQLITE3 C语言接口 API 函数简介 说明:本说明文档属作者从接触 SQLite 开始认识的 API 函数的使用方法, 由本人翻译, 不断更新. /* 2012-05-25 */ int sq ...

随机推荐

  1. 补习系列(11)-springboot 文件上传原理

    目录 一.文件上传原理 二.springboot 文件机制 临时文件 定制配置 三.示例代码 A. 单文件上传 B. 多文件上传 C. 文件上传异常 D. Bean 配置 四.文件下载 小结 一.文件 ...

  2. JDK源码分析(4)之 LinkedList 相关

    LinkedList的源码大致分三个部分,双向循环链表的实现.List的API和Deque的API. 一.定义 public class LinkedList<E> extends Abs ...

  3. [十七]基础类型BigDecimal简介

      BigDecimal是不可变的.任意精度的.有符号的.十进制数.   组成部分 BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成 BigDecimal ...

  4. 一篇文章彻底搞懂es6 Promise

    前言 Promise,用于解决回调地狱带来的问题,将异步操作以同步的操作编程表达出来,避免了层层嵌套的回调函数. 既然是用来解决回调地狱的问题,那首先来看下什么是回调地狱 var sayhello = ...

  5. 用TensorFlow教你手写字识别

    博主原文链接:用TensorFlow教你做手写字识别(准确率94.09%) 如需转载,请备注出处及链接,谢谢. 2012 年,Alex Krizhevsky, Geoff Hinton, and Il ...

  6. Identity Server 4 中文文档(v1.0.0)

    欢迎来到IdentityServer4 欢迎IdentityServer4 IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架. 它可以 ...

  7. DSAPI多功能组件编程应用-文件类

    [DSAPI.DLL下载地址]     本节内容,是属于"无需过多说明"就能使用的功能.由于实在是太简单,我就简单地示例一下. DSAPI.文件类.获取可读性强的字节大小信息(&q ...

  8. mysql报错:java.sql.SQLException: Incorrect string value: '\xE4\xB8\x80\xE6\xAC\xA1...' for column 'excelName' at row 1

    一.问题 用Eclipse做项目时候报错 java.sql.SQLException: Incorrect string value: '\xE4\xB8\x80\xE6\xAC\xA1...' fo ...

  9. nginx系列5:nginx的请求处理流程

    nginx的请求处理流程 如下图: nginx可以处理来自web(http),Email,TCP/UDP的三类请求. nginx底层使用非阻塞的事件驱动引擎,结合状态机来完成异步通知,其中处理Http ...

  10. npm 安装及使用

    1. 安装 npm 安装完node后,就自动完成npm的安装. 2. 常用的npm命令 #安装包 npm install <pkg> 或者 npm install <pkg>@ ...