论坛元老
- 积分
- 7862
- 金钱
- 7862
- 注册时间
- 2014-8-13
- 在线时间
- 1584 小时
|
发表于 2019-10-17 03:42:24
|
显示全部楼层
本帖最后由 mack13013 于 2019-10-17 13:31 编辑
我写了个跟楼主差不多的,不过任务优先级我是直接用的数组,数组中直接排列任务优先级,同样的数组中的任务不可以被数组中的任务抢占(优先级高也不行),但是可以被MCU中断抢占,MCU中断大多的任务就是不停的弹射任务编号到数组中去(当然弹射任务时会区分优先级,分配中断处理程序时会定义好弹射任务的数组中的优先级,而且可配置),中断中大多执行一两句aa = bb;就退出MCU中断(当时这样设计的目的是实在是不想处理MCU的任务抢占时的“现场保护”,又不想让MCU中断占用太多资源)。
数组从0到N优先级依次降低,每次先执行最高优先级的任务,执行过程只会被中断打断,执行完成之后任务移除数组并继续从数组中优先级最高的任务开始执行(也就是说,如果MCU负荷比较重,一直有高优先级任务,那么低优先级任务就永远不会被执行)。
并且数组可以转化为二维,数组放置环形队列指针,实现更复杂的操作(比如同级队列)。
我可能还多设计了一个功能:定时器高级管理,对于某些定时执行的任务,程序不需要再去在现写申请硬件定时器的代码,定时器可以实现间隔一定时间执行某项任务,该任务可以被设定执行次数(执行N次自动停止或者一直执行下去),定时器被管理起来,根据定时时长分配不同的定时器资源(是基于STM32F407开发的,STM32F407有32位和16位定时器,如果申请时间间隔长,16位无法满足,那么就会自动分配32位定时器,并且有高级功能的定时器不被优先分配)。
用法也简单SetTimer(*nId, nEclisp, nPeriod, nCount, fnTimerHandler, nParam);就可以执行了。
参数解释:nId 定时器Id:返回值,SetTimer执行成功之后会返回Id,该Id可用于该定时器任务管理(目前实现了KillTimer(nId);功能,可以关闭该定时器。应该还实现一个Pause或者Suspend功能)。
nEclisp:延迟多久之后开始第一次执行
nPeriod:执行时间间隔,不能为0(为0会导致定时器任务不停执行,其他任务无法获得MCU资源)
nCount:执行次数。为0时表示一直执行,直到程序执行了KillTimer(nId);
fnTimerHandler:函数指针,定时器任务的函数体,由用户实现,不能非法。
nParam:定时器任务的传参。
这样,定时执行某个任务(比如采集某些数据定时发送或者定时保存)就会很简单。
缺陷:1、为了避免做CPU现场保护,所以没有任务抢占系统,导致某些被动任务(比如红外的外部中断)就不能用任务数组来配置(其实也可以配置到任务数组中,将任务数组优先级最低处添加一个扫描任务,不停扫描即可,但是速度响应可能没那么快),就需要占用MCU的中断资源。
2、没有添加同步处理;
3、同样的原子操作也没有,只能在程序中想办法保证;
4、内存管理也没戏;
5、外设管理只能放到任务数组中去,无法以驱动加载至内核的方式进行和保护;
6、也没有分配内核和用户区,没有内核保护。
只是简单的任务分配(都不能说是调度),所以算不上一个系统。
|
|