虽然M0才没写几个模块,不过我觉得现在这样写和写单片机的程序差不多,就决定看能不能从LOOK入手边了解基于LOOK的程序,边熟悉M0的模块。先写个简单的LOOK程序,根据老师的文档和大家的例子搭建LOOK,刚开使遇到点问题,像LOOK版本搞错会编译错误,我现在用的是0522版的,0909的以前向导不能用。基本的框架搞定后就开始写程序了,基本框架:
在LOOK中任务是一个派生类,其中routine()就是代表1个任务
- class task_led_t : public task_t {
- public:
- task_led_t() __OPT_ATTR__; // 构造函数
-
- protected:
- void routine(); // 任务例程
- };
下面这段是声明一个task_led的任务对象,task类已经将task_led_t类加到调度器中
- #ifdef LOOK_SCHEDULING_PRIORITY
- instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led(0);
- #else
- instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
- #endif
下面这一段是我在instantiate中找的,是task类模板的结构
- template<typename TASK, uintptr_t STACK_SIZE>
- class task : public TASK {
- #ifndef __DOXYGEN__
- public:
- static_assert(__is_base_of(task_t, TASK), "the type argument for <TASK> must be derived from task_t");
- #ifdef LOOK_SCHEDULING_PRIORITY
- template<typename ... R>
- task(uintptr_t priority, R ... r)
- : TASK(r ...)
- {
- init(stack[STACK_SIZE], priority);
- scheduler.add_task(*this); //将任务加到调度器里
- }
- #else
- template<typename ... R>
- task(R ... r)
- : TASK(r ...)
- {
- init(stack[STACK_SIZE]);
- scheduler.add_task(*this);
- }
- #endif // LOOK_SCHEDULING_PRIORITY
- private:
- uint8_t align[8 - ((sizeof(TASK) + (STACK_SIZE + TASK::MIN_CONTEXT_SIZE) * sizeof(uintptr_t)) & 7)];
- uintptr_t stack[STACK_SIZE + TASK::MIN_CONTEXT_SIZE];
- #endif // __DOXYGEN__
- };
那么如何创建多任务呢,知道了任务是如何创建和加到调度器的,那多任务就是将多个任务加到调度器,而要任务不一样那就要写多个任务类了,下面是我的2个简单任务,都是亮LED的
led.h
- #include "look_config.h"
- #include <look.h>
- #include <instantiate>
- #include"M0Base.h"
- // 任务类 task_led_t 的定义
- class task_led_t : public task_t {
- public:
- task_led_t() __OPT_ATTR__; // 构造函数
-
- protected:
- void routine(); // 任务例程
- };
- // 任务类 task_led_t 的构造函数
- __OPT_INLINE__ task_led_t::task_led_t()
- {
- // TODO: 在此初始化 task_led_t 的类成员
- LedIoOpen();
- }
- class task_led2_t : public task_t {
- public:
- task_led2_t() __OPT_ATTR__; // 构造函数
-
- protected:
- void routine(); // 任务例程
- };
- // 任务类 task_led_t 的构造函数
- __OPT_INLINE__ task_led2_t::task_led2_t()
- {
- // TODO: 在此初始化 task_led_t 的类成员
- LedIoOpen();
- }
- extern instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2;
- extern instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
led.cpp
- #include "led.h"
- #include <NUC1xx.h>
- #include"NUC1xxM051Seriescfg.h"
- #include"M0Base.h"
- // 任务类 task_led_t 的例程
- void task_led_t::routine()
- {
- // TODO: 在此编写 task_led_t 例程的内容
-
- while (true) {
- for(uint8_t i=BIT0;i<BIT4;i<<=1 )
- {
- LedSet(i);
- DrvSYS_Delay(100000);
- }
- scheduler.yield(); //当前的任务进入就绪态,调度下一个任务
-
- // TODO: 在此编写 task_led_t 例程的内容
- }
- }
- void task_led2_t::routine()
- {
- while (true){
- for(uint8_t i=BIT3;i>0;i>>=1 )
- {
- LedSet(i);
- DrvSYS_Delay(100000);
- }
- scheduler.yield(); //当前的任务进入就绪态,调度下一个任务
- // TODO: 在此编写 task_led_t 例程的内容
- }
- }
- #ifdef LOOK_SCHEDULING_PRIORITY
- instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led(0);
- instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2(1);
- #else
- instantiate::task<task_led_t, LOOK_STACK_SIZE> task_led;
- instantiate::task<task_led2_t, LOOK_STACK_SIZE> task_led2;
- #endif
LOOK有6中调度算法,我这里简单的用了协作调度,时间片轮也试了下,其他调度就不怎么清楚了,
在协作调度中,任务结束后调用scheduler.yield(); 可进入下一个任务,
在时间片轮则是不调用scheduler.yield(); 当时间到就会进入下一个任务
- //*** <<< Use Configuration Wizard in Context Menu >>> ***
- // <o> 调度算法
- // <0=> 协作(Co-operative)
- // <1=> 时间片轮转(Round-Robin)
- // <2=> 固定优先级(Fixed Priority)
- // <3=> 最早截止期优先(Earliest Deadline First)
- // <4=> 多级队列(Multi-Level Queue)
- // <5=> 多级队列+时间片轮转(Multi-Level Queue & Round-Robin)
- #define LOOK_SCHEDULING_VAL 0
先写这么多,虽然弄出来了,不过很多东西只是了解点皮毛,看来还有好多要像大叔和John lee老师
|