以cortex-M4为例,在/libcpu/arm/cortex-m4/cpuport.c中被定义
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
struct stack_frame * stack_frame;
rt_uint8_t * stk;
unsigned long i;
stk = stack_addr + sizeof(rt_uint32_t);
stk -= sizeof(struct stack_frame);
stack_frame = (struct stack_frame *)stk;
/* init all register */
for(i=0; i {
((rt_uint32_t*)stack_frame)
= 0xdeadbeef;
}
stack_frame->exception_stack_frame.r0 = (unsigned long)parameter; /* r0 : argument */
stack_frame->exception_stack_frame.r1 = 0; /* r1 */
stack_frame->exception_stack_frame.r2 = 0; /* r2 */
stack_frame->exception_stack_frame.r3 = 0; /* r3 */
stack_frame->exception_stack_frame.r12 = 0; /* r12 */
stack_frame->exception_stack_frame.lr = (unsigned long)texit; /* lr */
stack_frame->exception_stack_frame.pc = (unsigned long)tentry; /* entry point, pc */
stack_frame->exception_stack_frame.psr = 0x01000000L; /* PSR */
/* return task's current stack address */
return stk;
}
在thead.c文件_rt_thread_init()中被调用
thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
(void *) ((char *)thread->stack_addr + thread->stack_size - 4),
(void *)rt_thread_exit);
先将栈指针从栈底stack_addr指向栈顶stack_addr + thread->stack_size - 4,然后向下移动sizeof(struct stack_frame)个字节,顺次初始化exception_stack_frame中的寄存器中的值,这样栈也是向下生长的。其中,R0存了线程的入口参数,pc存了线程的入口函数地址,lr存了线程的exit函数地址(rt_thread_exit为所有线程公用),而SP是保存在线程自己的TCB结构体中,线程切换时根据SP换入/换出这些寄存器。
栈指针的起始地址可以来源于heap(rt_thread_create( )使用rt_malloc( )得到),也可以从静态RAM区获得(如rt_thread_idle_init()就使用的是数组rt_thread_stack[IDLE_THREAD_STACK_SIZE]的起始地址)。
stack的初始化是线程初始化的重要一环,里面使用到了_rt_thread_init()中的entry, parameter,stack_addr, stack_size多个参数。
以cortex-M4为例,在/libcpu/arm/cortex-m4/cpuport.c中被定义
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
rt_uint8_t *stack_addr, void *texit)
{
struct stack_frame * stack_frame;
rt_uint8_t * stk;
unsigned long i;
stk = stack_addr + sizeof(rt_uint32_t);
stk -= sizeof(struct stack_frame);
stack_frame = (struct stack_frame *)stk;
/* init all register */
for(i=0; i {
((rt_uint32_t*)stack_frame)
= 0xdeadbeef;
}
stack_frame->exception_stack_frame.r0 = (unsigned long)parameter; /* r0 : argument */
stack_frame->exception_stack_frame.r1 = 0; /* r1 */
stack_frame->exception_stack_frame.r2 = 0; /* r2 */
stack_frame->exception_stack_frame.r3 = 0; /* r3 */
stack_frame->exception_stack_frame.r12 = 0; /* r12 */
stack_frame->exception_stack_frame.lr = (unsigned long)texit; /* lr */
stack_frame->exception_stack_frame.pc = (unsigned long)tentry; /* entry point, pc */
stack_frame->exception_stack_frame.psr = 0x01000000L; /* PSR */
/* return task's current stack address */
return stk;
}
在thead.c文件_rt_thread_init()中被调用
thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
(void *) ((char *)thread->stack_addr + thread->stack_size - 4),
(void *)rt_thread_exit);
先将栈指针从栈底stack_addr指向栈顶stack_addr + thread->stack_size - 4,然后向下移动sizeof(struct stack_frame)个字节,顺次初始化exception_stack_frame中的寄存器中的值,这样栈也是向下生长的。其中,R0存了线程的入口参数,pc存了线程的入口函数地址,lr存了线程的exit函数地址(rt_thread_exit为所有线程公用),而SP是保存在线程自己的TCB结构体中,线程切换时根据SP换入/换出这些寄存器。
栈指针的起始地址可以来源于heap(rt_thread_create( )使用rt_malloc( )得到),也可以从静态RAM区获得(如rt_thread_idle_init()就使用的是数组rt_thread_stack[IDLE_THREAD_STACK_SIZE]的起始地址)。
stack的初始化是线程初始化的重要一环,里面使用到了_rt_thread_init()中的entry, parameter,stack_addr, stack_size多个参数。
举报