[Tinyos Core WG] Meeting: Sept 13
Philip Levis
pal at cs.stanford.edu
Tue Sep 12 17:33:44 PDT 2006
Wednesday, September 13, 2006 11:00 AM US Pacific Time
Bridge: 5, Passcode: 0137679
Numbers:
US: 1-916-356-2663 or 1-888-875-9370 (non-Intel)
UK: +44 1793 402663
Denmark: +45 4527 5090
Agenda:
Status/membership changes (Ralph Kling and Pi Peng from Crossbow)
TEP 117 (PLEASE READ, attached, it's short)
TEP 109 (new version attached)
-------------- next part --------------
=========================
Sensors and Sensor Boards
=========================
:TEP: 109
:Group: Core Working Group
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
:Author: David Gay, Phil Levis, Wei Hong, Joe Polastre, and Gilman Tolle
:Draft-Created: 10-Jun-2006
:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements. Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.
Abstract
====================================================================
This memo documents how sensor drivers are organized in TinyOS and how
sets of sensor drivers are combined into sensor boards and sensor
platforms, along with general principles followed by the components
that provide access to sensors.
1. Principles
====================================================================
This section describes the basic organization principles for sensor
drivers in TinyOS.
For background, a sensor may be attached to the microcontroller on a
TinyOS platform through a few different types of connections:
* Included within the microcontroller itself
* Connected to general-purpose IO pins for level/edge detection
* Connected to an ADC in the microcontroller for voltage sampling
* Connected to general-purpose IO pins for digital communication
* Connected through a standard digital bus protocol (1-Wire, I2C, SPI)
Physically, these connections may also be decoupled by attaching the
sensors to a `sensor board`, which can be removed from the TinyOS
platform, and may fit multiple different TinyOS platforms.
The capabilities of a physical sensor are made available to a TinyOS
application through a `sensor driver`.
According to the HAA [TEP2]_, TinyOS devices should provide both
simple hardware-independent interfaces for common-case use (HIL) and
rich hardware-dependent interfaces for special-case use (HAL). Sensor
drivers should follow this spirit as well.
TinyOS 2.x represents each sensor as an individual component. This
allows the compilation process to minimize the amount of code
included. A sensor board containing multiple sensors should be
represented as a collection of components, one for each sensor,
contained within a sensor board directory.
Sensors, being physical devices that may be shared, can benefit from
virtualization and arbitration. This document describes a design
pattern for sensor virtualization that may be followed by sensor
drivers.
The same physical sensor may be attached to multiple different TinyOS
platforms, through platform-dependent interconnections. The common
logic of sensor driver should be factored into chip-dependent,
platform-independent components, and those components should be bound
to the hardware resources on a platform by platform-dependent
components, and to the hardware resources on a sensor board by
sensorboard-dependent components.
A physical sensor has a general class and a specific set of
performance characteristics, captured by the make and model of the
sensor itself. The naming of the sensor driver components should
reflect the specifc name of the sensor, and optionally provide a
component with a generic name for application authors who only care
about the general class of the sensor.
This document takes no position on the meaning of the values returned
by sensor drivers. They may be raw uninterpreted values or they may
have some physical meaning. If a driver returns uninterpreted values,
the driver may provide additional interfaces that would allow
higher-level clients to interpret the value properly.
2. Sensor HIL Components
====================================================================
A sensor HIL component MUST provide:
- One or more SID interfaces [TEP114]_, for reading data.
A sensor HIL component MAY provide:
- One or more SID interfaces [TEP114]_, for reading or
writing calibration coefficients or control registers.
A sensor device driver SHOULD be a generic component that virtualizes
access to the sensor. A sensor device driver can provide such
virtualization for itself by defining a nesC generic client
component. When a client component is being used, a call to a
top-level SID interface should be delayed when the device is busy,
rather than failing. This virtualization may be easier to accomplish
by using one of the arbiters provided by the system.
For example::
generic configuration SensirionSht11C() {
provides interface Read<uint16_t> as Temperature;
provides interface ReadStream<uint16_t> as TemperatureStream;
provides interface Read<uint16_t> as Humidity;
provides interface ReadStream<uint16_t> as HumidityStream;
}
implementation {
// connect to the ADC HIL, GPIO HAL, or sensor's HAL
}
When a HIL component is being used, the sensor MUST initialize itself,
either by including the `MainC` component and wiring to the
`SoftwareInit` interface, or by allowing a lower-level component (like
an ADC) to initialize itself.
In addition, the HIL sensor driver MUST start the physical sensor
automatically. For sensors without a constant power draw, the sensor
MAY be started once at boot time by wiring to the `MainC.Boot`
interface. Sensors that draw appreciable power MUST be started in
response to a call to one of the top-level SID interfaces, and stopped
some time after that call completes. One of the power-management
components described in [TEP115]_ may be useful for this purpose.
Generally, simple types are made up of octets. However, sensor values
often have levels of precision besides a multiple of 8. A device MAY
specify the precision of one of its interfaces with the DeviceMetadata
interface::
interface DeviceMetadata {
command uint8_t getSignificantBits();
}
The name of the instance of DeviceMetadata SHOULD clearly indicate
which interface it corresponds to.
A value contained returned from the device through a SID interface
MAY be left shifted so that it covers as much of the type's range as
possible. For example, if a 12-bit ADC reading is presented as a
16-bit Read interface::
component DemoSensorC {
provides interface Read<uint16_t>;
}
then the driver MAY shift the 12-bit value left so that its range is
0x0000 - 0xfff0, rather than 0x0000 - 0x0fff.
Sensor driver components SHOULD be named according to the make and
model of the sensing device being presented. Using specific names
gives the developer the option to bind to a particular sensor, which
provides compile-time detection of missing sensors. However, wrapper
components using "common" names MAY also be provided by the driver
author, to support application developers who are only concerned with
the particular type of the sensor and not its make, model, or detailed
performance characteristics.
A "common" naming layer atop a HIL may look like this::
generic configuration TemperatureC() {
provides interface Read<uint16_t>;
provides interface ReadStream<uint16_t>;
}
implementation {
components new SensirionSht11C();
Read = SensirionSht11C.Temperature;
ReadStream = SensirionSht11C.TemperatureStream;
}
generic configuration HumidityC() {
provides interface Read<uint16_t>;
provides interface ReadStream<uint16_t>;
}
implementation {
components new SensirionSht11C();
Read = SensirionSht11C.Humidity;
ReadStream = SensirionSht11C.HumidityStream;
}
3. Sensor HAL Components
====================================================================
Sensors with a richer interface than would be supported by the SID
interfaces MAY provide a HAL component in addition to a HIL
component.
A sensor HAL component MUST provide:
- A SID-based interface or a specific hardware-dependent interface
with commands for sampling and controlling the sensor device.
A sensor HAL component MAY need to provide:
- A `StdControl` or `SplitControl` interface for manual power
management by the user, following the conventions described in
[TEP115]_.
- A Resource[] interface for requesting access to the device and
possibly performing automated power management.
- Any other interfaces needed to control the device.
For example::
configuration SensirionSht11DeviceC {
provides interface Resource[ uint8_t client ];
provides interface SensirionSht11[ uint8_t client ];
}
implementation {
// connect to the sensor's platform-dependent HPL here
}
4. Directory Organization Guidelines
====================================================================
Because the same physical sensor may be attached to TinyOS platforms
in many different ways, the organization of sensor drivers should
reflect the distinction between sensor and sensor interconnect.
Sensor components commonly exist at three levels:
platform-independent, sensorboard-dependent, and
platform-dependent. Factoring a sensor driver into these three pieces
allows for greater code reuse when the same sensor is attached to
different sensorboards or platforms.
Platform-independent sensor driver components for a particular sensor,
like protocol logic, when in the core TinyOS 2.x source tree, SHOULD
be placed into "tos/chips/<sensor>", where <sensor> reflects the make
and model of the sensor device being supported. When not a part of the
core source tree, this directory can be placed anywhere as long as the
nesC compiler recieves a `-I` directive pointing to the sensor's
directory. However, not all sensors have a sufficiently large amount
of platform-independent logic to justify a separate "chips"
directory. Sensor chips are more likely to be digital sensors than
analog sensors, for example.
A sensor board is a collection of sensor components with a fixed name,
intended for attachment to multiple platforms. Each sensor board MUST
have its own directory named <sensorboard>. Default TinyOS 2.x sensor
boards are placed in "tos/sensorboards/<sensorboard>", but sensor
board directories can be placed anywhere as long as the nesC compiler
receives a `-I` directive pointing to the sensor board's directory.
Both sensors and sensor boards MUST have unique names. Case is
significant, but two sensor boards MUST differ in more than case. This
is necessary to support platforms where filename case differences are
not significant.
Each sensor board directory MUST contain a `.sensor` file. This file
is a perl script which gets executed as part of the `ncc` nesC
compiler frontend. It can add or modify any compile-time options
necessary for a particular sensor board. It MAY modify the following
perl variables, and MUST NOT modify any others:
- @new_args: This is the array of arguments which will be passed to
nescc. For instance, you might add an include directive to @new_args
with push @new_args, `-Isomedir`. This could be used to include
subdirectories.
- @commonboards: This can be set to a list of sensor board names which
should be added to the include path list. These sensor boards must be
in tinyos-2.x/tos/sensorboards.
If the sensor board wishes to define any C types or constants, it
SHOULD place these in a file named <sensorboard>.h in the sensor
board's directory.
A sensor board directory MAY contain a "chips" directory, with
subdirectories for each of the sensors connected to the sensor board.
If a "chips" subdirectory is used, sensorboard-dependent driver
components needed to connect platform-independent logic to a
particular attachment for that sensor should be placed in
"<sensorboard>/chips/<sensor>".
Components needed to connect the platform-independent sensor driver
components or sensorboard-dependent components to the hardware
resources available on a particular platform SHOULD be placed in
"tos/<platform>/chips/<sensor>". In addition, components for a sensor
that only exists on a particular platform should be placed in a such a
directory.
Sensors that exist as part of a larger chip, like a MCU internal
voltage sensor, SHOULD be placed in a subdirectory of the chip's
directory. "tos/<chip>/sensors/<sensor>".
The `.platform` and `.sensor` files need to include enough `-I`
directives to locate all of the necessary components needed to support
the sensors on a platform and/or sensorboard.
All of these directory organization guidelines are only intended for
code that will enter the core source tree. In general, sensor
components may be placed anywhere as long as the nesC compiler
receives enough `-I` directives to locate all of the necessary pieces.
5. Authors' Addresses
====================================================================
| David Gay
| 2150 Shattuck Ave, Suite 1300
| Intel Research
| Berkeley, CA 94704
|
| phone - +1 510 495 3055
|
| email - david.e.gay at intel.com
|
| Wei Hong
| Arch Rock
| 657 Mission St. Suite 600
| San Francisco, CA 94105
|
| email - wei.hong at gmail.com
|
| Philip Levis
| 358 Gates Hall
| Computer Science Department
| 353 Serra Mall
| Stanford, CA 94305
|
| phone - +1 650 725 9046
|
| email - pal at cs.stanford.edu
|
| Joe Polastre
| 467 Soda Hall
| UC Berkeley
| Berkeley, CA 94720
|
| email - polastre at cs.berkeley.edu
|
| Gilman Tolle
| Arch Rock
| 657 Mission St. Suite 600
| San Francisco, CA 94105
|
| email - gtolle at archrock.com
6. Citations
====================================================================
.. [TEP2] TEP 2: Hardware Abstraction Architecture
.. [TEP114] TEP 114: SIDs: Source and Sink Indepedent Drivers
.. [TEP115] TEP 115: Power Management of Non-Virtualized Devices
Appendix A: Sensor Driver Examples
====================================================================
1. Analog ADC-Connected Sensor
------------------------------
The Analog sensor requires two components
* a component to present the sensor itself (HamamatsuS1087ParC)
* a component to select the appropriate hardware resources, such as
ADC port 4, reference voltage 1.5V, and a slow sample and hold time
(HamamatsuS1087ParP).
The AdcReadClientC component and underlying machinery handles all of
the arbitration and access to the ADC.
::
tos/platforms/telosa/chips/s1087/HamamatsuS1087ParC.nc
generic configuration HamamatsuS1087ParC() {
provides interface Read<uint16_t>;
provides interface ReadStream<uint16_t>;
}
implementation {
components new AdcReadClientC();
Read = AdcReadClientC;
components new AdcReadStreamClientC();
ReadStream = AdcReadStreamClientC;
components HamamatsuS1087ParP;
AdcReadClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
AdcReadStreamClientC.Msp430Adc12Config -> HamamatsuS1087ParP;
}
::
tos/platforms/telosa/chips/s1087/HamamatsuS1087ParP.nc
module HamamatsuS1087ParP {
provides interface Msp430Adc12Config;
}
implementation {
async command msp430adc12_channel_config_t
Msp430Adc12Config.getChannelSettings() {
msp430adc12_channel_config_t config = {
inch: INPUT_CHANNEL_A4,
sref: REFERENCE_VREFplus_AVss,
ref2_5v: REFVOLT_LEVEL_1_5,
adc12ssel: SHT_SOURCE_ACLK,
adc12div: SHT_CLOCK_DIV_1,
sht: SAMPLE_HOLD_4_CYCLES,
sampcon_ssel: SAMPCON_SOURCE_SMCLK,
sampcon_id: SAMPCON_CLOCK_DIV_1
};
return config;
}
}
2. Binary Pin-Connected Sensor
------------------------------
The Binary sensor gets a bit more complex, because it has three
components:
* one to present the sensor (UserButtonC)
* one to execute the driver logic (UserButtonLogicP)
* one to select the appropriate hardware resources, such as MSP430
Port 27 (HplUserButtonC).
Note that the presentation of this sensor is not arbitrated because
none of the operations are split-phase.
::
tos/platforms/telosa/UserButtonC.nc
configuration UserButtonC {
provides interface Get<bool>;
provides interface Notify<bool>;
}
implementation {
components UserButtonLogicP;
components HplUserButtonC;
UserButtonLogicP.GpioInterrupt -> HplUserButtonC.GpioInterrupt;
UserButtonLogicP.GeneralIO -> HplUserButtonC.GeneralIO;
Get = UserButtonLogicP;
Notify = UserButtonLogicP;
}
::
tos/platforms/telosa/UserButtonLogicP.nc
module UserButtonLogicP {
provides interface Get<bool>;
provides interface Notify<bool>;
uses interface GeneralIO;
uses interface GpioInterrupt;
}
implementation {
norace bool m_pinHigh;
task void sendEvent();
command bool Get.get() { return call GeneralIO.get(); }
command error_t Notify.enable() {
call GeneralIO.makeInput();
if ( call GeneralIO.get() ) {
m_pinHigh = TRUE;
return call GpioInterrupt.enableFallingEdge();
} else {
m_pinHigh = FALSE;
return call GpioInterrupt.enableRisingEdge();
}
}
command error_t Notify.disable() {
return call GpioInterrupt.disable();
}
async event void GpioInterrupt.fired() {
call GpioInterrupt.disable();
m_pinHigh = !m_pinHigh;
post sendEvent();
}
task void sendEvent() {
bool pinHigh;
pinHigh = m_pinHigh;
signal Notify.notify( pinHigh );
if ( pinHigh ) {
call GpioInterrupt.enableFallingEdge();
} else {
call GpioInterrupt.enableRisingEdge();
}
}
}
::
tos/platforms/telosa/HplUserButtonC.nc
configuration HplUserButtonC {
provides interface GeneralIO;
provides interface GpioInterrupt;
}
implementation {
components HplMsp430GeneralIOC as GeneralIOC;
components new Msp430GpioC() as UserButtonC;
UserButtonC -> GeneralIOC.Port27;
GeneralIO = UserButtonC;
components HplMsp430InterruptC as InterruptC;
components new Msp430InterruptC() as InterruptUserButtonC;
InterruptUserButtonC.HplInterrupt -> InterruptC.Port27;
GpioInterrupt = InterruptUserButtonC.Interrupt;
}
3. Digital Bus-Connected Sensor
-------------------------------
The Digital sensor is the most complex out of the set, and includes
six components:
* one to present the sensor (SensirionSht11C)
* one to request arbitrated access and to transform the sensor HAL
into the sensor HIL (SensirionSht11P)
* one to present the sensor HAL (HalSensirionSht11C)
* one to perform the driver logic needed to support the HAL, which
twiddles pins according to a sensor-specific protocol
(SensirionSht11LogicP).
* one to select the appropriate hardware resources, such as the clock,
data, and power pins, and to provide an arbiter for the sensor
(HplSensirionSht11C).
* one to perform the power control logic needed to support the power
manager associated with the arbiter (HplSensirionSht11P).
This bus-connected sensor is overly complex because it does not rely
on a shared framework of bus manipulation components. A sensor built
on top of the I2C or SPI bus would likely require fewer components.
::
tos/platforms/telosa/chips/sht11/SensirionSht11C.nc
generic configuration SensirionSht11C() {
provides interface Read<uint16_t> as Temperature;
provides interface Read<uint16_t> as Humidity;
}
implementation {
components new SensirionSht11ReaderP();
Temperature = SensirionSht11ReaderP.Temperature;
Humidity = SensirionSht11ReaderP.Humidity;
components HalSensirionSht11C;
enum { TEMP_KEY = unique("Sht11.Resource") };
enum { HUM_KEY = unique("Sht11.Resource") };
SensirionSht11ReaderP.TempResource -> HalSensirionSht11C.Resource[ TEMP_KEY ];
SensirionSht11ReaderP.Sht11Temp -> HalSensirionSht11C.SensirionSht11[ TEMP_KEY ];
SensirionSht11ReaderP.HumResource -> HalSensirionSht11C.Resource[ HUM_KEY ];
SensirionSht11ReaderP.Sht11Hum -> HalSensirionSht11C.SensirionSht11[ HUM_KEY ];
}
::
tos/chips/sht11/SensirionSht11ReaderP.nc
generic module SensirionSht11ReaderP() {
provides interface Read<uint16_t> as Temperature;
provides interface Read<uint16_t> as Humidity;
uses interface Resource as TempResource;
uses interface Resource as HumResource;
uses interface SensirionSht11 as Sht11Temp;
uses interface SensirionSht11 as Sht11Hum;
}
implementation {
command error_t Temperature.read() {
call TempResource.request();
return SUCCESS;
}
event void TempResource.granted() {
error_t result;
if ((result = call Sht11Temp.measureTemperature()) != SUCCESS) {
call TempResource.release();
signal Temperature.readDone( result, 0 );
}
}
event void Sht11Temp.measureTemperatureDone( error_t result, uint16_t val ) {
call TempResource.release();
signal Temperature.readDone( result, val );
}
command error_t Humidity.read() {
call HumResource.request();
return SUCCESS;
}
event void HumResource.granted() {
error_t result;
if ((result = call Sht11Hum.measureHumidity()) != SUCCESS) {
call HumResource.release();
signal Humidity.readDone( result, 0 );
}
}
event void Sht11Hum.measureHumidityDone( error_t result, uint16_t val ) {
call HumResource.release();
signal Humidity.readDone( result, val );
}
event void Sht11Temp.resetDone( error_t result ) { }
event void Sht11Temp.measureHumidityDone( error_t result, uint16_t val ) { }
event void Sht11Temp.readStatusRegDone( error_t result, uint8_t val ) { }
event void Sht11Temp.writeStatusRegDone( error_t result ) { }
event void Sht11Hum.resetDone( error_t result ) { }
event void Sht11Hum.measureTemperatureDone( error_t result, uint16_t val ) { }
event void Sht11Hum.readStatusRegDone( error_t result, uint8_t val ) { }
event void Sht11Hum.writeStatusRegDone( error_t result ) { }
default event void Temperature.readDone( error_t result, uint16_t val ) { }
default event void Humidity.readDone( error_t result, uint16_t val ) { }
}
::
tos/platforms/telosa/chips/sht11/HalSensirionSht11C.nc
configuration HalSensirionSht11C {
provides interface Resource[ uint8_t client ];
provides interface SensirionSht11[ uint8_t client ];
}
implementation {
components new SensirionSht11LogicP();
SensirionSht11 = SensirionSht11LogicP;
components HplSensirionSht11C;
Resource = HplSensirionSht11C.Resource;
SensirionSht11LogicP.DATA -> HplSensirionSht11C.DATA;
SensirionSht11LogicP.CLOCK -> HplSensirionSht11C.SCK;
SensirionSht11LogicP.InterruptDATA -> HplSensirionSht11C.InterruptDATA;
components new TimerMilliC();
SensirionSht11LogicP.Timer -> TimerMilliC;
components LedsC;
SensirionSht11LogicP.Leds -> LedsC;
}
::
tos/chips/sht11/SensirionSht11LogicP.nc
generic module SensirionSht11LogicP() {
provides interface SensirionSht11[ uint8_t client ];
uses interface GeneralIO as DATA;
uses interface GeneralIO as CLOCK;
uses interface GpioInterrupt as InterruptDATA;
uses interface Timer<TMilli>;
uses interface Leds;
}
implementation {
... bus protocol details omitted for brevity ...
}
::
tos/platforms/telosa/chips/sht11/HplSensirionSht11C.nc
configuration HplSensirionSht11C {
provides interface Resource[ uint8_t id ];
provides interface GeneralIO as DATA;
provides interface GeneralIO as SCK;
provides interface GpioInterrupt as InterruptDATA;
}
implementation {
components HplMsp430GeneralIOC;
components new Msp430GpioC() as DATAM;
DATAM -> HplMsp430GeneralIOC.Port15;
DATA = DATAM;
components new Msp430GpioC() as SCKM;
SCKM -> HplMsp430GeneralIOC.Port16;
SCK = SCKM;
components new Msp430GpioC() as PWRM;
PWRM -> HplMsp430GeneralIOC.Port17;
components HplSensirionSht11P;
HplSensirionSht11P.PWR -> PWRM;
HplSensirionSht11P.DATA -> DATAM;
HplSensirionSht11P.SCK -> SCKM;
components new TimerMilliC();
HplSensirionSht11P.Timer -> TimerMilliC;
components HplMsp430InterruptC;
components new Msp430InterruptC() as InterruptDATAC;
InterruptDATAC.HplInterrupt -> HplMsp430InterruptC.Port15;
InterruptDATA = InterruptDATAC.Interrupt;
components new FcfsArbiterC( "Sht11.Resource" ) as Arbiter;
Resource = Arbiter;
components new SplitControlPowerManagerC();
SplitControlPowerManagerC.SplitControl -> HplSensirionSht11P;
SplitControlPowerManagerC.ArbiterInit -> Arbiter.Init;
SplitControlPowerManagerC.ArbiterInfo -> Arbiter.ArbiterInfo;
SplitControlPowerManagerC.ResourceController -> Arbiter.ResourceController;
}
::
tos/platforms/telosa/chips/sht11/HplSensirionSht11P.nc
module HplSensirionSht11P {
provides interface SplitControl;
uses interface Timer<TMilli>;
uses interface GeneralIO as PWR;
uses interface GeneralIO as DATA;
uses interface GeneralIO as SCK;
}
implementation {
task void stopTask();
command error_t SplitControl.start() {
call PWR.makeOutput();
call PWR.set();
call Timer.startOneShot( 11 );
return SUCCESS;
}
event void Timer.fired() {
signal SplitControl.startDone( SUCCESS );
}
command error_t SplitControl.stop() {
call SCK.makeInput();
call SCK.clr();
call DATA.makeInput();
call DATA.clr();
call PWR.clr();
post stopTask();
return SUCCESS;
}
task void stopTask() {
signal SplitControl.stopDone( SUCCESS );
}
}
-------------- next part --------------
-------------- next part --------------
============================
Pins and Buses
============================
:TEP: 117
:Group: Core Working Group
:Type: Documentary
:Status: Draft
:TinyOS-Version: 2.x
:Author: Phil Buonadonna
:Draft-Created: 23-Jan-2006
:Draft-Version: $Revision: 1.1.2.4 $
:Draft-Modified: $Date: 2006/01/25 18:13:43 $
:Draft-Discuss: TinyOS Developer List <tinyos-devel at mail.millennium.berkeley.edu>
.. Note::
This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements. Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.
Abstract
====================================================================
The memo documents the TinyOS 2.x interfaces used for controlling
digital IO functionality and digital interfaces other than serial
communication covered in [tep113].
1. Introduction
====================================================================
The canonical TinyOS device is likely to have a variety of digital
interfaces. These interfaces may be divided into two broad
categories. The first are general purpose digital I/O lines (pins)
for individual digital signals at physical pins on a chip or
platform. The second are digital I/O interfaces that have predefined
communication protocol formats. The two buses covered in this
document are the Serial Peripheral Interface (SPI) and the
Inter-Integrated Circuit (I2c) or Two-Wire interface. While there are
likely other bus formats, we presume SPI and I2C to have the largest
coverage. While the UART interface is also in this category, it is
covered separately in [tep113].
This memo documents the interfaces used for pins and the two buses.
2. Pins
====================================================================
General Purpose I/O (GPIO) pins are single, versatile digital I/O signals
individually controllable on a particular chip or platform. Each GPIO
can be placed into either an input mode or an output mode. On
some platforms a third 'tri-state' mode may exist, but this
functionality is platform specific and will not be covered in this
document.
On many platforms, a physical pin may function as either a digital GPIO
or another special function I/O such. Examples include ADC I/O or a bus
I/O. Interfaces to configure the specific function of a pin are
platform specific.
The objective of the interfaces described here is not to attempt to
cover all possibilities of GPIO functionality and features, but to
distill down to a basis that may be expected on most platforms.
In input mode, we assume the following capabilities:
* The ability to arbitrarily sample the pin
* The ability to generate an interrupt/event from either a rising edge or falling edge digital signal.
In output mode, we assume the following capabilities:
* An I/O may be individually cleared (low) or set (hi)
Platform that provide GPIO capabilities MUST provide the following HIL
interfaces:
* GeneralIO
* GpioInterrupt
Platforms MAY provide the following capture interface.
* GpioCapture
2.1 GeneralIO
--------------------------------------------------------------------
The GeneralIO HIL interface is the fundamental mechanism for controlling a
GPIO pin. The interface provides a mechanism for setting the pin mode
and reading/setting the pin value. The toggle function switches the
output state to the opposite of what it currently is.
Platforms with GPIO functionality MUST provide this interface. It
SHOULD be provided in a component named GeneralIOC, but MAY be
provided in other components as needed. ::
interface GeneralIO
{
async command void set();
async command void clr();
async command void toggle();
async command bool get();
async command void makeInput();
async command void makeOutput();
}
2.2 GpioInterrupt
--------------------------------------------------------------------
The GPIO Interrupt HIL interface provides baseline event control for a
GPIO pin. It provides a mechanism to detect a rising edge OR a falling
edge. Note that calls to enableRisingEdge and enableFallingEdge are
NOT cumulative and only one edge may be detected at a time. There may
be other edge events supported by the platform which MAY be exported
through a platform specific HAL interface. ::
interface GpioInterrupt {
async command error_t enableRisingEdge();
async command error_t enableFallingEdge();
async command error_t disable();
async event void fired();
}
2.3 GpioCapture
--------------------------------------------------------------------
The GpioCapture interface provides a means of associating a timestamp
with a GPIO event. Platforms MAY provide this interface.
Some platforms may have hardware support for such a feature. Other
platforms may emulate this capability using the SoftCaptureC
component. The interface makes not declaration of the precision or
accuracy of the timestamp with respect to the associated GPIO event. ::
interface GpioCapture {
async command error_t captureRisingEdge();
async command error_t captureFallingEdge();
async event void captured(uint16_t time);
async command void disable();
}
3. Buses
====================================================================
Bus operations may be divided into two categories: data and
control. The control operations of a particular bus controller are
platform specific and not covered here. Instead, we focus on the data
interfaces at the HIL level that are expected to be provided.
3.1 Serial Peripheral Interface
--------------------------------------------------------------------
The Serial Peripheral Interface (SPI) is part of a larger class of
Synchronous Serial Protocols. The term SPI typically refers to the
Motorola SPI protocols. Other protocols include the National
Semiconductor Microwire, the TI Synchronous Serial Protocol and the
Programmable Serial Protocol. The dataside interfaces here were
developed for the Motorola SPI format, but may work for others.
Platforms supporting SPI MUST provide these interfaces.
Of note, the interfaces DO NOT define the behavior of any chip select
or framing signals. These SHOULD determined by platform specific HAL
interfaces and implementations.
The interface is split into a synchronous byte level and an
asynchronous packet level interface. The byte level interface is
intended for short transactions (3-4 bytes) on the SPI bus. ::
interface SPIByte {
async command error_t write( uint8_t tx, uint8_t* rx );
}
The packet level interface is for larger bus transactions. The
pointer/length interface permits use of hardware assist such as DMA. ::
interface SPIPacket {
async command error_t send( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len );
async event void sendDone( uint8_t* txBuf, uint8_t* rxBuf, uint16_t len,
error_t error );
}
3.2 I2C
--------------------------------------------------------------------
The Inter-Integrated Circuit (I2C) interface is another type of
digital bus that is often used for chip-to-chip communication. It is
also known as a two-wire interface.
The I2CPacket interface provides for asynchronous Master mode communication on an
I2C with application framed packets. It supports only single
transfers with a start-stop condition around each transfer.
Platforms providing I2C capability MUST provide this interface. ::
interface I2CPacket {
async command result_t readPacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
async command result_t writePacket(uint16_t _addr, uint8_t _length, uint8_t* _data);
async event void readPacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
async event void writePacketDone(uint16_t addr, uint8_t length, uint8_t* data, result_t success);
}
4. Author's Address
====================================================================
| Phil Buonadonna
| Arched Rock Corporation
| 657 Mission St. Ste 600
| San Francisco, CA 94105-4120
|
| phone - +1 415 692-0828 x2833
5. Citations
====================================================================
.. [tep113] TEP 113: Serial Communication.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.millennium.berkeley.edu/pipermail/tinyos-2.0wg/attachments/20060912/4cb27725/tep109-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.millennium.berkeley.edu/pipermail/tinyos-2.0wg/attachments/20060912/4cb27725/tep117-0001.html
-------------- next part --------------
Phil
More information about the Tinyos-2.0wg
mailing list