添加一个指令实现打印rt thread的全部线程当前的栈回溯

实现代码

c 复制代码
#ifdef RT_USING_FINSH
#include <finsh.h>
#endif


#define LED3_PIN GET_PIN(C, 13)

#if defined(__GNUC__) && defined(RT_USING_FINSH)
static void thread_stack_call_fun(int argc, char **argv)
{
    struct rt_object_information *info;
    rt_list_t *node;
    int max_depth = RT_BACKTRACE_LEVEL_MAX_NR;
    int dump_all = 0;
    const char *target_name = RT_NULL;

    if (argc > 1)
    {
        if (rt_strcmp(argv[1], "-a") == 0)
            dump_all = 1;
        else
            target_name = argv[1];

        if (argc > 2)
            max_depth = atoi(argv[2]);
    }

    info = rt_object_get_information(RT_Object_Class_Thread);
    if (!info)
    {
        rt_kprintf("Failed to get thread object information\n");
        return;
    }

    for (node = info->object_list.next; node != &info->object_list; node = node->next)
    {
        rt_thread_t thread = rt_list_entry(node, struct rt_thread, parent.list);
        rt_ubase_t *sp;
        rt_ubase_t *stack_start;
        rt_ubase_t *stack_end;
        int count = 0;

        if (target_name && rt_strcmp(thread->parent.name, target_name) != 0)
            continue;

        rt_kprintf("\n========== thread: %s ==========\n", thread->parent.name);

        if (thread->sp == RT_NULL)
        {
            rt_kprintf(" (no stack info)\n");
            continue;
        }

        stack_start = (rt_ubase_t *)thread->stack_addr;
        stack_end = (rt_ubase_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size);
        sp = (rt_ubase_t *)thread->sp;

        rt_kprintf(" stack: %p - %p, sp: %p, size: %d\n",
                   stack_start, stack_end, sp, thread->stack_size);

        if (!dump_all)
        {
            rt_kprintf(" (use -a to dump all stack, now only scan from sp to stack end)\n");
        }

        {
            rt_ubase_t *scan_start = sp;
            rt_ubase_t *scan_end = dump_all ? stack_end : (sp + 128);

            if (scan_end > stack_end)
                scan_end = stack_end;

            rt_kprintf(" call stack (addr2line -e rtthread.elf -a -f):\n");
            for (rt_ubase_t *p = scan_start; p < scan_end && count < max_depth; p++)
            {
                rt_ubase_t val = *p;
                if (val >= 0x08000000 && val <= 0x08080000)
                {
                    rt_kprintf(" 0x%08lx", val);
                    count++;
                }
            }
            if (count == 0)
                rt_kprintf(" (empty)");
            rt_kprintf("\n");
        }

        if (target_name)
            break;
    }
}
MSH_CMD_EXPORT(thread_stack_call_fun, dump threads stack for addr2line);
#endif

如何使用

示例输出:

========== thread: tidle ==========

stack: 0x20000f08 - 0x20001308, sp: 0x200012f0, size: 1024

call stack (addr2line -e rtthread.elf -a -f):

0x0800abcd 0x0800cdef

把输出的地址复制出来,在 PC 命令行中执行:

addr2line -e rtthread.elf -a -f 0x0800abcd 0x0800cdef

查看函数名和源码位置。

带参数用法:

│命令 │说明 │

│thread_stack_call_fun │列出所有线程栈中的调用地址 │

│thread_stack_call_fun -a │扫描整个栈空间(默认只扫 sp 后 128 字节) │

│thread_stack_call_fun tidle │只看指定线程 │

│thread_stack_call_fun tidle 10 │只看指定线程,最多输出 10 个地址 |

相关推荐
π同学4 个月前
基于RT-Thread的STM32开发第十二讲SD卡篇——DFS文件系统
stm32·dfs·rtthread·sdio
jomoly2 年前
RT Studio 仍存在的一些bug
bug·rtthread
Rice嵌入式开发3 年前
RT-Thread上部署TinyMaix推理框架,使MCU赋予AI能力
rtthread·tinymaix