美文网首页OneOS物联网操作系统
OneOS-Lite代码学习:任务调度与中断的开关

OneOS-Lite代码学习:任务调度与中断的开关

作者: 罗蓁蓁 | 来源:发表于2021-12-22 11:33 被阅读0次

任务调度开关

以下这些代码在/oneos-kernel/source/os_sched.c

调度的初始化:
k_sched_init->_k_readq_bmap_init:这里初始化的是优先级位图为0,优先级链表数组。

启动内核调度:
k_start->os_first_task_start-

关闭任务调度:

void os_schedule_lock(void)
{
    register unsigned long    kernel_irq_save;
    kernel_irq_save = os_irq_lock();
    g_os_sched_lock_cnt++;
    os_irq_unlock(kernel_irq_save);
}

开启任务调度:

void os_schedule_unlock(void)
{
    register unsigned long    kernel_irq_save;
    kernel_irq_save = os_irq_lock();
    g_os_sched_lock_cnt--;
    os_irq_unlock(kernel_irq_save);

    if (0 == g_os_sched_lock_cnt)
    {
        kernel_irq_save = os_irq_lock();

        if ((OS_NULL == g_os_current_task) || (0 != g_os_sched_lock_cnt))
        {
            os_irq_unlock(kernel_irq_save);
        }
        else
        {
            g_os_next_task = g_os_high_task;
            if (g_os_current_task != g_os_next_task)
            {
                os_task_switch();
            }
            os_irq_unlock(kernel_irq_save);
        }
    }
}

这里需要注意的是:

g_os_sched_lock_cnt的初始值是0,关闭任务调度则+1,开启则-1,如果值为0,则表示调度开启状态。如果值为负值,则表明出错了!有点问题!
当值为0时,开启调度,则要去寻找最高优先级的任务,如果最高优先级和当前优先级任务不同,则进行任务切换。

可见:确定任务调度是否开启的关键是全局变量:g_os_sched_lock_cnt。所以我们对他的操作要特别小心。在操作它的时候,关闭了中断,防止干扰。

中断开关

再说说开关中断:
以下这段代码使用内联汇编,在/arch/arm/armv7march_interrupt.c中:

os_ubase_t os_irq_lock(void)
{
    os_ubase_t primask;
    __asm__ __volatile__(
        "MRS     %0, PRIMASK\n"
        "CPSID   I"
        : "=r"(primask)
        : 
        : "memory");
    return primask;
}
void os_irq_unlock(os_ubase_t irq_save)
{
    __asm__ __volatile__(
        "MSR     PRIMASK, %0"
        : 
        : "r"(irq_save)
        : "memory");
    return;
}
void os_irq_disable(void)
{
    __asm__ __volatile__(
        "CPSID   I"
        :
        : 
        :);
    return;
}
void os_irq_enable(void)
{
    __asm__ __volatile__(
        "CPSIE   I"
        :
        : 
        :);
    return;
}

这里需要注意几个点:MRS,PRIMASK,CPSID I

  1. PRIMASK:中断屏蔽寄存器,这个寄存器只有一个位,置1后,将关闭所有可屏蔽中断的异常,只剩NMI和硬fault,默认值为0;
  2. MRS: 状态寄存器到通用寄存器的传送指令。
  3. MSR: 通用寄存器到状态寄存器的传送指令。

因此:

  1. "MRS %0, PRIMASK\n"就是把PRIMASK中断屏蔽寄存器的值保存到primask

  2. "MSR PRIMASK, %0\n"就是把保存在primask的值写回到PRIMASK中断屏蔽寄存器

  3. CPS全称Change Processor State,改变处理器状态。

  4. IE:Interrupt or abort enable. 使能中断

  5. ID: Interrupt or abort disable. 关闭中断

因此:

  1. CPSID I就是改变处理器的状态,关闭irq中断
  2. CPSIE I则是改变处理器的状态,开启irq中断

可见:os_irq_lockos_irq_unlock是一套接口,os_irq_disableos_irq_enable则是另一套,都可以使用。

关注&&联系

开源轻量操作系统: https://gitee.com/cmcc-oneos/OneOS-Lite

docs文档中心: https://oneos-lite.com/

相关文章

  • OneOS-Lite代码学习:任务调度与中断的开关

    任务调度开关 以下这些代码在/oneos-kernel/source/os_sched.c[https://git...

  • 2017-12-15

    今天我们学习了临界区与中断开关,普通的禁止和使能中断,在禁止中断时有触发中断的事件发生,当使能中断时该中断不会在响...

  • FreeRTOS操作系统例程(4):调度锁

    1.调度锁函数只是禁止了任务调度,并没有关闭任何中断 2.调度锁开启函数 vTaskSuspendAll 和调度锁...

  • springboot 任务调度

    任务调度 添加启动注解 测试代码

  • 线程管理调度

    任务调度器和任务切换 调度器schedule并不仅仅由时钟中断函数来处理,他还有被其他函数调用的情况例如threa...

  • 鸿蒙轻内核M核源码分析:中断Hwi

    摘要:本文带领大家一起剖析了鸿蒙轻内核的中断模块的源代码,掌握中断相关的概念,中断初始化操作,中断创建、删除,开关...

  • 任务调度学习

    jdk自带三种定时任务实现方式 1 Thread 2 java.util.TimeTask 3 java.util...

  • Linux内核——进程调度以及进程切换过程

    进程调度的时机 明确一点:一般来说,进程调度都是发生在进程外的(即进程运行的时候会持续执行代码),当执行代码中断跳...

  • 12/15

    今天学习了用开关2控制蜂鸣器的响声,按键控制蜂鸣器利用中断。中断调用子函数。

  • [逆解] FreeRTOS 2 - 任务分拆

    任务切换点 FreeRTOS是用中断的方式,将完整的任务函数分拆成代码段。任务函数运行中断,被称做任务挂起。可能挂...

网友评论

    本文标题:OneOS-Lite代码学习:任务调度与中断的开关

    本文链接:https://www.haomeiwen.com/subject/vodqqrtx.html