最新版本uC-OS2-2.93.01已移植到STC8上,帮忙查错每条错误感谢200元
本帖最后由 8051爱好者 于 2023-8-22 10:48 编辑最新版本uC-OS2-2.93.01已移植到STC最新的 1T 8051, STC8H8K64U上
===适用于STC8系列所有型号
===解决了网络上不同移植版本潜在的bug
===鼓励大家在STC官方论坛 www.STCAIMCU.com 帮忙查错, 200元/每条错误, 感谢, 大家一起前行
许可改成 APACHE 2.0 也就是可以商业使用不用授权。具体可以查看APACHE 2.0内容。
声明:本移植版本参考了陈是知移植版本和STC网站上的原网友版, 另外测试例子使用杨为民老师移植的版本
一,提升速度
1. 重要的变量使用data修饰
2. 结构体指针变量使用xdata修饰
3. 使用DPTR自增方式
注意,使用DPTR自增方式,这部分代码不能硬件仿真,单独调试,可以全速运行。
os_cpu_a.A51文件,有测试信号。
P20 测试OSIntExit 运行时间(有任务切换4us)(无任务2.83us)
P21 测试OSIntCtxSw系统级切换任务时间 (8.6us)
P23 测试OSCtxSw 任务级切换任务时间 (8.7us)
P26 测试滴答定时器中断全过程时间 (有任务24.3us) (无任务13us)
P27 测试OSTimeTick运行时间 (有任11.2us)(无任务9.3us)
以上测试,选择 STC8H8K64U 工作时钟是 40MHz
os_cpu_a.A51文件,有测试信号。
P20 测试OSIntExit 运行时间(有任务切换4us)(无任务2.83us)
P21 测试OSIntCtxSw系统级切换任务时间(8.6us)
P23 测试OSCtxSw 任务级切换任务时间 (8.7us)
P26 测试滴答定时器中断全过程时间 (有任务24.3us) (无任务13us)
P27 测试OSTimeTick运行时间 (有任11.2us)(无任务9.3us)
以上测试,选择工作时钟是40MHz
二,允许任务堆栈空间任意大小
修改了OSTaskCreate,增加stk_size入口
[*]INT8UOSTaskCreate (void (*task)(void *p_arg),
[*] void *p_arg,
[*] OS_STK*ptos,
[*] INT16U stk_size,
[*] INT8U prio) large reentrant
复制代码OS_STK*OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)
对 OSTaskStkInit函数利用 opt 传入任务堆栈大小 实现不等长任务堆栈
三 ,临界区保护方法,支持方法2和方法3
[*]#if OS_CRITICAL_METHOD==2
[*]//执行OS_ENTER_CRITICAL()时,先将中断状态保存到堆栈,然后关中断;
[*]//执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。这种方法不会改变中断状态,避免前面的问题。
[*]//但是,当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。
[*]//问题分析:OS_ENTER_CRITICAL()时导致中断切换任务的时候硬件堆栈多入了一个_push_(IE),
[*]//解决方法:OSIntCtxSw()函数调整SP的时候应该多减1,原来SP=SP-4改为SP=SP-5
[*]#include <intrins.h>
[*]#define OS_ENTER_CRITICAL()do{_push_(IE);EA = 0;}while(0) /* 利用堆栈保存中断状态,再关中断*/
[*]#define OS_EXIT_CRITICAL()do{ _pop_ (IE);}while(0) /* 将IE从堆栈弹出,恢复IE值 */
[*]#endif
[*]
[*]#if OS_CRITICAL_METHOD==3
[*]//获取当前中断状态的值,并将其保存在C函数局部变量之中
[*]//问题分析:可重入函数的局部变量cpu_sr会入仿真栈。导致中断切换任务的时候,仿真堆栈出问题。
[*]//解决方法:OSIntCtxSw()函数执行时需要对仿真堆栈指针++操作。
[*]#define OS_ENTER_CRITICAL() do{ cpu_sr=IE;EA = 0;}while(0)
[*]#define OS_EXIT_CRITICAL()do{ IE = cpu_sr; }while(0)
[*]#endif
复制代码
四,支持软件定时器
之前移植的版本没有适配软件定时器功能。OS_VERSION >= 281 支持软件定时器。
移植过程中遇到一个困难,就是回调函数,函数指针问题。重点是指针ptmr需要加上xdata修饰。
[*]typedefvoid (code *OS_TMR_CALLBACK)(void xdata*ptmr, void *parg) large reentrant;
复制代码五,解决RET和RETI混用问题
OSIntCtxSw 是在中断中调用的,需要调用RETI返回
OSStartHighRdy 运行第一个任务,应该用RET返回
OSCtxSw在任务中调用的,应该用RET返回
这三个函数最后部分的代码都一样。之前移植的版本统一用RETI返回,导致混用。
本移植提供2个解决方法,原则是OSIntCtxSw 函数提前退出中断,统一用RET返回
[*];方法1:直接把OSIntCtxSw_in函数地址入栈,由RETI中断返回,跳转到OSIntCtxSw_in函数,共6T
[*] MOV DPTR,#OSIntCtxSw_in
[*] PUSH DPL
[*] PUSH DPH
[*] RETI
[*]
[*] ;方法2:;巧妙的利用函数返回RETI执行了中断完毕,跳转到下一条语句。这样任务可以无忧使用RET作为返回,共9T。
[*] LCALL RE_RETI
[*] LJMP OSIntCtxSw_in
[*]RE_RETI: RETI
复制代码显然方法1更优秀
当然还有方法3,3个函数独立,不要共同出口。这里不推荐,浪费代码空间。
六,关于中断嵌套的做法
提供了2个中断例子:
定时器1 中断演示允许中断嵌套
定时器3 中断演示禁止中断嵌套
[*]; ==== 定时器1 中断服务程序 =============
[*];演示允许中断嵌套
[*]EXTRN CODE(_?Timer1_Handler)
[*]Timer1_ISR:
[*] USING 0 ;工作寄存器0
[*] CLR EA;调用OSIntEnter之前先关中断
[*];SETB P20
[*] PUSHALL ;现场保护
[*] LCALL _?OSIntEnter ;通知内核进入中断
[*] SETB EA;允许中断嵌套
[*]
[*] LCALL _?Timer1_Handler
[*]
[*] LCALL _?OSIntExit ;通知内核退出中断
[*] POPALL ;恢复现场
[*];CLR P20
[*] RETI
[*]
[*]
[*]; ==== 定时器3 中断服务程序 =============
[*];演示禁止中断嵌套
[*]EXTRN CODE(_?Timer3_Handler)
[*]Timer3_ISR:
[*] USING 0 ;工作寄存器0
[*];SETB P20;
[*] CLR EA ;禁止中断嵌套
[*] PUSHALL ;现场保护
[*]
[*] LCALL _?Timer3_Handler
[*]
[*] POPALL ;恢复现场
[*];CLR P20
[*] SETBEA ;中断函数执行完毕,重新允许中断
[*] RETI
复制代码
对于OSIntEnter 还有更优秀的做法,在中断里面直接OSIntNesting++,我之前另一帖子有讲,需要改动源码。
推荐使用OSIntEnter 函数。
七,堆栈初始化函数,对void *p_arg正确做法
//R3、R2、R1用于传递任务参数p_arg,其中R3代表存储器类型,R2为高字节偏移,R1为低字节位移。
*stk++ = (INT16U)p_arg & 0xFF; // R1
*stk++ = (INT16U)p_arg >> 8; // R2
*stk++ = (INT32U)p_arg >> 16; // R3 存储器类型有code(0xFF),xdata(0x01),data(0x00),idata(0x00),pdata(0xFE)
八,统一用寄存器组0,加快出入栈速度
汇编使用 USING 0
[*];定义压栈出栈宏
[*]PUSHALL MACRO
[*] PUSH PSW
[*] PUSH ACC
[*] PUSH B
[*] PUSH DPL
[*] PUSH DPH
[*] PUSH AR0
[*] PUSH AR1
[*] PUSH AR2
[*] PUSH AR3
[*] PUSH AR4
[*] PUSH AR5
[*] PUSH AR6
[*] PUSH AR7
[*] ENDM
[*]
[*]POPALL MACRO
[*] POPAR7
[*] POPAR6
[*] POPAR5
[*] POPAR4
[*] POPAR3
[*] POPAR2
[*] POPAR1
[*] POPAR0
[*] POPDPH
[*] POPDPL
[*] POPB
[*] POPACC
[*] POPPSW
[*] ENDM
源码从这下载:
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=3934&page=1&extra=#pid26085
页:
[1]