虽然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老师 |