在 ESP-IDF 中,您可以使用 xTaskCreate() 函数创建任务:
static BaseType_t xTaskCreate(TaskFunction_t pvTaskCode, const char *constpcName, const uint32_t usStackDepth, void *constpvParameters, UBaseType_t uxPriority, TaskHandle_t *constpvCreatedTask)
文档说:
usStackDepth:任务堆栈的大小,指定为字节数。请注意,这与普通 FreeRTOS 不同。
通常我会看到这样的例子:
void myTask(void *arg);
TaskHandle_t myTaskHandle = NULL;
xTaskCreate(myTask, "myTask", 2048, NULL, 10, &myTaskHandle);
我想知道如何正确选择堆栈深度(示例中为 2048)。因为它保留了内存空间,所以我打赌我不能盲目猜测并插入更高的值,否则我会耗尽内存空间。
阅读文档,我发现了另一个函数 uxTaskGetStackHighWaterMark() 并查看返回值,它应该告诉我我距离指定任务的堆栈溢出有多近。
因此,唯一的方法是设置一个“随机”值,然后检查高水印并根据?有没有编译器功能可以帮助我选择一个值而无需猜测?
函数指针、可变长度数组、
alloca
和递归等技术使得静态分析工具无法生成有关任何给定代码执行流的最大堆栈大小的报告。
如果您正在使用 VLA、分配和递归,您可能需要重新考虑其中一些技术和/或确保您的代码对每项技术实施限制,以防止运行时过多的堆栈消耗。
正如评论和其他答案中提到的,大多数编译器可以告诉您使用
-fstack-usage
等标志编译的每个函数的非动态分配堆栈内存的堆栈使用情况。但是,要使其有用,您仍然需要非常清楚地了解将调用哪些函数以及堆栈的深度,并且它不会报告可变大小分配的内存,因此堆栈报告实际上最好用于查找函数那可能会占用内存。请参阅如何使用 gcc 确定嵌入式系统中的最大堆栈使用量?
我能建议的最好的技术是对堆栈大小的上限进行有根据的猜测(希望比随机更好)(如果你真的想不出什么,可以尝试 25% 的 RAM)。
接下来,将
configCHECK_FOR_STACK_OVERFLOW
设置为 2 并实施 vApplicationStackOverflowHook()
。有关详细信息,请参阅 https://www.freertos.org/Stacks-and-stack-overflow-checking.html。
最终通过尽可能多的预期执行流来运行您的任务,并在最后调用
uxTaskGetStackHighWaterMark()
。
如果程序达到极限,则提高极限并重复。当你得到它时查看高水位线数字,并乘以某个因数以获得可能的变化和未来的代码更改,比方说 1.2x。