测试还是有问题,移植的是一个基于setjmp实现的协程(arm/x86等都可以使用,只需要实现set_stack),和set_stack相关的部分代码如下:
Code: Select all
static void __vsf_thread_evthandler(uintptr_t local, vsf_evt_t evt)
{
jmp_buf ret;
VSF_KERNEL_ASSERT(local != (uintptr_t)NULL);
class_internal( *(void **)((uintptr_t)local - sizeof(uintptr_t)),
this_ptr, vsf_thread_cb_t);
this_ptr->ret = &ret;
if (!setjmp(ret)) {
if (VSF_EVT_INIT == evt) {
uintptr_t stack = (uintptr_t)(&this_ptr->stack[(this_ptr->stack_size>>3)]);
printf("set_stack to 0x%08X %d \r\n", stack, this_ptr->stack_size);
__asm__("mov sp, %0;" : : "r"(stack));
printf("run on new stack\r\n");
__vsf_thread_entry();
} else {
longjmp(*(this_ptr->pos), evt);
}
}
}
这里需要通过set_stack设置新任务的堆栈,原来的堆栈,在之前的setjmp里被记录下来了,新任务返回后,会longjmp到原来的堆栈。
运行结果如下:
I (6018) heap_init: Initializing. RAM available for dynamic allocation:
I (6052) heap_init: At 3FF80000 len 00002000 (8 KiB): RTCRAM
I (6067) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (6083) heap_init: At 3FFB4A10 len 0002B5F0 (173 KiB): DRAM
I (6094) heap_init: At 3FFE0440 len 0001FBC0 (126 KiB): D/IRAM
I (6109) heap_init: At 40078000 len 00008000 (32 KiB): IRAM
I (6116) heap_init: At 4008A844 len 000157BC (85 KiB): IRAM
I (6307) spi_flash: detected chip: gd
I (6371) spi_flash: flash io: dio
W (6386) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (6436) cpu_start: Starting scheduler on PRO CPU.
set_stack to 0x3FFB4160 4096
Guru Meditation Error: Core 0 panic'ed (Double exception).
Core 0 register dump:
PC : 0x400849c3 PS : 0x00040136 A0 : 0x00000000 A1 : 0x3ffb4110
A2 : 0x3f400c9c A3 : 0x3ffafe24 A4 : 0x00001000 A5 : 0x3ffb8540
A6 : 0x3ffb84f0 A7 : 0x3ffb8540 A8 : 0x800d7960 A9 : 0x3ffb3e00
A10 : 0x00002889 A11 : 0x3ffb3e10 A12 : 0x3f400c9c A13 : 0x3ffb4140
A14 : 0x3ffb4120 A15 : 0x00000004 SAR : 0x00000015 EXCCAUSE: 0x00000002
EXCVADDR: 0x00000fe0 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace:0x400849c0:0x3ffb4110
ELF file SHA256: 9ca09f3ea1fea98f
Rebooting...
这里Double exception网上查到是双重异常,到时不知道是如何引发的。