📄 tep110.txt
字号:
This abstraction represents a node's ability to view and possibly
suppress packets it has received for forwarding. It provides
the Intercept, CollectionPacket, and Packet interfaces.
CollectionSnooperC
This abstraction allows a node to overhear routing packets
sent to other nodes to forward. It provides the Receive,
CollectionPacket, and Packet interfaces.
All of the collection routing communication abstractions take a
parameter, similar to active messages and broadcasts, so multiple
components can independelty use collection routing. In addition to
communication, collection routing has an additional abstraction:
CollectionControlC
This abstraction controls whether a node is a collection root
or not.
Finally, collection routing has ``CollectionServiceC`` and
``CollectionServiceNotifierC`` abstractions, which follow an OR
policy.
3.5 UART
--------------------------------------------------------------------
**NOTE: These services are not supported as of the 2.x prerelease.
They will be supported by the first full release.
They will be fully defined pending discussion/codification of
UART interfaces.**
4. OSKI Service Structure and Design
====================================================================
Presenting services through abstractions hides the underlying wiring
details and gives a distribution a great deal of implementation
freedom. One issue that arises, however, is initialization. If a user
component instantiates a service, then a distribution MUST make sure
the service is initialized properly. OSKI achieves this by
encapsulating a complete service as a working component; abstractions
export the service's interfaces.
4.1 Example: Timers
--------------------------------------------------------------------
For example, the timer service provides a single abstraction,
OskiTimerMilliC, which is a generic component. OskiTimerMilliC provides a
single instance of the Timer<TMilli> interface. It is implemented as a
wrapper around the underlying timer service, a component named
``TimerMilliImplP``, which provides a parameterized interface and
follows the Service Instance design pattern[sipattern]_:
| generic configuration OskiTimerMilliC() {
| provides interface Timer<TMilli>;
| }
| implementation {
| components TimerMilliImplP;
| Timer = TimerMilliImplP.TimerMilli[unique("TimerMilliC.TimerMilli")];
| }
TimerMilliImplP is a fully composed and working service. It takes
a platform's timer implementation and makes sure it is initialized through
the TinyOS boot sequence[boot]_:
| configuration TimerMilliImplP {
| provides interface Timer<TMilli> as TimerMilli[uint8_t id];
| }
| implementation {
| components TimerMilliC, Main;
| Main.SoftwareInit -> TimerMilliC;
| TimerMilli = TimerMilliC;
| }
This composition means that if any component instantiates a timer,
then TimerMilliImplP will be included in the component graph. If
TimerMilliImplP is included, the TimerMilliP (the actual platform HIL
implementation) will be properly initialized at system boot time. In
this case, the order of initialization isn't important; in cases where
there are services that have to be initialized in a particular
sequence to ensure proper ordering, the Impl components can
orchestrate that order. For example, a distribution can wire
Main.SoftwareInit to a DistributionInit component, which calls
sub-Inits in a certain order; when a service is included, it wires
itself to one of the sub-Inits.
The user does not have to worry about unique strings to manage the
underlying Service Instance pattern: the abstractions take care of
that.
4.2 Example: Active Messages
--------------------------------------------------------------------
Active messaging reprsent a slightly more complex service, as it has
several abstractions and a control interface. However, it follows the
same basic pattern: abstractions are generics that export wirings to
the underlying service, named ``ActiveMessageImplP``:
| configuration ActiveMessageImplP {
| provides {
| interface SplitControl;
| interface AMSend[am_id_t id];
| interface Receive[am_id_t id];
| interface Receive as Snoop[am_id_t id];
| interface Packet;
| interface AMPacket;
| }
| }
|
| implementation {
| components ActiveMessageC, Main;
|
| Main.SoftwareInit -> ActiveMessageC;
|
| SplitControl = ActiveMessageC;
| AMSend = ActiveMessageC;
| Receive = ActiveMessageC.Receive;
| Snoop = ActiveMessageC.Snoop;
| Packet = ActiveMessageC;
| AMPacket = ActiveMessageC;
| }
For example, this is the AMSender abstraction:
| generic configuration AMSenderC(am_id_t AMId) {
| provides {
| interface AMSend;
| interface Packet;
| interface AMPacket;
| }
| }
|
| implementation {
| components ActiveMessageImplP as Impl;
|
| AMSend = Impl.AMSend[AMId];
| Packet = Impl;
| AMPacket = Impl;
| }
AMReceiver is similar, except that it wires to the Receive interface,
while AMSnooper wires to the Snoop interface, and AMSnoopingReceiver
provides a single Receive that exports both Snoop and Receive (the
unidirectional nature of the Receive interface makes this simple to
achieve, as it represents only fan-in and no fan-out).
ActiveMessageImplP does not provide a Service interface; it provides
the SplitControl interface of the underlying active message
layer. OSKI layers a *ServiceController* on top of SplitControl. As
the active message service follows an OR policy, OSKI uses a
``ServiceOrControllerM``, which is a generic component with the
following signature:
| generic module ServiceOrControllerM(char strID[]) {
| provides {
| interface Service[uint8_t id];
| interface ServiceNotify;
| }
| uses {
| interface SplitControl;
| }
| }
ServiceOrControllerM follows the Service Instance pattern[sipattern];
it calls its underlying SplitControl based on the state of each of its
instances of the Service interface. The parameter denotes the string
used to generate the unique service IDs. The active messages service
controller implementation, AMServiceImplP, instantiates a
ServiceOrControllerM, wires it to ActiveMessageImplP:
| configuration AMServiceImplP {
| provides interface Service[uint8_t id];
| provides interface ServiceNotify;
| }
| implementation {
| components ActiveMessageImplP;
| components new ServiceOrControllerM("AMServiceImplP.Service");
|
| Service = ServiceOrControllerM;
| ServiceOrControllerM.SplitControl -> ActiveMessageImplP;
| ServiceNotify = ServiceOrControllerM;
| }
AMServiceC then provides an instance of AMServiceImplP.Service:
| generic configuration AMServiceC() {
| provides interface Service;
| }
|
| implementation {
| components AMServiceImplP;
|
| Service = AMServiceImplP.Service[unique("AMServiceImplP.Service")];
| }
Note that the two strings are the same, so that the uniqueCount() in
the ServiceOrControllerM is correct based on the number of instances
of AMServiceC. As with timers, encapsulating the service instance
pattern in generic components relieves the programmer of having to
deal with unique strings, a common source of bugs in TinyOS 1.x code.
4.3 OSKI Requirements
--------------------------------------------------------------------
OSKI is a layer on top of system components: it presents a more
usable, less error-prone, and simpler interface to common TinyOS
functionality. For OSKI to work properly, a platform MUST be compliant
with the following TEPs:
o TEP 102: Timers
o TEP 106: Schedulers and Tasks
o TEP 107: TinyOS 2.x Boot Sequence
o TEP 1XX: Active Messages
o TEP 1XX: Collection Routing
Not following some of these TEPS MAY lead to OSKI services being
inoperable, exhibit strange behavior, or being uncompilable.
5. Distribution Interfaces
====================================================================
The basic notion of a distribution is that it provides a self-contained,
tested, and complete (for an application domain) programming interface
to TinyOS. Layers can be added on top of a distribution, but as a
distribution is a self-contained set of abstractions, adding new
services can lead to failures. A distribution represents a hard line
above which all other code operates. One SHOULD NOT add new services,
as they can disrupt the underlying organization. Of course, one MAY
create a new distribution that extends an existing one, but this is
in and of itself a new distribution.
Generally, as distributions are intended to be higher-level abstractions,
they SHOULD NOT provide any asynchronous (async) events. They can,
of course, provide async commands. The idea is that no code written on
top of a distribution should be asynchronous, due to the complexity
introduced by having to manage concurrency. Distributions are usually
platform independent; if an application needs async events, then
chances are it is operating close to the hardware, and so is not
platform independent.
6. Author's Address
====================================================================
| Philip Levis
| 467 Soda Hall
| UC Berkeley
| Berkeley, CA 94720
|
| phone - +1 510 290 5283
|
| email - pal@cs.berkeley.edu
7. Citations
====================================================================
.. [rst] reStructuredText Markup Specification. <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html>
.. [sipattern] The Service Instance Pattern. In *Software Design Patterns for TinyOS.* David Gay, Philip Levis, and David Culler. Published in Proceedings of the ACM SIGPLAN/SIGBED 2005 Conference on Languages, Compilers, and Tools for Embedded Systems (LCTES'05).
.. [boot] TEP 107: TinyOS 2.x Boot Sequence.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -