神农鼎 发表于 2023-5-10 14:35:29

****, O/S专家,CosyOS开发,申请   STC32G12K128实验箱-V9.6,1套;STC32G12K128转DIP64核心功能实验板三-V3.2,1套,STC8H8K64U实验箱-V9.6,1套,STC8H8K64U转DIP64核心功能实验板-V2.2,1套;STC-USB Link1D4 , 1套=====好

CosyOS 发表于 2023-5-10 16:31:11

神农鼎 发表于 2023-5-10 14:35
****, O/S专家,CosyOS开发,申请   STC32G12K128实验箱-V9.6,1套;STC32G12K128转DIP64核心功能实验板三-V ...

感谢支持{:4_196:}

CosyOS 发表于 2023-5-11 10:37:11

本帖最后由 CosyOS 于 2023-5-11 14:07 编辑

CosyOS 与 FreeRTOS 中的 “定时服务”


我们知道,MCU都有定时器和定时器中断,当定时器溢出时,CPU可以响应中断并调用相应的定时器中断服务程序。
然而,硬件定时器的数量是有限的,在较复杂的应用中往往是不够用的。所以,RTOS都提供了软件定时器,以弥补硬件定时器数量的不足,
同时也支持“定时服务”功能,来模拟定时器中断。

下面,简单对比一下三者“定时服务”的区别:

MCU:
            调用
中断响应 ——> 定时器中断服务程序


FreeRTOS:
            调用
守护任务 ——> 定时器回调函数


CosyOS:
            调用
系统滴答 ——> 定时中断/查询钩子

            恢复
系统滴答 ——> 定时中断/查询任务


FreeRTOS是在守护任务中统一调用所有的定时器回调函数,所有“定时服务”都具有相同的优先级,即守护任务的优先级。

CosyOS则分为两种情况:
一、在系统滴答中调用定时中断/查询钩子,“定时服务”享有系统滴答的优先级(高于任务);
二、在系统滴答中恢复定时中断/查询任务,“定时服务”的优先级即任务优先级(用户定义)。
注意:只有极为精简的代码才可创建为钩子,否则会对系统的实时性造成不利影响。

可见,CosyOS的“定时服务”,优先级都可由用户灵活配置。


关于CosyOS的软件定时器和定时任务/钩子的详细介绍,请参考 技术要点.md。
关于CosyOS的定时任务/钩子的应用示例请参考源码:
任务管理器 Taskmgr,为定时查询任务,\System\taskmgr.c;
调试任务 Debugger,为定时中断任务,\System\debug.c;
调试钩子 debug_hook,为定时查询钩子,\System\debug.c。



CosyOS 发表于 2023-5-13 22:03:50

本帖最后由 CosyOS 于 2023-5-14 12:47 编辑

CosyOS - 全局不关中断特性的详细说明


首先,鉴于“全局不关中断”的说法可能存在异议,正考略改一个名字,如称之为:“全局不关总中断的RTOS”、或“零中断延迟的RTOS”。

相关名词解释
系统中断:包括SysTick_Handler/定时器0中断、PendSV_Handler/其它替代中断,均为最低优先级。
进入任务临界区:8051/251内核:关闭上述两个系统中断;Arm内核:屏蔽最低优先级的中断。
退出任务临界区:开启关闭的中断。
:任务节点(Task Node)。
:中断服务栈(interrupt service stack),用于push/pop中断异步服务的结构体指针。

CosyOS全局不关中断特性
CosyOS的全局不关中断,是全局不关总中断和用户中断。
在进入任务临界区时,对于8051、80251内核,会关闭上述两个系统中断;对于Arm内核,会屏蔽最低优先级的中断。
所以,只要您的用户中断不是最低优先级就可实现零中断延迟。
虽然CosyOS也提供了全局临界区(系统级的临界区保护,会关闭总中断)给用户,但CosyOS内核中从来不会进入全局临界区,提供此项服务只是为了便于用户对全局公共资源的保护。



所有内核全局不关中断原理

SysTick_Handler/定时器0中断
● 软件RTC计时
● 调用滴答钩子
● 定时中断定时器计数 && 恢复定时中断任务 && 调用定时中断钩子
● 定时查询定时器计数 && 恢复定时查询任务 && 调用定时查询钩子
● 延时定时器计数
● 同步服务:本地执行服务(滴答钩子、定时中断钩子、定时查询钩子)

PendSV_Handler/其它替代中断
● 中断异步服务的执行
● 任务异步服务的执行
● 任务调度与切换

任务中调用服务
● 同步服务:进入任务临界区 → 本地执行服务 → 退出任务临界区
● 异步服务:进入任务临界区 → 服务入 → 触发任务调度 → 退出任务临界区 // 含有超时机制的服务

用户中断中调用服务
● 同步服务:本地执行服务 // “只读访问”
● 异步服务:// “含有写的访问”
   Arm内核:服务入 → 触发PendSV
   8051/251内核:服务入 → 设置中断服务标志 → 触发PendSV

首先,SysTick和PendSV中断优先级相同,均为最低优先级。任务中调用服务时会进入任务临界区(关闭SysTick和PendSV),这就实现了SysTick、PendSV、任务中调用服务,三者间的互斥访问。
只有中断同步服务需另行安排,以实现用户中断中的“只读访问”与上述三者(SysTick、PendSV、任务中调用服务)中的“写访问”之间的互斥,这就是互斥访问机制。

互斥访问机制
用户中断中读全局变量:未写时:读全局变量 / 正在写时:读局部变量
用户中断中接收邮件:未写时:读全局邮箱 / 正在写时:读局部邮箱
用户中断中接收消息:互斥量
详情请参阅源码。

中断服务栈(ISS)
需实现中断异步服务的结构体指针入出ISS为原子操作。
1、Arm内核:ISS为LIFO队列,利用Arm内核的特性及Arm汇编即可实现(详情请参阅源码)。
2、8051/251内核:
8051/251内核无法使用与Arm相同的方法入出ISS,只能采用如下的标志位法。
服务的结构体指针入vISS,设置中断服务标志(vISV_F##svid);
在PendSV中执行时,从中断服务标志(vISV_F0)开始依次查询,若为真则从vISS[]中取出结构体指针并执行服务。
详情请参阅源码。

由此,可实现CosyOS的所有内核全局不关中断(零中断延迟)。



Keil RTX与CosyOS全局不关中断特性的简单对比
RTX4/5,采用SysTick+PendSV+SVC+互斥访问指令,实现了Cortex-M3/M4内核全局不关中断。
CosyOS,采用SysTick+PendSV+任务临界区+互斥访问机制,实现了所有内核全局不关中断。

用户中断注意事项
1、对于8051、80251内核,您的用户中断应尽量避免使用最低优先级;对于Arm内核,您的用户中断干脆不要使用最低优先级。
2、您的用户中断应遵循快进快出的原则,仅执行最为紧急的工作,而把不太紧急的工作转为在任务中执行(中断服务任务)。
3、您的用户中断的最大执行时间应远小于系统滴答周期,这将促使整个系统更加良性的运行。

补充说明
其实,CosyOS也可以采用像Keil RTX一样的方法,在任务中调用服务时通过调用SVC_Handler/其它替代中断来执行服务,这样就不用进入任务临界区(不会关闭上述两个系统中断),但这种方法并不适用于CosyOS,原因有三:
1、调用SVC的方法相较于进入临界区的方法无疑会花更多的时间,对于一些比较老的、主频低的内核来说,这并不是一个好主意。
2、调用SVC的方法其实还有一个重要目的,就是实现服务的空间隔离,而对于没有Thread模式/Handler模式的内核来说,这种方法是无法实现栈空间隔离的。
3、调用SVC的方法,SVC的优先级必须比SysTick和PendSV高一级。而对于某些内核来说,中断优先级是非常有限的(如增强的8051共有四级),SysTick+PendSV+SVC就占用了两级,用户中断中要想实现零中断延迟,就只剩两级优先级可用了,而这往往是不够用的。
综上所述,对于CosyOS来说,在任务中调用服务时,进入任务临界区的方法优于调用SVC的方法,性能上也会更进一步。
之所以补充说明这一点,是因为有人可能会说:“你还不是关中断了吗,关了SysTick和PendSV”?CosyOS虽然是关了中断,但关的是系统专用中断,并没有关总中断和用户中断啊!再者,即使采用了调用SVC的方法,当调用SVC时,如果SysTick或PendSV也同时到来,虽然它们没有被关闭,但也只能乖乖挂起,在后面排队,这又与关闭它们有什么区别呢?
可见,无论是调用SVC的方法还是进入任务临界区的方法,对于任务中调用服务结果都是一样的,对零中断延迟都无影响。
调用SVC的方法除了感觉上更“牛”之外(不用关闭SysTick和PendSV,实现了全局不关所有中断),性能上却不如进入任务临界区的方法,这种“牛”只不过是一种错觉。

中断中调用服务注意事项
1、发送邮件
同一处调用的相邻两次调用,间隔时间不可过短(大于一个滴答周期为宜),以确保局部邮箱不会重入。
实际上只有足够间隔时间时,才适合使用邮箱,否则可能会导致邮件覆盖。
2、全局变量写访问
同一处调用的相邻两次调用,间隔时间不可过短(大于一个滴答周期为宜),或是局部变量不要发生变化,以确保局部变量不会重入或可重入。
3、计数信号量释放(8051/251内核)
同一处调用的相邻两次调用,间隔时间不可过短(大于一个滴答周期为宜),否则可能会导致漏记次数。
4、中断异步服务总数(8051/251内核)
由于8051/251内核,在PendSV中要依次查询所有的中断服务标志,所以,中断异步服务总数不可过多(至多64个),否则有可能造成PendSV的运行时间过长,对系统实时性造成不利影响。建议在中断中仅执行最为紧急的工作,且调用必要的异步服务。不过您也不用过于担心,中断服务标志是bit型变量,查询采用JNB指令(2个时钟),清零采用CLR指令(1个时钟),还是非常高效的,仅需注意减少不必要的调用即可。

神农鼎 发表于 2023-5-13 23:04:44

必须学习{:4_196:}

新手 发表于 2023-5-13 23:30:59

必须学习{:4_196:}

CosyOS 发表于 2023-5-14 22:46:24

本帖最后由 CosyOS 于 2023-5-16 21:35 编辑

STC32G - 不同内存模型(XSmall、Large)及配置方案对RTOS性能的影响

测试环境
编译器:Keil C251 V5.60
开发板:屠龙刀三.1(STC32G12K128)
操作系统:CosyOS V2.3.10-beta
测试代码:CosyOS-STC32G-CORE-V1.0.3-Library-DemoCode-20230513(基于 FreeRTOS-STC32G-CORE-V1.0.2-Library-DemoCode-20220817 修改,将FreeRTOS替换为CosyOS最新版 V2.3.10-beta)

任务栈模式
首先有必要对任务栈模式做一下说明:

MSP模式
每个任务运行时用的都是主栈,只有任务切换时才在主栈和任务栈之间拷贝数据。任务栈中不存储中断入栈,所以任务栈可以很小。
MSP模式拥有100%可靠的任务栈重分配机制,只要主栈和内存池足够大就可确保所有任务栈永不溢出。
MSP模式,任务栈可以是任意一块内存,包括xdata。

MSP+PSP模式
每个任务栈都是主栈,任务切换时不拷贝数据,仅是SP指针的切换。哪个任务运行时,就入哪个任务的任务栈(包括中断入栈),所以每个任务栈都要足够大,因为要把中断嵌套入栈都加到里面。
如果任务栈不够大,会有溢出的风险,一旦溢出,会导致数据覆盖,而覆盖的不一定是哪些关键数据,有可能会导致系统跑飞或某些任务运行异常。
但,这并不是CosyOS的bug,是所有RTOS都面临的问题。
MSP+PSP模式,任务栈只能在edata中。



测试一
直接使用示例代码 CosyOS-STC32G-CORE-V1.0.3-Library-DemoCode-20230513 进行测试。

配置原则:全局尽量使用edata,不使用xdata。

配置情况:

1、系统配置
此处省略,用户可自行查看syscfg.h。在后续的其它测试中,系统配置项均保持不变。
但需先声明一点,共有12个任务,4个系统任务、8个用户任务,均为动态创建(任务节点和任务栈均为动态内存分配)。

2、内存模型(XSmall)


3、MCU配置



栈内存为edata,即主栈为edata(size:256Bytes)。
任务栈模式为MSP+PSP模式。
内存池分配到edata中。
只有“DEBUG大内存”定义为xdata,即编译后的xdata=1096。

测试结论:

任务管理器刷新周期为250ms。


测试二
在测试一的基础上,仅是把任务栈模式改为MSP模式,并指定最低优先级中断寄存器库为非bank0。

测试结论:

任务管理器刷新周期为250ms。


测试三
以测试二为基础,相关配置做适当调整。

配置原则:除主栈使用edata(size:256Bytes),其它尽量使用xdata。

配置情况:

1、系统配置(保持不变)

2、内存模型(Large)


3、三个头文件中的内存配置
STC32G_I2C.h:   #define      I2C_BUF_type      xdata
STC32G_SPI.h:   #define      SPI_BUF_type      xdata
STC32G_UART.h:#define      UART_BUF_type   xdata
把这三个接口缓存均改为xdata。

4、MCU配置



栈内存为edata,即主栈为edata(size:256Bytes)。
任务栈模式为MSP模式,并指定最低优先级中断寄存器库为非bank0。因为任务栈动态分配到xdata中,只能采用MSP模式。
内存池分配到xdata中。内存池指针 68036 为 0x10000+2500。因为xdata的起始地址为0x10000,已经静态分配了2419。

测试结论:

任务管理器刷新周期为250ms。



结论
鉴于任务管理器现有的监控条件,可根据各个任务的CPU使用率、总的CPU使用率、系统滴答时间等做出如下判断:
1、“测试二”相较于“测试一”,总的CPU使用率升高了约1.4倍,系统滴答时间未改变,这证明在其它配置不变的情况下,MSP模式的性能相较于MSP+PSP模式还是有明显的降低(因为MSP模式在任务切换时要拷贝数据)。
2、“测试三”相较于“测试一”、总的CPU使用率升高了约2.9倍,系统滴答时间延长了约1.6倍,性能下降非常明显。
注:任务CPU使用率,是把所有中断(SysTick、PendSV、用户中断)所用的时间都折算到当前任务的使用时间中,再计算使用率。
所以,任务的CPU使用率高,不一定真的是被任务用了,可能是任务被中断的次数太多了或中断所用的时间过长(如MSP模式在任务切换时要拷贝数据)。


最终结论
1、“测试一”为“性能方案”,但需要较大的edata内存;
2、“测试三”为”节约方案”,仅需少量的edata内存(256~512)即可,但性能会大打折扣;
3、“测试二”为“折中方案“,性能折中,又可显著的减少RTOS对edata的需求;


折中方案的基本配置
0、任务创建模式为动态创建或平衡创建
1、内存模型为XSmall
2、栈内存为edata
3、内存池为edata
4、任务栈模式为MSP模式,并指定最低优先级中断寄存器库为非bank0(将不会入栈DR0、DR4,有助于进一步减少任务栈)
5、DEBUG大内存为xdata
任务栈都可以定义的小一些,MSP模式拥有100%可靠的任务栈重分配机制,只要主栈和内存池足够大就可确保所有任务栈永不溢出。
如下图所示,是以测试二为基础,重新调整了用户任务栈的大小,
#define configDEFAULT_STACK_SIZE      30
8个用户任务的任务栈都进行了重分配。


折中方案,兼顾了性能与节约edata内存。


折中方案 - 动态内存大小的估算
仅是对任务所需要的动态内存(包括任务节点和任务栈)的估算,不包括消息队列、用户在任务中自己使用动态内存分配...在内。

一、任务为动态创建模式(任务节点和任务栈均为动态内存分配)
任务节点SIZE:58Bytes,任务栈SIZE:按平均每个任务64Bytes估算,这样平均每个任务需要动态内存122Bytes;
MEMPOOL_SIZE = 122 x (任务总数 - 1) + 后备内存(最小256Bytes);
以示例代码为例:MEMPOOL_SIZEmin = 122 x (12 - 1) + 256 = 1598;

二、任务为平衡创建模式(只有任务栈为动态内存分配)
任务栈SIZE:按平均每个任务64Bytes估算;
MEMPOOL_SIZE = 64 x (任务总数 - 1) + 后备内存(最小256Bytes);
以示例代码为例:MEMPOOL_SIZEmin = 64 x (12 - 1) + 256 = 960;






CosyOS最新版 V2.3.10-beta 变更通知:
1、简化了临界区代码,使进出临界区都更为高效;
2、定时任务的启动位置由main()迁移到start_task;
3、启动、恢复、挂起、删除任务,设置任务优先级,调整为增加返回值,均返回错误码(ECODE);
4、发送消息,由原来的返回结果调整为返回错误码;




大刀阔斧 发表于 2023-5-15 13:19:02

学习!{:4_196:}

神农鼎 发表于 2023-5-15 20:23:24

必须学习,必须为8051原生 RTOS 摇旗呐喊{:4_196:}

测试一

STC32G8K64, RMB1.99起, 也可以使用啊

神农鼎 发表于 2023-5-15 21:27:21



下周公司2位大佬亲自下场测试,
STC32系列原生RTOS/CosyOS,
为8051原生 RTOS 保驾护航

页: 1 2 3 4 [5] 6 7 8 9 10 11 12 13 14
查看完整版本: 全局不关总中断的 RTOS,CosyOS-III-V1.2.0, 送 擎天柱-AI8051U转89C52核心板