bat文件是dos下的批處理文件。批處理文件是無格式的文本文件,它包含一條或多條命令。它的文件擴展名為 .bat 或 .cmd。 ...
目錄
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;
}