硬汉嵌入式论坛

 找回密码
 立即注册
查看: 348|回复: 4
收起左侧

[有问必答] 关于RTOS任务的动态初始化

[复制链接]

3

主题

8

回帖

17

积分

新手上路

积分
17
发表于 2025-5-7 19:23:24 | 显示全部楼层 |阅读模式
大家能帮我看一下V2到底错在哪里了吗 一旦使用V2PendSVHandler就直接进入HardDefault了 自己不知道错在哪里了

// 这是正常版本的

// 动态创建任务
void tTaskCreated(tTask * task,void (*entry)(void *), void *param,
        uint32_t prio, uint32_t stack_size)
{


                taskENTER_CRITICAL();
                tTaskStack * stackTop = NULL;
                tTaskStack * StackStart = NULL;
                StackStart = (tTaskStack *)pvPortMalloc(stack_size);
                configASSERT((uint32_t)StackStart%8==0);
                if(StackStart == NULL)
                {
                                return;
                }
                task->stackBase = StackStart;
    task->stackSize = stack_size;
    memset(StackStart, 0, stack_size);
               
                stackTop = StackStart + stack_size / sizeof(tTaskStack);
               
                *(--stackTop) = (uint32_t)(1<<24);                // XPSR, 设置了Thumb模式,恢复到Thumb状态而非ARM状态运行
    *(--stackTop) = (uint32_t)entry;                  // 程序的入口地址
    *(--stackTop) = (uint32_t)portINITIAL_EXC_RETURN;         // R14(LR), 任务不会通过return xxx结束自己,所以未用
    *(--stackTop) = (uint32_t)0x12;                   // R12, 未用
    *(--stackTop) = (uint32_t)0x3;                    // R3, 未用
    *(--stackTop) = (uint32_t)0x2;                    // R2, 未用
    *(--stackTop) = (uint32_t)0x1;                    // R1, 未用
    *(--stackTop) = (uint32_t)param;                  // R0 = param, 传给任务的入口函数
   
    for (int i = 31; i >= 16; i--) {
        *(--stackTop) = (uint32_t)(0x00000000);  // S16–S31: 初始化为特殊值方便调试
    }
                *(--stackTop) = (uint32_t)portINITIAL_EXC_RETURN;  // R14(LR)
                *(--stackTop) = (uint32_t)0x11;                   // R11, 未用
    *(--stackTop) = (uint32_t)0x10;                   // R10, 未用
    *(--stackTop) = (uint32_t)0x9;                    // R9, 未用
    *(--stackTop) = (uint32_t)0x8;                    // R8, 未用
    *(--stackTop) = (uint32_t)0x7;                    // R7, 未用
    *(--stackTop) = (uint32_t)0x6;                    // R6, 未用
    *(--stackTop) = (uint32_t)0x5;                    // R5, 未用
    *(--stackTop) = (uint32_t)0x4;                    // R4, 未用


    task->slice = TINYOS_SLICE_MAX;                     // 初始化任务的时间片计数
    task->stack = stackTop;                             // 保存最终的值
    task->prio = prio;                                  // 设置任务的优先级
    task->state = TINYOS_TASK_STATE_RDY;                // 设置任务为就绪状态
    task->suspendCount = 0;                             // 初始挂起次数为0
    task->clean = (void(*)(void *))0;                   // 设置清理函数
    task->cleanParam = (void *)0;                       // 设置传递给清理函数的参数
    task->requestDeleteFlag = 0;                        // 请求删除标记


    task->waitEvent = (tEvent *)0;                      // 没有等待事件
    task->eventMsg = (void *)0;                         // 没有等待事件
    task->waitEventResult = tErrorNoError;              // 没有等待事件错误


    tNodeInit(&(task->delayNode));                      // 初始化延时结点
   
    tNodeInit(&(task->linkNode));                       // 初始化链接结点


    tTaskSchedRdy(task);                                // 将任务插入就绪队列
                taskEXIT_CRITICAL();
                return;
}

// 这是V2 tTask也动态分配
tTask * tTaskCreatedV2(void (*entry)(void *), void *param,
        uint32_t prio, uint32_t stack_size)
{


                taskENTER_CRITICAL();
                tTask * task = NULL;
                tTaskStack * stackTop = NULL;
                tTaskStack * StackStart = NULL;
                task = (tTask *)pvPortMalloc(sizeof(tTask));
                memset(task, 0x00, sizeof(tTask));
                StackStart = (tTaskStack *)pvPortMalloc(stack_size);
                configASSERT((uint32_t)StackStart%8==0);
                if(StackStart == NULL)
                {
                                vPortFree(task);
                                task = NULL;
                                return task;
                }
                task->stackBase = StackStart;
    task->stackSize = stack_size;
    memset(StackStart, 0, stack_size);
               
                stackTop = StackStart + stack_size / sizeof(tTaskStack);
               
                *(--stackTop) = (uint32_t)(1<<24);                // XPSR, 设置了Thumb模式,恢复到Thumb状态而非ARM状态运行
    *(--stackTop) = (uint32_t)entry;                  // 程序的入口地址
    *(--stackTop) = (uint32_t)portINITIAL_EXC_RETURN;         // R14(LR), 任务不会通过return xxx结束自己,所以未用
    *(--stackTop) = (uint32_t)0x12;                   // R12, 未用
    *(--stackTop) = (uint32_t)0x3;                    // R3, 未用
    *(--stackTop) = (uint32_t)0x2;                    // R2, 未用
    *(--stackTop) = (uint32_t)0x1;                    // R1, 未用
    *(--stackTop) = (uint32_t)param;                  // R0 = param, 传给任务的入口函数
   
    for (int i = 31; i >= 16; i--) {
        *(--stackTop) = (uint32_t)(0x00000000);  // S16–S31: 初始化为特殊值方便调试
    }
                *(--stackTop) = (uint32_t)portINITIAL_EXC_RETURN;  // R14(LR)
                *(--stackTop) = (uint32_t)0x11;                   // R11, 未用
    *(--stackTop) = (uint32_t)0x10;                   // R10, 未用
    *(--stackTop) = (uint32_t)0x9;                    // R9, 未用
    *(--stackTop) = (uint32_t)0x8;                    // R8, 未用
    *(--stackTop) = (uint32_t)0x7;                    // R7, 未用
    *(--stackTop) = (uint32_t)0x6;                    // R6, 未用
    *(--stackTop) = (uint32_t)0x5;                    // R5, 未用
    *(--stackTop) = (uint32_t)0x4;                    // R4, 未用


    task->slice = TINYOS_SLICE_MAX;                     // 初始化任务的时间片计数
    task->stack = stackTop;                             // 保存最终的值
    task->prio = prio;                                  // 设置任务的优先级
    task->state = TINYOS_TASK_STATE_RDY;                // 设置任务为就绪状态
    task->suspendCount = 0;                             // 初始挂起次数为0
    task->clean = (void(*)(void *))0;                   // 设置清理函数
    task->cleanParam = (void *)0;                       // 设置传递给清理函数的参数
    task->requestDeleteFlag = 0;                        // 请求删除标记


    task->waitEvent = (tEvent *)0;                      // 没有等待事件
    task->eventMsg = (void *)0;                         // 没有等待事件
    task->waitEventResult = tErrorNoError;              // 没有等待事件错误


    tNodeInit(&(task->delayNode));                      // 初始化延时结点
   
    tNodeInit(&(task->linkNode));                       // 初始化链接结点


    tTaskSchedRdy(task);                                // 将任务插入就绪队列
                taskEXIT_CRITICAL();
                return task;
}

其中动态分配内存来自一个uHeap大数组和FreeRTOS一样 通过调试可以发现是卡在了

LDR     R0, =currentTask          // 好了,准备切换了
    LDR     R1, =nextTask            
    LDR     R2, [R1]  
    STR     R2, [R0]                  // 先将currentTask设置为nextTask,也就是下一任务变成了当前任务

    LDR     R0, [R2]                  // 这里V2获得的R0莫名奇妙
    LDMIA   R0!, {R4-R11,LR}         // 导致这里直接错误了

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 2025-5-8 09:44:58 | 显示全部楼层
这个是仿造FreeRTOS,自制了一个任务创建API?
回复

使用道具 举报

3

主题

8

回帖

17

积分

新手上路

积分
17
 楼主| 发表于 2025-5-8 15:52:25 | 显示全部楼层
eric2013 发表于 2025-5-8 09:44
这个是仿造FreeRTOS,自制了一个任务创建API?

对我想自己了解了解原理 结果就出了这么个问题自己也没思路去解决
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116197
QQ
发表于 2025-5-9 01:38:17 | 显示全部楼层
LightingSky 发表于 2025-5-8 15:52
对我想自己了解了解原理 结果就出了这么个问题自己也没思路去解决

这种的可以考虑调用他们的API,然后在逐步修改这个API为自己的理解方式,逐步修改,这样可能更有利于学习
回复

使用道具 举报

3

主题

8

回帖

17

积分

新手上路

积分
17
 楼主| 发表于 2025-5-9 10:28:44 | 显示全部楼层
感谢您的回复
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-6-9 19:28 , Processed in 0.223932 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表