然后是OSIntCtxSw():完成中断级任务切换,大部分和上一个函数一样
_OSIntCtxSw:
CALL _OSTaskSwHook
//OSUCBCur=OSTCBHighRdy
R1=_OSTCBCur
R2=[_OSTCBHighRdy]
[R1]=R2
//OSPrioCur=OSPrioHighRdy
R1=[_OSPrioHighRdy]
[_OSPrioCur]=R1
R1=[_OSTCBHighRdy]
SP=[R1]
POP R1 FROM [SP]
[_InterruptC]=R1
CMP R1,0
//查看是否需要关中断处理
JE KAI1
//如果不需要则直接返回
IRQ OFF
//需要就关中断
KAI1:
POP R1,R5 FROM [SP]
RETI
还有一个是OSTickISR():
这个函数其实不是必须叫这个名字,可以根据具体情况改变的,在uCOS_II.h里面关于函数原型的部分可以看到,它的原型是条件编译的,只要你定义一个OS_ISR_PROTO_EXT,编译器就不会再去编译这个原型了,定义OS_ISR_PROTO_EXT意味着你告诉编译器你将自己另写中断函数的,不再使用OSTickISR(),同时由于OSCtxSw()和OSTickISR()使用相同的
条件编译,你还必须再自己在
OS_CPU.H里面写一条语句:#define
OS_TASK_SW()
OSCtxSw();这样的话,就在任务切换时将调用你编写的函数(不过我开始没有定义那个OS_ISR_PROTO_EXT时也没有出现问题,所以这块我也不太肯定)
我自己写的中断函数是针对凌阳的,代码如下:
_IRQ6:
PUSH R1,R5 TO [SP]
R1=0x0002
[P_INT_Clear]=R1
//清中断标志
CALL _Clear_Dog
//俗称喂狗
R1=[_OSIntNesting]
R1+=1
[_OSIntNesting]=R1
CMP R1,1
JNE TCB
//查看是否发生中断嵌套,
R1=[_InterruptC]
//如果没有嵌套,则保存当前任务的中断计数器
PUSH R1 TO [SP]
//及任务堆栈地址
R2=[_OSTCBCur]
[R2]=SP
TCB:
CALL _OSTimeTick
CALL _OSIntExit
R1=[_OSIntNesting]
//如果能执行到此,则说明不需要任务切换
CMP R1,0
//查看是否发生过中断嵌套
JNE TCB1
//如果发生过,则没有保存中断计数器
POP R1 FROM [SP]
//否则需要弹出中断计数器调整堆栈指针
[_InterruptC]=R1
TCB1:
POP
R1,R5 FROM [SP]
RETI
OS_CPU.H:
在这个文件里面主要就是定义数据类型,一样的数据不同的CPU有不同的位数,在这里就是要定义移植过程中的数据位数问题,还有就是定义堆栈的生长方式,及OS_ENTER_CRITICAL( ),OS_EXIT_CRITICAL( ),OS_TASK_SW( ),也都是比较简单的问题,比较容易处理,不多废话
虽然说编译器有时候出些莫名其妙的问题,但我还是要说用好你的IDE真的是太重要了,象我在开始时老有问题,我不知道到底哪有毛病,怀疑是在保存堆栈指针时有问题,因为那一块尽是一堆的指针操作,我开始不知道怎么用那个变量查看窗口,就没办法确定我是否操作正确,最后比不得已,弄了半天学会了,通过那个窗口查看变量后,才确定自己真的是错在那了……
再有一个小小的经验就是像这种比较大的东西你要step调试真的很晕,我是自己搭了个小小的测试平台(其实就是8个发光二极管),连到B口,建立任务直接看结果,很简单,但真的很管用!
关键词:
UCOS移植心
加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW
或用微信扫描左侧二维码