目錄
- TencentOS_Tiny 任務堆疊使用率
- API呼叫
- 在CONFIG.h中使能
- 在任務中呼叫
- 原始碼分析
- 任務創建時對任務堆疊進行了初始化
- 檢測任務堆疊最多使用位元組數
TencentOS_Tiny 任務堆疊使用率
在使用rtos時需要給任務分配合適大小的任務堆疊,任務運行時所占用的任務堆疊大小由整個任務所使用的臨時變數多少決定,當任務不復雜且呼叫子函式不多時,可以通過簡單的計算來判斷需要給任務分配多大的任務堆疊,當任務比較復雜,呼叫函式比較多時,計算起來比較麻煩,TencentOS Tiny提供了API可以檢測任務最多使用了任務堆疊多少位元組,在使用最多位元組的基礎上多分配一部分空間,就是一個合適的任務堆疊大小,
API呼叫
在CONFIG.h中使能
TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1U
在任務中呼叫
int depth;
tos_task_stack_draught_depth(&task1, &depth);
printf("%d", depth);
原始碼分析
任務創建時對任務堆疊進行了初始化
在tos_task_creat()中使用了cpu_task_stk_init()函式對任務堆疊進行處理
__API__ k_err_t tos_task_create(k_task_t *task,char *name,
k_task_entry_t entry,
void *arg,
k_prio_t prio,
k_stack_t *stk_base,
size_t stk_size,
k_timeslice_t timeslice)
{
.......
.......
/* task_exist是提前宣告的私有函式,用于銷毀任務
* __STATIC__ void task_exit(void)
* {
* tos_task_destroy(K_NULL);
* }
*/
task->sp = cpu_task_stk_init((void *)entry, arg, (void *)task_exit, stk_base, stk_size);
task->entry = entry;
task->arg = arg;
task->prio = prio;
task->stk_base = stk_base;
task->stk_size = stk_size;
strncpy(task->name, name, K_TASK_NAME_LEN_MAX);
......
......
return K_ERR_NONE;
}
cpu_task_stk_init()函式在使能了TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN后會給任務堆疊的所有位元組初始化為0xCC,并將暫存器壓堆疊
__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
void *arg,
void *exit,
k_stack_t *stk_base,
size_t stk_size)
{
cpu_data_t *sp;
// 堆疊頂做4位元組對齊
sp = (cpu_data_t *)&stk_base[stk_size];
sp = (cpu_data_t *)((cpu_addr_t)sp & 0xFFFFFFF8);
#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u
// 從堆疊底到堆疊頂所有位元組初始化為0xCC
uint8_t *slot = (uint8_t *)&stk_base[0];
for (; slot < (uint8_t *)sp; ++slot) {
*slot = 0xCC;
}
#endif
// 按順序將暫存器壓入任務堆疊
/* auto-saved on exception(pendSV) by hardware */
*--sp = (cpu_data_t)0x01000000u; /* xPSR */
*--sp = (cpu_data_t)entry; /* entry */
*--sp = (cpu_data_t)exit; /* R14 (LR) */
*--sp = (cpu_data_t)0x12121212u; /* R12 */
*--sp = (cpu_data_t)0x03030303u; /* R3 */
*--sp = (cpu_data_t)0x02020202u; /* R2 */
*--sp = (cpu_data_t)0x01010101u; /* R1 */
*--sp = (cpu_data_t)arg; /* R0: arg */
/* Remaining registers saved on process stack */
/* EXC_RETURN = 0xFFFFFFFDL
Initial state: Thread mode + non-floating-point state + PSP
31 - 28 : EXC_RETURN flag, 0xF
27 - 5 : reserved, 0xFFFFFE
4 : 1, basic stack frame; 0, extended stack frame
3 : 1, return to Thread mode; 0, return to Handler mode
2 : 1, return to PSP; 0, return to MSP
1 : reserved, 0
0 : reserved, 1
*/
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
*--sp = (cpu_data_t)0xFFFFFFFDL;
#endif
*--sp = (cpu_data_t)0x11111111u; /* R11 */
*--sp = (cpu_data_t)0x10101010u; /* R10 */
*--sp = (cpu_data_t)0x09090909u; /* R9 */
*--sp = (cpu_data_t)0x08080808u; /* R8 */
*--sp = (cpu_data_t)0x07070707u; /* R7 */
*--sp = (cpu_data_t)0x06060606u; /* R6 */
*--sp = (cpu_data_t)0x05050505u; /* R5 */
*--sp = (cpu_data_t)0x04040404u; /* R4 */
return (k_stack_t *)sp;
}
檢測任務堆疊最多使用位元組數
在 tos_task.c 檔案中提供了 API:tos_task_stack_draught_depth(k_task_t *task, int *depth)
__API__ k_err_t tos_task_stack_draught_depth(k_task_t *task, int *depth)
{
TOS_CPU_CPSR_ALLOC();
k_err_t rc;
// 判斷傳入的引數depth是否合法,不合法直接return
TOS_PTR_SANITY_CHECK(depth);
// 判斷傳入的引數task是否合法,不合法則使用當前的運行的任務task
if (unlikely(!task)) {
task = k_curr_task;
}
TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
// 關中斷
TOS_CPU_INT_DISABLE();
// 實際用于檢測任務堆疊最大深度的函式
rc = cpu_task_stack_draught_depth(task->stk_base, task->stk_size, depth);
// 開中斷
TOS_CPU_INT_ENABLE();
return rc;
}
可以看到實際檢測任務堆疊最大深度的函式是 cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth)
__KNL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth)
{
uint8_t *slot;
uint8_t *sp, *bp;
int the_depth = 0;
// 堆疊底
bp = (uint8_t *)&stk_base[0];
// 堆疊頂4位元組對齊
sp = &stk_base[stk_size];
sp = (uint8_t *)((cpu_addr_t)sp & 0xFFFFFFF8);
/*
* 從堆疊頂開始遍歷到堆疊底,
* 由于在初始化時將任務堆疊的每個位元組初始化為了0xCC,
* 如果當前位置的值不為0xCC則是被任務使用了,
* 堆疊頂的地址與當前位置的地址的差值為此時任務使用的深度,
* 當遍歷到最后一個不為0xCC的地址時,
* 差值為任務堆疊使用的最大深度
*/
for (slot = sp - 1; slot >= bp; --slot) {
if (*slot != 0xCC) {
the_depth = sp - slot;
}
}
*depth = the_depth;
if (the_depth == stk_size) {
return K_ERR_TASK_STK_OVERFLOW;
}
return K_ERR_NONE;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/458188.html
標籤:嵌入式
上一篇:圖文詳細程序Linux 使用yum安裝telnet-server、telnet、xinetd以及telnet本機ip
