嵌入式技术论坛
直播中

泡芙奶昔

11年用户 716经验值
私信 关注
[问答]

请问rt_hw_stack_init()函数到底是怎么用的呢

在移植的时候,发现rt_hw_stack_init()函数,
没有函数体,也没有说明,
请问,它到底是怎么用的呢?
谢谢!

回帖(7)

ss

2022-4-7 11:40:59
这个函数是用于准备线程的初始栈的。
举报

那些年儿ing

2022-4-7 11:41:32
以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多个参数。
举报

世态薄凉

2022-4-7 11:42:02
最新版多了一行:

    stk  = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);

以保证栈是8字节对齐的,Clib,特别是浮点运算库对此有要求!
举报

剑寒九州

2022-4-7 11:42:14
为啥不是用4字节对齐?
举报

ss

2022-4-7 11:42:30
大多数处理器,当需要使用浮点时,需要8字节对齐
举报

倪love

2022-4-7 11:42:56
那么它访问寄存器时是四字节对齐的还是八字节对齐的呢?
举报

ss

2022-4-7 11:43:08
是按4字节对齐出栈, 关于8字节对齐的原因是因为浮点库的问题, 在arm的浮点库中有一段代码, 它是假定栈是按8字节对齐且浮点数也是如此对齐, 而它用的代码是类似 addr = (addr + 7) & ~7, 去计算浮点数的地址, 一旦不是8对齐就会导致浮点数有4字节的错位, 严重时会导致死机
举报

更多回帖

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