为了方便开发,方便使用,WRTOS4.0对任务创建做了精简化处理,做为软件工程师,经常会对一个函数或是方法要求的一大堆入口参数而感到用起来复杂,这点在MCU里面特别突出。通常MCU使用的C编译器,都不提供高级语言中那种方法收集与参数预测的功能,所以需要手动去翻找,一个个参数对应入座,这样使用起来效率低且容易出错,WRTOS4.0将几乎所有的系统API函数都做了参数精简处理。
任务的创建是在运行前的准备工作。WRTOS4.0里面,可以同时并行运行最多32个任务,全部可由用户创建,但任务可以进入注销状态,任务的位置便可以重用,这样,事实上,任务总数可能达到无限多个,只是他们需要在不同的时刻被创建,被运行。WRTOS4.0支持任务动态创建,但任务本身,却都是静态的。
WRTOS4.0里,将系统存储空间分为堆和栈两部分,堆存放全局变量或全局结构,而栈存放任务局部变量或结构。堆位于栈的下方,栈的起始位置是堆的结束位置,这样处理的好处是可以使堆不至于重合到栈的位置,因为全局变量的地址是由编译器分配得到,所以在程序运行前堆占用的空间便是已知的。WRTOS4.0从堆尾(即栈底)开始,将其余空间按任务需求进行分片,每一片都做为相应任务的私有栈空间,栈具有向上增长或向下递减的特性,由此,可由栈底和栈顶位置区分开各个任务的运行内存空间。系统对所有任务的私有栈都进行维护,以保护任务私有的数据。
WRTOS4.0里定义了栈的起始位置,这之前的存储地址空间,是留给堆使用的:
任务栈从此地址开始向后分配,这是WRTOS4.0任务创建前做的栈区位置设置。任务创建用系统调用Wrtos_TaskCreate()方法。
一般MCU级的OS里面任务都不需要传入参数,这样可以提高效率,但也可以修改Func形式以期望获得参数,推荐使用void参数,大量参数的传递可以使用其它方法。
WRTOS4.0里的任务优先级从0-31,数字越小优先级越高,STM32里面栈是向下递减型,所以定义的是栈高地址,栈从此地址位开始向下减,这便是任务私有栈,Faddr是任务的初始运行地址,不多说明。如下方法,创建了两个任务:
上面的方法定义了两个任务,各自完成自己事务,任务各有一个局部变量,任务A的私有栈从2000开始下向扩展,任务B有私有栈从3000开始向下扩展,这样的话任务A的最大使用栈为0-2000,否则将重合到堆空间,任务B私有栈从2000-3000,否则将重合到任务A的栈空间,WRTOS4.0自动将任务栈位置累加到栈起始区,即前面定义的Wrtos_StackStart上,以获得正确的栈地址。任务在创建时指定的栈大小应该按自己的运行需求进行分配,理论上越大越好。WRTOS4.0里任务创建是没有返回态的,因任务同时运行的个数不能超过32个,这点必须由用户自己保证,否则创建失败。同时被创建的任务数在32个以内且优先级不冲突的时候,一定能创建成功。这些条件,留给用户自己保证。
WRTOS4.0里任务的形式必须如下:
任务是没有返回态的,否则将产生系统复位。任务可以有初始参数,但需要自己定义Func形式。
任务在WRTOS4.0里被创建后,便进入就绪态,等待被系统切入运行态。当任务自己的工作完成后,便可以从系统注销,这样可以减小系统负荷,同时释放该任务所占用的资源。任务从系统注销的方法如下:
任务从系统消销后,任务的TCB块被系统收回,同时所有用到的资源被系统释放,任务的删除过程一定成功,所以没有返回状态。被收回的TCB又可以重新被利用,这样便实现了任务优先级重用,实现了任务的动态装载,如:
上例是任务Task_System_Init()完成自己的工作后即从系统注销,而任务E则根据自己收到的邮件Wrtso_TaskMail来判断当前应该载入哪个任务,任务B、C、D共享同一个优先级号3,共享同一个栈空间,因为它们被创建,运行各自的工作后,即从系统注销了,这些资源又被系统回收了的原故,从而可以重新分配。
WRTOS4.0里任务创建、注销、动态创建是非常方便非常灵活的,但若重新创建一个任务到还未注销的任务空间上去,将产生不可预测的后果。