1.什么是任务?
简单通俗的来讲,任务就是一个不会返回的函数。
void task1(void *param)
{
while(1)
{
//执行区域
..........
//执行区域
}
}
更加深入的来谈任务的话,不得不考虑栈、堆、数据区、代码区和内核寄存器。其中数据区和代码区由编译器自动分配,各个任务相互独立,并不冲突。堆的作用主要是用在动态能存分配上面。而栈和内核寄存器在任务切换的过程需要将数据保存,以方便下次任务切换回来可以从断点出执行。
2.建立任务结构体,该结构部分现在比较简单,只定义了一个指向任务堆栈地址的指针。
//任务结构体
typedef struct
{
um_uint32_t *stack_addr; //指向任务堆栈地址
}um_os;
3. 通过任务结构体创建任务1与任务2,通过数组创建任务1和任务2的堆栈。
um_os OS_Task1;
um_os OS_Task2;
um_uint32_t task1_stack[1024];
um_uint32_t task2_stack[1024];
4. 创建任务实现函数task1与task2,这里什么也不做。
void task1(void *param)
{
while(1)
{
}
}
void task2(void *param)
{
while(1)
{
}
}
5.创建任务初始化函数,这里包含了四个形参:
参数1: um_os *task; 任务结构指针
参数2: void(*entry)(void *) 任务入口函数
参数3: void *param 传递给任务的参数
参数4: UM_OS_uint32_t *stask_stack 任务对应堆栈地址
void Task_Init(um_os *task,void(*entry)(void *),void *param,um_uint32_t *stack)
{
task->stack_addr = stack;
}
6. 初始化任务1和任务2
Task_Init(&OS_Task1,task1,(void *)0x11111111,&task1_stack[1024]);
Task_Init(&OS_Task2,task2,(void *)0x22222222,&task2_stack[1024]);
7.在keil工程中新建um_os.h文件,向该文件定义一些常用的数据类型和任务结构体,具体代码如下:
#ifndef _UM_OS_H
#define _UM_OS_H
#include <stdint.h>
/* UM-OS basic data type definitions */
typedef signed char um_int8_t;
typedef signed short um_int16_t;
typedef signed long um_int32_t;
typedef unsigned char um_uint8_t;
typedef unsigned short um_uint16_t;
typedef unsigned long um_uint32_t;
/* boolean type definitions */
#define um_true 1 /**< boolean true */
#define um_false 0 /**< boolean fails */
typedef struct
{
um_uint32_t *stack_addr;
}um_os;
8.主函数中我们包含um_os.h头文件,通过um_os 任务结构体来新建两个任务OS_Task1与OS_Task2,通过重定义的um_uint32_t 来定义两个任务堆栈task1_stack与task2_stack.
9.在main.c中创建任务初始化函数,并将stack_addr指针指向任务堆栈地址,main()中分别对Task1和Task2做了初始化。
本次创建了um_os 的任务,并将任务函数和任务堆栈联系起来了,为后续的任务切换打下基础。