本帖最后由 ruihuan 于 2013-5-25 15:32 编辑
当你看到操作系统的多任务并行的时候,你是否觉的很神奇呢?你是否想过那些任务的时间片轮转是怎么实现的呢?这个时间片轮转的秘密是什么呢?相信很多
单片机初学者都会对这个问题感兴趣。
当你查看单片机的汇编指令的时候,你是否留意过中断返回指令的操作过程?如果你留意过这个操作过程的话,你一定会发现它通过堆栈复原PC指针的过程。也就是说:当单片机产生中断的时候,它会把当前程序正在运行的PC指针保存在堆栈当中;然后当中断程序运行完毕的时候,程序执行中断返回指令,把堆栈中保存的PC指针再返回出来。这个是单片机运行的正常情况,但是如果在单片机的中断中修改了堆栈中的PC指针值,那么是不是中断就返不回来原来的程序地址?如果还是这个地址是我故意设定的值那么他是不是执行完这个中断就跳到我的设定的这个地址上去了?如果这个地址又是另外一个任务的地址的时候不是正好实现了从一个任务的死循环中跳到了另外一个任务的死循环中去了?对了!没错!多任务并行运行、时间片轮转的秘密就是:在定时中断中修改堆栈,使保存在中断中PC指针按照预定的方式改变从而让PC指针在几个任务地址中不停的跳转。如果你有空去看UCOS的移植代码的时候,你会发现切换任务的asm函数就是在修改堆栈的内容。当然了,真正的任务的切换过程不仅仅是修改PC指针的堆栈内容,同时也修改了单片机所用到的所有可能被用到的寄存器的内容。
分享的是我写的一个双任务并行的程序。一个任务是“main”函数的死循环,另外一个任务是函数“task1”中的死循环。任务操作很简单,就是两个io口不停在切换电平,但是由于两个任务中的时间延时不一样而是切换电平的频率不一样。单片机用的是瑞萨k0s系列的单片机(应为这个是我工作中常用的型号,我现在对这个比较熟,而51单片机很久没有用过了,所以用的是这个型号,什么时候有空了我再写个51单片机的程序)。有这个系列单片机
开发板的可以单步运行看看任务切换过程中“偷换”堆栈内容的过程。(后面将分享我在这个平台下写的一个简单的时间片轮转的小操作系统)修改堆栈内容的中断函数:
__interrupt void MD_INTTM80( void )
{
/* TODO */
#asm
push ax
push bc
push de
push hl
movw ax,sp
movw bc,ax
mov a,#0ffh
sub a, c
inc a
mov c,a ;the sp_long
;/*********************;load the sp_long*****************************/
mov a,c
mov !0fec0h,a ;load the sp_long
;/**************************************************/
mov b,a ;load the data
movw de,#0feffh
movw hl,#0fec1h
?L_mov1: mov a,[de]
mov [hl],a
decw de
dec b
incw hl
mov a,b
cmp a,#0h
bnz $?L_mov1
;/************************load the data to sp**************************/
mov a,!0fea0h ;load the data to sp
mov b,a
movw de,#0fea1h
movw hl,#0feffh
?L_mov2: mov a,[de]
mov [hl],a
incw de
dec b
decw hl
mov a,b
cmp a,#0h
bnz $?L_mov2
;/*************************get the new sp_point*************************/
mov a,#0ffh ;get the new sp_point
sub a,!0fea0h
inc a
mov !0fe90h,a
mov a,#0feh
mov !0fe91h,a
;/************************save the sp_data**************************/
mov a,!0fec0h ;save the sp_data
mov !0fea0h,a
mov b,a
movw de,#0fec1h
movw hl,#0fea1h
?L_mov_sp: mov a,[de]
mov [hl],a
incw de
dec b
incw hl
mov a,b
cmp a,#0h
bnz $?L_mov_sp
#endasm
/**************************************************/
#asm
mov a,!0fe90h
mov x,a
mov a,!0fe91h
movw sp,ax
pop hl
pop de
pop bc
pop ax
#endasm
}
在上面基础上自己写的基于NEC k0s系列 PM+ 开发环境下的简易操作系统源码分享
https://bbs.elecfans.com/forum.p ... 857&pid=1600685
一步步在自己熟悉的单片机平台上写自己的简易操作系统
(1)NEC k0s系列 PM+ 开发环境下的自己写的简易 操作系统代码
https://bbs.elecfans.com/forum.ph ... 0685&fromuid=756106
一步步在自己熟悉的单片机平台上写自己的简易操作系统
(2)代码分析一
https://bbs.elecfans.com/forum.ph ... 2371&fromuid=756106
一步步在自己熟悉的单片机平台上写自己的简易操作系统
(3)代码分析二
https://bbs.elecfans.com/forum.ph ... 9110&fromuid=756106
一步步在自己熟悉的单片机平台上写自己的简易操作系统
(3)代码分析三
https://bbs.elecfans.com/forum.ph ... 8743&fromuid=756106