找回密码
 立即注册
楼主: CosyOS

全局不关总中断的 RTOS,CosyOS-III-V1.2.0, 送 擎天柱-AI8051U转89C52核心板

 火... [复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-08 10:41:18

2

主题

45

回帖

440

积分

中级会员

积分
440
发表于 2024-10-31 15:33:57 | 显示全部楼层

/* 启动任务 */
#define uStartTask(task, status) sUSV_StartTask(&u_taskhand_##task, (s_voidvoid_tfp)task, status) /** \return ecode */

/* 启动任务 */
#define sUSV_StartTask(hand, entry, status) \
( \
        (m_boolvoid_tf(su_enter_critical_one))() || true ? su_startup_task((s_taskhand_tsp)hand, entry, !status ? OS_STATUS_READY : OS_STATUS_SUSPENDED) : false \
)


(m_boolvoid_tf(su_enter_critical_one))() || true  这个表达式值是true,那为什么 启动任务 表达式这样写

( \
        (m_boolvoid_tf(su_enter_critical_one))() || true ? su_startup_task((s_taskhand_tsp)hand, entry, !status ? OS_STATUS_READY : OS_STATUS_SUSPENDED) : false \
)

(m_boolvoid_tf(su_enter_critical_one))() 能不能解释下这个表达式的意思。

点评

再总结一下思路就是: 1、要先进入任务临界区,而后再调用服务函数。 这样做的目的是:服务函数可以是不可重入函数。 所以,要先调用 进入任务临界区函数,再调用服务函数。 2、由于服务函数要返回值,而且是后调  详情 回复 发表于 2024-10-31 20:30
你的问题涉及到 CosyOS 的一个核心技术: 独家技术实现系统服务函数的可重入,使51彻底摆脱可重入栈、全面提速。 原理是:对于任务中调用的服务,先进入任务临界区,而后再调用服务函数, 这样服务函数是不会发生重  详情 回复 发表于 2024-10-31 18:10
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-31 18:10:22 | 显示全部楼层
本帖最后由 CosyOS 于 2024-10-31 19:02 编辑
sdw*** 发表于 2024-10-31 15:33
/* 启动任务 */
#define uStartTask(task, status) sUSV_StartTask(&u_taskhand_##task, (s_voidvoid_tfp) ...

你的问题涉及到 CosyOS 的一个核心关键技术:
独家技术实现系统服务函数的可重入,使51彻底摆脱可重入栈、全面提速。
原理是:对于任务中调用的服务,先进入任务临界区,而后再调用服务函数,
这样服务函数是不会发生重入的,可以为
可重入函数
使得在C51下,CosyOS内核无需可重入栈支持,全面提速。

当然也还有服务函数会发生重入的情况,需要用另外的技术来解决,暂时先不提。

对于启动任务来说,首先是要进入任务临界区,而后再调用 su_startup_task 来启动任务。

su_enter_critical_one 是 进入任务临界区函数:void su_enter_critical_one (void);


(m_boolvoid_tf(su_enter_critical_one))() 是把 su_enter_critical_one 强制转换为 返回bool型的函数,

原因是它要 || ture 做条件判断,所以必须要有返回值。

由于 编译器知道,任何值 || true 的结果必然为真,
所以:
1、不会做条件判断(
      不会理会 (m_boolvoid_tf(su_enter_critical_one))() 的返回值,
      也不会 || true
);
2、但 su_enter_critical_one 是一个函数,所以必须要调用执行,不能优化掉;
3、而后必然会调用 su_startup_task。

所以最终编译后的结果就是,先调用 su_enter_critical_one,再调用 su_startup_task 并返回,其它全部优化掉。


至于为何要采用 三目运算 来实现,当然是为了 返回值 啊,服务要返回 结果 或 错误码 或 指针 等!


在 sv_task.h 中,会有大量的这种 任务服务的宏定义,都是相同的原理。


你再看一下 103楼,以前对该技术做过详细的介绍:
https://www.stcaimcu.com/forum.p ... 1807&extra=&page=11





回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-31 20:30:29 | 显示全部楼层
sdw*** 发表于 2024-10-31 15:33
/* 启动任务 */
#define uStartTask(task, status) sUSV_StartTask(&u_taskhand_##task, (s_voidvoid_tfp) ...

再总结一下思路就是:

1、要先进入任务临界区,而后再调用服务函数。
这样做的目的是:服务函数可以是不可重入函数。
所以,要先调用 进入任务临界区函数,再调用服务函数。

2、由于服务函数要返回值,而且是后调用,所以必须采用 三目运算 才能实现。

3、在实现的同时,还希望能优化掉不必要的环节。

最终,经过我一段时间的研究、试验,才有了这个方法。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:186
  • 最近打卡:2025-03-06 09:49:49

14

主题

133

回帖

1149

积分

金牌会员

积分
1149
发表于 2024-11-1 16:06:01 | 显示全部楼层
CosyOS是一款来自中国的开源实时操作系统
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:302
  • 最近打卡:2025-05-01 09:23:14

0

主题

24

回帖

365

积分

中级会员

积分
365
发表于 2024-11-1 17:04:18 | 显示全部楼层
你好,工程芯片用的是STC32G12K128,修改INT2代替INT0,在mcucfg_80251.h文件中修改如下:
// <o> 中断向量地址
// <i> 中断向量地址
#define MCUCFG_PENDSV_VECTORADDR        0053H

// <o> 中断开启
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例:EX0 = 1
#define mPendSV_Enable                  EX2 = 1

// <o> 中断关闭
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例:EX0 = 0
#define mPendSV_Disable                 EX2 = 0

// <o> 中断触发(置中断标志位)
// <i> 此项您应在文本编辑界面中定义。
// <i> 示例:IE0 = 1
#define mPendSV_Set                     INT2IF = 1

// <o> 中断清零(清中断标志位)
// <i> 此项您应在文本编辑界面中定义,必须使用汇编代码。
// <i> 即使该标志位能够在中断服务程序中硬件自动清零,仍建议用户不要省略,以确保其可靠清零。
// <i> 示例:CLR IE0
#define mPendSV_Clear                                         CLR INT2IF

编译工程出现如下报警,不知什么原因?
Port\port_80251s.s(100): error A45: UNDEFINED SYMBOL
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:302
  • 最近打卡:2025-05-01 09:23:14

0

主题

24

回帖

365

积分

中级会员

积分
365
发表于 2024-11-1 17:21:32 | 显示全部楼层
找到了,需要在port_80251.s文件中修改,修改如下:

;///////////////////////////////////////////////////////////////////////////////
;
; 用户定义寄存器
;
; 1、mcucfg_80251.h -> PendSV中断配置 -> 中断清零,涉及的寄存器;
; 2、用户自定义任务切换现场保护,汇编语言保护方案,涉及的寄存器;
;
; 通常,直接包含标准头文件(h、inc)即可。
; 如果包含h文件导致编译报错,说明h文件中存在汇编器不能识别的C语言语法,
; 您可包含inc文件或重写新的h文件,也可在此处直接定义相关寄存器。
;
AUXINTIF    DATA    0EFH
INT2IF     BIT     AUXINTIF^4

点评

恭喜你答对了,  详情 回复 发表于 2024-11-1 18:15
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-1 18:15:10 | 显示全部楼层
stc-x*** 发表于 2024-11-1 17:21
找到了,需要在port_80251.s文件中修改,修改如下:

;///////////////////////////////////////////////// ...

恭喜你答对了,
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-08 10:41:18

2

主题

45

回帖

440

积分

中级会员

积分
440
发表于 2024-11-1 23:29:49 | 显示全部楼层
这是用腾讯AI分析出来的这段代码的功能,作者看看AI分析的正确吗?

// 这段代码定义了任务管理器(Task Manager)的定时器ID(TMID)
// 根据OS_TIMQRYTOTAL的值不同,OS_TMID_TASKMGR的值也会相应变化
// OS_TIMQRYTOTAL表示系统中定时器的总数,OS_TMID_TASKMGR则是任务管理器使用的定时器ID
// 通过这种方式,可以根据系统中定时器的数量动态地分配任务管理器使用的定时器ID

#define OS_TMID_TASKMGR    4
#elif OS_TIMQRYTOTAL == 6
#define OS_TMID_TASKMGR    5
#elif OS_TIMQRYTOTAL == 7
#define OS_TMID_TASKMGR    6
#elif OS_TIMQRYTOTAL == 8
#define OS_TMID_TASKMGR    7
......后面的代码省略掉了

点评

看来AI真的很智能,分析的结果 可以打 90分了(满分100的话)。 OS_TASKTOTAL // 所有任务总数 OS_TIMINTTOTAL // 所有定时中断总数 OS_TIMQRYTOTAL // 所有定时查询总数 SYSCFG_USERTASKTOTAL // 用户任务总数  详情 回复 发表于 2024-11-2 01:16
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-2 01:16:19 | 显示全部楼层
本帖最后由 CosyOS 于 2024-11-2 01:34 编辑
sdw*** 发表于 2024-11-1 23:29
这是用腾讯AI分析出来的这段代码的功能,作者看看AI分析的正确吗?

// 这段代码定义了任务管理器(Task Ma ...

看来AI真的很智能,分析的结果 可以打 90分了(满分100的话)。

OS_TASKTOTAL // 所有任务总数
OS_TIMINTTOTAL // 所有定时中断总数
OS_TIMQRYTOTAL // 所有定时查询总数
SYSCFG_USERTASKTOTAL // 用户任务总数
SYSCFG_USERTIMINTTOTAL // 用户定时中断总数
SYSCFG_USERTIMQRYTOTAL // 用户定时查询总数

我给你讲一下原理:
CosyOS 至多有4个系统任务,分别是 Taskmgr、Debugger、Starter、Sysidle,
其中 Taskmgr 是 定时查询任务,Debugger 是定时中断任务;
1个定时查询钩子,debug_hook。

OS 在 SYSCFG_DEBUGGING == __ENABLED__ 的前提下,
共有 2个定时查询(Taskmgr、debug_hook),1个定时中断(Debugger)。

所以:
#if SYSCFG_DEBUGGING == 0
#define OS_TASKTOTAL      (SYSCFG_USERTASKTOTAL + 2) // 用户任务总数 + Starter、Sysidle
#define OS_TIMINTTOTAL     SYSCFG_USERTIMINTTOTAL
#define OS_TIMQRYTOTAL     SYSCFG_USERTIMQRYTOTAL
#else
#define OS_TASKTOTAL      (SYSCFG_USERTASKTOTAL + 4) // 用户任务总数 + Taskmgr、Debugger、Starter、Sysidle
#define OS_TIMINTTOTAL    (SYSCFG_USERTIMINTTOTAL + 1) // 用户定时中断总数 + Debugger
#define OS_TIMQRYTOTAL    (SYSCFG_USERTIMQRYTOTAL + 2) // 用户定时查询总数 + Taskmgr、debug_hook
#endif

CosyOS 规定,用户的 定时中断定时器 和 定时查询定时器,ID均是从0开始;
系统的 定时中断定时器 和 定时查询定时器,ID自动跟在用户的定时器ID后面。

所以:
1、
用户的定时中断定时器ID 是 0~SYSCFG_USERTIMINTTOTAL-1,
Debugger 的 定时中断定时器ID 是 SYSCFG_USERTIMINTTOTAL;
所以,#define OS_TMID_DEBUGGER   SYSCFG_USERTIMINTTOTAL

2、
用户的定时查询定时器ID 是 0~SYSCFG_USERTIMQRYTOTAL-1,
debug_hook 的 定时查询定时器ID 是 SYSCFG_USERTIMQRYTOTAL,
所以,#define OS_TMID_DEBUGHOOK  SYSCFG_USERTIMQRYTOTAL

3、
Taskgmr 的 定时查询定时器ID 是 SYSCFG_USERTIMQRYTOTAL+1,也就是 OS_TIMQRYTOTAL-1。
但 Taskgmr 的 定时查询定时器ID 必须直接宏定义为常量,
而不能是 算术表达式(SYSCFG_USERTIMQRYTOTAL+1 或 OS_TIMQRYTOTAL-1),
原因是 在创建任务时,这个定时器ID 要做 字符串拼接(代码拼接),所以必须直接给出常量,
所以,才需要一大段条件编译来定义 OS_TMID_TASKMGR。






回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-04-08 10:41:18

2

主题

45

回帖

440

积分

中级会员

积分
440
发表于 2024-11-2 16:29:35 | 显示全部楼层
本帖最后由 sdwys 于 2024-11-2 16:45 编辑

这个结构体定义的东西大多数能模糊的知道做什么用,于是让AI来分析了下,作者看看AI分析的正确吗?
2024-11-02 16 22 05-task_struct.jpg
2024-11-02 16 39 35.jpg
2024-11-02 16 42 47-2.jpg
2024-11-02 16 44 19-3.jpg

点评

八成是差不多的,但一些细节还不够准确。  详情 回复 发表于 2024-11-2 18:00
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 07:07 , Processed in 0.150334 second(s), 115 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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