ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

rtos 3 - 实现一个可以运行多任务的简易rtos

2022-04-09 20:32:49  阅读:167  来源: 互联网

标签:STAK do 多任务 -- rtos CPU 简易 ptr stak


  1.创建任务

  创建任务的主要工作是对任务的stack进行初始化,也就是伪造一个现场。

/**********************************************************************************
    创建任务
**********************************************************************************/
int
osTaskCreate(OsTcb *tcb_ptr, TaskFunc task_ptr, char *name, void *param, CPU_STAK *stak_base, uint32_t stak_size)
{
    if(tcb_ptr == NULL) return -1;
    if(task_ptr == NULL) return -1;
    if(stak_base == NULL) return -1;
    
    /** 初始化堆栈,伪造现场 **/
    tcb_ptr->stak_ptr = _osTaskStakInit(task_ptr, param, stak_base, stak_size);
    
    /** 将任务加入就序列表 **/
    osTaskAddReadyList(tcb_ptr);
    return 0;
}

/**********************************************************************************
    堆栈初始化操作完任务栈空间的现场伪造,保证任务第一次执行时能正常运行。
**********************************************************************************/
static inline CPU_STAK *
_osTaskStakInit(TaskFunc task_ptr, void *param, CPU_STAK *stak_base, uint32_t stak_size)
{
    CPU_STAK * stak_ptr = &stak_base[stak_size];
    
    stak_ptr = (CPU_STAK *)((CPU_STAK)stak_ptr & 0xFFFFFFF8);
    
    * --stak_ptr = (CPU_STAK)0x01000000;        /** xPSR, bit24 = 1, use thumb instruction **/
    * --stak_ptr = (CPU_STAK)task_ptr;          /** R15/PC, enter point **/
    * --stak_ptr = (CPU_STAK)_osTaskReturn;     /** R14/LR, task return function **/
    * --stak_ptr = (CPU_STAK)0x12121212;        /** R12, do not care **/
    * --stak_ptr = (CPU_STAK)0x03030303;        /** R3, do not care **/
    * --stak_ptr = (CPU_STAK)0x02020202;        /** R2, do not care **/
    * --stak_ptr = (CPU_STAK)0x01010101;        /** R1, do not care **/
    * --stak_ptr = (CPU_STAK)param;             /** R0, parameter **/
    
    * --stak_ptr = (CPU_STAK)0x11111111;        /** R11, do not care **/
    * --stak_ptr = (CPU_STAK)0x10101010;        /** R10, do not care **/
    * --stak_ptr = (CPU_STAK)0x09090909;        /** R9, do not care **/
    * --stak_ptr = (CPU_STAK)0x08080808;        /** R8, do not care **/
    * --stak_ptr = (CPU_STAK)0x07070707;        /** R7, do not care **/
    * --stak_ptr = (CPU_STAK)0x06060606;        /** R6, do not care **/
    * --stak_ptr = (CPU_STAK)0x05050505;        /** R5, do not care **/
    * --stak_ptr = (CPU_STAK)0x04040404;        /** R4, do not care **/
    
    return stak_ptr;
}

  2. 任务切换

  任务切换在 SysTick_Handler 中执行,每次中断都进行一次任务切换。这里强调一点,由于任务切换是在systick中断中执行,因此在恢复完成新任务的现场之后,需要通过将进入中断时写入LR寄存器中的EXC_RETURN数据来触发中断返回,从而恢复现场,也即由硬件将R0 - R3、R12、LR、PC、xPSR寄存器的值从栈中恢复,而在中断执行过程中,又有函数调用会将LR中的值破坏掉,因此在进入 SysTick_Handler 时要第一时间把 EXC_RETURN 数据保存起来,已备触发中断返回时使用。

SysTick_Handler\
                PROC
                IMPORT    osTick
                
                ;保存 LR = EXC_RETURN
                ;将LR作为参数输入osTick,否则中断程序的过程调用会将LR中的值破坏
                MOV R0, LR
                BL  osTick
                ENDP
void
osTick(uint32_t lr)
{
    if(!os_running) return;
    
    /** 保存现场 **/
    if(g_cur_task != NULL)
        pushCtxAsm(g_cur_task->stak_ptr);
    
    /** 获取下一个就绪任务 **/
    osGetNextReadyTask();
    
    /** 切换任务 **/
    popCtxAsm(g_cur_task->stak_ptr, lr);
}
pushCtxAsm        PROC
                
                ;保存R4-R11寄存器到堆栈
                STMDB R0!, {R4 - R11}
                BX LR
                
                ENDP

popCtxAsm        PROC
            
                ;将 R4-R11从堆栈中写入寄存器
                ;R0 :任务的栈顶地址
                ;R1 :LR = EXC_RETURN
                
                LDMIA R0!, {R4 - R11}
                MSR MSP, R0        ;跟新SP指针
                BX  R1             ;将 EXC_RETURN 写入PC,触发中断返回
                
                ENDP

  完整代码:https://gitee.com/ivan1024/os.git

标签:STAK,do,多任务,--,rtos,CPU,简易,ptr,stak
来源: https://www.cnblogs.com/ivan0512/p/16123325.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有