📄 tep108.txt
字号:
inside a generic configuration. Wrapping the component in this way ensures that
each Resource client is given a unique client ID, with the added
benefit of properly coupling multiple components that all need to
refer to the same client ID.
Appendix B also provides a complete example of how an I2C resource might be
abstracted according to this pattern. For further examples see the various
chip implementations in the tinyos-2.x source tree under tinyos-2.x/chips/
3.2 ArbiterInfo
-------------------------------
Arbiters MUST provide an instance of the ArbiterInfo interface.
The ArbiterInfo interface allows a component to query the current
status of an arbiter::
interface ArbiterInfo {
async command bool inUse();
async command uint8_t clientId();
}
In contrast to the parameterized Resource interface provided by an arbiter,
only a single ArbiterInfo interface is provided. Its purpose is
to allow one to find out:
- Whether the resource for which it is arbitrating use is currently in use or not
- Which client is using it.
One can view ArbiterInfo as an interface for obtaining global information about
the use of a resource, while Resource can be viewed as an interface for obtaining
local access to that resource.
The primary use of the ArbiterInfo interface is to allow a shared resource to reject
any calls made through its data interface by clients that do not currently have access to
it. For an example of how this interface is used in this fashion refer to Appendix B.::
/|\ /|\
| |
| Data Interface | Resource
| |
-----------------------------------------------------------
| Shared Resource |
-----------------------------------------------------------
/|\ /|\ /|\
| | |
| Data Interface | Resource | ArbiterInfo
| | |
---------------------- -------------------------------
| Dedicated Resource | | Arbiter |
---------------------- -------------------------------
3.3 ResourceRequested
-------------------------------
Sometimes it is useful for a client to be able to hold onto a resource until
someone else needs it and only at that time decide to release it. Using the
ResourceRequested interface, this information is made available to the current
owner of a resource::
interface ResourceRequested {
async event void requested();
async event void immediateRequested();
}
A requested event is signaled to the current owner of the resource if another
client makes a request for the resource through the request() command of
its Resource interface. If a request is made through the immediateRequest()
command, then the immediateRequested() event is signaled.
An arbiter SHOULD provide a parameterized ResourceRequested interface to its
clients, but is not required to. The client id of the parameterized
ResourceRequested interface should be coupled with the client id of the Resource
interface to ensure that all events are signaled to the proper clients. Please
refer to Appendix B for an example of how this interface might be used.::
/|\ /|\ /|\
| | |
| Data Interface | Resource | ResourceRequested
| | |
--------------------------------------------------------------------------------
| Shared Resource |
--------------------------------------------------------------------------------
/|\ /|\ /|\ /|\
| | | |
| Data Interface | Resource | ArbiterInfo | ResourceRequested
| | | |
---------------------- ----------------------------------------------------
| Dedicated Resource | | Arbiter |
---------------------- ----------------------------------------------------
3.4 ResourceConfigure
-------------------------------
The existence of the ResourceConfigure interface allows a resource to be
automatically configured just before a client is granted access to it.
Components providing the ResourceConfigure interface use the interfaces
provided by an underlying dedicated resource to configure it into one
of its desired modes of operation. A cleint then wires its shared resource
abstraction to the component implementing the desired configuration. The
configure command is called immediataely before the client is granted access
to the resource, and the unconfigure command is called just before fully
releasing it.::
interface ResourceConfigure {
async command void configure();
async command void unconfigure();
}
::
ResourceConfigure ResourceConfigure ResourceConfigure
| | /|\
| | |
\|/ \|/ |
------------------- ------------------- -------------------
| Configuration 1 | | Configuration 2 | | Shared Resource |
------------------- ------------------- -------------------
| | /|\
| Control Interface | | ResourceConfigure
\|/ \|/ |
------------------------------ -----------
| Dedicated Resource | | Arbiter |
------------------------------ -----------
The arbiter SHOULD use a parameterized ResourceConfigure interface, with
its client ID parameter coupled with the client id of its parameterized
Resource interface. If an arbiter uses the ResourceConfigure interface,
it MUST call ResourceConfigure.configure() on the granted client ID
before it signals the Resource.granted() event. Similarly, after a valid
call to Resource.release(), it MUST call ResourceConfigure.unconfigure()
on the releasing client ID. By calling ResourceConfigure.configure() just
before granting a client access to a resource and calling
ResourceConfigure.unconfigure() just before fully releasing it, it is guaranteed
that a resource is always unconfigured before an attempt to configure it can be
made again.
The commands included in this interface could have been made part of the standard
Resource interface (and changed into callback events), but at a higher cost than
keeping them separate. Introducing these new commands into the Resource interface
would have lead to a large number of clients all including redundant configuration
code, while using the call out approach to a separate component ensures that we
only have a single instance of the code.
For an example of how configurations for the three different modes of the
Msp430 Usart component can take advantage of the ResourceConfigure
interface refer to Appendix B as well as section 4 on the use of
cross-component reservation.
3.5 ResourceDefaultOwner
-------------------------------
The normal Resource interface is for use by clients that all share the resource
in an equal fashion. The ResourceDefaultOwner interface is for use by a single
client that needs to be given control of the resource whenever no one else is
using it. An arbiter MAY provide a single instance of the ResourceDefaultOwner
interface. It MUST NOT provide more than one.::
interface ResourceDefaultOwner {
async event void granted();
async command error_t release();
async command bool isOwner();
async event void requested();
async event void immediateRequested();
}
The Arbiter MUST guarantee that the client of the ResourceDefaulrClient interface is
made the owner of the resource before the boot initialization sequence is
completed. When a normal resource client makes a request for the resource, the
ResourceDefaultOwner will receive either a requested() or an immediateRequested()
event depending on how the request was made. It must then decide if and when to
release it. Once released, all clients that have pending requests will be
granted access to the resource in the order determined by the queuing policy of
the arbiter in use. Once all pending requests have been granted (including
those that came in while other clients had access to the resource), the
ResourceDefaultOwner is automatically given control of the resource, receiving its
granted() event in the process. The ResourceDefaultOwner interface also contains
the same isOwner() command as the normal Resource interface, and the semantics
of its use are exactly the same.
Although the ResourceDefaultOwner interface looks similar to a combination of the
normal Resource interface and the ResourceRequested interface, its intended use
is quite different. The ResourceDefaultOwner interface should only be used by
clients that wish to have access to a resource only when no other clients are
using it. They do not actively seek access to the resource, but rather use
it to perform operations when it would otherwise simply be idle.
The primary motivation behind the definition of the ResourceDefaultOwner
interface is to allow for an easy integration of power management
for a resource with its arbitration policy. Arbiters that want to allow
a resource to be controlled by a particular power management policy can
provide the ResourceDefaultOwner interface for use by a component that
implements that policy. The power management component will receive the
granted() event whenever the resource has gone idle, and will proceed in
powering it down. When another client requests the resource, the power
manager will be notified through either the requested() or
immediateRequested() events as appropriate. It can then power up the resource
and release it once the power up has completed. Note that if power up is
a split-phase operation (takes a while), then calls by clients to
immediateRequest() when in the powered down state will return
FAIL. Please see the TEP on the Power Management of Non-Virtualized devices
([4]_) for more details.
4. Cross-Component Reservation
====================================================================
In some cases, it is desirable to share the reservation of a
single resource across multiple components. For example, on the TI
MSP430, a single USART component can be used as an I2C bus, a UART,
or an SPI connection. Clearly, on this chip, a reservation of the I2C
bus implicitly restricts the corresponding UART and SPI
services from gaining access to the resource. Enforcing such a policy
can be accomplished in the framework described above by:
1) Creating a set of unique ids for each service using the shared
resource.
2) Mapping these ids onto the ids of the underlying resource
Clients connecting to these services do not know that that this
mapping is taking place. As far as they are concerned, the only
arbitration taking place is between other clients using the same
service. In the MSP430 example, a single client of the I2C bus could
be contending with a single client of the SPI connection, but they
would probably have the same service level client ID. These two
service level client ids would be mapped onto 2 unique resource ids
for use by the shared USART component. The proper way to achieve this
mapping is through the use of generic components. The example given
below shows how to perform this mapping for the SPI component on the
MSP430. It is done similarly for the UART and I2C bus::
#include "Msp430Usart.h"
generic configuration Msp430Spi0C() {
provides interface Resource;
provides interface SpiByte;
provides interface SpiPacket;
}
implementation {
enum { CLIENT_ID = unique(MSP430_SPIO_BUS) };
components Msp430Spi0P as SpiP;
Resource = SpiP.Resource[ CLIENT_ID ];
SpiByte = SpiP.SpiByte;
SpiPacket = SpiP.SpiPacket[ CLIENT_ID ];
components new Msp430Usart0C() as UsartC;
SpiP.UsartResource[ CLIENT_ID ] -> UsartC.Resource;
SpiP.UsartInterrupts -> UsartC.HplMsp430UsartInterrupts;
}
The definition of the MSP430_SPIO_BUS string is defined in
Msp430Usart.h. A unique id is created from this string every time a
new Msp430Spi0C component is instantiated. This id is used as a
parameter to the parameterized Resource interface provided by the
Msp430Spi0P component. This is where the mapping of the two
different ids begins. As well as *providing* a parameterized
Resource interface (Msp430Spi0P.Resource), the Msp430Spi0P component
also *uses* a parameterized Resource interface (Msp430Spi0P.UsartResource).
Whenever a client makes a call through the provided Resource interface
with id CLIENT_ID, an underlying call to the Msp430Spi0P.Resource interface
with the same id is implicitly made. By then wiring the Msp430Spi0P.UsartResource
interface with id CLIENT_ID to an instance of the Resource interface
provided by the instantiation of the Msp430Usart0C component, the mapping
is complete. Any calls to the Resource interface provided by a new
instantiation of the Msp430Spi0C component will now be made through a
unique Resource interface on the underlying Msp430Usart0C component.
This level of indirection is necessary because it may not always be
desirable to directly wire the service level Resource interface to
the underlying shared Resource interface. Sometimes we may want to
perform some operations between a service level command being
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -