8051爱好者 发表于 2023-8-22 10:36:46

最新版本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]
查看完整版本: 最新版本uC-OS2-2.93.01已移植到STC8上,帮忙查错每条错误感谢200元