nesC编程入门
1.接口
NesC程序主要由各式组件(component)构成,组件和组件之间通过特定的接口(interface)互相沟通。一个接口内声明了提供相关服务的方法(C语言函数)。例如数据读取接口(Read)内就包含了读取(read)、读取结束(readDone)函数。接口只是制定了组件之间交流的规范,也就是通过某一个接口,只能通过该接口提供的方法实现两个组件之间的交流。但是接口终归只是接口,只是一组函数的声明,并为包含对接口的实现。
interface Read<val_t> {
command error_t read();
event void readDone( error_t result, val_t val );
}
2.组件
NesC程序由组件构成。组件内主要是包含了对各类接口的使用(uses)和提供(provides)。例如组件A提供了Read接口,那A就需要负责实现Read接口内的read命令,也就是read命令的函数体,即“具体这个值是如何读取出来的”。因为命令(command)是由接口的提供者(provider)负责实现的。如果组件B使用了A提供的Read接口,那在读取数据结束以后,系统会返回给B一个“读取结束”的事件,而B则需要负责处理这个事件,即“数据读取完毕以后,我用这个数据干什么”,将值返回给计算机,或者是通过无线发送给其他传感器等等,所以事件(event)是由接口的使用者(user)来负责实现的。
组件分为两类。分别是模块(module)和配置(configuration)。模块内包含了程序的主干,也就是对各类命令和事件的实现,是NesC程序的可执行代码的主体。而配置则是负责将各个模块,通过特定的接口连接起来,其本身并不负责实现任何特定的命令或者事件。
以TinyOS附带的Blink(闪烁发光二极管)程序为例:
// BlinkC.nc
#include "Timer.h" module BlinkC @safe()
{
uses interface Timer<TMilli> as Timer0;
uses interface Timer<TMilli> as Timer1;
uses interface Timer<TMilli> as Timer2;
uses interface Leds;
uses interface Boot;
}
implementation
{
event void Boot.booted()
{
call Timer0.startPeriodic( );
call Timer1.startPeriodic( );
call Timer2.startPeriodic( );
} event void Timer0.fired()
{
dbg("BlinkC", "Timer 0 fired @ %s.\n", sim_time_string());
call Leds.led0Toggle();
} event void Timer1.fired()
{
dbg("BlinkC", "Timer 1 fired @ %s \n", sim_time_string());
call Leds.led1Toggle();
} event void Timer2.fired()
{
dbg("BlinkC", "Timer 2 fired @ %s.\n", sim_time_string());
call Leds.led2Toggle();
}
}
//BlinkAppC.nc
configuration BlinkAppC
{
}
implementation
{
components MainC, BlinkC, LedsC;
components new TimerMilliC() as Timer0;
components new TimerMilliC() as Timer1;
components new TimerMilliC() as Timer2; BlinkC -> MainC.Boot; BlinkC.Timer0 -> Timer0;
BlinkC.Timer1 -> Timer1;
BlinkC.Timer2 -> Timer2;
BlinkC.Leds -> LedsC;
}
Blink程序由两个组件构成。BlinkC.nc为模块,BlinkAppC.nc为配置。
2.1 调用命令和事件信号
一个简单commanda可以使用call a()来调用,一个简单的event可以使用signal a()来触发。
若带参数的命令a有n个接口,类型为T1,...Tn由接口参数表达式e1...en调用如下:call a[e1,...en]();相应的可以用signal a[e1,...en](...)来触发事件。
2.2 任务
任务是一个独立的控制实体,由返回类型为void且无参数的函数定义。一个任务可以预先声明。例如:task void myTask(); 任务通过前缀post来提交,例如:post myTask().
2.3 原子
原子通常是最小的运行单元,其主要目的是其运行时,没有其他运算同时发生。一般用于更新并发性的互斥变量。例如:atomic{flag = 1;};
2.4 绑定
1)赋值绑定:endpoint1 = endpoint2;设S1是endpoint1的规范元素,S2是endpoint2的规范元素,则必须满足一下条件之一:
S1是内部的,S2是外部的(反之亦然),而且S1和S2都是被提供或被使用。
S1和S2都是外部的,一个被提供,一个被使用。
2)联编绑定:endpoint2->endpoint2,S1和S2都为内部的。
3.编程注意事项
3.1 所有的中断处理程序都是异步的,因此它们不能调用同步的函数。在中断处理程序中,执行同步函数唯一的方式是通过发布任务。任务的发布时一个异步过程,但任务本身的运行却是同步的操作。
3.2 TinyOS应用程序编写应当尽量采用同步代码。
3.3 atomic语句块能保证变量的读取具有原子性。注意:这并不意味着atomic语句块不会被抢占。即使是atomic语句块,倘若两个代码块使用不同得变量,也可以相互抢占。从理论上讲,funC可以抢占funA不可冒犯的原子性,但funA不能抢占它自身,funC也一样,即包含共同变量的atomic代码块不能相互抢占执行。
3.4 如果某个函数没有包含在一个atomic代码块里,但它总是在atomic代码块里被调用,那么编译器就不会发出警告。
3.5 atomic代码块会浪费cpu资源,应该尽量简短,从而使中断的延迟减少。
3.6 组件间的指针传递
组件调用send命令或者产生sendDone事件,就会放弃消息缓冲区的所有权,例如:组件A使用组件B提供的send接口,如果A调用了send传递参数message_t x,那么x的所有权就传给了B。在B可能访问x期间A不能再访问x。当B产生以x作为参数的sengDone事件后,x的所有权又归还给了A。
如果一个传递参数的接口有error_t类型的返回值,那么所有权只有在返回值为SUCCESS得时候才传递。
nesC编程入门的更多相关文章
- PHP面向对象(OOP)编程入门教程
面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...
- Windows编程入门程序详解
引用:http://blog.csdn.net/jarvischu/article/details/8115390 1. 程序 /******************************* ...
- 【PHP面向对象(OOP)编程入门教程】1.什么是面向对象?
面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成 ...
- Linux 利器- Python 脚本编程入门(一)
导读 众所周知,系统管理员需要精通一门脚本语言,而且招聘机构列出的职位需求上也会这么写.大多数人会认为 Bash (或者其他的 shell 语言)用起来很方便,但一些强大的语言(比如 Python)会 ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- OpenAl编程入门:播放一段音频
OpenAl编程入门 关于OpenAl我就不多介绍了,这两篇说明对于初步了解已经足够了:http://baike.baidu.com/view/1355367.htmhttp://en.wikiped ...
- [电子书] 《Android编程入门很简单》
<Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...
- MFC编程入门之五(MFC消息映射机制概述)
在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作.比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应. 一.什 ...
- 完成《Java编程入门》初稿
Java编程入门 现在的运维工程师不但要懂得集合网络.系统管理而且要和开发人员一起调试系统,社会上也需要"复合性"的运维人员,所以需要做运维的也要懂一些开发,知道软件系统接口的调试 ...
随机推荐
- vue shorthands
vue shorthands : & @ https://vuejs.org/v2/guide/syntax.html#Shorthands v-for https://vuejs.org/v ...
- [LeetCode] MaximumDepth of Binary Tree
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...
- Docker学习笔记二:Docker常用命令及提升拉取镜像的速度
一.Docker命令: 1.docker images //命令用来查看docker中所包含的镜像信息 2.docker ps -a //命令用来查看docker中所包含所有容器信息(运行状 ...
- BZOJ 1070 修车 【费用流】
Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...
- smb(ms17-010)远程命令执行之msf
本次用到的环境: kali(2016.2)32位系统.ip地址:192.168.1.104 目标靶机为:win7sp1x64系统(关闭防火墙),ip地址:192.168.1.105 具体的步骤如下: ...
- Codeforces 576C. Points on Plane(构造)
将点先按x轴排序,把矩形竖着划分成$10^3$个块,每个块内点按y轴排序,然后蛇形走位上去. 这样一个点到下一个点的横坐标最多跨越$10^3$,一共$10^6$个点,总共$10^9$,一个块内最多走$ ...
- 解题:POI 2013 Taxis
题面 设当前位置为$pos$,那么可以发现在出租车总部左侧时,每辆车的贡献是$x[i]-(d-pos)$,而在右侧时只有$x[i]>=m-d$的车能够把人送到,那么首先我们要找出最小的满足$x[ ...
- 洛谷 P1486 BZOJ 1503 NOI 2004 郁闷的出纳员 fhq treap
思路: 1. 此处的fhq treap的分裂是按照权值分裂然后插入的.将小于k的分为一棵子树,大于等于k的分为另一棵子树. 2. 删除的时候只要将大于等于min的分裂到以root为根的树中,另一部分不 ...
- 编写优质嵌入式C程序(转)
前言:这是一年前我为公司内部写的一个文档,旨在向年轻的嵌入式软件工程师们介绍如何在裸机环境下编写优质嵌入式C程序.感觉是有一定的参考价值,所以拿出来分享,抛砖引玉. 转载请注明出处:http://bl ...
- OpenCV---图像二值化
一:什么是二值图像 彩色图像:三个通道0-,-,-,所以可以有2^24位空间 灰度图像:一个通道0-,所以有256种颜色 二值图像:只有两种颜色,黑和白,1白色,0黑色 二:图像二值化 (一)先获取阈 ...