打印
[AVR单片机]

LOOK 示例1

[复制链接]
4788|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
John_Lee|  楼主 | 2008-8-7 17:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ST, TI, ck, se, vr
示例定义了两个任务 task1 和 task2。task1 获取一个信号灯后,根据结果翻转 PB0 或 PB1,而 task2 按 10 个 tick 间隔时间,周期性地释放信号灯。
当然,这个示例过于简单,某些喜欢裸奔的朋友可能会不屑(其实裸奔一样可以实现),但这只是教程的第一步,不好用个太复杂的示例。

这个示例包含了 3 个文件:config.h, sample1.cc, arch.cc

config.h 文件:
#ifndef __CONFIG_H
#define __CONFIG_H

const unsigned long FOSC = 14745600L;            //    晶振频率
const unsigned int TICKS_PER_SEC = 100;            //    每秒 tick
const int SIZE_INTERRUPT_STACK = 32;            //    中断栈长度

#endif


sample1.cc 文件:
#include "look.h"                            //    必须在第一行
#include <new>
#include <avr/io.h>
#include "config.h"

#define SIZE_TASK1_STACK    64                //    定义 task1 的栈长度
#define SIZE_TASK2_STACK    64                //    定义 task2 的栈长度
#define PRIO_TASK1    1                        //    定义 task1 的优先级
#define PRIO_TASK2    2                        //    定义 task2 的优先级

class task1_t : public task_t
{
public:
    task1_t (size_t stack_size) __attribute__ ((always_inline));        //    构造函数
    void notify () __attribute__ ((always_inline));

private:
    virtual void process (void* arg);                                    //    任务函数
    sema_t sema;                                                        //    semaphore,这里将semaphore定义在task1对象里,就相当于task1的per-thread data。
};

uint8_t task1[sizeof (task1_t) + SIZE_TASK1_STACK];        //    为task1分配空间,由于task1_t的对象将创建在这里,所以除了task1的栈空间外,还要加上task1_t的大小。

//    task1的构造函数
inline task1_t::task1_t (size_t stack_size)
: task_t (stack_size),                                //    初始化基类 task_t,参数为任务空间大小。
  sema (0)                                            //    初始化 sema,参数为 semaphore 的初始值。
{
    //    用户可以在此对task1的其它方面进行初始化,但不要在此创建其它任务对象。
    DDRB |= _BV (PB0) | _BV (PB1);
}

//    task_t::sema的访问函数
inline void task1_t::notify ()
{
    sema.put ();                        //    释放 semaphore(V操作)
}

class task2_t : public task_t
{
public:
    task2_t (size_t stack_size) __attribute__ ((always_inline));

private:
    virtual void process (void* arg);
};

uint8_t task2[sizeof (task2_t) + SIZE_TASK2_STACK];        //    为task2分配空间,同task1。

inline task2_t::task2_t (size_t stack_size)
: task_t (stack_size)                                    //    同 task1。
{
}

//    task1的任务函数
void task1_t::process (void* arg)
{
    //    在函数主循环之前,可以进行一些任务刚进入时所要做的工作,也可以创建其它任务对象。
    //    本例中,就在此创建了task2对象。
    sched_t::add (new (task2) task2_t (sizeof (task2)), PRIO_TASK2);    //    在 task2 空间上创建 task2_t 的对象
    while (true) {                                        //    任务循环
        if (sema.get () == sync_t::DONE)                //    获取 semaphore(P操作)
            PORTB ^= _BV (PB0);                            //    成功,翻转 PB0 表示,用户可以测量。
        else
            PORTB ^= _BV (PB1);                            //    失败,任务意外退出阻塞状态(应该不会运行到这个地方),翻转 PB1 表示,用户可以测量。
    }
}

//    task2的任务函数
void task2_t::process (void* arg)
{
    while (true) {                                        //    任务循环
        delay (10);                                        //    延时 10 ticks
        task1_t *task = static_cast<task1_t *> (sched_t::get_task (PRIO_TASK1));    //    调用 sched_t::get_task 取得task1的句柄(指针)
        task->notify ();                                //    通知 task1
    }
}

LOOK_CONFIG (_VECTORS_SIZE, SIZE_INTERRUPT_STACK);    //    配置中断系统,此为定式,不要修改

LOOK_START ()                     //    系统入口点。相当于 main
{
    //    在这里加入任务。可以创建所有的任务,也可以只创建第一个任务(其它任务由第一个任务创建)。
    sched_t::add (new (task1) task1_t (sizeof (task1)), PRIO_TASK1);        //    在 task1 空间上创建 task1_t 的对象
}


arch.cc 文件,这个文件是与系统节拍定时器的定义,用户可以根据具体项目修改,目前这个文件是为 atmega8 写的,系统节拍定时器使用了 timer2:
#include "look.h"
#include <avr/io.h>
#include "config.h"

#undef _VECTOR
#define _VECTOR(n)    (n - 1)

void systick_t::init ()
{
    attach (SIG_OUTPUT_COMPARE2);                                    //    将系统节拍中断绑定到 SIG_OUTPUT_COMPARE2。
    //    设定 timer2 为 10ms 周期性中断。
    OCR2 = (FOSC / 1024 / TICKS_PER_SEC) - 1;
    TIMSK |= _BV (OCIE2);
    TCCR2 = _BV (WGM21) | _BV (CS22) | _BV (CS21) | _BV (CS20);
}


此示例展示了 LOOK 系统的一般结构,信号灯,延时和 per-thread data。

为了简便,我就不写 makefile 了,直接给出编译命令行(假定 look 系统的所有头文件在当前目录):
avr-gcc -c -Os -g -D__AVR_ATmega8__ -fshort-enums -pipe -mmcu=avr4 -fno-rtti -fno-exceptions -Wa,-ahlms=sample3.lst sample1.cc -o sample1.o
avr-gcc -c -Os -g -D__AVR_ATmega8__ -fshort-enums -pipe -mmcu=avr4 -fno-rtti -fno-exceptions arch.cc -o arch.o


链接命令行(假定liblook.a 在当前目录):
avr-gcc -mmcu=atmega8 -nostartfiles -L. -o sample1.elf sample1.o arch.o -llook -Wl,-Map=sample1.map,--cref

生成的程序空间占用情况:
avr-size sample1.elf
   text    data     bss     dec     hex filename
   2110      70     343    2523     9db sample1.elf

可以看出此程序占用 flash 大小为 2180bytes,占用 ram 大小为 413bytes。

然后可以在 avr studio 中调试。



运行一段时间后,message 框中就会出现下列文字:
AVR Simulator: PORTB -  001477586:01 002952146:00 004426706:01 005901266:00 007375826:01

大家可以在网上查一下 avr studio 的 stimuli 格式。然后分析一下上面的文字。就可以得出结果了。

相关帖子

沙发
kanprin| | 2008-8-8 15:58 | 只看该作者

看不大明白

C++没学好,不过C++的类封装确实使结构比较明了。 努力学习……

版主快来发裤子了。

使用特权

评论回复
板凳
hotpower| | 2011-5-12 01:52 | 只看该作者
顶起来~~~

使用特权

评论回复
地板
ming117284| | 2011-5-13 13:27 | 只看该作者
神马

使用特权

评论回复
5
zhao9183| | 2011-5-22 12:35 | 只看该作者

使用特权

评论回复
6
hotpower| | 2011-5-25 15:54 | 只看该作者
看了look for cm0,现在看明白了。

使用特权

评论回复
7
lwslws201| | 2011-5-26 19:59 | 只看该作者
:victory:

使用特权

评论回复
8
ttlasong| | 2011-7-6 15:14 | 只看该作者
:victory:

使用特权

评论回复
9
01dxwlm| | 2011-7-27 15:08 | 只看该作者
一个单片机还【跑C++,有效率吗,现实产品中能用么?

使用特权

评论回复
10
nayaix| | 2011-7-30 09:49 | 只看该作者
顶起啊

使用特权

评论回复
11
damien| | 2011-8-3 16:25 | 只看该作者
ding

使用特权

评论回复
12
afei9527| | 2011-8-31 00:15 | 只看该作者
顶起啊

使用特权

评论回复
13
技美电子| | 2011-9-6 22:14 | 只看该作者
就是太难了,看不懂!

使用特权

评论回复
14
fskjhm| | 2011-12-26 13:20 | 只看该作者
支持

使用特权

评论回复
15
我就是我lxw| | 2012-7-3 09:27 | 只看该作者
楼主,这个系统占用是多少啊?

使用特权

评论回复
16
aifei7320| | 2012-12-20 23:13 | 只看该作者
我这看得怎么都是html的代码!????

使用特权

评论回复
17
qin552011373| | 2012-12-21 17:29 | 只看该作者
还是喜欢在中低端单片机上面裸跑  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

1466

帖子

21

粉丝