开发指导

About 10 min

开发指导

任务创建后,内核可以执行锁任务调度,解锁任务调度,挂起,恢复,延时等操作,同时也可以设置任务优先级,获取任务优先级。

接口说明

OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。

表 1 任务管理模块接口

功能分类

接口名

描述

创建和删除任务

LOS_TaskCreateOnly

创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。

LOS_TaskCreate

创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。

LOS_TaskDelete

删除指定的任务。

控制任务状态

LOS_TaskResume

恢复挂起的任务,使该任务进入ready状态。

LOS_TaskSuspend

挂起指定的任务,然后切换任务

LOS_TaskDelay

任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。

LOS_Msleep

传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。

LOS_TaskYield

当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。

控制任务调度

LOS_TaskLock

锁任务调度,但任务仍可被中断打断。

LOS_TaskUnlock

解锁任务调度。

LOS_Schedule

触发任务调度。

控制任务优先级

LOS_CurTaskPriSet

设置当前任务的优先级。

LOS_TaskPriSet

设置指定任务的优先级。

LOS_TaskPriGet

获取指定任务的优先级。

获取任务信息

LOS_CurTaskIDGet

获取当前任务的ID。

LOS_NextTaskIDGet

获取任务就绪队列中优先级最高的任务的ID。

LOS_NewTaskIDGet

等同LOS_NextTaskIDGet。

LOS_CurTaskNameGet

获取当前任务的名称。

LOS_TaskNameGet

获取指定任务的名称。

LOS_TaskStatusGet

获取指定任务的状态。

LOS_TaskInfoGet

获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。

LOS_TaskIsRunning

获取任务模块是否已经开始调度运行。

任务信息维测

LOS_TaskSwitchInfoGet

获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。

开发流程

本节介绍任务模块的典型场景开发流程:

  1. 锁任务调度LOS_TaskLock,防止高优先级任务调度。
  2. 创建任务LOS_TaskCreate。
  3. 解锁任务LOS_TaskUnlock,让任务按照优先级进行调度。
  4. 延时任务LOS_TaskDelay,任务延时等待。
  5. 挂起指定的任务LOS_TaskSuspend,任务挂起等待恢复操作。
  6. 恢复挂起的任务LOS_TaskResume。

说明:

  • 执行Idle任务时,会对待回收链表中的任务控制块和任务栈进行回收。
  • 任务名是指针,并没有分配空间,在设置任务名时,禁止将局部变量的地址赋值给任务名指针。
  • 任务栈的大小按8字节大小对齐。确定任务栈大小的原则是,够用就行,多了浪费,少了任务栈溢出。
  • 挂起当前任务时,如果已经锁任务调度,则无法挂起。
  • Idle任务及软件定时器任务不能被挂起或者删除。
  • 在中断处理函数中或者在锁任务的情况下,执行LOS_TaskDelay会失败。
  • 锁任务调度,并不关中断,因此任务仍可被中断打断。
  • 锁任务调度必须和解锁任务调度配合使用。
  • 设置任务优先级时可能会发生任务调度。
  • 可配置的系统最大任务数是指:整个系统的任务总个数,而非用户能使用的任务个数。例如:系统软件定时器多占用一个任务资源,那么用户能使用的任务资源就会减少一个。
  • LOS_CurTaskPriSet和LOS_TaskPriSet接口不能在中断中使用,也不能用于修改软件定时器任务的优先级。
  • LOS_TaskPriGet接口传入的task ID对应的任务未创建或者超过最大任务数,统一返回-1。
  • 在删除任务时要保证任务申请的资源(如互斥锁、信号量等)已被释放。

编程实例

本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下:

UINT32 g_taskHiId;
UINT32 g_taskLoId;
#define TSK_PRIOR_HI 4
#define TSK_PRIOR_LO 5

UINT32 Example_TaskHi(VOID)
{
    UINT32 ret;

    printf("Enter TaskHi Handler.\n");

    /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */
    ret = LOS_TaskDelay(100);
    if (ret != LOS_OK) {
        printf("Delay TaskHi Failed.\n");
        return LOS_NOK;
    }

    /* 100个Ticks时间到了后,该任务恢复,继续执行 */
    printf("TaskHi LOS_TaskDelay Done.\n");

    /* 挂起自身任务 */
    ret = LOS_TaskSuspend(g_taskHiId);
    if (ret != LOS_OK) {
        printf("Suspend TaskHi Failed.\n");
        return LOS_NOK;
    }
    printf("TaskHi LOS_TaskResume Success.\n");
    return ret;
}

/* 低优先级任务入口函数 */
UINT32 Example_TaskLo(VOID)
{
    UINT32 ret;

    printf("Enter TaskLo Handler.\n");

    /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */
    ret = LOS_TaskDelay(100);
    if (ret != LOS_OK) {
        printf("Delay TaskLo Failed.\n");
        return LOS_NOK;
    }

    printf("TaskHi LOS_TaskSuspend Success.\n");

    /* 恢复被挂起的任务g_taskHiId */
    ret = LOS_TaskResume(g_taskHiId);
    if (ret != LOS_OK) {
        printf("Resume TaskHi Failed.\n");
        return LOS_NOK;
    }
    return ret;
}

/* 任务测试入口函数,创建两个不同优先级的任务 */
UINT32 Example_TskCaseEntry(VOID)
{
    UINT32 ret;
    TSK_INIT_PARAM_S initParam;

    /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */
    LOS_TaskLock();

    printf("LOS_TaskLock() Success!\n");

    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi;
    initParam.usTaskPrio = TSK_PRIOR_HI;
    initParam.pcName = "TaskHi";
    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;

    /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
    ret = LOS_TaskCreate(&g_taskHiId, &initParam);
    if (ret != LOS_OK) {
        LOS_TaskUnlock();

        printf("Example_TaskHi create Failed!\n");
        return LOS_NOK;
    }

    printf("Example_TaskHi create Success!\n");

    initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo;
    initParam.usTaskPrio = TSK_PRIOR_LO;
    initParam.pcName = "TaskLo";
    initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;

    /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
    ret = LOS_TaskCreate(&g_taskLoId, &initParam);
    if (ret != LOS_OK) {
        LOS_TaskUnlock();
        printf("Example_TaskLo create Failed!\n");
        return LOS_NOK;
    }

    printf("Example_TaskLo create Success!\n");

    /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */
    LOS_TaskUnlock();

    return LOS_OK;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

结果验证

编译运行得到的结果为:

LOS_TaskLock() Success!
Example_TaskHi create Success!
Example_TaskLo create Success!
Enter TaskHi Handler.
Enter TaskLo Handler.
TaskHi LOS_TaskDelay Done.
TaskHi LOS_TaskSuspend Success.
TaskHi LOS_TaskResume Success.
1
2
3
4
5
6
7
8