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

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

 火... [复制链接]
已绑定手机

4

主题

111

回帖

2156

积分

金牌会员

积分
2156
发表于 2024-10-30 14:45:14 | 显示全部楼层
Cos*** 发表于 2024-10-29 23:19
测试程序中,默认
串口1用做 printf,串口2用做 Taskmgr。
串口1中断未开启、接收也未使能,EA = 0; REN  ...

EA = 1; REN = 1;
下载后测试发现依然无法接收到 uart1 的数据(自发自收)
任务管理器uart2是能够正常收发的。
然后printf(s_debug_recvptr);
改为printf(DMABuffer);
DMABuffer数组是我自己定义的。
下载后测试发现依然无法接收到 uart1 的数据(自发自收)
  1. /**************************************************************************//**
  2. * @item     CosyOS-II User
  3. * @file     Taskmgr.c
  4. * @brief    CosyOS-II 任务管理器
  5. * @detail   当前配置为使用UART2,用户可自行调整。
  6.              正常情况下,下方代码中,您仅需调整:UART2_Isr、中断向量号、S2CON、S2TI、S2RI、S2BUF。
  7.              您需自行初始化串口、串口中断优先级、波特率等相关配置。
  8. * @author   迟凯峰
  9. * @version  V1.0.2
  10. * @date     2024.05.11
  11. ******************************************************************************/
  12. #include "..\System\os_link.h"
  13. #if SYSCFG_DEBUGGING == __ENABLED__
  14. #include "user.h"
  15. u8 xdata DMABuffer[256];  // 数据存放在XRAM(XDATA区域),需要使用关键字xdata
  16. bit DmaTxFlag;            // 发送完成标志
  17. bit DmaRxFlag;            // 接收完成标志
  18. bit B_TX1_Busy;           // 串口忙标志
  19. u8 Rx_cnt;                // Rx接收计数
  20. u8 RX_TimeOut;            // 串口接收超时计数
  21. /* 应用示例 - 8051/80251 UART1 */
  22. void UART1_Isr(void) interrupt 4
  23. {
  24.                 if (RI)  // 接收完成标志置1时
  25.     {
  26.         RI = 0;  // 清零接收完成标志
  27.         DMABuffer[Rx_cnt++] = SBUF;  // 将接收到的数据存入缓冲区
  28.         if (Rx_cnt >= 256) Rx_cnt = 255;  // 防止溢出
  29.         RX_TimeOut = 5;  // 如果5ms内没有接收到新的数据,判定一串数据接收完毕
  30.         DmaRxFlag = 1;  // 接收完成标志置1
  31.     }
  32.     if (TI)  // 发送标志置1时
  33.     {
  34.         TI = 0;  // 清零发送完成标志
  35.         B_TX1_Busy = 0;  // 清零串口忙标志
  36.         DmaTxFlag = 1;  // 发送完成标志置1
  37.     }
  38. }
  39. void UART2_Isr(void) interrupt 8// using 3
  40. {
  41.         if(S2CON & S2TI){
  42.                 S2CON &= ~S2TI;
  43.                 if(*s_debug_sendptr){
  44.                         S2BUF = *s_debug_sendptr++;
  45.                 }
  46.                 else{
  47.                         iDebugSend;
  48.                 }
  49.         }
  50.         if(S2CON & S2RI){
  51.                 S2CON &= ~S2RI;
  52.                 if(s_debug_recvptr - s_debug_recvbuff < OS_DEBUGRECVBUFFSIZE - 1){
  53.                         *s_debug_recvptr++ = S2BUF;
  54.                 }
  55.                 iDebugRecv;
  56.         }
  57. }
  58. #endif
复制代码

ES=1;
然后我将ES也设置,下载到单片机后系统不运行了。

点评

C51,如果用 printf,在打印之前需要先 TI = 1,而且不能开启串口1中断。如果需要开启串口1中断,就不能用 printf。  发表于 2024-10-30 22:57
C51 标准库 的 printf 是 串口1 查询方式,会与串口1中断冲突。如果用 printf,就不要用串口1中断;如果用串口1中断,就不要用 printf。  发表于 2024-10-30 22:44
你先把所有的 printf 都注释掉,再注释掉 init_hook 中的 TI = 1; 看 串口1中断和接收能否正常?  发表于 2024-10-30 22:33
是的,是 ES = 1; 是我写错了,不是 EA  发表于 2024-10-30 22:30
回复

使用道具 举报 送花

8

主题

89

回帖

1055

积分

金牌会员

积分
1055
发表于 2024-10-30 15:15:12 | 显示全部楼层
本帖最后由 Yang.Lian 于 2024-10-30 15:35 编辑

我插播一个简单的问题,
1. 创建一个二值信号量b
2. 创建一个 CTRL 任务,执行指定的操作,然后uLockBin(b) ; uTakeBin(b, 超时时间) 等待反馈
3. 创建一个定时中断任务,定时中断任务用于防抖处理,检测输入,如果检测到反馈就uGiveBin(b)

现在的问题是,CTRL 执行以后,如果超时,系统运行正常;如果不超时,检测到反馈,系统立即死机
我用类似的逻辑换成飞信,效果是一样的;
如果去掉这些同步代码,可以观察到反馈正常抵达。

补充一下,我判断死机的标准是
#define SYSCFG_DEBUGGING                 1
的时候,会有定时的输出,当输出停止的时候,认定为死机


好吧,解决了,
由于刚开始没有防抖的要求,代码非常简单,所以直接用 hook 处理,后来发现必须要加防抖,就直接改了代码,但是忘记从 hook 改成 task
所以只需要将 3 中提到的假的定时中断任务(实际是定时中断 hook)改成 真的定时中断任务就好了

点评

恭喜你解决了问题,  详情 回复 发表于 2024-10-30 22:49
希望这个世界让我小装一次B
回复

使用道具 举报 送花

5

主题

1070

回帖

4729

积分

荣誉版主

积分
4729
 楼主| 发表于 2024-10-30 22:49:38 | 显示全部楼层
Yang.*** 发表于 2024-10-30 15:15
我插播一个简单的问题,
1. 创建一个二值信号量b
2. 创建一个 CTRL 任务,执行指定的操作,然后uLockBin(b) ...

恭喜你解决了问题,
回复

使用道具 举报 送花

6

主题

89

回帖

818

积分

高级会员

积分
818
发表于 2024-10-31 09:43:06 | 显示全部楼层
Cos*** 发表于 2024-10-28 00:06
首先是了解 三目运算。
(条件表达式) ? 表达式1 : 表达式2;
如果条件表达式为真,执行表达式1并返回结果 ...

我测试了下,结果作者看看对不对。
编译时根据(group)的值只编译对应的一段代码,例如 group = s_u8_t ,就只编译sizeof(group) == 1 ? *(s_u8_t  *)&group ? true : false 这一段,其它被优化。执行结果,当 (group) 值 == 0时返回false,当(group) 值 != 0时返回true。

点评

你理解的差不多了,你的例子,最终结果是仅编译 *(s_u8_t *)&group ? true : false。 测试可采用 条件判断 或 赋值 等方法, 条件判断 更符合 实际应用。 u8 u8_1; if(sTSV_QueryFlagGroup(u8_1)) _nop_(); 这样  详情 回复 发表于 2024-10-31 13:49
回复

使用道具 举报 送花

已绑定手机

4

主题

111

回帖

2156

积分

金牌会员

积分
2156
发表于 2024-10-31 10:07:21 | 显示全部楼层
我刚发现一个小问题。
系统加入我自己的.c和.h程序之后,编译报错。
然后加上#include "..\System\os_link.h"就可以了。
截图202410311003378736.jpg
截图202410311006562652.jpg

点评

1、用户的各个c文件中应包含 os_link.h。 2、System、Config、Hook、Port,4个组为 CosyOS 文件; 其它组 User、Test 等,为 用户文件,只是设计用来方便测试和示例。 3、typedef.h 文件就是用户的h文件,要避  详情 回复 发表于 2024-10-31 13:25
回复

使用道具 举报 送花

5

主题

1070

回帖

4729

积分

荣誉版主

积分
4729
 楼主| 发表于 2024-10-31 13:25:06 | 显示全部楼层
DIY*** 发表于 2024-10-31 10:07
我刚发现一个小问题。
系统加入我自己的.c和.h程序之后,编译报错。
然后加上#include "..\System\os_link. ...

1、用户的各个c文件中应包含 os_link.h。
2、System、Config、Hook、Port,4个组为 CosyOS 文件;
     其它组 User、Test 等,为 用户文件,只是设计用来方便测试和示例。
3、typedef.h 文件就是用户的h文件,要避免与其它用户h文件 类型重定义。
回复

使用道具 举报 送花

16

主题

156

回帖

955

积分

高级会员

积分
955
发表于 2024-10-31 13:32:16 | 显示全部楼层
很好
回复

使用道具 举报 送花

0

主题

113

回帖

104

积分

注册会员

积分
104
发表于 2024-10-31 13:39:25 | 显示全部楼层
学习
回复

使用道具 举报 送花

5

主题

1070

回帖

4729

积分

荣誉版主

积分
4729
 楼主| 发表于 2024-10-31 13:49:14 | 显示全部楼层
sdw*** 发表于 2024-10-31 09:43
我测试了下,结果作者看看对不对。
编译时根据(group)的值只编译对应的一段代码,例如 group = s_u8_t  ...

你理解的差不多了,你的例子,最终结果是仅编译 *(s_u8_t  *)&group ? true : false。
测试可采用 条件判断 或 赋值 等方法,
条件判断 更符合 实际应用。

u8 u8_1;

if(sTSV_QueryFlagGroup(u8_1)) _nop_();

这样测试经常还会导致更激进的优化,*(s_u8_t  *)&u8_1 被优化为 u8_1。
如果换成标志组,就不会了,只能是 指针间接访问了。
回复

使用道具 举报 送花

6

主题

89

回帖

818

积分

高级会员

积分
818
发表于 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
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-11-12 01:47 , Processed in 0.079519 second(s), 99 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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