『TinyOS』学习笔记 #2

本文介绍TinyOS中主动消息(Active Message)层的基础知识及如何使用它进行无线节点间的数据发送与接收。通过实例演示了如何定义消息结构、配置消息类型,并实现简单的无线通信应用程序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lesson 3 : Mote-mote radio communication

 

 

Active Message Interfaces

Since it is very common to have multiple services using the same radio to communicate, TinyOS provides the Active Message (AM) layer to multiplex access to the radio. The term "AM type" refers to the field used for multiplexing. AM types are similar in function to the Ethernet frame type field, IP protocol field, and the UDP port in that all of them are used to multiplex access to a communication service. AM packets also includes a destination field, which stores an "AM address" to address packets to particular motes. Additional interfaces, also located in the tos/interfaces directory, were introduced to support the AM services:

 

  • AMPacket - Similar to Packet, provides the basic AM accessors for the message_t abstract data type. This interface provides commands for getting a node's AM address, an AM packet's destination, and an AM packet's type. Commands are also provides for setting an AM packet's destination and type, and checking whether the destination is the local node.
  • AMSend - Similar to Send, provides the basic Active Message sending interface. The key difference between AMSend and Send is that AMSend takes a destination AM address in its send command.

 

The AM address of a node can be set at installation time, using the make install.n or make reinstall.n commands. It can be changed at runtime using the ActiveMessageAddressC component.

 

 

 

Sending a Message over the Radio

 

Reimplementing Blink

BlinkToRadioC.nc

 

 

#include <Timer.h>
 #include "BlinkToRadio.h"
 
 module BlinkToRadioC {
   uses interface Boot;
   uses interface Leds;
   uses interface Timer<TMilli> as Timer0;
 }
 implementation {
   uint16_t counter = 0;
 
   event void Boot.booted() {
     call Timer0.startPeriodic(TIMER_PERIOD_MILLI);
   }
 
   event void Timer0.fired() {
     counter++;
     call Leds.set(counter);
   }
 }

 

 

 

 

BlinkToRadio.h header file

 

#ifndef BLINKTORADIO_H
 #define BLINKTORADIO_H
 
 enum {
   TIMER_PERIOD_MILLI = 250
 };
 
 #endif

 

the use of the ifndef(if not define), define, and endif directives. These directives are used to ensure that the definitions in each header file is not included multiple times because the compiler would complain about multiply-defined objects. By convention, the literal used for these directives is an all-caps version of the filename with any periods converted to underscores.

 

the use of an enum declaration for defining the constant TIMER_PERIOD_MILLI. Using enum for defining constants is preferred over using define because enum does not indiscriminantly replace every occurence of the defined literal, regardless of where it appears in the source. As a result, enums provide better scoping as well.

 

BlinkToRadioAppC.nc (用来连接use interface 和提供了它的实现的组件)to wire the interfaces that the implementation uses to the actual components which provide these interfaces

 

#include <Timer.h>
 #include "BlinkToRadio.h"
 
 configuration BlinkToRadioAppC {
 }
 implementation {
   components MainC;
   components LedsC;
   components BlinkToRadioC as App;
   components new TimerMilliC() as Timer0;
 
   App.Boot -> MainC;
   App.Leds -> LedsC;
   App.Timer0 -> Timer0;
 }

 

 最后建立Makefiel

 

COMPONENT=BlinkToRadioAppC
include $(MAKERULES)

 

The first line tells the TinyOS make system that the top-level application component is BlinkToRadioAppC.

 

The second line loads in the TinyOS build system, which has all of the rules for building and installing on different platforms.

 

 

 

 

Defining a Message Structure

message will send both the node id and the counter value over the radio. Rather than directly writing and reading the payload area of the message_t with this data, we will use a structure to hold them and then use structure assignment to copy the data into the message payload area.

 

用structure来读写payload更便利

Using a structure allows reading and writing the message payload more conveniently when your message has multiple fields or multi-byte fields (like uint16_t or uint32_t) because you can avoid reading and writing bytes from/to the payload using indices and then shifting and adding (e.g. uint16_t x = data[0] << 8 + data[1]).

 

Even for a message with a single field, you should get used to using a structure because if you ever add more fields to your message or move any of the fields around, you will need to manually update all of the payload position indices if you read and write the payload at a byte level. Using structures is straightforward.

 

typedef nx_struct BlinkToRadioMsg {
  nx_uint16_t nodeid;
  nx_uint16_t counter;
} BlinkToRadioMsg;

 

The nx_ prefix is specific to the nesC language and signifies that the struct and uint16_t are external types.

 

External types have the same representation on all platforms. The nesC compiler generates code that transparently reorders access to nx_ data types and eliminates the need to manually address endianness and alignment (extra padding in structs present on some platforms) issues.

 

the nx_ prefix on a type (e.g. nx_uint16_t) indicates the field is to serialized in big endian format. In contrast, the nxle_ prefix signifies that the field is serialized in little endian format.

 

 

 

Sending a Message

 

  1. First, we need to identify the interfaces (and components) that provide access to the radio and allow us to manipulate the message_t type.
  2. Second, we must update the module block in the BlinkToRadioC.nc by adding uses statements for the interfaces we need.
  3. Third, we need to declare new variables and add any initialization and start/stop code that is needed by the interfaces and components.
  4. Fourth, we must add any calls to the component interfaces we need for our application.
  5. Fifth, we need to implement any events specified in the interfaces we plan on using.
  6. Sixth, the implementation block of the application configuration file, BlinkToRadioApp.c, must be updated by adding a components statement for each component we use that provides one of the interfaces we chose earlier.
  7. Finally, we need to wire the interfaces used by the application to the components which provide those interfaces.  

Note using the as keyword to rename an interface. nesC allows interfaces to be renamed in this way for several reasons. First, it often happens that two or more components that are needed in the same module provide the same interface. Second, interfaces are sometimes renamed to something more meaningful.

 

 

components ActiveMessageC;
components new AMSenderC(AM_BLINKTORADIO);

 

ActiveMessageC is a singleton component that is defined once for each type of hardware platform. AMSenderC is a generic, parameterized component. The new keyword indicates that a new instance of AMSenderC will be created. The AM_BLINKTORADIO parameter indicates the AM type of the AMSenderC.  the value of AM_BLINKTORADIO 定义在BlinkToRadio.h header file 中的enum.

 

 

 

Receiving a Message over the Radio

 

 

和上面一样的过程去添加代码。 

 

Note that we can safely manipulate the counter variable outside of an atomic section. The reason is that receive event executes in task context rather than interrupt context (events that have the async keyword can execute in interrupt context). Since the TinyOS execution model allows only one task to execute at a time, if all accesses to a variable occur in task context, then no race conditions will occur for that variable. Since all accesses to counter occur in task context, no critical sections are needed when accessing it.  

 

The AM_BLINKTORADIO parameter indicates the AM type of the AMReceiverC and is chosen to be the same as that used for the AMSenderC used earlier, which ensures that the same AM type is being used for both transmissions and receptions.

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值