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. 通过钩子程序跨程序关闭Window

    需求: 在实际场景中会有自身程序在调用第三方的动态库过程中,因为第三方的动态库弹框导致线程阻塞,必须手动将弹窗关闭后才能回到自身程序的主线程中. 最简单的场景就是很多自助设备,本身是没有固定操作员的, ...

  2. ASP.NET Core教程【二】从保存数据看Razor Page的特有属性与服务端验证

    前文索引:ASP.NET Core教程[一]关于Razor Page的知识 在layout.cshtml文件中,我们可以看到如下代码: <a asp-page="/Index" ...

  3. MyBatis之分页插件(PageHelper)工作原理

      数据分页功能是我们软件系统中必备的功能,在持久层使用mybatis的情况下,pageHelper来实现后台分页则是我们常用的一个选择,所以本文专门类介绍下. PageHelper原理 相关依赖 & ...

  4. vue 双向数据绑定原理

    博客地址: https://ainyi.com/8 采用defineProperty的两个方法get.set 示例 <!-- 表单 --> <input type="tex ...

  5. 怎么获取泛型T.class类?

    public <T> void get(List<T> list){ getA(T.class); //报错,不能调用T.class } public void getA(Cl ...

  6. C#调用Windows(8/10)自带的虚拟键盘

    以下是调用代码: private const Int32 WM_SYSCOMMAND = 274; private const UInt32 SC_CLOSE = 61536; [DllImport( ...

  7. [日常] nginx记录post数据

    1.使用log_format指令来更改日志格式,该指令只能放在http{}段 log_format  日志名  '日志内容'; server { access_log /var/log/nginx/d ...

  8. C# 绘制Word形状——基本形状、组合形状

    一.序言 在Office Word中,支持在Word文档中插入类型非常丰富的形状,包括线条.矩形.基本形状(诸如圆形.多边形.星形.括号.笑脸等等图形).箭头形状.公式形状.流程图.旗帜图形.标注图形 ...

  9. noi.ac #289. 电梯(单调队列)

    题意 题目链接 Sol 傻叉的我以为给出的\(t\)是单调递增的,然后\(100\rightarrow0\) 首先可以按\(t\)排序,那么转移方程为 \(f[i] = min_{j=0}^{i-1} ...

  10. 少侠学代码系列(二)->JS实现

    少侠:小子,休息好了没,赶紧的 帅气的我:好了好了,嚷什么 少侠:(拔刀)嗯? 帅气的我:少侠,淡定淡定,我们来看秘籍吧,刚刚我们说了JS实现是由三个部分组成的 核心(ECMAScript),文档对象 ...