📄 tep108.txt
字号:
I2CPacket = I2C;
...
}
where I2CPacketImplP contains the actual implementation of the
I2C service, and I2CPacket.h contains the #define for the
name of the resource required by the arbiter::
#ifndef I2CPACKETC_H
#define I2CPACKETC_H
#define I2CPACKET_RESOURCE "I2CPacket.Resource"
#endif
This service would then be made available to a client through
the generic configuration seen below::
#include I2CPacket.h
generic configuration I2CPacketC {
provides interface Resource;
provides interface I2CPacket<I2CAddrSize>;
}
implementation {
enum { CLIENT_ID = unique(I2CPACKET_RESOURCE) };
components I2CPacketP as I2C;
Resource = I2C.Resource[CLIENT_ID];
I2CPacket = I2C.I2CPacket[CLIENT_ID];
}
In this example, an instance of the I2CPacket interface is coupled with
an instance of the Resource interface on every new instantiation of
the I2CPacketC component. In this way, a single Resource and a
single I2CPacket interface can be exported by this component together
for use by a client.
Clients of the I2C service would use it as follows::
module I2CClientP {
uses interface Resource as I2CResource;
uses interface I2CPacket<I2CAddrSize>;
} ...
configuration I2CClientC { }
implementation {
components I2CClientP, new I2CPacketC();
I2CClientP.I2CResource -> I2CPacketC.Resource;
I2CUserM.I2CPacket -> I2CPacket.I2CPacket;
}
ArbiterInfo
--------------------------------------------------------------------
In the implementation of the ADC component on the Msp430 microcontroller,
a simple arbiter is used to provide a round robin sharing policy
between clients of the ADC::
configuration Msp430Adc12C {
provides interface Resource[uint8_t id];
provides interface Msp430Adc12SingleChannel[uint8_t id];
provides interface Msp430Adc12FastSingleChannel[uint8_t id];
}
implementation {
components Msp430Adc12P,MainC,
new SimpleRoundRobinArbiterC(MSP430ADC12_RESOURCE) as Arbiter,
...
Resource = Arbiter;
SingleChannel = Msp430Adc12P.SingleChannel;
FastSingleChannel = Msp430Adc12P.FastSingleChannel;
Msp430Adc12P.Init <- MainC;
Msp430Adc12P.ADCArbiterInfo -> Arbiter;
...
}
In this configuration we see that the Resource interface provided by
Msp430Adc12C is wired directly to the instance of the SimpleRoundRobinArbiterC
component that is created. The ArbiterInfo interface provided by
SimpleRoundRobinArbiterC is then wired to Msp430Adc12P. The Msp430Adc12P
component then uses this interface to perform run time checks to ensure that
only the client that currently has access to the ADC resource is able to
use it::
async command error_t Msp430Adc12SingleChannel.getSingleData[uint8_t id]() {
if (call ADCArbiterInfo.clientId() == id){
configureChannel()
// Start getting data
}
else return ERESERVE;
}
async command error_t Msp430Adc12FastSingleChannel.configure[uint8_t id]() {
if (call ADCArbiterInfo.clientId() == id){
clientID = id
configureChannel()
}
else return ERESERVE;
}
async command error_t Msp430Adc12FastSingleChannel.getSingleData[uint8_t id]()
{
if (clientID = id)
// Start getting data
else return ERESERVE;
}
In order for these runtime checks to succeed, users of the
Msp430Adc12SingleChannel and Msp430Adc12FastSingleChannel interfaces will have
to match their client id's with the client id of a corresponding Resource
interface. This can be done in the following way::
generic configuration Msp430Adc12ClientC() {
provides interface Resource;
provides interface Msp430Adc12SingleChannel;
}
implementation {
components Msp430Adc12C;
enum { ID = unique(MSP430ADC12_RESOURCE) };
Resource = Msp430Adc12C.Resource[ID];
Msp430Adc12SingleChannel = Msp430Adc12C.SingleChannel[ID];
}
::
generic configuration Msp430Adc12FastClientC() {
provides interface Resource;
provides interface Msp430Adc12FastSingleChannel;
}
implementation {
components Msp430Adc12C;
enum { ID = unique(MSP430ADC12_RESOURCE) };
Resource = Msp430Adc12C.Resource[ID];
Msp430Adc12FastSingleChannel = Msp430Adc12C.SingleChannel[ID];
}
Since these are generic components, clients simply need to instantiate them
in order to get access to a single Resource interface that is already
properly coupled with a Msp430Adc12SingleChannel or Msp430Adc12FastSingleChannel
interface.
Take a look in the tinyos-2.x source tree under tinyos-2.x/tos/chips/adc12
to see the full implementation of these components in their original context.
ResourceRequested
--------------------------------------------------------------------
On the eyesIFXv2 platform, both the radio and the flash need access to the bus
provided by the Usart0 component on the Msp430 microcontroller. Using
a simple cooperative arbitration policy, these two components should able to
share the Usart resource by only holding on to it as long as they need it and
then releasing it for use by the other component. In the case of the MAC
implementation of the Tda5250 radio component, however, the Msp430 Usart
resource needs be held onto indefinitely. It only ever considers releasing the
resource if a request from the flash component comes in through its
ResourceRequested interface. If it cannot release it right away (i.e. it is in
the middle of receiving a packet), it defers the release until some later point
in time. Once it is ready to release the resource, it releases it, but then
immediately requests it again. The flash is then able to do what it wants with
the Usart, with the radio regaining control soon thereafter.
In the CsmaMacP implementation of the Tda5250 radio we see the ResourceRequested
event being implemented::
async event void ResourceRequested.requested() {
atomic {
/* This gives other devices the chance to get the Resource
because RxMode implies a new arbitration round. */
if (macState == RX) call Tda5250Control.RxMode()();
}
}
Through several levels of wiring, the Tda5250 interface is provided to this
component by the Tda5250RadioP component::
module Tda5250RadioP {
provides interface Tda5250Control;
uses interface Resource as UsartResource;
...
}
implementation {
async command error_t Tda5250Control.RxMode() {
if(radioBusy() == FALSE)
call UsartResource.release();
call UsartResource.request();
}
event void UsartResource.granted() {
// Finish setting to RX Mode
}
...
}
Although the full implementation of these components is not provided, the
functionality they exhibit should be clear. The CsmaMacP component receives the
ResourceRequested.requested() event when the flash requests the use of the
Msp430 Usart0 resource. If it is already in the receive state, it tries to
reset the receive state through a call to a lower level component. This
component checks to see if the radio is in the middle of doing anything (i.e.
the radioBusy() == FALSE check), and if not, releases the resource and then
requests it again.
To see the full implementations of these components and their wirings to one
another, please refer to the tinyos-2.x source tree under
tinyos-2.x/tos/chips/tda5250, tinyos-2.x/tos/chips/tda5250/mac,
tinyos-2.x/tos/platforms/eyesIFX/chips/tda5250, and
tinyos-2.x/tos/platforms/eyesIFX/chips/msp430.
Resource Configure
--------------------------------------------------------------------
The Msp430 Usart0 bus can operate in three modes: SPI, I2C,
and UART. Using all three concurrently is problematic: only one should
be enabled at any given time. However, different clients of the bus might
require the bus to be configured for different protocols. On Telos, for example
many of the available sensors use an I2C bus, while the radio and flash chip use
SPI.
A component providing the SPI service on top of the shared Usart component looks
like this::
generic configuration Msp430Spi0C() {
provides interface Resource;
provides interface SpiByte;
provides interface SpiPacket;
...
}
implementation {
enum { CLIENT_ID = unique( MSP430_SPIO_BUS ) };
components Msp430SpiNoDma0P as SpiP;
components new Msp430Usart0C() as UsartC;
SpiP.ResourceConfigure[ CLIENT_ID ] <- UsartC.ResourceConfigure;
SpiP.UsartResource[ CLIENT_ID ] -> UsartC.Resource;
SpiP.UsartInterrupts -> UsartC.HplMsp430UsartInterrupts;
...
}
And one providing the I2C service looks like this::
generic configuration Msp430I2CC() {
provides interface Resource;
provides interface I2CPacket<TI2CBasicAddr> as I2CBasicAddr;
...
}
implementation {
enum { CLIENT_ID = unique( MSP430_I2CO_BUS ) };
components Msp430I2C0P as I2CP;
components new Msp430Usart0C() as UsartC;
I2CP.ResourceConfigure[ CLIENT_ID ] <- UsartC.ResourceConfigure;
I2CP.UsartResource[ CLIENT_ID ] -> UsartC.Resource;
I2CP.I2CInterrupts -> UsartC.HplMsp430UsartInterrupts;
...
}
The implementation of the ResourceConfigure interface is
provided by both the Msp430SpiNoDma0P and the Msp430I2C0P. In the
two different components, the same Msp430Usart0C component is used,
but wired to the proper implementation of the ResourceConfigure
interface. In this way, different instances of the Msp430Usart0C
can each have different configurations associated with them, but
still provide the same functionality.
Take a look in the tinyos-2.x source tree under
tinyos-2.x/tos/chips/msp430/usart to see the full implementation of
these components along with the corresponding Uart implementation.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -