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()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM