首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

上下文切换

上下文切换

看本文请参考《都江堰操作系统与嵌入式系统设计》第15章,该书可在www.djyos.com下载。
写这一篇的时候,djyosstm32上已经跑起来了,只是串口驱动还没有写,不能输出而已。从之一到之五,东扯西扯了很多东西,包括移植方法,中断系统实现方法,上下文设计、开发工具等,除了在之三列出了初始化代码外,其他几篇都没有代码。这是因为代码一直在调试中,变化很大,写出来也是白搭,这不,之三列出的代码,就是针对gcc环境的,在mdk下全改了。写移植日志,如果没有代码的话,原理讲得再多,也是纸上谈兵,现在系统跑起来了,底层代码基本不会变了,我们就结合代码来讲解一下。
移植djyos,需要修改的代码主要有:中断相关代码、cpu硬件初始化代码、上下文操作代码等。djyos代码在所有可能需要在移植时修改的代码中,均有“移植关键”字样的注释。
我们先对比arm7来讲解一下cm3中上下文切换。
1、设置初始上下文

线程的上下文指线程执行环境的当前状态,其实也就是影响该线程执行的cpu寄存器的状态,在cm3中,这些寄存器一共有17个:R0-R15R15PC)和xpsr,但从之四上的那张图上,我们并没有看到R13(即SP),那是因为上下文保存在当前线程的栈的当前位置,该位置是变化的,而恢复上下文又必须先得到SP才可以,所以SP只能保存在某一个固定的位置,而不能保存在栈中。djyosSP保存在当前线程虚拟机的线程控制块中。
线程执行之前,我们必须为它准备好上下文,也就是初始上下文,djyos中,所有线程都是由函数__djy_vm_engine发动的,该函数有一个参数,即线程所属事件的处理函数指针,根据aapcs规定,该参数保存在R0中。因此,初始上下文中只有R0PC是有效的,xpsr应该给一个合法的初始值外,其他寄存器可以用任意值,所以,初始上下文设置为:
R0:线程所属事件的处理函数指针。
PC__djy_vm_engine函数的地址
xpsr0x01000000thumb状态,清掉其他所有标志。
其他寄存器:任意。
__asm_reset_thread函数完成线程初始上下文设置,意为复位线程到初始状态。函数本身注释已经很明白,就不再解释了。
;函数原型:void *__asm_reset_thread(void (*thread_routine)(struct event_script*),
;                                       struct  thread_vm *vm);
;-----------------------------------------------------------------------------
__asm_reset_thread  PROC
   EXPORT  __asm_reset_thread
   ldr    r2,[r1,#4]         ;取虚拟机栈顶指针
   mov    r4,#0x01000000     ;xpsr的初始值
   ldr    r3,=__djy_vm_engine ;取虚拟机引擎指针
   stmfd  r2!,{r3,r4}        ;pcxpsr
   sub    r2,r2,#14*4        ;后退14个寄存器,初始状态r0-r12中,除r0外均无意义,
                               ;__vm_engine函数不返回,lr也无意义
   ;存在r0中的thread_routine__vm_engine的参数,切换上下文时,thread_routine
   ;恢复到r0中,根据调用约定,r0的值就是__vm_engine函数的参数。
   str    r0,[r2,#8*4]       ;保存 thread_routine指针到r0的位置.
   str    r2,[r1]            ;保存vm的当前栈指针到vm->stack
   bx     lr

      ENDP

2、上下文切换

上下文切换即中止正在处理的事件(线程),转而处理另一个事件,在下列情形下,将引发上下文切换:
a、正在执行的线程因故被阻塞,比如请求使用设备,但该设备正忙。
b、有高优先级的线程就绪,比如释放了信号量,而使正在等待信号量的高优先级事件就绪
继承事业,薪火相传
返回列表