本帖最后由 djyos 于 2009-9-5 07:45 编辑
看本文请参考《都江堰操作系统与嵌入式系统设计》第15章,该书可在www.djyos.com下载。
写这一篇的时候,djyos在stm32上已经跑起来了,只是串口驱动还没有写,不能输出而已。从之一到之五,东扯西扯了很多东西,包括移植方法,中断系统实现方法,上下文设计、开发工具等,除了在之三列出了初始化代码外,其他几篇都没有代码。这是因为代码一直在调试中,变化很大,写出来也是白搭,这不,之三列出的代码,就是针对gcc环境的,在mdk下全改了。写移植日志,如果没有代码的话,原理讲得再多,也是纸上谈兵,现在系统跑起来了,底层代码基本不会变了,我们就结合代码来讲解一下。
移植djyos,需要修改的代码主要有:中断相关代码、cpu硬件初始化代码、上下文操作代码等。djyos代码在所有可能需要在移植时修改的代码中,均有“移植关键”字样的注释。
我们先对比arm7来讲解一下cm3中上下文切换。
1、设置初始上下文
线程的上下文指线程执行环境的当前状态,其实也就是影响该线程执行的cpu寄存器的状态,在cm3中,这些寄存器一共有17个:R0-R15(R15即PC)和xpsr,但从之四上的那张图上,我们并没有看到R13(即SP),那是因为上下文保存在当前线程的栈的当前位置,该位置是变化的,而恢复上下文又必须先得到SP才可以,所以SP只能保存在某一个固定的位置,而不能保存在栈中。djyos把SP保存在当前线程虚拟机的线程控制块中。
线程执行之前,我们必须为它准备好上下文,也就是初始上下文,djyos中,所有线程都是由函数__djy_vm_engine发动的,该函数有一个参数,即线程所属事件的处理函数指针,根据aapcs规定,该参数保存在R0中。因此,初始上下文中只有R0和PC是有效的,xpsr应该给一个合法的初始值外,其他寄存器可以用任意值,所以,初始上下文设置为:
R0:线程所属事件的处理函数指针。
PC:__djy_vm_engine函数的地址
xpsr:0x01000000,thumb状态,清掉其他所有标志。
其他寄存器:任意。
__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} ;存pc,xpsr
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
|