找回密码
 立即注册
查看: 6506|回复: 111

最新版本uC-OS2-2.93.01已移植到STC8上,请帮忙查错

[复制链接]

该用户从未签到

11

主题

329

回帖

872

积分

荣誉版主

积分
872
发表于 2023-8-21 23:30:48 | 显示全部楼层 |阅读模式
最新版本uC-OS2-2.93.01已移植到STC最新的 1T 8051, STC8H8K64U
===适用于STC8系列所有型号
===解决了网络上不同移植版本潜在的bug

===请大家在STC官方论坛 www.STCAIMCU.com 帮忙查错, 大家一起前行
最新版本uC-OS2许可改成 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


最新版本uC-OS2-2.93.01移植到STC8上,且修复之前移植版潜在的bug-1.png

最新版本uC-OS2-2.93.01移植到STC8上,且修复之前移植版潜在的bug-2.png

最新版本uC-OS2-2.93.01移植到STC8上,且修复之前移植版潜在的bug-3.png

最新版本uC-OS2-2.93.01移植到STC8上,且修复之前移植版潜在的bug-4.png

二,允许任务堆栈空间任意大小
修改了OSTaskCreate,增加stk_size入口

  1. INT8U  OSTaskCreate (void   (*task)(void *p_arg),
  2.                      void    *p_arg,
  3.                      OS_STK  *ptos,
  4.                      INT16U   stk_size,
  5.                      INT8U    prio) large reentrant
复制代码
OS_STK  *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt)

对 OSTaskStkInit函数利用 opt 传入任务堆栈大小 实现不等长任务堆栈

三 ,临界区保护方法,支持方法2和方法3

  1. #if OS_CRITICAL_METHOD==2
  2. //执行OS_ENTER_CRITICAL()时,先将中断状态保存到堆栈,然后关中断;
  3. //执行OS_EXIT_CRITICAL()时,再从堆栈中恢复原来的中断开/关状态。这种方法不会改变中断状态,避免前面的问题。
  4. //但是,当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。
  5. //问题分析:OS_ENTER_CRITICAL()时导致中断切换任务的时候硬件堆栈多入了一个_push_(IE),
  6. //解决方法:OSIntCtxSw()函数调整SP的时候应该多减1,原来SP=SP-4改为SP=SP-5
  7. #include <intrins.h>
  8. #define OS_ENTER_CRITICAL()do{_push_(IE);EA = 0;}while(0)   /* 利用堆栈保存中断状态,再关中断  */
  9. #define OS_EXIT_CRITICAL()do{ _pop_ (IE);}while(0)          /* 将IE从堆栈弹出,恢复IE值    */
  10. #endif
  11. #if OS_CRITICAL_METHOD==3
  12. //获取当前中断状态的值,并将其保存在C函数局部变量之中
  13. //问题分析:可重入函数的局部变量cpu_sr会入仿真栈。导致中断切换任务的时候,仿真堆栈出问题。
  14. //解决方法:OSIntCtxSw()函数执行时需要对仿真堆栈指针++操作。
  15. #define OS_ENTER_CRITICAL() do{ cpu_sr=IE;EA = 0;}while(0)
  16. #define OS_EXIT_CRITICAL()  do{ IE = cpu_sr; }while(0)
  17. #endif
复制代码

这样,STC的51单片机就能使用方法2和方法3进行临界区的保护。解决嵌套问题。
显然方法2的效率比较高,直接IE出入栈,没有变量的参与。
方法3会慢很多,因为是操作xdata进出仿真栈。

注意:通过网上查资料,方法2使用有注意问题,当用户使用的处理器有堆栈指针相对寻址模式时,可能出现严重错误。8051没有堆栈指针相对寻址模式可以放心用。

四,支持软件定时器
之前移植的版本没有适配软件定时器功能。OS_VERSION >= 281 支持软件定时器。
移植过程中遇到一个困难,就是回调函数,函数指针问题。重点是指针ptmr需要加上xdata修饰。

  1. typedef  void (code *OS_TMR_CALLBACK)(void xdata*ptmr, void *parg) large reentrant;
复制代码
五,解决RET和RETI混用问题
OSIntCtxSw 是在中断中调用的,需要调用RETI返回
OSStartHighRdy 运行第一个任务,应该用RET返回
OSCtxSw  在任务中调用的,应该用RET返回

这三个函数最后部分的代码都一样。之前移植的版本统一用RETI返回,导致混用。
本移植提供2个解决方法,原则是OSIntCtxSw 函数提前退出中断,统一用RET返回

  1. ;方法1:直接把  OSIntCtxSw_in函数地址入栈,由RETI中断返回,跳转到OSIntCtxSw_in函数,共6T
  2.         MOV DPTR,#OSIntCtxSw_in
  3.         PUSH DPL
  4.         PUSH DPH
  5.         RETI
  6. ;方法2:;巧妙的利用函数返回RETI执行了中断完毕,跳转到下一条语句。这样任务可以无忧使用RET作为返回,共9T。
  7.         LCALL    RE_RETI
  8.         LJMP OSIntCtxSw_in
  9. RE_RETI:        RETI
复制代码
显然方法1更优秀
当然还有方法3,3个函数独立,不要共同出口。这里不推荐,浪费代码空间。

六,关于中断嵌套的做法
提供了2个中断例子:
定时器1 中断演示允许中断嵌套
定时器3 中断演示禁止中断嵌套


  1. ; ==== 定时器1 中断服务程序 =============
  2. ;演示允许中断嵌套
  3. EXTRN CODE  (_?Timer1_Handler)
  4. Timer1_ISR:
  5.         USING 0        ;工作寄存器0
  6.         CLR EA  ;调用OSIntEnter之前先关中断
  7. ;SETB P20
  8.         PUSHALL            ;现场保护
  9.         LCALL _?OSIntEnter        ;通知内核进入中断     
  10.         SETB EA  ;允许中断嵌套
  11.         
  12.         LCALL _?Timer1_Handler
  13.         
  14.         LCALL _?OSIntExit   ;通知内核退出中断
  15.         POPALL      ;恢复现场   
  16. ;CLR P20
  17.         RETI
  18.         
  19.         
  20. ; ==== 定时器3 中断服务程序 =============
  21. ;演示禁止中断嵌套
  22. EXTRN CODE  (_?Timer3_Handler)
  23. Timer3_ISR:
  24.         USING 0        ;工作寄存器0
  25. ;SETB P20;
  26.         CLR EA      ;禁止中断嵌套
  27.         PUSHALL            ;现场保护
  28.         LCALL _?Timer3_Handler
  29.         POPALL      ;恢复现场   
  30. ;CLR    P20
  31.         SETB  EA   ;中断函数执行完毕,重新允许中断
  32.         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

  1. ;定义压栈出栈宏
  2. PUSHALL    MACRO
  3.         PUSH PSW
  4.         PUSH ACC
  5.         PUSH B
  6.         PUSH DPL
  7.         PUSH DPH
  8.         PUSH AR0
  9.         PUSH AR1
  10.         PUSH AR2
  11.         PUSH AR3
  12.         PUSH AR4
  13.         PUSH AR5
  14.         PUSH AR6
  15.         PUSH AR7
  16.         ENDM
  17.    
  18. POPALL    MACRO
  19.         POP  AR7
  20.         POP  AR6
  21.         POP  AR5
  22.         POP  AR4
  23.         POP  AR3
  24.         POP  AR2
  25.         POP  AR1
  26.         POP  AR0
  27.         POP  DPH
  28.         POP  DPL
  29.         POP  B
  30.         POP  ACC
  31.         POP  PSW
  32.         ENDM
复制代码


九,修复一个隐藏很深的bug,任务堆栈总空间需要分配很大系统才能运行。

折腾很长时间,最后跟踪代码发现OSTCBFreeList指针指向xdata 地址0,空指针作怪。
任务堆栈总空间比较少的时候OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS];数组从地址0开始存放。

初始化的时候OSTCBFreeList           = &OSTCBTbl[0]; 导致OSTCBFreeList指针指向xdata 地址0,分配到一个空指针。
解决方法。xdata地址0声明一个null变量占用了该地址。


最新版本uC-OS2-2.93.01移植到STC8上,且修复之前移植版潜在的bug-5.png
修改后测试,任务堆栈空间分配32字节,也能顺利运行。

源码:
最新版本uC/OS-II源码在本贴的附件中



无任务切换.mp4

178.15 KB, 下载次数: 85

无任务测试

中断切换任务.mp4

184.1 KB, 下载次数: 75

中断切换任务测试

uCOSII-STC8-V1.06.zip

423.56 KB, 下载次数: 1077

uCOS2移植源码

回复 送花

使用道具 举报

该用户从未签到

61

主题

622

回帖

1万

积分

荣誉版主

积分
10816
发表于 2023-8-22 01:29:46 | 显示全部楼层
祝贺楼主推出自己的移植版本,并且做了很多有价值的改进,我也会仔细学习的。

回复 支持 1 反对 1 送花

使用道具 举报

该用户从未签到

550

主题

9235

回帖

1万

积分

管理员

积分
13946
发表于 2023-8-22 07:52:26 | 显示全部楼层
强烈支持,会组织测试这个版本,由
www.STCAIMCU.com 官方论坛来确保这个版本的OS移植的正确性
===网友们每发现1个错误奖励 RMB200/每条错误





回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    开心
    2 小时前
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    0

    主题

    16

    回帖

    368

    积分

    中级会员

    积分
    368
    发表于 2023-8-22 14:23:43 | 显示全部楼层
    恭喜熊仔移植uC/OS-II首捷。
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    7 分钟前
  • 签到天数: 138 天

    [LV.7]常住居民III

    5

    主题

    88

    回帖

    1065

    积分

    荣誉版主

    积分
    1065
    发表于 2023-8-23 08:48:57 | 显示全部楼层
    支持楼主,已在STC官网下载学习。操作系统会让STC8的应用更强大、更广泛。。。。

    188
    uCOSII-STC8-V1.00-20230821版(改错200元条).jpg
    (仅供参考,欢迎探讨)
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    329

    回帖

    872

    积分

    荣誉版主

    积分
    872
     楼主| 发表于 2023-8-23 22:43:23 | 显示全部楼层
    本帖最后由 熊仔 于 2023-8-23 22:47 编辑

    *修改版本: V1.01
    *修改时间: 2023-08-23
    *修改内容: 1.定时器0时钟改1T模式,系统节拍更准确。
               2.os_cpu_a.A51   屏蔽测试信号,用户需要测试请自行开启测试信号。
               3.修改部分注释




    定时器0时钟改1T模式,各种系统频率,1ms定时都是0误差。缺点是不能修改成更长的延时,比如2ms,5ms,10ms

    一般RTOS用1ms可以了。



    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    61

    主题

    622

    回帖

    1万

    积分

    荣誉版主

    积分
    10816
    发表于 2023-8-24 01:28:43 | 显示全部楼层
    中断现场保护的“PUSHALL”宏指令中存在BUG

    (1)楼主推出的“uCOSII-STC8-V1.01-20230823”移植版中,定时器1和定时器3的中断服务程序写的十分规范:
    Fig_X01_ISR.jpg
    (2)系统中对于中断时将STC8工作寄存器压入堆栈和弹出堆栈的宏定义如下:
    Fig_X02_PUSHALL.jpg
    其中使用了“绝对寄存器 AR0-AR7”的汇编助记符。

    (3)按照Keil C51中使用“USING”指令的说明:
    Fig_X03_USING.jpg
    其中说到“USING语句不会生成任何用于切换当前寄存器组的代码。汇编程序必须选择正确的寄存器组。例如,以下代码选择寄存器组2:”
    Fig_X04_ARX.jpg
    因此,用户在使用“绝对寄存器 AR0-AR7”的汇编助记符前,必须在使用“PUSH  PSW”保存当前的PSW状态寄存器内容后,必须使用“MOV     PSW, #(2 SHL 3)”这样的指令来指定寄存器页,使得“PUSH”和“POP”指令中的“AR0-AR7”与后面程序汇编指令中使用的“R0-R7”保持一致。

    (4)下面是Keil编译器对C语言中断服务程序编译出来的结果:
    Fig_X05_PSW.jpg
    其中可以清楚地看到在使用“PUSH  PSW”保存当前的PSW状态寄存器内容后,使用了“MOV     PSW, # 0”的指令来保证下面的“AR0-AR7”与“R0-R7”都是使用BANK0页的寄存器。

    (5)结论:前面给出的uC/OS-II移植系统中的压栈宏的第94行之后,少了一行汇编指令“MOV  PSW, # 0”。


    点评

    因为使用了USING 0 对应入栈的地址就是00~07.所以入栈前“MOV PSW, # 0”不需要的。 使用USING不会切换寄存器组,需要用户手动切换。 如果用户需要在入栈后切换寄存器组,可以在PUSHALL 之后修改PSW的值。 比如 P  详情 回复 发表于 2023-8-24 10:13
    感谢杨老师对移植版本找错误。 对于压栈宏的第94行之后,少了一行汇编指令“MOV PSW, # 0”这个问题,我当时特意改的,节省1T时间,因为规定RS0,RS1的值不会改。 规定统一使用寄存器组0,永远不要使用 寄存器组1  详情 回复 发表于 2023-8-24 09:46
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9235

    回帖

    1万

    积分

    管理员

    积分
    13946
    发表于 2023-8-24 07:59:46 | 显示全部楼层
    感谢杨老师多年来对 STC 8051世界的呵护和关怀
    熊仔加油 !
    STC 1T 8051 / STC8H8K64U 因为您而更加精彩


    uC-OSII for STC8H8K64U

    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    329

    回帖

    872

    积分

    荣誉版主

    积分
    872
     楼主| 发表于 2023-8-24 09:46:47 | 显示全部楼层
    杨为民 发表于 2023-8-24 01:28
    中断现场保护的“PUSHALL”宏指令中存在BUG
    (1)楼主推出的“uCOSII-STC8-V1.01-20230823”移植版中,定时 ...

    感谢杨老师对移植版本找错误。
    对于压栈宏的第94行之后,少了一行汇编指令“MOV  PSW, # 0”这个问题,我当时特意改的,节省1T时间,因为规定RS0,RS1的值不会改


    规定统一使用寄存器组0,永远不要使用 寄存器组1,2,3。
    这样做有2个好处:
    1,剩余的3组寄存器组3*8=24个字节,留给data区。因为8051的data实在太少了,不要为了提升中断压栈零点几微妙的速度,浪费了这么多的data空间。STC的最新一代51单片机已经是单周期运行了,压栈速度是传统51的12倍。
    2,使用操作系统后,统一管理中断,中断函数入口都是在isr_a.A51编写,全部使用 USING 0 。统一PUSHALL和POPALL 这样代码简洁,更好管理中断。整个工程代码不会更改PSW寄存器RS0,RS1的值。


    当然使用者不按照规定做,可以加上“MOV  PSW, # 0”


    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    11

    主题

    329

    回帖

    872

    积分

    荣誉版主

    积分
    872
     楼主| 发表于 2023-8-24 10:13:43 | 显示全部楼层
    本帖最后由 熊仔 于 2023-8-24 12:11 编辑
    杨为民 发表于 2023-8-24 01:28
    中断现场保护的“PUSHALL”宏指令中存在BUG
    (1)楼主推出的“uCOSII-STC8-V1.01-20230823”移植版中,定时 ...



    因为使用了USING 0 对应入栈的地址就是00~07.所以入栈前“MOV PSW, # 0”不需要的。



    改成USING 3测试
    ; ==== 定时器0 中断服务程序 =============
    OSTickISR:               
            USING 3     ;工作寄存器0



    注意:使用USING不会切换寄存器组,需要用户手动切换。
    如果用户需要在入栈后切换寄存器组,可以在PUSHALL 之后修改PSW的值。
    当然也可以在PUSH PSW之后修改,位置没有关系,因为不影响压栈内容,但是不能统一用宏PUSHALL ,因为用户使用的寄存器组不一样,需要修改不一样的PSW值。
    例子:
    USING 0
    PUSHALL
    MOV     PSW, #(2 SHL 3)   使用寄存器组2,后面的操作R0到R7都是寄存器组2.
    .
    .
    .
    POPALL


    结论:统一使用寄存器组0。永远不要用寄存器1,2,3带来的不必要麻烦,高手除外。

    点评

    可以在说明文本里面说清楚,不然确实容易出现杨老师叙述的问题  发表于 2023-8-24 14:31
    回复 支持 1 反对 0 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-29 18:46 , Processed in 0.167163 second(s), 69 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表