006-ESP32学习开发(SDK)-关于操作系统-任务,任务堆栈空间,任务的挂起,恢复,删除

<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnESP32" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

 

说明

esp32是跑的freertos, 如果没有学过操作系统的朋友把此节当做esp32的内部api使用就可以.

 

创建任务,每隔一段时间打印 Hello world

 

 

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

//任务函数
static void  function(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(1000 / portTICK_PERIOD_MS);//延时约1S
        printf("Hello world!\r\n");
        fflush(stdout);//手动调用刷新缓存,让printf输出数据
    }
}

void app_main(void)
{
    //创建任务
    //第一个function是任务函数; 第二个"function"是给任务取个名字
    //第三个2048是保存任务数据的栈区大小; 第四个传递给任务的参数写的NULL
    //第五个任务的优先等级是10;  第六个记录任务的变量写的NULL
    xTaskCreate(function, "function", 2048, NULL, 10, NULL);
}

 

各个细节说明

1.首先如果没有学过rtos的把这个当做创建定时器就可以了

2.下面的是必须写的

注:那个vTaskDelay函数有时候可以用别的替代,到时候遇到之后再说.

写了下面的程序以后,就会不停的执行while(1)里面的程序.

 

 

3.可以修改延时时间

 

 

4.可以再创建个任务

 

 

 

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

//任务函数
static void  function(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(500 / portTICK_PERIOD_MS);//延时约500ms
        printf("Hello world!\r\n");
        fflush(stdout);//手动调用刷新缓存,让printf输出数据
    }
}

//任务函数
static void  function_1(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(500 / portTICK_PERIOD_MS);//延时约500ms
        printf("1111111111!\r\n");
        fflush(stdout);//手动调用刷新缓存,让printf输出数据
    }
}

void app_main(void)
{
    //创建任务
    //第一个function是任务函数; 第二个"function"是给任务取个名字
    //第三个2048是保存任务数据的栈区大小; 第四个传递给任务的参数写的NULL
    //第五个任务的优先等级是10;  第六个记录任务的变量写的NULL
    xTaskCreate(function, "function", 2048, NULL, 10, NULL);

    xTaskCreate(function_1, "function_1", 2048, NULL, 11, NULL);
}

 

 

5.可以看到两个字符串几乎是每隔500ms同时打印

 

 

 

6.关于栈区大小

任务在运行的时候,每个任务是来回切换运行的,操作系统在切换别的任务运行的时候,会把当前任务运行的寄存器,变量的值存储到内存(ram)里面.

当再次回到这个任务运行的时候,从内存把寄存器,变量的值读取出来,这样子的话就可以接着上次运行了.

保存数据大小我设置的是2048.

 

 

7.获取这个任务自启动以后剩余的最小栈区空间 

uxTaskGetStackHighWaterMark( NULL );
 

 

 

 

中文是乱码....不用理会,咱可以看出剩下的栈空间是568

 

 

 

8.难道使用了 2048-568 = 1480 ????

一个啥也没有的任务不可能使用这么多的,其实返回的是这个任务运行的时候使用的最大空间.

但是网络是都是说这个函数是剩下的栈空间呢? 如何解释?

其实是栈的生长方向的问题!

首先呢保存数据就是使用的数组保存的,数组有首地址和尾地址.

假设存储数据的时候是从首地址开始存储的,假设存储了568个数据,那么数据最大存储在568这个地址

那么就剩余1480个空间没有使用.那么返回的时候返回剩下的就是1480;

 

如果存储数据的时候是从数组的尾地址开始存储的,假设存储568个数据,其实数据是存储到 2047,2046,...,1479,1480 这些地址上

最终存储的地址是1480,但是呢从数组的首地址开始计算的话就会认为存储了1480个数据

那么便会计算出剩余568,正好和上面的相反.所以才返回568.

 

9.大家伙可以把这个地方改为 566  和 569测试

大家伙会发现设置为566的时候,任务启动不起来,程序总是在重启. 设置569是可以的.

所以呢函数  uxTaskGetStackHighWaterMark( NULL ); 在这个里面其实是获取的使用的最大空间

 

 

 

10.一般呢把空间设置为实际使用空间的1.5倍或者2倍就可以 568*2=1136

 

 

停止(挂起)任务 vTaskSuspend(任务句柄)

function1运行约3秒后,停止function任务的运行

 

 

 

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
//任务句柄,用来对任务做其它操作
TaskHandle_t TaskHandle_t_function;

//任务函数
static void  function(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(500 / portTICK_PERIOD_MS);//延时约500ms
        printf("222222!\r\n");
        fflush(stdout);//手动调用刷新缓存,让printf输出数据
    }
}

//任务函数
static void  function_1(void *pvParameters)
{while(1)
    {
        vTaskDelay(3000 / portTICK_PERIOD_MS);//延时约3000ms
        vTaskSuspend(TaskHandle_t_function);//停止function任务运行(挂起function任务)
    }
}

void app_main(void)
{
    //第一个function是任务函数; 第二个"function"是给任务取个名字
    //第三个2048是保存任务数据的栈区大小; 第四个传递给任务的参数写的NULL
    //第五个任务的优先等级是10;  第六个记录任务的变量写的NULL
    xTaskCreate(function, "function", 1136, NULL, 10, &TaskHandle_t_function);

    xTaskCreate(function_1, "function_1", 2048, NULL, 11, NULL);
}

 

 

 

 

 

 

启动被停止(挂起)的任务 vTaskResume(任务句柄)

 

 

 

删除任务  vTaskDelete()

 

posted on 2021-08-02 14:40  广源时代  阅读(1356)  评论(0编辑  收藏  举报

导航

支付宝 QQ群