我们继续上篇。上篇我漏了个开总中断忘说了。

开中断。 对了调试的时候吧任务A的睡眠给隐掉。因为一步一步来学习嘛! 当开了中断,于是开始执行定时器0中断,定时器中的代码一个是OSTimeTick(); 执行任务时间片的分配。这里注意了,我自个写的时候调试出现问题才发现的。他是先判断是否有时间片,有则--,然后再判断是否为0为0则 OSIntSendSignal(TaskId)。 OSIntSendSignal就是把任务置为就绪的没什么,有必要提的就是关中断和开中断。这个为了避免产生中断导致不可预知的错误。 然后回到定时器0的中断服务程序中,执行OSIntExit()。然后转到==》OSIntCtxSw ==》 C_OSCtxSw ==》LoadCtx 然后就切换到任务B 。现在我开始慢慢的分析这几个函数,因为这里是需要慢慢讲解的。首先从原理上讲下。定时器中断时依次把
中断后 然后查看 内存 按推断应该是sp-15 个字节 =i:0x16 如图
你可以看出 中断服务程序保存环境是按什么次序入栈的。帅吧~~~
然后执行OSIntExit()压入 0x0256
15+2 =17个字节然后 再跳转到 OSIntCtxSw
这里开始用51
汇编写的,这里是经常执行的代码必须有效率。 在OSIntCtxSw 判断当前任务是什么性质的,现在这个是任务A随意是sp=sp-4 并置中断类型标志位,清任务运行标志位,LMJP OSCtxSw 首先压入一个中断计数,然后开始吧 【前任务+1的存放地址 ----下个任务+1的地址】 这里有个第优先级上还存放了个任务就是为符合这个处理方式。吧括号中的数据整个搬到上图sp后面,然后吧修改后的函数首地址重新分配 OSTsakStackBotton存放 然后把下个任务切换成当前任务,他的内存空间就是现在SP ---任务+1之间的空间。 这里的堆栈是从低到高分配的和PC里不一样。然后还做了个清中断标志的操作 压入 LoadCtx 的函数地址的栈然后RETI 这个主要是清掉中断标志,然后跳转到环境加载函数 。然后LoadCtx 就把堆栈中下个任务的地址直接RET返回给$P于是就切换到下个任务了。 优先级低的也差不对这样处理的。
为了模拟跳转到任务B 在中断前加 extern uint8 OSTaskRuning; 在 OSIntExit(); 前+OSTaskRuning &=~OSMapTbl[0]; 这样就模拟跳转到任务B
嘿嘿,不好意思 +了那么入栈的数据就有变化了。但是数目应该没变,我就不重新截图了。
OSIntCtxSw 执行后SP-4
放B的地址可以通过
看到i:0xF7是存储的B的首地址,
数据块应该是 【A+1】- 【B+1】之间的数据整个搬到当前sp+1后面 搬移后的内存分布
后面 中断计数 00 +搬过来的B-C间的2个字节 C7 03这个正好是B任务的首地重新修改存放函数首地址的数组
这里可以跳转到LoadCtx 吧任务切到任务B中。
至此通过中断任务切换已经完毕,此时可以向下如果任务中有数据在其中,那么这样做会不会丢失数据,其实仔细想想就可以了解,不会的。
本例源代码下载:http://www.51hei.com/f/small_rtos1.12.1.zip
接下篇: