昨晚看到了任務切換時的匯編文件,才終于知道人為怎么才可以制造一次模擬中斷,任務切換時就是模擬發生了一次中斷,其實!他工作的原理是什么呢?
這就要看匯編文件:
MOV DPH,#HIGH (OSRunning)
MOV DPL,#LOW (OSRunning)
MOV A,#1
MOVX @DPTR,A
SETB TR0
這一段是把系統狀態改成運行
并且開啟系統定時器
MOV DPH,#HIGH(OSTCBHighRdy)
MOV DPL,#LOW (OSTCBHighRdy)
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R0
MOV DPL,A
;Move OSTCBStkPtr to dptr
MOVX A,@DPTR
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV DPH,R0
MOV DPL,A
上面的一段是用DPTR指向任務的堆棧,這一點非常重要。這里不得不說他分兩次查找,第一次它裝載指向堆棧的指針,找到這指針變量的位置后他再一次的吧指針里面的地址取出來裝載到DPTR中,所以看到的是兩次對DPTR進行賦值,R0作為暫存無實際意義
MOVX A,@DPTR
MOV ?C_IBP,A
JZ OSCPUASmltRstOver ;
INC DPTR
MOVX A,@DPTR
MOV R0,#StkBottom - 1 ;
MOV R1,A ;
ADD A,R0 ;sp
MOV SP,A
這一段非常重要他做了什么?
他首先取出用戶堆棧的第一個數據,這個數據叫做IBP,
然后取出堆棧的第二個數據,就是初始化的時后定義的堆棧的大小,
然后又取出系統設定好的堆棧開始地址,然后兩者求和,求出的和就是SP最后的大小,也就是說SP指針已經指向了最高的地址(如果堆棧向上升成長)
OSCPUARstHardStk:
INC R0
INC DPTR
MOVX A,@DPTR
MOV @R0,A
DJNZ R1,OSCPUARstHardStk
顯然這是一個循環,他的做用就是吧剩下的用戶對戰里的數據全部加載到CPU硬件堆棧中,比如函數入口地址,ACCb,psw等保存在用戶堆棧的數據全部加載到系統棧中,接下來才是關鍵的也是最后的一哆嗦,
POP 07
POP 06
POP 05
POP 04
POP 03
POP 02
POP 01
POP 00
POP PSW
POP DPL
POP DPH
POP B
POP ACC ;A is register but ACC is direct ram
SETB EA ;after start, enable EA
RETI
這個是個出棧命令,POP,前面已經說到SP已經指向了最高的堆棧地值,那么這就表示把系統棧的所有的數據全部彈入對應的寄存器寄存器中,也就是說他用MOV指令代替了PUSH,他用MOV把用戶棧數據復制到系統棧中,然后用戶POP把系統棧的數據又恢復到寄存器中,是不是有點多此一舉?直接把用戶數據恢復到CPU寄存器不是更快馬?開始我那么想,向下看,有個RETI,再看棧頂正好存入的是函數的入口地址,哈哈所以他就跳轉到了對應的任務中去了,跟中斷幾乎是一模一樣的,都是保護現場,一個樣,
注意區分戶任務棧和系統棧,所謂系統棧就是那個用SP做棧指針,用RETI返回的棧,而用戶棧其實說白了就是個數組而已!需要用戶自己定義。
以上是出棧,入站的問題上比較糾結,主要是不符合預想,有待學習!他壓棧的時候是把一組從f0-ff之間的數據寫進去了后面又緊跟著系統棧的內容,按理說入棧就把系統棧內的寄存器保存就可以了吧,為什么還要入一塊不相關的內存?而且任務加載總是從初始化開始,沒有進行任務間的轉換,還看不到他處理的方法,不過思路都差不多,入站的格式一定得和出站的格式是一樣的存放順序(在用戶站立)否則他不可能找到正確的如口的!糾結中。。。。。。。
|