TencentOS_Tiny 任务栈使用率(检测任务栈最大使用深度)
2022/4/15 7:14:11
本文主要是介绍TencentOS_Tiny 任务栈使用率(检测任务栈最大使用深度),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 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; }
这篇关于TencentOS_Tiny 任务栈使用率(检测任务栈最大使用深度)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享