单片机/MCU论坛
直播中

凤毛麟角

9年用户 1026经验值
私信 关注
[问答]

请问如何仅使用软件和 TC375 精简板来测量函数调用的堆栈使用情况?

  我想测量 AURIX TriCore™ TC3xx 项目的函数调用的堆栈使用情况。 我不知道该怎么做。

我知道事实上作为硬件我只有一个 TC375 lite 开发板,没有 BlueBox 或任何类型的硬件调试模块。
基本上,我通过 USB 将开发板连接到计算机,然后使用 ADS 进行编译、运行、调试等。

是否可以?如果是:该怎么做?我想要一个逐步的教程。我不习惯使用这些工具(ADS、winIDEA 等),而且使用起来很困难。我甚至很难浏览文档(如果有办法实现我想要实现的目标)

回帖(1)

张国厚

2025-8-13 17:49:43

测量 TC375 函数调用堆栈使用量的软件方法指南(基于 AURIX ADS)


以下是无需额外硬件(仅用 TC375 Lite 板和 ADS)的详细步骤。我们使用栈填充模式分析技术来实现堆栈深度测量。




步骤 1:配置链接脚本(.ld 文件)



  1. 定位链接脚本:在 ADS 项目中打开链接脚本(通常为 Lcf_Tasking_Tricore_Tc.ld

  2. 定义栈区域符号:在 .stack 段前后添加标签:
    .stack :
    {
    __STACK_START = .;   /* 添加起始标签 */
    *(.stack)
    . = ALIGN(8);
    __STACK_END = .;     /* 添加结束标签 */
    } > DSram1




步骤 2:添加栈检测代码


main.c 中添加以下代码:


#include 
#include

// 声明链接器定义的符号
extern uint32_t __STACK_START[];
extern uint32_t __STACK_END[];

// 栈填充模式(可自定义)
#define STACK_PATTERN 0xCAFEBABE

// 初始化栈为填充模式
void init_stack_pattern(void) {
    for (uint32_t *ptr = __STACK_START; ptr > __STACK_END; ptr--) {
        *ptr = STACK_PATTERN;
    }
}

// 计算最大栈使用量(字节)
size_t get_max_stack_usage(void) {
    const uint32_t *ptr = __STACK_END;
    while (ptr < __STACK_START && *ptr == STACK_PATTERN) {
        ptr++;
    }
    return (uint8_t*)__STACK_START - (uint8_t*)ptr;
}

// 目标函数示例
void critical_function(void) {
    volatile char buffer[256]; // 测试大数组
    // 函数操作...
}



步骤 3:测量特定函数的栈使用


main() 函数中实现测试逻辑:


int main(void) {
    init_stack_pattern();  // 初始化栈模式

    // 测试前禁用中断(确保测量准确)
    uint32_t psr = _mfcr(0xFE04); // 读取PSW
    _disable();            // 关闭全局中断

    // 调用目标函数
    critical_function();

    // 测量并打印栈使用
    size_t stack_used = get_max_stack_usage();
    printf("[Stack Usage] %d bytesn", stack_used);

    // 恢复中断状态
    if (psr & 0x8000) _enable(); // 如果原先中断开启则恢复

    while(1); // 保持程序运行
}



步骤 4:配置 ADS 输出(查看结果)



  1. 启用串口调试

    • IfxAsclin_Asc.h 中配置 ASCLIN 串口

    • 重定向 printf 到串口(参考 ADS 示例中的 UART_printf 工程)


  2. 连接开发板

    • 使用 USB 转串口工具连接 TC375 的 TX/RX 引脚

    • 电脑端用 PuTTY 或 Tera Term 监听对应 COM 端口(波特率 115200)





步骤 5:编译运行与结果解析



  1. 编译下载

    • 在 ADS 中点击 Build → 生成 .elf 文件

    • 使用 MiniWiggler/J-Link 下载程序到板子


  2. 查看输出

    • 复位开发板

    • 串口终端将显示:[Stack Usage] 348 bytes(示例值)


  3. 结果分析

    • 值包含 critical_function + 中断上下文 + 安全余量

    • 多次测试取最大值(考虑最坏执行路径)





关键注意事项



  1. 中断处理

    • 测量期间禁用中断可能影响实时性,仅用于测试场景

    • 如需包含中断栈,在 .intstack 段实施相同检测


  2. 栈增长方向

    • Tricore 栈从高地址向低地址增长(代码已适配)


  3. 编译器优化

    • 禁用尾部调用优化(-fno-optimize-sibling-calls

    • 确保 volatile 防止局部变量被优化掉


  4. 精度提升
    // 在函数入口/出口添加手动标记
    #define STACK_MARKER() do {
       asm volatile ("mov d15, 0xDEADBEEF");
    } while(0)



替代方案:使用 ADS 内置静态分析(编译时估算)  



  1. 项目属性 → C/C++ Build → Settings  

  2. CompilerStack 中启用 --call-graph  

  3. 编译后查看 callgraph.html(但无法反映运行时动态行为)



这种方法无需额外硬件,通过软件填充和内存扫描实现堆栈深度测量,适合资源受限环境。建议结合静态分析和动态测量验证结果。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分