static void vTaskLED1(void *pvParameters)
{
uint8_t j = 0;
while(1) {
j++;
vTaskDelay(3);
}
}
StackType_t user1_puxStackBuffer[24] = {0};
StaticTask_t user1_pxTaskBuffer[256] = {0};
int main(void)
{
xTaskCreateStatic(vTaskLED1, "vTaskLED1", 24, NULL, 1, user1_puxStackBuffer, user1_pxTaskBuffer);
vTaskStartScheduler();
}
其中user1_puxStackBuffer的首地址是0x20000068
执行函数xTaskCreateStatic,当执行完pxNewTCB->pxTopOfStack = pxTopOfStack;之后得到:
0 | 0x20000068 | ||
1 | 0x2000006C | ||
2 | 0x20000070 | ||
3 | 0x20000074 | ||
4 | 0x20000078 | ||
5 | 0x2000007C | ||
6 | 0x20000080 | R4 | <==pxTopOfStack |
7 | 0x20000084 | R5 | |
8 | 0x20000088 | R6 | |
9 | 0x2000008C | R7 | |
10 | 0x20000090 | R8 | |
11 | 0x20000094 | R9 | |
12 | 0x20000098 | R10 | |
13 | 0x2000009C | R11 | |
14 | 0x200000A0 | R0 | pvParameters |
15 | 0x200000A4 | R1 | |
16 | 0x200000A8 | R2 | |
17 | 0x200000AC | R3 | |
18 | 0x200000B0 | R12 | |
19 | 0x200000B4 | LR | prvTaskExitError |
20 | 0x200000B8 | PC | pxTaskCode |
21 | 0x200000BC | xPSR | portINITIAL_XPSR |
22 | 0x200000C0 | ||
23 | 0x200000C4 |
watchlist如下图:
然后执行到图的位置发现watchlist没有任何变化,如下图:
但是上图可以看到 j 的值已经变为 1 了。
然后单步(快捷键F11)进入taskdelay,看到寄存器R0的值变味3,如下图:
然后再单步运行一步(快捷键F11),如下图:
可以看到register界面的R4也变为1,右侧watchlist的虚拟堆栈[18]的值有个1.
然后全速运行(快捷键F5),如下图:
可以看到上图右侧watchlist虚拟堆栈的[17]值是0x61000000,这个位置正是xPSR的位置,在本文的开头xPSR的位置在[21]的位置,可以看出虚拟栈的位置向低地址挪了(21-17)*4=16字节,挪出来给虚拟堆(就是给临时变量)使用了。
另外,非常值得注意的几点:
(1)仔细观察可以发现上图[21]有个0x08000423,。
经过试验发现,如果把临时变量弄多一点,比如把变量j改成个数组,那么类似于0x08000423就没了。说白了就是说这个0x08000423是什么我还是没有搞清楚。
(2)task下的临时内存定义了,即便没有调用,也会占用虚拟堆的资源。因为这个虚拟毕竟是虚拟的,没有真实的编译器那么智能,真实的编译器(就是说非OS情况下)会判断临时变量没有被使用,不将其编译进去(就是不分配内存),即便在优先级是0的情况下。这个ARMCC编译器还是很牛的。
一点心得,长路漫漫,离真正弄懂这个freeRtos还有很长的路要走!!