Small RTOS OSStart 函数解析 以及 内存堆栈 变化 (二)

Small RTOS OSStart 函数解析 以及 内存堆栈 变化 (二)

中断:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

地址:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注意 :
4F 05 对应的 是 taskA函数 的 最后一个地址
59 05 对应的 是 taskB函数的 最后一个地址
63 05 对应的 是 taskC函数的 最后一个地址

83 01 91 03 是干嘛的?
0x0183是 调用完OSSched 子函数之后,返回的PC指针的地址
在这里插入图片描述

0x0391 也是一个地址 对应的是,调用完毕 OS_TASK_SW() 也就是,OSCtxSw()之后,程序的返回地址。
因为程序是在OSCtxSw() 中切换出去,到另外一个任务中去了,下次,轮到之前的任务运行的时候,是从之前切换出去的地方,继续运行的。

在这里插入图片描述
任务的运行状态是,
1 任务A执行
2 到达断点,
3 切换出去,
4 任务A等待,其他任务B运行
5 时间到了,任务A运行,从之前断点继续运行。

如果想要从之前的断点 继续运行,需要保存好,堆栈中的内容。
并且堆栈指针的位置,应该设置对。

当前的正在运行的任务B,在执行的时候,会不断的刷新堆栈中的内容。

函数,调用子函数,子函数 再次调用 子函数,这个样子,占用的堆栈内容会多一些。
任务不同,代码中,函数调用的情况不 一样,所以 在任务切换的时候,每个任务的堆栈 被占用的情况,不一样。

进入中断之后,
在这里插入图片描述

Keil C51 反汇编代码

在这里插入图片描述

任务A,B ,C 之间 在切换的时候,如果是因为 发生中断,进而产生了任务切换,因为中断是可能在任意某个代码位置发生中断,中断发生完毕之后,如果还想继续从之前被中断的位置继续执行,需要保存好断点时候的所有的现场数据,对应的汇编代码,会用到 R0—R7 寄存器,进行MOV 等等操作。
在中断服务程序中,也会用到 MOV R0 等等操作。

任务切换,两种情况,
一种的是 发生中断,这个不可控,是随机产生的。
每个代码位置都可能产生。

一种是 任务主动调用OS_Wait ,进行任务切换
主动 调用OS_Wait是 函数 调用子函数。函数与子函数之间 ,Keil C51 在汇编的时候,会自动避开容易被修改的R0 – R7 等寄存器。这个是可控的,不是随机的。

任务 有 TaskIdle —> OSIntExit
//OSTaskID = 3
//OSNextTaskID = 0

进入 OSIdle 之后的 切换到 TaskA

在这里插入图片描述

在这里插入图片描述

整体的数据,从0x28 到 0x38的数据,从 0x28 复制到0xEF

在这里插入图片描述
应该是那个地方的 下一条指令 继续执行

书中的 C代码 :要么是我没有看懂,要么是错误的,汇编代码是正确的

    /*0  < 3*/
    if(OSNextTaskID  < OSTaskID){


        /*cp2 = 0xFF*/
        cp2-- ; 
         
        /*0x38*/ 
        cp1-- ;

        
        
        
        /*0xFF  ! = 0x28*/
        while(cp2 != (uint8 idata *)temp ){

            *cp2-- = *cp1-- ;
            
        }


        /*0x28 -1 = 0x27*/
        SP = (uint8) OSTsakStackBotton[OSNextTaskID + 1 ] -1 ; 

        temp = OSTsakStackBotton[OSTaskID + 1] - (uint8 idata *)SaveSP -1 ;

        for(i = OSNextTaskID +1 ; i < OSTaskID +1 ; i++ ){

            OSTsakStackBotton[i] += temp ;
        }

        OSTaskID = OSNextTaskID ; 
        goto aaa ;
    }

在这里插入图片描述

看第5章需要知道的基础知识:
1 Keil C51 中的 函数 调用另外一个函数,函数中的局部变量 是给分配了一个固定的地址。相当于全局变量。Keil ARM 不是这样

2 任务A,运行到一半,主动调用一个等待函数,会触发调用任务切换函数,切换到别的任务B,进行执行。
当任务B 正在执行过程中,任务A的等待时间到了,而且任务A的,优先级够,在中断服务程序中,会调用任务切换函数,会自动切换会任务A执行,任务A执行的那个点,是之间被中断的代码的 下一条代码。而不是从任务A的函数的第一句代码开始执行。

3 函数A调用函数B,函数B调用函数C ,会自动的在堆栈中,保存函数A的断点,函数B的断点。
当函数C执行完毕,会回到函数B的断点继续执行。函数B执行完毕,会从函数A的断点处继续执行。

4 比如有三个任务,如果三个任务都处于等待状态,这个时间需要一个默认的 OsIdle 任务。

5.Keil C51 在分配内存的时候,会自动的将全局变量和局部变量,放在内存的前面,剩下的内存 才会赋值给堆栈指针,作为堆栈使用。

6.C51 的堆栈 是 指针 是向上生长的,主要是注意 C51汇编指令的PUSH 和POP的说明。

7.中断 可能在任务代码运行在随机的某个地方发生,参考Keil C51 的反汇编代码,这个时候,可能会用到 工作寄存器,PSW等,然后中断服务寄存器中也可能用到工作寄存器,会被改写,所以需要用户,保存好,工作寄存器 PSW寄存器。

8 . 任务的切换 原理 ,就是重新设置 堆栈指针的位置。并且预先在堆栈指针的地方填写 ,要跳转的任务函数的地址。
这个切换函数返回的时候,会自动的 调用 RET 汇编指令,
该指令 和 堆栈相关。

Small RTOS(51) 1.20.3v 说明文件 编写动机: 就像在嵌入系统中使用C语言替代汇编一样,在嵌入系统中使用RTOS是大势所趋。原因主要是现在在大多数情况下编程效率比执行效率重要(单片机便宜嘛)。但纵观51的RTOS,keil c51 所带的RTX Full 太大(6k多),且需要外部ram,又无源代码,很多时候不实用。RTX Tiny虽然小(900多字节),但是任务没有优先级和中断管理,也无源代码,也不太实用。而ucosII虽有源代码,但是它太大,又需要外部ram,所有函数又必须是重入函数,用在51这类小片内RAM的单片机上有点勉强。于是,我借鉴ucosII和RTX Tiny编写了Small RTOS 51,虽然它为51系列编写,但是它还是比较容易移植到其它CPU上。 与作者联系方法: 可以给chenmingji@tom.com(原chenmingji@163.net)写信,或是在www.zlgmcu.com.cn上的论坛ARM与ucosII区提问(目前本人是版主)或是在www.c51bbs.com的论坛上提问(不推荐。c51bbs和21ic网名均为cmj)。 版本号定义方式: a.bc.d a:主版本号,一般重大改变时改变它。 bc:次便本号,一般功能增加时改变它。 d:同一版本的修订序号。 版本升级: 1.20.3版 2004年6月8日 修正Os_q.c的一个BUG,造成FIFO发送数据时,在队列中有大量数据且队列较大时,可能会出错。 1.20.2版 2004年2月4日 修正for Keil c51的Os_cpu_c.c的StkDelB函数的BUG,它会影响任务删除的正确执行。 1.20.1版 2004年2月4日 修改OSWait(K_SIG | K_TMO, x) 只能通过信号唤醒的bug。 1.20.0版 2003年8月3日 支持任务动态建立与删除。函数功能向一般的RTOS靠拢。支持C51的重入函数(用关键字reentrant定义的函数)。支持动态内存分配(使用动态内存分配的任务必须使用重入)。 1.12.1版 2003年2月5日 修正OS_MAX_TASKS为8、16时的bug。同时修正一些小bug。 1.12.0版 2003年1月24日 OS_MAX_TASKS就是用户任务数量。同时修正一些小bug。 1.11.0版 2002年12月2日 各个任务具有自己的关中断计数器,不在互相影响(这意味着如果一个任务在任务放弃CPU前关了中断,当它再次进入运行态时中断还是关的)。优先级最低的任务作为系统保留任务不再需要用户编写,同时节约一些内存。增加一些注释。更正在Keil C51下Memory Model为非Small 模式的Bug。 1.10.5版 2002年10月26日 更正许多小Bug。 1.10.4版 2002年10月6日 合并Os_cpu_a.asm和OS_CPU_A_task16.ASM。统一了一下代码风格 1.10.3版 2002年9月16日 修改了Os_cpu_a.asm和OS_CPU_A_task16.ASM的LoadCtx代码使之执行更快,代码更小 1.10.2版 2002年9月9日 更正OSWait()的Bug,在极端情况下,这个Bug可能造成可能锁死任务。 修改OSQIntPost()的Keil C51特殊代码,它会造成阅读障碍。 1.10.1版 2002年9月4日 更正OSTimeTick的Bug,它在keil c51中不会有问题,但移植的其它系统可能出错。 1.10版 2002年9月1日 增加Small RTOS 对消息队列(简化的)和信号量的支持;改变了开关中断的方式;增加可移植的变量定义;修正一些Bug。 1.00版 2002年6月20日 使用户可以进行更多的配置,可以禁止中断管理,51系列支持软的非屏蔽中断,并调整目录结构等. 0.60版 2002年5月10日 修改OS_CORE.c使之在keil c51可以重入。不再需要禁止覆盖分析。 0.52版
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值