TINYOS_MAKEDEFAULTS ?= $(TINYOS_MAKE_PATH)/Makedefaults
# Allow users to specify additional directories to find TOSMake files.
-TOSMAKE_TEMP_PATH := $(TOSMAKE_PATH)
-TOSMAKE_PATH = $(TINYOS_MAKE_PATH)
-TOSMAKE_PATH += $(TOSMAKE_TEMP_PATH)
+TOSMAKE_PATH += $(TINYOS_MAKE_PATH)
# Save makecmdgoals (a read only var) to goals so that we can modify it.
GOALS += $(MAKECMDGOALS)
// The unique string for accessing HAL2 via ReadStream
#define ADCC_READ_STREAM_SERVICE "AdcC.ReadStream.Client"
-/* Test for GCC bug (bitfield access) - only version 3.2.3 is known to be stable */
+/* Test for GCC bug (bitfield access) - versions 3.2.3 and 4.4.3 are known to
+ * be stable
+ */
// TODO: check whether this is still relevant...
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION == 332
#error "The msp430-gcc version (3.3.2) contains a bug which results in false accessing \
of bitfields in structs and makes MSP430ADC12M.nc fail ! Use version 3.2.3 instead."
#elif GCC_VERSION != 323
+#if GCC_VERSION < 443
#warning "This version of msp430-gcc might contain a bug which results in false accessing \
of bitfields in structs (MSP430ADC12M.nc would fail). Use version 3.2.3 instead."
+#endif
#endif
#ifndef __msp430_have_adc12
implementation {
enum {
/* Bit positions in m_pins */
- PINS_RXD = 1,
+ PINS_RXD = 0,
PINS_TXD
};
call TXD.selectModuleFunc();
}
+ /* Reset important state variables */
+ m_robuf = 0;
+ m_sobuf = 0;
+
/* Clear interrupts; we'll add them as needed */
call Registers.clrIeRx();
call Registers.clrIeTx();
/* Enable the device */
call Registers.clrCtl1(UCSWRST);
+
+ /* TOS convention is for receive interrupts on by default. */
+ call Registers.clrIfgRx();
+ call Registers.setIeRx();
}
}
call Registers.clrIeTx();
call Registers.clrIfgRx();
+ /* Reset important state variables */
+ m_robuf = 0;
+ m_sobuf = 0;
+
/* Restore pins to their pre-configure state */
- if (m_pins & PINS_RXD)
+ if (m_pins & (1 << PINS_RXD))
call RXD.selectIOFunc();
- if (m_pins & PINS_TXD)
+ if (m_pins & (1 << PINS_TXD))
call TXD.selectIOFunc();
}
}
/* FIXME: this can cause an arbitrarily long ISR, if m_slen is large.
* But depending on timing, we may always only write 1 byte.
*/
- while (!call Registers.getIfgTx()); /* in case interleaved UB.send */
- while (m_slen && call Registers.getIfgTx()) {
- call Registers.setTxbuf(*m_sbuf);
- if (--m_slen)
- m_sbuf++;
- }
- if (m_slen == 0) {
- call Registers.clrIeTx();
- m_sobuf = 0;
- signal UartStream.sendDone(m_sobuf, m_solen, SUCCESS);
+ if (m_sobuf) {
+ while (!call Registers.getIfgTx()); /* in case interleaved UB.send */
+ while (m_slen && call Registers.getIfgTx()) {
+ call Registers.setTxbuf(*m_sbuf);
+ if (--m_slen)
+ m_sbuf++;
+ }
+ if (m_slen == 0) {
+ call Registers.clrIeTx();
+ m_sobuf = 0;
+ signal UartStream.sendDone(m_sobuf, m_solen, SUCCESS);
+ }
}
}
UBRX_1MHZ_19200=54, UMCTL_1MHZ_19200=(0 << 4) + (5 << 1) + 0,
UBRX_1MHZ_38400=27, UMCTL_1MHZ_38400=(0 << 4) + (2 << 1) + 0,
UBRX_1MHZ_115200=9, UMCTL_1MHZ_115200=(0 << 4) + (1 << 1) + 0,
- UBRX_1E6MHZ_9600=104, UMCTL_1E6MHZ_9600=(0 << 4) + (1 << 1) + 0,
- UBRX_1E6MHZ_115200=8, UMCTL_1E6MHZ_115200=(0 << 4) + (6 << 1) + 0,
+ UBRX_1E6HZ_9600=104, UMCTL_1E6HZ_9600=(0 << 4) + (1 << 1) + 0,
+ UBRX_1E6HZ_19200=52, UMCTL_1E6HZ_19200=(0 << 4) + (0 << 1) + 0,
+ UBRX_1E6HZ_115200=8, UMCTL_1E6HZ_115200=(0 << 4) + (6 << 1) + 0,
} msp430_usci_uart_rate_t;
typedef struct {
--- /dev/null
+/**
+ * Copyright (c) 2005 Arch Rock Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of the Arch Rock Corporation nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE
+ *
+ */
+
+/**
+ * The ReadRef interface is intended for split-phase low-rate or
+ * high-latency reading of large values. The type of the value is
+ * given as a template argument. When a value is too large to be
+ * comfortably passed on the stack, the caller should allocate space
+ * for the value and pass the pointer to read(). When the readDone()
+ * comes back, the space will be filled with the new value.
+ *
+ * <p>
+ * This interface has the same calling semantics as the Read interface
+ * described in TEP 114, except that it is async.
+ *
+ * See TEP114 - SIDs: Source and Sink Independent Drivers for details.
+ *
+ * @param val_t the type of the object that will be returned
+ *
+ * @author Gilman Tolle <gtolle@archrock.com>
+ * @version $Revision$ $Date$
+ */
+
+interface ReadRefNow<val_t> {
+ /**
+ * Initiates a read of the value.
+ *
+ * @param 'val_t* ONE val' a pointer to space that will be filled by the value
+ *
+ * @return SUCCESS if a readDone() event will eventually come back.
+ */
+ async command error_t read( val_t* val );
+
+ /**
+ * Signals the completion of the read(). The returned pointer will
+ * be the same as the original pointer passed to read().
+ *
+ * @param result SUCCESS if the read() was successful
+ * @param 'val_t* ONE val' a pointer to the value that has been read
+ */
+ async event void readDone( error_t result, val_t* val );
+}
--- /dev/null
+/* Copyright (c) 2006-2010 by Sporian Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * This document is the proprietary and confidential property of Sporian
+ * Microsystems, Inc. All use, distribution, reproduction or re-distribution
+ * is disallowed without the prior express written consent of Sporian
+ * Microsystems, Inc.
+ */
+
+/**
+ * The Write interface is intended for split-phase low-rate or
+ * high-latency writing of small values. The type of the value is
+ * given as a template argument. Because this interface is
+ * split-phase, these values may be backed by hardware, or a
+ * long-running computation. This interface is the output analog
+ * of the standard Read interface.
+ *
+ * @param val_t the type of the object that will be written
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+
+interface Write<val_t> {
+ /**
+ * Initiate a write of the provided value.
+ *
+ * @param val The value to write.
+ * @return SUCCESS if <code>writeDone()</code> will later be signalled,
+ * EBUSY if a write is already in progress, or FAIL for other errors.
+ */
+ command error_t write(val_t val);
+
+ /**
+ * Signalled upon completion of the write operation initiated by the previous
+ * <code>write()</code> command.
+ */
+ event void writeDone(error_t error);
+}
--- /dev/null
+/* Copyright (c) 2006-2010 by Sporian Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * This document is the proprietary and confidential property of Sporian
+ * Microsystems, Inc. All use, distribution, reproduction or re-distribution
+ * is disallowed without the prior express written consent of Sporian
+ * Microsystems, Inc.
+ */
+
+/**
+ * The Write interface is intended for split-phase low-rate or
+ * high-latency writing of small values. The type of the value is
+ * given as a template argument. Because this interface is
+ * split-phase, these values may be backed by hardware, or a
+ * long-running computation. This interface is the output analog
+ * of the standard Read interface.
+ *
+ * This interface is equivalent to the Write interface, except that its
+ * operations are defined async.
+ *
+ * @param val_t the type of the object that will be written
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+
+interface WriteNow<val_t> {
+ /**
+ * Initiate a write of the provided value.
+ *
+ * @param val The value to write.
+ * @return SUCCESS if <code>writeDone()</code> will later be signalled,
+ * EBUSY if a write is already in progress, or FAIL for other errors.
+ */
+ async command error_t write(val_t val);
+
+ /**
+ * Signalled upon completion of the write operation initiated by the previous
+ * <code>write()</code> command.
+ */
+ async event void writeDone(error_t error);
+}
implementation {
- components new Msp430Uart0C() as UartC;
+ components PlatformUartC as UartC;
UartStream = UartC;
UartByte = UartC;
components TelosSerialP;
StdControl = TelosSerialP;
- TelosSerialP.Msp430UartConfigure <- UartC.Msp430UartConfigure;
- TelosSerialP.Resource -> UartC.Resource;
}
+++ /dev/null
-/*
- * Copyright (c) 2008, Titanium Mirror, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the Technische Universität Berlin nor the names
- * of its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- /**
- * @author R. Steve McKown <rsmckown@gmail.com>
- */
-
-module PlatformSerialP {
- provides interface StdControl;
- uses interface Resource;
-}
-implementation {
- command error_t StdControl.start()
- {
- return call Resource.immediateRequest();
- }
-
- command error_t StdControl.stop()
- {
- call Resource.release();
- return SUCCESS;
- }
-
- event void Resource.granted() {}
-}
--- /dev/null
+/*
+ * Copyright (c) 2008-2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /**
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration PlatformUartC {
+ provides {
+ interface Resource;
+ interface UartStream;
+ interface UartByte;
+ }
+}
+implementation {
+ components new Msp430Uart0C() as UartC;
+ Resource = UartC;
+ UartStream = UartC;
+ UartByte = UartC;
+
+ components TelosSerialP;
+ TelosSerialP.Msp430UartConfigure <- UartC.Msp430UartConfigure;
+ TelosSerialP.Resource -> UartC.Resource;
+
+}
implementation {
command error_t Init.init()
{
- uint16_t i;
+ volatile uint16_t i;
#if defined (CALDCO_8MHZ_) && !defined(__DisableCalData)
if (CALBC1_8MHZ != 0xff || CALDCO_8MHZ != 0xff) {
provides interface UartByte;
}
implementation {
- components new Msp430UartA1C() as UartC;
+ components PlatformUartC as UartC;
UartStream = UartC;
UartByte = UartC;
components PlatformSerialP;
StdControl = PlatformSerialP;
PlatformSerialP.Resource -> UartC;
-
-#if 0 /* If you want to change the configuration... */
- components SomeConfigurationComponentC as ConfigC;
- UartC.AsyncConfigure -> ConfigC;
-#endif
}
--- /dev/null
+/*
+ * Copyright (c) 2008-2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /**
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+configuration PlatformUartC {
+ provides {
+ interface Resource;
+ interface UartStream;
+ interface UartByte;
+ }
+}
+implementation {
+ components new Msp430UartA1C() as UartC;
+ Resource = UartC;
+ UartStream = UartC;
+ UartByte = UartC;
+
+#if 0 /* If you want to change the Uart's configuration... */
+ components SomeConfigurationComponentC as ConfigC;
+ UartC.AsyncConfigure -> ConfigC;
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * A shared arbiter that allows 1...N clients to acquire the resource
+ * simultaneously, with the intention of returning control to the default
+ * owner upon release by all clients.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic configuration SharedArbiterC(char resourceName[]) {
+ provides {
+ interface Resource[uint8_t id];
+ interface ResourceDefaultOwner;
+ interface ArbiterInfo;
+ }
+}
+implementation {
+ enum { CLIENTS = uniqueCount(resourceName) };
+
+ components new SharedArbiterP();
+ Resource = SharedArbiterP;
+ ResourceDefaultOwner = SharedArbiterP;
+ ArbiterInfo = SharedArbiterP;
+
+ components new BitVectorC(CLIENTS) as GrantedVectorC;
+ SharedArbiterP.GrantedVector -> GrantedVectorC;
+
+ components new BitVectorC(CLIENTS) as RequestingVectorC;
+ SharedArbiterP.RequestingVector -> RequestingVectorC;
+
+ components new StateC();
+ SharedArbiterP.State -> StateC;
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * A shared arbiter that allows 1...N clients to acquire the resource
+ * simultaneously. The purpose of this arbiter to allow access to a shared,
+ * switched subsystem. For example, a communications bus that can handle IO
+ * for multiple clients simultaneously, but is powered down when not in use.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module SharedArbiterP() {
+ provides {
+ interface Resource[uint8_t id];
+ interface ResourceDefaultOwner;
+ interface ArbiterInfo;
+ }
+ uses {
+ interface BitVector as GrantedVector;
+ interface BitVector as RequestingVector;
+ interface State;
+ }
+}
+implementation {
+ enum {
+ S_IDLE = 0, /* Resource is not in use; owned by default owner */
+ S_REQUESTING, /* Requesting the resource from the default owner */
+ S_IMMREQUESTING, /* Immediate resource request from the default owner */
+ S_GRANTED, /* One or more clients have been granted the resource */
+
+ NO_CLIENT = 0xff,
+ };
+
+ uint8_t m_granted; /* Count of clients granted the resource */
+ uint8_t m_requesting; /* Count of clients requesting the resource */
+
+ uint8_t addRequesting(uint8_t id)
+ {
+ atomic {
+ call RequestingVector.set(id);
+ return ++m_requesting;
+ }
+ }
+
+ uint8_t rmRequesting(uint8_t id)
+ {
+ atomic {
+ call RequestingVector.clear(id);
+ return --m_requesting;
+ }
+ }
+
+ uint8_t addGranted(uint8_t id)
+ {
+ atomic {
+ call GrantedVector.set(id);
+ return ++m_granted;
+ }
+ }
+
+ uint8_t rmGranted(uint8_t id)
+ {
+ atomic {
+ call GrantedVector.clear(id);
+ return --m_granted;
+ }
+ }
+
+ task void grantedTask()
+ {
+ unsigned id;
+
+ atomic {
+ if (m_requesting == 0)
+ return;
+ }
+
+ for (id = 0; id < call RequestingVector.size(); id++) {
+ bool grant = FALSE;
+
+ atomic {
+ if (call RequestingVector.get(id)) {
+ rmRequesting(id);
+ addGranted(id);
+ grant = TRUE;
+ }
+ }
+ if (grant)
+ signal Resource.granted[id]();
+ }
+ }
+
+ async command error_t Resource.request[uint8_t id]()
+ {
+ /* The Resource docs do not say what happens when a user calls
+ * Resource.request() after the resource has already been granted. We
+ * elect to call EBUSY, as if the request was still in process.
+ */
+ if (call RequestingVector.get(id) || call GrantedVector.get(id))
+ return EBUSY;
+
+ addRequesting(id);
+ if (call State.requestState(S_REQUESTING) == SUCCESS)
+ signal ResourceDefaultOwner.requested();
+ else if (call State.isState(S_GRANTED))
+ post grantedTask();
+ return SUCCESS;
+ }
+
+ async command error_t Resource.immediateRequest[uint8_t id]()
+ {
+ /* The Resource docs do not say what happens when a user calls
+ * Resource.request() after the resource has already been granted. We
+ * elect to call EBUSY, as if the request was still in process.
+ */
+ if (call RequestingVector.get(id) || call GrantedVector.get(id))
+ return EBUSY;
+
+ if (call State.requestState(S_IMMREQUESTING) == SUCCESS) {
+ signal ResourceDefaultOwner.immediateRequested();
+ if (call State.isState(S_IMMREQUESTING))
+ call State.toIdle();
+ }
+ if (call State.isState(S_GRANTED)) {
+ addGranted(id);
+ return SUCCESS;
+ }
+ return FAIL;
+ }
+
+ async command error_t Resource.release[uint8_t id]()
+ {
+ if (!call GrantedVector.get(id))
+ return FAIL;
+
+ if (rmGranted(id) == 0) {
+ call State.toIdle();
+ signal ResourceDefaultOwner.granted();
+ }
+ return SUCCESS;
+ }
+
+ async command error_t ResourceDefaultOwner.release()
+ {
+ if (call State.isState(S_REQUESTING)) {
+ call State.forceState(S_GRANTED);
+ post grantedTask();
+ return SUCCESS;
+ } else if (call State.isState(S_IMMREQUESTING)) {
+ call State.forceState(S_GRANTED);
+ return SUCCESS;
+ } else
+ return FAIL;
+ }
+
+ async command bool ArbiterInfo.inUse()
+ {
+ atomic {
+ if (m_granted)
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ /* The ArbiterInfo interface doesn't work so well for a shared resource, as
+ * 1+ users may hold the resource at any time.
+ */
+ async command uint8_t ArbiterInfo.userId()
+ {
+ atomic {
+ if (m_granted)
+ return 1;
+ }
+ return NO_CLIENT;
+ }
+
+ async command uint8_t Resource.isOwner[uint8_t id]()
+ {
+ atomic return call GrantedVector.get(id);
+ }
+
+ async command uint8_t ResourceDefaultOwner.isOwner()
+ {
+ atomic return !(call State.isState(S_GRANTED));
+ }
+
+ default event void Resource.granted[uint8_t id]() {}
+ default async event void ResourceDefaultOwner.granted() {}
+ default async event void ResourceDefaultOwner.requested()
+ {
+ call ResourceDefaultOwner.release();
+ }
+ default async event void ResourceDefaultOwner.immediateRequested()
+ {
+ call ResourceDefaultOwner.release();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Allows multiple clients, who all need to have some underlying component
+ * started, to share the control of a SplitControl (MasterControl) interface.
+ * Any client successfully starting with SplitControl.start() / startDone()
+ * means the MasterControl state is on/started. That state is retained until
+ * the last client successfully completes SplitControl.stop() / stopDone(),
+ * at which time the MasterControl state will be off/stopped.
+ *
+ * @param p_deferStopTime is the number of mibbiseconds the implementation
+ * waits after all clients have completed stop operations before the device
+ * wired to MasterControl is actually stopped. Ths allows implementations to
+ * control 'flapping' of the state of the underlying device.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic configuration SharedSplitControlC(char resourceName[],
+ uint16_t p_deferStopTime) {
+ provides interface SplitControl[uint8_t id];
+ uses interface SplitControl as MasterControl;
+}
+implementation {
+ enum { CLIENTS = uniqueCount(resourceName) };
+
+ components new SharedSplitControlP(CLIENTS, p_deferStopTime);
+ SplitControl = SharedSplitControlP;
+ MasterControl = SharedSplitControlP;
+
+ components MainC;
+ MainC.SoftwareInit -> SharedSplitControlP;
+
+ components new TimerMilliC();
+ SharedSplitControlP.Timer -> TimerMilliC;
+
+ components new StateC();
+ SharedSplitControlP.State -> StateC;
+}
--- /dev/null
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ * of its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Allows multiple clients, who all need to have some underlying component
+ * started, to share the control of a SplitControl (MasterControl) interface.
+ * Any client successfully starting with SplitControl.start() / startDone()
+ * means the MasterControl state is on/started. That state is retained until
+ * the last client successfully completes SplitControl.stop() / stopDone(),
+ * at which time the MasterControl state will be off/stopped.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module SharedSplitControlP(uint8_t p_clients,
+ uint16_t p_deferStopTime) {
+ provides {
+ interface Init;
+ interface SplitControl[uint8_t id];
+ }
+ uses {
+ interface SplitControl as MasterControl;
+ interface Timer<TMilli>;
+ interface State;
+ }
+}
+implementation {
+ enum {
+ /* MasterControl states */
+ S_IDLE = 0,
+ S_START,
+ S_ON,
+ S_STOPWAIT,
+ S_STOP,
+
+ /* S_STOPWAIT is special, for the master only. After all clients have
+ * stopped, the master could be stopped. But, we leave it on in the
+ * S_STOPWAIT state for a little bit before actually stopping it, so that
+ * we can reduce start/stop thrashing in our application. This behavior
+ * is controlled by the p_deferStopTime parameter.
+ */
+ };
+
+ uint8_t m_state[p_clients];
+
+ command error_t Init.init()
+ {
+ return SUCCESS;
+ }
+
+ task void signalStarts()
+ {
+ unsigned id;
+
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_START) {
+ m_state[id] = S_ON;
+ signal SplitControl.startDone[id](SUCCESS);
+ }
+ }
+ }
+
+ command error_t SplitControl.start[uint8_t id]()
+ {
+ error_t error;
+
+ if (id >= p_clients)
+ return FAIL;
+
+ switch (m_state[id]) {
+ case S_IDLE:
+ switch (call State.getState()) {
+ case S_IDLE:
+ error = call MasterControl.start();
+ if (error == SUCCESS) {
+ call State.forceState(S_START);
+ m_state[id] = S_START;
+ }
+ return error;
+ break;
+ case S_START:
+ m_state[id] = S_START;
+ return SUCCESS;
+ break;
+ case S_STOPWAIT:
+ call Timer.stop();
+ call State.forceState(S_ON);
+ /* fall through */
+ case S_ON:
+ m_state[id] = S_START;
+ post signalStarts();
+ return SUCCESS;
+ break;
+ case S_STOP:
+ /* Master will restart as soon as its stop is done */
+ m_state[id] = S_START;
+ return SUCCESS;
+ break;
+ default:
+ /* Should never get here */
+ return FAIL;
+ }
+ break;
+ case S_START:
+ return SUCCESS;
+ break;
+ case S_ON:
+ return EALREADY;
+ break;
+ case S_STOP:
+ default:
+ return EBUSY;
+ break;
+ }
+ }
+
+ event void MasterControl.startDone(error_t error)
+ {
+ unsigned id;
+ unsigned newState = (error == SUCCESS) ? S_ON : S_IDLE;
+
+ /* Master is starting, implying >= 1 client starting and all others are off.
+ * Master and all starting clients transition to the on state if the start
+ * was successful, or fall back to the idle (off) state if not.
+ */
+ call State.forceState(newState);
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_START) {
+ m_state[id] = newState;
+ signal SplitControl.startDone[id](error);
+ }
+ }
+ }
+
+ task void signalStops()
+ {
+ unsigned id;
+ bool allOff = TRUE;
+
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_STOP) {
+ m_state[id] = S_IDLE;
+ signal SplitControl.stopDone[id](SUCCESS);
+ } else if (m_state[id] != S_IDLE)
+ allOff = FALSE;
+ }
+ if (allOff) {
+ /* All clients are off. We can stop the master, but we might wait a bit
+ * before stopping the master.
+ */
+ if (p_deferStopTime) {
+ call State.forceState(S_STOPWAIT);
+ call Timer.startOneShot(p_deferStopTime);
+ } else {
+ if (call MasterControl.stop() == SUCCESS)
+ call State.forceState(S_STOP);
+ }
+ }
+ }
+
+ command error_t SplitControl.stop[uint8_t id]()
+ {
+ if (id >= p_clients)
+ return FAIL;
+
+ switch (m_state[id]) {
+ case S_IDLE:
+ return EALREADY;
+ break;
+ case S_ON:
+ switch (call State.getState()) {
+ case S_ON:
+ /* fall through */
+ case S_STOPWAIT:
+ case S_IDLE:
+ /* Invalid condition. If the master is off, then all clients
+ * should also be off. Go ahead signal the client to stop.
+ */
+ m_state[id] = S_STOP;
+ post signalStops();
+ return SUCCESS;
+ break;
+ case S_START:
+ case S_STOP:
+ default:
+ /* Invalid condition. For the master to be starting, all clients
+ * must either be off or starting. For the master to be stopping,
+ * no client can be on. We can generally correct this invalid
+ * condition by setting the client to S_STOP and dealing with it
+ * in MasterControl.startDone() or stopDone() (respectively).
+ */
+ m_state[id] = S_STOP;
+ return SUCCESS;
+ break;
+ }
+ break;
+ case S_STOP:
+ return SUCCESS;
+ break;
+ case S_START:
+ default:
+ return EBUSY;
+ break;
+ }
+ /* If we get here, we had an invalid state combination */
+ }
+
+ event void Timer.fired()
+ {
+ error_t error = call MasterControl.stop();
+
+ if (error == SUCCESS)
+ call State.forceState(S_STOP);
+ else {
+ unsigned id;
+
+ /* If we failed to start, we need to signal any starting clients */
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_START) {
+ m_state[id] = S_ON;
+ signal SplitControl.startDone[id](SUCCESS);
+ }
+ }
+ }
+ }
+
+ event void MasterControl.stopDone(error_t error)
+ {
+ unsigned id;
+ unsigned newState = (error == SUCCESS) ? S_IDLE : S_ON;
+ bool starts = FALSE;
+
+ /* Master is stopping, implying >= 1 client stopping. Other clients may
+ * be in any other state. Master and all stopping clients transition to
+ * the off state if the start was successful, or fall back to the on state
+ * if not.
+ */
+ call State.forceState(newState);
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_STOP) {
+ m_state[id] = newState;
+ signal SplitControl.stopDone[id](error);
+ } else if (m_state[id] == S_START)
+ starts = TRUE;
+ }
+
+ /* While the master was stopping, some clients that were off may have
+ * issued a start. It is possible that we need to start the master again.
+ * If the master start() fails, all clients in start get kicked back to
+ * off, in error.
+ */
+ if (starts) {
+ error = call MasterControl.start();
+
+ if (error == SUCCESS)
+ call State.forceState(S_START);
+ else {
+ for (id = 0; id < p_clients; id++) {
+ if (m_state[id] == S_START) {
+ m_state[id] = S_IDLE;
+ signal SplitControl.startDone[id](error);
+ }
+ }
+ }
+ }
+ }
+
+ default event void SplitControl.startDone[uint8_t id](error_t error) {}
+ default event void SplitControl.stopDone[uint8_t id](error_t error) {}
+}