【UCOSIII】【中断管理、时间管理】OS_CRITICAL_ENTER()、OS_CRITICAL_EXIT()、OSTimeDlyHMSM

中断管理

2种方式:直接发布、延时发布

OS_CFG_ISR_POST_DEFERRED_EN = 1 延时发布 中断消息  defer ISR POST En使能

OS_CFG_ISR_POST_DEFERRED_EN = 0 直接发布 中断消息

1.延时发布
#if OS_CFG_ISR_POST_DEFERRED_EN > 0u                             /* Deferred ISR Posts ------------------------------ */
                                                                 /* Lock the scheduler                                */
/*if:如果采用 延迟发布 中断处理*/
//访问全局资源OSSchedLockNestingCtr 
//才 关中断CPU_CRITICAL_ENTER() 打开中断CPU_CRITICAL_EXIT()
//对临界段代码的保护还是采用调度器加锁的方式

//进入临界区 给 调度器上锁
#define  OS_CRITICAL_ENTER()                                       \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr++;                              \
             if (OSSchedLockNestingCtr == 1u) {                    \
                 OS_SCHED_LOCK_TIME_MEAS_START();                  \
             }                                                     \
             CPU_CRITICAL_EXIT();                                  \
         } while (0)

                                                     
//退出临界区 给 调度器解锁
#define  OS_CRITICAL_EXIT()                                        \
         do {                                                      \
             CPU_CRITICAL_ENTER();                                 \
             OSSchedLockNestingCtr--;                              \
             if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {     \
                 OS_SCHED_LOCK_TIME_MEAS_STOP();                   \
                 if (OSIntQNbrEntries > (OS_OBJ_QTY)0) {           \
                     CPU_CRITICAL_EXIT();                          \
                     OS_Sched0();                                  \
                 } else {                                          \
                     CPU_CRITICAL_EXIT();                          \
                 }                                                 \
             } else {                                              \
                 CPU_CRITICAL_EXIT();                              \
             }                                                     \
         } while (0)
2.直接发布
/*else: 直接发布 中断服务程序 */
//关中断 保护临界代码区
	//CPU_CRITICAL_ENTER()    最终调用  CPU_SR_Save()  在cpu_a.asm 用汇编定义
#define  OS_CRITICAL_ENTER()                    CPU_CRITICAL_ENTER()	

//开中断 退出
	//CPU_CRITICAL_EXIT()	最终调用 CPU_SR_Restore()  在cpu_a.asm 用汇编定义
#define  OS_CRITICAL_EXIT()                     CPU_CRITICAL_EXIT()

#endif

时间管理

1. OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err);

    hour:0-99

    minutes:0-59

    seconds:0-59

    milli:0-999

    opt:OS_OPT_TIME_HMSM_STRICT

#if OS_CFG_TIME_DLY_HMSM_EN > 0u
/* 任务延时函数 */
void  OSTimeDlyHMSM (CPU_INT16U   hours,	//0-99
                     CPU_INT16U   minutes,	//0-59
                     CPU_INT16U   seconds,	//0-59
                     CPU_INT32U   milli,	//0-999
                     OS_OPT       opt,		//OS_OPT_TIME_HMSM_STRICT严格参数
                     OS_ERR      *p_err)
{
#if OS_CFG_ARG_CHK_EN > 0u
    CPU_BOOLEAN  opt_invalid;
    CPU_BOOLEAN  opt_non_strict;
#endif
    OS_OPT       opt_time;
    OS_RATE_HZ   tick_rate;
    OS_TICK      ticks;
    CPU_SR_ALLOC();

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
    if (OSIntNestingCtr > (OS_NESTING_CTR)0u) {             /* Not allowed to call from an ISR                        */
       *p_err = OS_ERR_TIME_DLY_ISR;
        return;
    }
#endif

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0u) {       /* Can't delay when the scheduler is locked               */
       *p_err = OS_ERR_SCHED_LOCKED;
        return;
    }

    opt_time = opt & OS_OPT_TIME_MASK;                      /* Retrieve time options only.                            */
    switch (opt_time) {
        case OS_OPT_TIME_DLY:
        case OS_OPT_TIME_TIMEOUT:
        case OS_OPT_TIME_PERIODIC:
             if (milli == (CPU_INT32U)0u) {                 /* Make sure we didn't specify a 0 delay                  */
                 if (seconds == (CPU_INT16U)0u) {
                     if (minutes == (CPU_INT16U)0u) {
                         if (hours == (CPU_INT16U)0u) {
                            *p_err = OS_ERR_TIME_ZERO_DLY;
                             return;
                         }
                     }
                 }
             }
             break;

        case OS_OPT_TIME_MATCH:
             break;

        default:
            *p_err = OS_ERR_OPT_INVALID;
             return;
    }

#if OS_CFG_ARG_CHK_EN > 0u                                  /* Validate arguments to be within range                  */
    opt_invalid = DEF_BIT_IS_SET_ANY(opt, ~OS_OPT_TIME_OPTS_MASK);
    if (opt_invalid == DEF_YES) {
       *p_err = OS_ERR_OPT_INVALID;
        return;
    }

    opt_non_strict = DEF_BIT_IS_SET(opt, OS_OPT_TIME_HMSM_NON_STRICT);
    if (opt_non_strict != DEF_YES) {
         if (milli   > (CPU_INT32U)999u) {
            *p_err = OS_ERR_TIME_INVALID_MILLISECONDS;
             return;
         }
         if (seconds > (CPU_INT16U)59u) {
            *p_err = OS_ERR_TIME_INVALID_SECONDS;
             return;
         }
         if (minutes > (CPU_INT16U)59u) {
            *p_err = OS_ERR_TIME_INVALID_MINUTES;
             return;
         }
         if (hours   > (CPU_INT16U)99u) {
            *p_err = OS_ERR_TIME_INVALID_HOURS;
             return;
         }
    } else {
         if (minutes > (CPU_INT16U)9999u) {
            *p_err = OS_ERR_TIME_INVALID_MINUTES;
             return;
         }
         if (hours   > (CPU_INT16U)999u) {
            *p_err = OS_ERR_TIME_INVALID_HOURS;
             return;
         }
    }
#endif

                                                            /* Compute the total number of clock ticks required..     */
                                                            /* .. (rounded to the nearest tick)                       */
    //默认 系统时钟节拍:200Hz 5ms
	tick_rate = OSCfg_TickRate_Hz;
    ticks     = ((OS_TICK)hours * (OS_TICK)3600u + (OS_TICK)minutes * (OS_TICK)60u + (OS_TICK)seconds) * tick_rate
              + (tick_rate * ((OS_TICK)milli + (OS_TICK)500u / tick_rate)) / (OS_TICK)1000u;

    if (ticks > (OS_TICK)0u) {
        OS_CRITICAL_ENTER();
        OSTCBCurPtr->TaskState = OS_TASK_STATE_DLY;
        OS_TickListInsert(OSTCBCurPtr,
                          ticks,
                          opt_time,
                          p_err);
        if (*p_err != OS_ERR_NONE) {
             OS_CRITICAL_EXIT_NO_SCHED();
             return;
        }
        OS_RdyListRemove(OSTCBCurPtr);                      /* Remove current task from ready list                    */
        OS_CRITICAL_EXIT_NO_SCHED();
        OSSched();                                          /* Find next task to run!                                 */
       *p_err = OS_ERR_NONE;
    } else {
       *p_err = OS_ERR_TIME_ZERO_DLY;
    }
}
#endif

2. OSTimeDly()

void  OSTimeDly (OS_TICK   dly,
                 OS_OPT    opt,
                 OS_ERR   *p_err)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用 os_evt_get 函数之前,需要先创建并初始化事件标志。一般而言,可以使用操作系统提供的函数来创建和初始化事件标志。 以下是一个示例代码,展示了如何使用 os_evt_get 函数等待事件发生: ``` #include "os.h" // 定义事件标志 #define EVENT_FLAG_1 (1 << 0) #define EVENT_FLAG_2 (1 << 1) // 定义任务堆栈和控制块 #define TASK_STACK_SIZE 128 static OS_TCB task_tcb; static CPU_STK task_stack[TASK_STACK_SIZE]; // 任务函数 static void task_func(void *p_arg) { OS_ERR err; CPU_TS ts; OS_FLAGS flags; while (1) { // 等待 EVENT_FLAG_1 或 EVENT_FLAG_2 事件 flags = os_evt_get(EVENT_FLAG_1 | EVENT_FLAG_2, OS_OPT_PEND_BLOCKING, &ts, &err); // 处理事件 if (flags & EVENT_FLAG_1) { // 处理 EVENT_FLAG_1 事件 } if (flags & EVENT_FLAG_2) { // 处理 EVENT_FLAG_2 事件 } } } int main() { OS_ERR err; // 初始化操作系统 OSInit(&err); // 创建任务 OSTaskCreate(&task_tcb, "Task", task_func, NULL, 2, task_stack, TASK_STACK_SIZE / 10, TASK_STACK_SIZE, 0, 0, NULL, OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, &err); // 创建事件标志并初始化为 0 OSFlagCreate(0, &err); // 等待一段时间 OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 设置 EVENT_FLAG_1 事件 OSFlagPost(EVENT_FLAG_1, OS_OPT_POST_FLAG_SET, &err); // 等待一段时间 OSTimeDlyHMSM(0, 0, 1, 0, OS_OPT_TIME_HMSM_STRICT, &err); // 设置 EVENT_FLAG_2 事件 OSFlagPost(EVENT_FLAG_2, OS_OPT_POST_FLAG_SET, &err); // 运行操作系统 OSStart(&err); return 0; } ``` 在上述示例代码中,先定义了 EVENT_FLAG_1 和 EVENT_FLAG_2 两个事件标志,然后创建了一个任务,并在任务函数中使用 os_evt_get 函数等待这两个事件的发生。在主函数中先创建了事件标志,并在一定时间后分别设置了 EVENT_FLAG_1 和 EVENT_FLAG_2 事件,从而触发任务函数中的相应处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值