默認情況下用戶創建的任務棧大小是由參數Task stack size決定的。
如果覺得每個任務都分配同樣大小的棧空間不方便的話,可以采用自定義任務棧的方式創建任務。采用自定義方式更靈活些
由於Cortex-M3和M4內核具有雙堆棧指針,MSP主堆棧指針和PSP進程堆棧指針,或者叫PSP任務堆棧指針也是可以的。
在RTX操作系統中,主堆棧指針MSP是給系統棧空間使用的,進程堆棧指針PSP是給任務棧使用的。
也就是說,在RTX任務中,所有棧空間的使用都是通過PSP指針進行指向的。一旦進入了中斷函數已經可能發生的中斷嵌套都是用的MSP指針
實際應用中系統棧空間分配多大,主要是看可能發生的中斷嵌套層數,下面我們就按照最壞執行情況進行考慮,所有的寄存器都需要入棧,此時分為兩種情況:
64字節
對於Cortex-M3內核和未使用FPU(浮點運算單元)功能的Cortex-M4內核在發生中斷時需要將16個通用寄存器全部入棧,每個寄存器占用4個字節,也就是16*4 = 64字節的空間。 可能發生幾次中斷嵌套就是要64乘以幾即可。當然,這種是最壞執行情況,也就是所有的寄存器都入棧。 (注:
任務執行的過程中發生中斷的話,有8個寄存器是自動入棧的,這個棧是任務棧,進入中斷以后其余寄存器入棧以及發生中斷嵌套都是用的系統棧)。
200字節 對於
具有FPU(浮點運算單元)功能的Cortex-M4內核,如果在任務中進行了浮點運算,那么在發生中斷的時候除了16個通用寄存器需要入棧,還有34個浮點寄存器也是要入棧的,也就是(16+34)*4 = 200字節的空間。當然,這種是最壞執行情況,也就是所有的寄存器都入棧。(注:
任務執行的過程中發送中斷的話,有8個通用寄存器和18個浮點寄存器是自動入棧的,這個棧是任務棧,進入中斷以后其余通用寄存器和浮點寄存器入棧以及發生中斷嵌套都是用的系統棧。)。
os_sys_init()
void os_sys_init (
void (*task)(void) ); /* 操作系統啟動后執行的任務 */
函數描述:
該方法初始化並啟動操作系統內核.
參數為系統初始化完成之后啟動的任務的指針. 內核給予該任務默認的優先級1.
注意要點:
該函數在 rtl.h中定義.
該方法必須在主函數中調用main.
該任務使用默認的堆棧大小,該大小在 rtx_config.c中為任務定義.
返回值:
該函數不返回,函數會直接開始執行參數中指向的方法.
演示:
#include <rtl.h>
void main (void) {
os_sys_init (task1); /* start the kernel */
while(1); /* will never come here */
}
os_sys_init_prio
void os_sys_init_prio (
void (*task)(void), /* Task to start */
U8 priority); /* Task priority (1-254) */
函數描述:
該函數初始化並啟動RTX內核.
task指針指向啟動后系統執行的第一個任務.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留.
該函數定義在rtl.h.
注意要點:
該函數必須在main函數中被調用.
該任務使用默認的堆棧大小,該大小在 rtx_config.c中為任務定義
.
優先級255表示最重要任務,優先級越高,任務越重要.
返回值:
函數不返回,直接開始執行參數中指定的方法任務
演示:
#include <rtl.h>
void main (void) {
os_sys_init_prio (task1, 10);
while(1);
}
os_sys_init_user
void os_sys_init_user (
void (*task)(void), /* Task to start */
U8 priority, /* Task priority (1-254) */
void* stack, /* Task stack */
U16 size); /* Stack size */
函數描述:
初始化並啟動操作系統內核. 當啟動任務需要比較大的堆棧的時候使用該函數,可以自定義堆棧.
task參數指向系統啟動后執行的第一個任務的指針.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留
.
stack參數指向啟動任務將使用的堆棧的開頭.
size表明任務堆棧的大小.
該函數定義在rtl.h.
該函數定義在rtl.h.注意要點:
T
該函數必須在main函數中被調用
.
任務棧空間必須8字節對齊,可以將任務棧數組定義成uint64_t類型即可(unsigned long long).
默認的堆棧大小,該大小在 rtx_config.c中為任務定義
.
優先級255表示最重要任務,優先級越高,任務越重要
.
返回值:
函數不返回,直接開始執行參數中指定的方法任務.
演示:
static U64 stk1[400/8]; /* 400-byte stack */
void main (void) {
os_sys_init_user (task1, 10, &stk1, sizeof(stk1));
while(1);
}
os_tsk_create
OS_TID os_tsk_create (
void (*task)(void), /* Task to create */
U8 priority ); /* Task priority (1-254) */
函數描述:
該任務創建一個任務,任務指向task指針指向的方法,函數將動態的創建一個任務表示符TID,並將該任務放到系統就緒任務隊列中.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留
.
如果新創建的了任務優先級高於當前正在執行的任務,將引發一次調度,系統執行更高優先級的任務
.
該函數定義在rtl.h.
注意要點:
該API創建的任務使用rtx_config.c定義的堆棧大小創建任務.
優先級255表示最重要任務,優先級越高,任務越重要
.
返回值:
該函數返回創建的任務的標識符TID
. 如果函數調用失敗,將會返回0.
演示:
OS_TID tsk1, tsk2;
__task void task1 (void) {
..
tsk2 = os_tsk_create (task2, 1);
..
}
__task void task2 (void) {
..
}
os_tsk_create_ex
OS_TID os_tsk_create_ex (
void (*task)(void *), /* Task to create */
U8 priority, /* Task priority (1-254) */
void* argv ); /* Argument to the task */
函數描述:
該任務創建一個任務,任務指向task指針指向的方法,函數將動態的創建一個任務表示符TID,並將該任務放到系統就緒任務隊列中
. 該函數是os_tsk_create的擴展方法,可以支持先task指針指定的任務發送一個參數argv
.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留
.
.
argv參數在創建的任務被啟動的時候,被系統傳遞給該任務. 該函數對於同一方法的多個任務的模式下比較實用.
該函數定義在rtl.h.
注意要點:
函數定義任務的時候使用rtx_config.c中指定的任務堆棧大小
返回值:
該函數返回創建的任務的標識符TID
. 如果函數調用失敗,將會返回0.
演示:
#include <rtl.h>
OS_TID tsk1, tsk2_0, tsk2_1;
int param[2] = {0, 1};
__task void task1 (void) {
..
tsk2_0 = os_tsk_create_ex (task2, 1, ¶m[0]);
tsk2_1 = os_tsk_create_ex (task2, 1, ¶m[1]);
..
}
__task void task2 (void *argv) {
..
switch (*(int *)argv) {
case 0:
printf("This is a first instance of task2.\n");
break;
case 1:
printf("This is a second instance of task2.\n");
break;
}
..
}
os_tsk_create_user
OS_TID os_tsk_create_user(
void (*task)(void), /* Task to create */
U8 priority, /* Task priority (1-254) */
void* stk, /* Pointer to the task's stack */
U16 size ); /* Number of bytes in the stack */
函數描述:
該任務創建一個任務,任務指向task指針指向的方法,函數將動態的創建一個任務表示符TID,並將該任務放到系統就緒任務隊列中
. 該函數支持為任務定義私有堆棧區. 在任務需要一個大的堆棧的時候該函數比較實用.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留
.
如果新創建的了任務優先級高於當前正在執行的任務,將引發一次調度,系統執行更高優先級的任務
.
第3個參數是任務棧地址
. 第4個參數是任務棧大小,單位是字節.
該函數定義在rtl.h.
注意要點:
任務棧空間必須8字節對齊,可以將任務棧數組定義成uint64_t類型即可 (unsigned long long).
返回值:
該函數返回創建的任務的標識符TID
. 如果函數調用失敗,將會返回0.
演示:
OS_TID tsk1,tsk2;
static U64 stk2[400/8];
__task void task1 (void) {
..
/* Create task 2 with a bigger stack */
tsk2 = os_tsk_create_user (task2, 1, &stk2, sizeof(stk2));
..
}
__task void task2 (void) {
/* We need a bigger stack here. */
U8 buf[200];
..
}
os_tsk_create_user_ex
OS_TID os_tsk_create_user_ex (
void (*task)(void *), /* Task to create */
U8 priority, /* Task priority (1-254) */
void* stk, /* Pointer to the task's stack */
U16 size, /* Size of stack in bytes */
void* argv ); /* Argument to the task */
函數描述:
該任務創建一個任務,任務指向task指針指向的方法,函數將動態的創建一個任務表示符TID,並將該任務放到系統就緒任務隊列中
. 該函數支持為任務定義私有堆棧區. 在任務需要一個大的堆棧的時候該函數比較實用.同時還可以向任務傳遞一個argv參數
.
優先級參數設置系統啟動之后的第一個執行的任務的優先級
. 默認優先級為1. 優先級0為空閑任務保留. 如果設置參數值為0,他會自動被參數1取代. 優先級255同樣被保留
.
如果新創建的了任務優先級高於當前正在執行的任務,將引發一次調度,系統執行更高優先級的任務
.
第3個參數是任務棧地址
.
第4個參數是任務棧大小,單位是字節.
argv參數在創建的任務被啟動的時候,被系統傳遞給該任務
. 該函數對於同一方法的多個任務的模式下比較實用.
注意要點:
任務棧空間必須8字節對齊,可以將任務棧數組定義成uint64_t類型即可 (unsigned long long).
返回值:
該函數返回創建的任務的標識符TID
. 如果函數調用失敗,將會返回0.
演示:
#include <rtl.h>
OS_TID tsk1,tsk2_0,tsk2_1;
static U64 stk2[2][400/8];
__task void task1 (void) {
..
/* Create task 2 with a bigger stack */
tsk2_0 = os_tsk_create_user_ex (task2, 1,
&stk2[0], sizeof(stk2[0]),
(void *)0);
tsk2_1 = os_tsk_create_user_ex (task2, 1,
&stk2[1], sizeof(stk2[1]),
(void *)1);
..
}
__task void task2 (void *argv) {
/* We need a bigger stack here. */
U8 buf[200];
..
switch ((int)argv) {
case 0:
printf("This is a first instance of task2.\n");
break;
case 1:
printf("This is a second instance of task2.\n");
break;
}
..
}
os_tsk_delete
OS_RESULT os_tsk_delete (
OS_TID task_id ); /* Id of the task to delete */
函數描述:
當任務完成所有工作並不再想要的時候,可以調用該函數停止並刪除任務,依靠task_id來停止並刪除任務
注意要點:
如果task_id為0,則當前正在執行的任務被停止和刪除. 程序將執行就緒隊列中的下一個就緒任務.
返回值:
如果任務刪除成功,函數返回OS_R_OK,其余所有情況返回OS_R_NOK,比如所寫的任務ID不存在
.
演示:
#include <rtl.h>
OS_TID tsk3;
__task void task2 (void) {
tsk3 = os_tsk_create (task3, 0);
..
if (os_tsk_delete (tsk3) == OS_R_OK) {
printf("\n'task 3' deleted.");
}
else {
printf ("\nFailed to delete 'task 3'.");
}
}
__task void task3 (void) {
..
}
os_tsk_delete_self
#include <rtl.h>
void os_tsk_delete_self (void);
函數描述:
該函數停止並刪除當前正在執行的任務,
程序將執行就緒隊列中的下一個就緒任務
.
注意要點:
該函數沒有返回
.
,
程序將執行就緒隊列中的下一個就緒任務
返回值:
該函數沒有返回
.
,
程序將執行就緒隊列中的下一個就緒任務.
演示:
#include <rtl.h>
__task void task2 (void) {
..
os_tsk_delete_self();
}
os_tsk_pass
#include <rtl.h>
void os_tsk_pass (void);
函數描述:
該函數將切換到和當前任務優先級相同的就緒隊列中的其他任務. 如果就緒隊列中沒有相同優先級的任務, 當前任務將繼續執行且沒有任務切換發生。
注意要點:
可以用該方法在相同優先級的幾個任務之間切換.
返回值:
None
演示:
#include <rtl.h>
OS_TID tsk1;
__task void task1 (void) {
..
os_tsk_pass();
..
}
os_tsk_prio
OS_RESULT os_tsk_prio (
OS_TID task_id, /* ID of the task */
U8 new_prio ); /* New priority of the task (1-254) */
函數描述:
該函數將修改task_id指定的任務的優先級.
如果新設置的優先級比當前執行的任務的優先級高,那么任務切換將會切換到task_id指定的任務並執行,同時優先級被修改. 如果低,那么依然執行當前任務.
如果task_id為0,修改的優先級是當前運行任務的優先級.
注意要點:
新優先級的取值為1-254.
新的優先級將一直保持直到你再次修改它.
優先級0是idle任務的優先級,如果設置某個任務優先級為0,程序將自動修改為1,255是保留優先級,也是一樣的.
優先級數值越大,優先級越高.
返回值:
返回值如下所示:
演示:
#include <RTL.h>
OS_TID tsk1,tsk2;
__task void task1 (void) {
..
os_tsk_prio_self (5);
/* Changing the priority of task2 will cause a task switch. */
os_tsk_prio(tsk2, 10);
..
}
__task void task2 (void) {
..
/* Change priority of this task will cause task switch. */
os_tsk_prio_self (1);
..
}
os_tsk_prio_self
#include <rtl.h>
OS_RESULT os_tsk_prio_self (
U8 new_prio ); /* New priority of task (1-254) */
函數描述:
修改當前運行任務的優先級為新的優先級.
注意要點:
新優先級的取值為1-254.
新的優先級將一直保持直到你再次修改它.
優先級0是idle任務的優先級,如果設置某個任務優先級為0,程序將自動修改為1,255是保留優先級,也是一樣的.
優先級數值越大,優先級越高..
返回值:
該函數始終返回 OS_R_OK.
演示:
#include <rtl.h>
OS_TID tsk1;
__task void task1 (void) {
..
os_tsk_prio_self(10); /* Increase its priority, for the critical section */
.. /* This is a critical section */
..
os_tsk_prio_self(2); /* Decrease its priority at end of critical section */
..
}
os_tsk_self
#include <rtl.h>
OS_TID os_tsk_self (void);
函數描述:
該函數將返回當前運行任務的標識符,也就是TID.
注意要點:
無
返回值:
返回當前執行任務的TID標識符
.
演示:
#include <rtl.h>
OS_TID tsk1;
__task void task1 (void) {
tsk1 = os_tsk_self();
..
}
isr_tsk_get
#include <rtl.h>
OS_TID isr_tsk_get (void);
函數描述:
該函數返回當前正在運行的中斷任務的標識符TID.
注意要點:
該函數只能在ISR任務中調用.
返回值:
該函數返回當前正在運行的中斷任務的標識符TID
.
演示:
#include <rtl.h>
void os_error (U32 err_code) {
/* This function is called when a runtime error is detected. */
OS_TID err_task;
switch (err_code) {
case OS_ERR_STK_OVF:
/* Identify the task with stack overflow. */
err_task = isr_tsk_get();
break;
case OS_ERR_FIFO_OVF:
break;
case OS_ERR_MBX_OVF:
break;
}
for (;;);
}
