]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
- bugfix: ReadStream did not work with a "usPeriod" parameter > 0xFFFF (the fix uses...
authorjanhauer <janhauer>
Mon, 7 Apr 2008 09:41:55 +0000 (09:41 +0000)
committerjanhauer <janhauer>
Mon, 7 Apr 2008 09:41:55 +0000 (09:41 +0000)
- bugfix: overflow interrupts were not handled/signalled correctly from the HAL
- fixed the wiring for DMA, which was not correct when used by more than one client
- polished the HPL and added some comments
- introduced a compile time warning when DMA/TimerA is accessed (will be removed once we decide how these components are arbitrated)

14 files changed:
apps/tests/msp430/Adc12/TestAdcMultiC.nc
apps/tests/msp430/Adc12/TestAdcSingleC.nc
tos/chips/msp430/adc12/AdcP.nc
tos/chips/msp430/adc12/AdcReadStreamClientC.nc
tos/chips/msp430/adc12/AdcStreamP.nc [new file with mode: 0644]
tos/chips/msp430/adc12/HplAdc12P.nc
tos/chips/msp430/adc12/Msp430Adc12ClientAutoDMAC.nc
tos/chips/msp430/adc12/Msp430Adc12ClientAutoDMA_RVGC.nc
tos/chips/msp430/adc12/Msp430Adc12ClientAutoRVGC.nc
tos/chips/msp430/adc12/Msp430Adc12DMAWireC.nc [new file with mode: 0644]
tos/chips/msp430/adc12/Msp430Adc12ImplP.nc
tos/chips/msp430/adc12/Msp430Adc12MultiChannel.nc
tos/chips/msp430/adc12/README.txt
tos/chips/msp430/adc12/WireAdcStreamP.nc [new file with mode: 0644]

index 26737838a144d6bfc577ec7de7ef9be49147e668..5393334234971288dbbbcdf2e1bf3fa8d595cdd1 100644 (file)
@@ -68,7 +68,7 @@ implementation
 #define BUFFER_SIZE 100
   const msp430adc12_channel_config_t config = {inch, sref, ref2_5v, adc12ssel, adc12div, sht, sampcon_ssel, sampcon_id};
   adc12memctl_t memCtl = {inch2, sref2};
-  uint8_t state;
+  norace uint8_t state;
   uint16_t buffer[BUFFER_SIZE];
   void task getData();
 
@@ -85,6 +85,8 @@ implementation
   bool assertData(uint16_t *data, uint16_t num)
   {
     uint16_t i;
+    if (num != BUFFER_SIZE)
+      post signalFailure();
     for (i=0; i<num; i++)
       if (!data[i] || data[i] >= 0xFFF){
         post signalFailure();
@@ -117,8 +119,10 @@ implementation
 
   async event void MultiChannel.dataReady(uint16_t *buf, uint16_t numSamples)
   {
-    if (assertData(buf, numSamples))
+    if (assertData(buf, numSamples) && state++ == 0)
       post signalSuccess();
+    else
+      post signalFailure();
     call Resource.release();
   }
 
index e1fe427c3b7e7044845b137ba9072b1976a189f3..809e4cac444b7025497c94296190f25509cfcffa 100644 (file)
@@ -64,6 +64,7 @@ implementation
 #define BUFFER_SIZE 100
   const msp430adc12_channel_config_t config = {inch, sref, ref2_5v, adc12ssel, adc12div, sht, sampcon_ssel, sampcon_id};
   uint8_t state;
+  norace uint8_t numDone;
   uint16_t buffer[BUFFER_SIZE];
   void task getData();
 
@@ -117,13 +118,15 @@ implementation
                 call SingleChannel.getData();
               break;
       default: call Resource.release();
-              signal Notify.notify(TRUE);
+              if (numDone == state)
+                signal Notify.notify(TRUE);
               break;
     }
   }
 
   async event error_t SingleChannel.singleDataReady(uint16_t data)
   { 
+    numDone++;
     assertData(&data, 1);
     call Resource.release();
     post getData();
@@ -133,6 +136,7 @@ implementation
     
   async event uint16_t* SingleChannel.multipleDataReady(uint16_t *buf, uint16_t length)
   {
+    numDone++;
     assertData(buf, length);
     call Resource.release();
     post getData();
index 654807adcebe044371fd97f46b27c1902b74866d..7536a0a39cfb5a7f50844523026ea97ccf50f19b 100644 (file)
@@ -38,7 +38,6 @@ module AdcP {
     interface Read<uint16_t> as Read[uint8_t client];
     interface ReadNow<uint16_t> as ReadNow[uint8_t client];
     interface Resource as ResourceReadNow[uint8_t client];
-    interface ReadStream<uint16_t> as ReadStream[uint8_t streamClient];
   }
   uses {
     // for Read only:
@@ -48,11 +47,6 @@ module AdcP {
     // for Read and ReadNow:
     interface AdcConfigure<const msp430adc12_channel_config_t*> as Config[uint8_t client];
     interface Msp430Adc12SingleChannel as SingleChannel[uint8_t client];
-    // for ReadStream only:
-    interface AdcConfigure<const msp430adc12_channel_config_t*> as ConfigReadStream[uint8_t streamClient];
-    interface Msp430Adc12SingleChannel as SingleChannelReadStream[uint8_t streamClient];
-    interface Resource as ResourceReadStream[uint8_t streamClient];
-
   }
 }
 implementation
@@ -61,28 +55,12 @@ implementation
     STATE_READ,
     STATE_READNOW,
     STATE_READNOW_INVALID_CONFIG,
-    STATE_READSTREAM,
-  };
-  
-  struct stream_entry_t {
-    uint16_t count;
-    struct stream_entry_t *next;
   };
   
   // Resource interface / arbiter makes norace declaration safe
   norace uint8_t state;
   norace uint8_t owner;
   norace uint16_t value;
-  norace uint16_t *resultBuf; 
-
-  // atomic section in postBuffer() makes norace safe
-  norace struct stream_entry_t *streamBuf[uniqueCount(ADCC_READ_STREAM_SERVICE)];
-  norace uint32_t usPeriod[uniqueCount(ADCC_READ_STREAM_SERVICE)];
-  msp430adc12_channel_config_t streamConfig;
-    
-  void task finishStreamRequest();
-  void task signalBufferDone();
-  void nextReadStreamRequest(uint8_t streamClient);
 
   error_t configure(uint8_t client)
   {
@@ -96,8 +74,6 @@ implementation
 
   command error_t Read.read[uint8_t client]()
   {
-    if (call ResourceRead.isOwner[client]())
-      return EBUSY;
     return call ResourceRead.request[client]();
   }
 
@@ -108,8 +84,7 @@ implementation
     if (result == SUCCESS){
       state = STATE_READ;
       result = call SingleChannel.getData[client]();
-    }
-    if (result != SUCCESS){
+    } else {
       call ResourceRead.release[client]();
       signal Read.readDone[client](result, 0);
     }
@@ -189,137 +164,6 @@ implementation
     // error !
     return 0;
   }
-  
-  command error_t ReadStream.postBuffer[uint8_t streamClient]( uint16_t* buf, uint16_t count )
-  {
-    struct stream_entry_t *newEntry = (struct stream_entry_t *) buf;
-    
-    newEntry->count = count;
-    newEntry->next = 0;
-    atomic {
-      if (!streamBuf[streamClient])
-        streamBuf[streamClient] = newEntry;
-      else {
-        struct stream_entry_t *tmp = streamBuf[streamClient];
-        while (tmp->next)
-          tmp = tmp->next;
-        tmp->next = newEntry;
-      }
-    }
-    return SUCCESS;
-  }
-  
-  command error_t ReadStream.read[uint8_t streamClient]( uint32_t _usPeriod )
-  {
-    if (!streamBuf[streamClient])
-      return EINVAL;
-    if (call ResourceReadStream.isOwner[streamClient]())
-      return EBUSY;
-    usPeriod[streamClient] = _usPeriod;
-    return call ResourceReadStream.request[streamClient]();
-  }
-
-  void task finishStreamRequest()
-  {
-    call ResourceReadStream.release[owner]();
-    if (!streamBuf[owner])
-      // all posted buffers were filled
-      signal ReadStream.readDone[owner]( SUCCESS, usPeriod[owner] );
-    else {
-      // the commented code below makes gcc throw
-      // "internal error: unsupported relocation error" !?!
-      /*
-      do {
-        signal ReadStream.bufferDone[owner]( FAIL, (uint16_t *) streamBuf[owner], 0);
-        streamBuf[owner] = streamBuf[owner]->next;
-      } while (streamBuf[owner]);
-      */
-      signal ReadStream.readDone[owner]( FAIL, 0 );
-    }
-  }  
-
-  event void ResourceReadStream.granted[uint8_t streamClient]() 
-  {
-    error_t result;
-    const msp430adc12_channel_config_t *config;
-    struct stream_entry_t *entry = streamBuf[streamClient];
-
-    if (!entry)
-      result = EINVAL;
-    else {
-      config = call ConfigReadStream.getConfiguration[streamClient]();
-      if (config->inch == INPUT_CHANNEL_NONE)
-        result = EINVAL;
-      else {
-        owner = streamClient;
-        streamConfig = *config;
-        streamConfig.sampcon_ssel = SAMPCON_SOURCE_SMCLK; // assumption: SMCLK runs at 1 MHz
-        streamConfig.sampcon_id = SAMPCON_CLOCK_DIV_1; 
-        streamBuf[streamClient] = entry->next;
-        result = call SingleChannelReadStream.configureMultiple[streamClient](
-            &streamConfig, (uint16_t *) entry, entry->count, usPeriod[streamClient]);
-        if (result == SUCCESS)
-          result = call SingleChannelReadStream.getData[streamClient]();
-        else {
-          streamBuf[streamClient] = entry;
-          post finishStreamRequest();
-          return;
-        }
-      }
-    }
-    if (result != SUCCESS){
-      call ResourceReadStream.release[streamClient]();
-      signal ReadStream.readDone[streamClient]( FAIL, 0 );
-    }
-    return;
-  }
-
-
-  async event uint16_t* SingleChannelReadStream.multipleDataReady[uint8_t streamClient](
-      uint16_t *buf, uint16_t length)
-  {
-    error_t nextRequest;
-    
-    if (!resultBuf){
-      value = length;
-      resultBuf = buf;
-      post signalBufferDone();
-      if (!streamBuf[streamClient])
-        post finishStreamRequest();
-      else {
-        // fill next buffer (this is the only async code dealing with buffers)
-        struct stream_entry_t *entry = streamBuf[streamClient];
-        streamBuf[streamClient] = streamBuf[streamClient]->next;
-        nextRequest = call SingleChannelReadStream.configureMultiple[streamClient](
-            &streamConfig, (uint16_t *) entry, entry->count, usPeriod[streamClient]);
-        if (nextRequest == SUCCESS)
-          nextRequest = call SingleChannelReadStream.getData[streamClient]();
-        if (nextRequest != SUCCESS){
-          streamBuf[owner] = entry;
-          post finishStreamRequest();
-        }
-      }
-    } else {
-      // overflow: can't signal data fast enough
-      struct stream_entry_t *entry = (struct stream_entry_t *) buf;
-      entry->next = streamBuf[streamClient];
-      streamBuf[streamClient] = entry; // what a waste
-      post finishStreamRequest();
-    }
-    return 0;
-  }
-
-  void task signalBufferDone()
-  {
-    signal ReadStream.bufferDone[owner]( SUCCESS, resultBuf, value);
-    resultBuf = 0;
-  }
-  
-  async event error_t SingleChannelReadStream.singleDataReady[uint8_t streamClient](uint16_t data)
-  {
-    // won't happen
-    return SUCCESS;
-  }
 
   default async command error_t ResourceRead.request[uint8_t client]() { return FAIL; }
   default async command error_t ResourceRead.immediateRequest[uint8_t client]() { return FAIL; }
@@ -332,52 +176,19 @@ implementation
   default async command bool SubResourceReadNow.isOwner[uint8_t client]() { return FALSE; }
   default event void ResourceReadNow.granted[uint8_t nowClient](){}
   default async event void ReadNow.readDone[uint8_t client]( error_t result, uint16_t val ){}
-  default async command error_t SubResourceReadNow.immediateRequest[uint8_t nowClient]()
-  { 
-    return FAIL; 
-  }
-  
-  default async command error_t ResourceReadStream.request[uint8_t streamClient]() { return FAIL; }
-  default async command error_t ResourceReadStream.release[uint8_t streamClient]() { return FAIL; }
-  default async command bool ResourceReadStream.isOwner[uint8_t streamClient]() { return FALSE; }
-  default event void ReadStream.bufferDone[uint8_t streamClient]( error_t result, 
-                        uint16_t* buf, uint16_t count ){}
-  default event void ReadStream.readDone[uint8_t streamClient]( error_t result, uint32_t actualPeriod ){ } 
-
+  default async command error_t SubResourceReadNow.immediateRequest[uint8_t nowClient]() { return FAIL; }
   default async command error_t SingleChannel.getData[uint8_t client]()
   {
     return EINVAL;
   }
 
-  // will be placed in flash
   const msp430adc12_channel_config_t defaultConfig = {INPUT_CHANNEL_NONE,0,0,0,0,0,0,0}; 
   default async command const msp430adc12_channel_config_t*
     Config.getConfiguration[uint8_t client]()
   { 
     return &defaultConfig;
-  }
-
-  default async command const msp430adc12_channel_config_t*
-    ConfigReadStream.getConfiguration[uint8_t client]()
-  { 
-    return &defaultConfig;
-  }
-
-  default async command error_t SingleChannelReadStream.configureMultiple[uint8_t client](
-      const msp430adc12_channel_config_t *config, uint16_t buffer[], 
-      uint16_t numSamples, uint16_t jiffies)
-  {
-    return FAIL;
-  }
-
-  default async command error_t SingleChannelReadStream.getData[uint8_t client]()
-  {
-    return FAIL;
-  }
-
+  }  
   default async command error_t SingleChannel.configureSingle[uint8_t client](
       const msp430adc12_channel_config_t *config){ return FAIL; }
-
-
-}
-
+  
+} 
index 94efef51805cf6f6b44b63f728fea1083594664b..696bf71b3dd6a411e24f31662c8444c05f6cb5ff 100644 (file)
@@ -48,26 +48,24 @@ generic configuration AdcReadStreamClientC() {
   provides interface ReadStream<uint16_t>;
   uses interface AdcConfigure<const msp430adc12_channel_config_t*>;
 } implementation {
-  components AdcP,
+  components WireAdcStreamP, 
 #ifdef REF_VOLT_AUTO_CONFIGURE     
              // if the client configuration requires a stable 
              // reference voltage, the reference voltage generator 
              // is automatically enabled
-             new Msp430Adc12ClientAutoRVGC() as Msp430AdcPlient;
+             new Msp430Adc12ClientAutoRVGC() as Msp430AdcClient;
+  AdcConfigure = Msp430AdcClient.AdcConfigure;
 #else
-             new Msp430Adc12ClientC() as Msp430AdcPlient;
+             new Msp430Adc12ClientC() as Msp430AdcClient;
 #endif
 
   enum {
     RSCLIENT = unique(ADCC_READ_STREAM_SERVICE),
   };
 
-  ReadStream = AdcP.ReadStream[RSCLIENT];
-  AdcConfigure = AdcP.ConfigReadStream[RSCLIENT];
-  AdcP.SingleChannelReadStream[RSCLIENT] -> Msp430AdcPlient.Msp430Adc12SingleChannel;
-  AdcP.ResourceReadStream[RSCLIENT] -> Msp430AdcPlient.Resource;
-#ifdef REF_VOLT_AUTO_CONFIGURE
-  AdcConfigure = Msp430AdcPlient.AdcConfigure;
-#endif
+  ReadStream = WireAdcStreamP.ReadStream[RSCLIENT];
+  AdcConfigure = WireAdcStreamP.AdcConfigure[RSCLIENT];
+  WireAdcStreamP.Resource[RSCLIENT] -> Msp430AdcClient.Resource;
+  WireAdcStreamP.Msp430Adc12SingleChannel[RSCLIENT] -> Msp430AdcClient.Msp430Adc12SingleChannel;
 }
   
diff --git a/tos/chips/msp430/adc12/AdcStreamP.nc b/tos/chips/msp430/adc12/AdcStreamP.nc
new file mode 100644 (file)
index 0000000..af14a47
--- /dev/null
@@ -0,0 +1,314 @@
+/* $Id$
+ * Copyright (c) 2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE     
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
+ * 94704.  Attention:  Intel License Inquiry.
+ *
+ * Copyright (c) 2004, Technische Universitaet Berlin
+ * 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 Universitaet 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.
+ *
+ */
+
+/**
+ * Convert MSP430 HAL A/D interface to the HIL interfaces (adapted atmega code).
+ * @author David Gay
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ */
+#include "Timer.h"
+
+module AdcStreamP {
+  provides {
+    interface Init @atleastonce();
+    interface ReadStream<uint16_t>[uint8_t client];
+  }
+  uses {
+    interface Msp430Adc12SingleChannel as SingleChannel[uint8_t client];
+    interface AdcConfigure<const msp430adc12_channel_config_t*>[uint8_t client];
+    interface Alarm<TMilli, uint32_t>;
+  }
+}
+implementation {
+  enum {
+    NSTREAM = uniqueCount(ADCC_READ_STREAM_SERVICE)
+  };
+
+  /* Resource reservation is required, and it's incorrect to call getData
+     again before dataReady is signaled, so there are no races in correct
+     programs */
+  norace uint8_t client = NSTREAM;
+
+  /* Stream data */
+  struct list_entry_t {
+    uint16_t count;
+    struct list_entry_t *next;
+  };
+  struct list_entry_t *bufferQueue[NSTREAM];
+  struct list_entry_t **bufferQueueEnd[NSTREAM];
+  uint16_t *lastBuffer, lastCount;
+
+  norace uint16_t *buffer, *pos, count;
+  norace uint32_t now, period;
+  norace bool periodModified;
+
+
+  command error_t Init.init() {
+    uint8_t i;
+
+    for (i = 0; i != NSTREAM; i++)
+      bufferQueueEnd[i] = &bufferQueue[i];
+
+    return SUCCESS;
+  }
+
+  void sampleSingle() {
+    call SingleChannel.getData[client]();
+  }
+
+  command error_t ReadStream.postBuffer[uint8_t c](uint16_t *buf, uint16_t n) {
+    if (n < sizeof(struct list_entry_t))
+      return ESIZE;
+    atomic
+    {
+      struct list_entry_t *newEntry = (struct list_entry_t *)buf;
+
+      if (!bufferQueueEnd[c]) // Can't post right now.
+        return FAIL;
+
+      newEntry->count = n;
+      newEntry->next = NULL;
+      *bufferQueueEnd[c] = newEntry;
+      bufferQueueEnd[c] = &newEntry->next;
+    }
+    return SUCCESS;
+  }
+
+  task void readStreamDone() {
+    uint8_t c = client;
+    uint32_t actualPeriod = period;
+    if (periodModified)
+      actualPeriod = period - (period % 1000);
+
+    atomic
+    {
+      bufferQueue[c] = NULL;
+      bufferQueueEnd[c] = &bufferQueue[c];
+    }
+
+    client = NSTREAM;
+    signal ReadStream.readDone[c](SUCCESS, actualPeriod);
+  }
+
+  task void readStreamFail() {
+    /* By now, the pending bufferDone has been signaled (see readStream). */
+    struct list_entry_t *entry;
+    uint8_t c = client;
+
+    atomic entry = bufferQueue[c];
+    for (; entry; entry = entry->next)
+      signal ReadStream.bufferDone[c](FAIL, (uint16_t *)entry, entry->count);
+
+    atomic
+    {
+      bufferQueue[c] = NULL;
+      bufferQueueEnd[c] = &bufferQueue[c];
+    }
+
+    client = NSTREAM;
+    signal ReadStream.readDone[c](FAIL, 0);
+  }
+
+  task void bufferDone() {
+    uint16_t *b, c;
+    atomic
+    {
+      b = lastBuffer;
+      c = lastCount;
+      lastBuffer = NULL;
+    }
+
+    signal ReadStream.bufferDone[client](SUCCESS, b, c);
+  }
+
+  void nextAlarm() {
+    call Alarm.startAt(now, period);
+    now += period;
+  }
+
+  async event void Alarm.fired() {
+    sampleSingle();
+  }
+
+  error_t nextBuffer(bool startNextAlarm) {
+    atomic
+    {
+      struct list_entry_t *entry = bufferQueue[client];
+
+      if (!entry)
+      {
+        // all done
+        bufferQueueEnd[client] = NULL; // prevent post
+        post readStreamDone();
+        return FAIL;
+      }
+      else
+      {
+        bufferQueue[client] = entry->next;
+        if (!bufferQueue[client])
+          bufferQueueEnd[client] = &bufferQueue[client];
+        pos = buffer = (uint16_t *)entry;
+        count = entry->count;
+        if (startNextAlarm)
+          nextAlarm();
+        return SUCCESS;
+      }
+    }
+  }
+
+  void nextMultiple(uint8_t c)
+  {
+    if (nextBuffer(FALSE) == SUCCESS){
+      msp430adc12_channel_config_t config = *call AdcConfigure.getConfiguration[c]();
+      config.sampcon_ssel = SAMPCON_SOURCE_SMCLK; // assumption: SMCLK runs at 1 MHz
+      config.sampcon_id = SAMPCON_CLOCK_DIV_1; 
+      call SingleChannel.configureMultiple[c]( &config, pos, count, period);
+      call SingleChannel.getData[c]();
+    }
+  }
+
+  command error_t ReadStream.read[uint8_t c](uint32_t usPeriod)
+  {
+    if (usPeriod & 0xFFFF0000){
+      // "manual" sampling
+      period = usPeriod / 1000;
+      periodModified = TRUE;
+      client = c;
+      now = call Alarm.getNow();
+      call SingleChannel.configureSingle[c](call AdcConfigure.getConfiguration[c]());
+      if (nextBuffer(FALSE) == SUCCESS)
+        sampleSingle();
+    } else {
+      period = usPeriod;
+      periodModified = FALSE;
+      client = c;
+      nextMultiple(c);
+    }
+    return SUCCESS;
+  }
+
+
+  async event error_t SingleChannel.singleDataReady[uint8_t streamClient](uint16_t data)
+  {
+    if (client == NSTREAM)
+      return FAIL;
+
+    if (count == 0)
+    {
+      now = call Alarm.getNow();
+      nextBuffer(TRUE);
+    }
+    else
+    {
+      *pos++ = data;
+      if (!--count)
+      {
+        atomic
+        {
+          if (lastBuffer)
+          {
+            /* We failed to signal bufferDone in time. Fail. */
+            bufferQueueEnd[client] = NULL; // prevent post
+            post readStreamFail();
+            return FAIL;
+          }
+          else
+          {
+            lastBuffer = buffer;
+            lastCount = pos - buffer;
+          }
+        }
+        post bufferDone();
+        nextBuffer(TRUE);
+      }
+      else
+        nextAlarm();
+    }
+    return FAIL;
+  }
+  
+  async event uint16_t* SingleChannel.multipleDataReady[uint8_t streamClient](
+      uint16_t *buf, uint16_t length)
+  {
+    atomic
+    {
+      if (lastBuffer)
+      {
+        /* We failed to signal bufferDone in time. Fail. */
+        bufferQueueEnd[client] = NULL; // prevent post
+        post readStreamFail();
+        return 0;
+      }
+      else
+      {
+        lastBuffer = buffer;
+        lastCount = pos - buffer;
+      }
+    }
+    post bufferDone();
+    nextMultiple(streamClient);
+    return 0;
+  }
+
+  const msp430adc12_channel_config_t defaultConfig = {
+      inch: SUPPLY_VOLTAGE_HALF_CHANNEL,
+      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
+  };
+  default async command const msp430adc12_channel_config_t* AdcConfigure.getConfiguration[uint8_t c]()
+  { 
+    return &defaultConfig;
+  }
+  default async command error_t SingleChannel.configureMultiple[uint8_t c](
+      const msp430adc12_channel_config_t *config, uint16_t b[], 
+      uint16_t numSamples, uint16_t jiffies)
+  {
+    return FAIL;
+  }
+  default async command error_t SingleChannel.getData[uint8_t c]()
+  {
+    return FAIL;
+  }  
+  default async command error_t SingleChannel.configureSingle[uint8_t c](
+      const msp430adc12_channel_config_t *config){ return FAIL; }
+}
index 2423dba00de14cc0044a31307aacf100a307906f..aaee9ce507e61846f7c65072b5226979c6a46382 100644 (file)
@@ -53,21 +53,25 @@ implementation
   MSP430REG_NORACE(ADC12IFG);
   MSP430REG_NORACE(ADC12IE);
   MSP430REG_NORACE(ADC12IV);
+
+  // SFRs are accessed directly or cast to a pointer, both works fine
+  // (we don't access all SFRs directly, because that would result in
+  // much higher memory footprint)
   
   async command void HplAdc12.setCtl0(adc12ctl0_t control0){
-    ADC12CTL0 = *(uint16_t*)&control0
+    ADC12CTL0 = *((uint16_t*) &control0)
   }
   
   async command void HplAdc12.setCtl1(adc12ctl1_t control1){
-    ADC12CTL1 = *(uint16_t*)&control1
+    ADC12CTL1 = *((uint16_t*) &control1)
   }
   
   async command adc12ctl0_t HplAdc12.getCtl0(){ 
-    return *(adc12ctl0_t*) &ADC12CTL0
+    return *((adc12ctl0_t*) &ADC12CTL0)
   }
   
   async command adc12ctl1_t HplAdc12.getCtl1(){
-    return *(adc12ctl1_t*) &ADC12CTL1
+    return *((adc12ctl1_t*) &ADC12CTL1)
   }
   
   async command void HplAdc12.setMCtl(uint8_t i, adc12memctl_t memControl){
@@ -92,15 +96,8 @@ implementation
   async command uint16_t HplAdc12.getIEFlags(){ return (uint16_t) ADC12IE; } 
   
   async command void HplAdc12.resetIFGs(){ 
-    if (!ADC12IFG)
-      return;
-    else {
-      // workaround, because ADC12IFG is not writable 
-      uint8_t i;
-      volatile uint16_t tmp;
-      for (i=0; i<16; i++)
-        tmp = call HplAdc12.getMem(i);
-    }
+    ADC12IV = 0; 
+    ADC12IFG = 0;
   } 
   
   async command void HplAdc12.startConversion(){ 
@@ -108,7 +105,9 @@ implementation
     ADC12CTL0 |= (ADC12SC + ENC); 
   }
   
-  async command void HplAdc12.stopConversion(){ 
+  async command void HplAdc12.stopConversion(){
+    // stop conversion mode immediately, conversion data is unreliable
+    ADC12CTL1 &= ~(CONSEQ0 | CONSEQ1);
     ADC12CTL0 &= ~(ADC12SC + ENC); 
     ADC12CTL0 &= ~(ADC12ON); 
   }
index 2f75f47dd706e212e5b08f9f5f43b4f4ce6ac1a8..74db72f90c806bc27551e2ec3482629dc6043a19 100644 (file)
@@ -48,19 +48,19 @@ generic configuration Msp430Adc12ClientAutoDMAC()
   provides {\r
     interface Resource;\r
     interface Msp430Adc12SingleChannel;\r
+    interface Msp430Adc12Overflow;\r
   }\r
 } implementation {\r
-  components Msp430DmaC, Msp430Adc12DMAP, Msp430Adc12P;\r
+  components Msp430DmaC, Msp430Adc12DMAP, Msp430Adc12P, Msp430Adc12DMAWireC;\r
    \r
   enum {\r
     ID = unique(MSP430ADC12_RESOURCE),\r
   };\r
   Resource = Msp430Adc12P.Resource[ID];\r
   Msp430Adc12SingleChannel = Msp430Adc12DMAP.SingleChannel[ID];\r
+  Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];\r
   \r
   Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];\r
   Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];\r
 \r
-  Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;\r
-  Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel0;\r
 }\r
index 7377496e18c158d7e7e7460a1085804e42644b13..9d554ee9f20db8cfda757dc27b80eec0063a45c0 100644 (file)
@@ -47,15 +47,17 @@ generic configuration Msp430Adc12ClientAutoDMA_RVGC()
   provides {\r
     interface Resource;\r
     interface Msp430Adc12SingleChannel;\r
+    interface Msp430Adc12Overflow;\r
   }\r
   uses interface AdcConfigure<const msp430adc12_channel_config_t*>;\r
 } implementation {\r
-  components Msp430Adc12P, Msp430RefVoltArbiterP;\r
+  components Msp430Adc12P, Msp430RefVoltArbiterP, Msp430Adc12DMAWireC;\r
 \r
   enum {\r
     ID = unique(MSP430ADC12_RESOURCE),\r
   };\r
   Resource = Msp430RefVoltArbiterP.ClientResource[ID];\r
+  Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];\r
   \r
   Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];\r
 \r
@@ -69,8 +71,4 @@ generic configuration Msp430Adc12ClientAutoDMA_RVGC()
   \r
   Msp430Adc12DMAP.SubSingleChannel[ID] -> Msp430Adc12P.SingleChannel[ID];\r
   Msp430Adc12DMAP.AsyncAdcControl[ID] -> Msp430Adc12P.DMAExtension[ID];\r
-\r
-  Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;\r
-  Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel0;\r
-  \r
 }\r
index 246f5860859b37a6ed64169723c21951a984444f..b7e5c6c58281d03b416847205cf6c1b06e778e5f 100644 (file)
@@ -46,6 +46,7 @@ generic configuration Msp430Adc12ClientAutoRVGC()
     interface Resource;\r
     interface Msp430Adc12SingleChannel;\r
     interface Msp430Adc12MultiChannel;\r
+    interface Msp430Adc12Overflow;\r
   }\r
   uses interface AdcConfigure<const msp430adc12_channel_config_t*>;\r
 } implementation {\r
@@ -57,6 +58,7 @@ generic configuration Msp430Adc12ClientAutoRVGC()
   Resource = Msp430RefVoltArbiterP.ClientResource[ID];\r
   Msp430Adc12SingleChannel = Msp430Adc12P.SingleChannel[ID];\r
   Msp430Adc12MultiChannel = Msp430Adc12P.MultiChannel[ID];\r
+  Msp430Adc12Overflow = Msp430Adc12P.Overflow[ID];\r
   \r
   Msp430RefVoltArbiterP.AdcResource[ID] -> Msp430Adc12P.Resource[ID];\r
 \r
diff --git a/tos/chips/msp430/adc12/Msp430Adc12DMAWireC.nc b/tos/chips/msp430/adc12/Msp430Adc12DMAWireC.nc
new file mode 100644 (file)
index 0000000..2a1f8ba
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006, Technische Universitaet Berlin
+ * 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 Universitaet 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.
+ *
+ * - Revision -------------------------------------------------------------
+ * $Revision$
+ * $Date$
+ * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+configuration Msp430Adc12DMAWireC
+{ 
+} implementation { 
+  components Msp430DmaC, Msp430Adc12DMAP;
+  Msp430Adc12DMAP.DMAControl -> Msp430DmaC.Control;
+  Msp430Adc12DMAP.DMAChannel -> Msp430DmaC.Channel2;
+#warning Accessing DMA.channel2 for ADC12
+}
index 36c80b8f4839b5361a18b2ead88b3d71ffdb41ce..e815ee61e0ef5b1dcd5154fd81843957b6c3e289 100644 (file)
@@ -63,6 +63,7 @@ module Msp430Adc12ImplP
 }
 implementation
 { 
+#warning Accessing TimerA for ADC12 
   enum {
     SINGLE_DATA = 1,
     SINGLE_DATA_REPEAT = 2,
@@ -86,7 +87,12 @@ implementation
 
   command error_t Init.init()
   {
+    adc12ctl0_t ctl0;
     call HplAdc12.stopConversion();
+    ctl0 = call HplAdc12.getCtl0();
+    ctl0.adc12tovie = 1;
+    ctl0.adc12ovie = 1;
+    call HplAdc12.setCtl0(ctl0);
     return SUCCESS;
   }
 
@@ -325,7 +331,7 @@ implementation
       if (call ADCArbiterInfo.userId() == id){
         adc12ctl1_t ctl1 = {
           adc12busy: 0,
-          ctl1.conseq = 3,
+          conseq: 3,
           adc12ssel: config->adc12ssel,
           adc12div: config->adc12div,
           issh: 0,
@@ -404,8 +410,7 @@ implementation
       if (call ADCArbiterInfo.userId() == id){
         adc12ctl1_t ctl1 = {
           adc12busy: 0,
-          // use seq. of channels (rep.seq. channel does not work with TimerA + MSC ?)
-          conseq: (jiffies == 0) ? 3 : 1, 
+          conseq: (numSamples > numMemctl+1) ? 3 : 1, 
           adc12ssel: config->adc12ssel,
           adc12div: config->adc12div,
           issh: 0,
@@ -420,7 +425,7 @@ implementation
         };     
         uint16_t i, mask = 1;
         adc12ctl0_t ctl0 = call HplAdc12.getCtl0();
-        ctl0.msc = 1;
+        ctl0.msc = (jiffies == 0) ? 1 : 0;
         ctl0.sht0 = config->sht;
         ctl0.sht1 = config->sht;
 
@@ -481,13 +486,14 @@ implementation
 #endif
     resetAdcPin( (call HplAdc12.getMCtl(0)).inch );
     if (state & MULTI_CHANNEL){
-      ADC12IV = 0; // clear any pending overflow
       for (i=1; i<numChannels; i++)
         resetAdcPin( (call HplAdc12.getMCtl(i)).inch );
     }
-    call HplAdc12.stopConversion();
-    call HplAdc12.resetIFGs(); 
-    state &= ~ADC_BUSY;
+    atomic {
+      call HplAdc12.stopConversion();
+      call HplAdc12.resetIFGs(); 
+      state &= ~ADC_BUSY;
+    }
   }
 
   async command error_t DMAExtension.start[uint8_t id]()
@@ -504,13 +510,8 @@ implementation
   
   async command error_t DMAExtension.stop[uint8_t id]()
   {
-    atomic {
-      if (call ADCArbiterInfo.userId() == id){
-        stopConversion();
-        return SUCCESS;
-      }
-    }
-    return FAIL;
+    stopConversion();
+    return SUCCESS;
   }
   
   async event void TimerA.overflow(){}
@@ -519,11 +520,15 @@ implementation
 
   async event void HplAdc12.conversionDone(uint16_t iv)
   {
+    bool overflow = FALSE;
     if (iv <= 4){ // check for overflow
       if (iv == 2)
         signal Overflow.memOverflow[clientID]();
       else
         signal Overflow.conversionTimeOverflow[clientID]();
+      // only if the client didn't ask for data as fast as possible (jiffies was not zero)
+      if (!(call HplAdc12.getCtl0()).msc)
+        overflow = TRUE;
     }
     switch (state & CONVERSION_MODE_MASK) 
     { 
@@ -536,29 +541,31 @@ implementation
           error_t repeatContinue;
           repeatContinue = signal SingleChannel.singleDataReady[clientID](
                 call HplAdc12.getMem(0));
-          if (repeatContinue == FAIL)
+          if (repeatContinue != SUCCESS)
             stopConversion();
           break;
         }
 #ifndef ADC12_ONLY_WITH_DMA
       case MULTI_CHANNEL:
         {
-          uint16_t i = 0;
+          uint16_t i = 0, k;
           do {
             *resultBuffer++ = call HplAdc12.getMem(i);
           } while (++i < numChannels);
           resultBufferIndex += numChannels;
-          if (resultBufferLength == resultBufferIndex){
+          if (overflow || resultBufferLength == resultBufferIndex){
             stopConversion();
-            resultBuffer -= resultBufferLength;
+            resultBuffer -= resultBufferIndex;
+            k = resultBufferIndex - numChannels;
             resultBufferIndex = 0;
-            signal MultiChannel.dataReady[clientID](resultBuffer, resultBufferLength);
+            signal MultiChannel.dataReady[clientID](resultBuffer, 
+                overflow ? k : resultBufferLength);
           } else call HplAdc12.enableConversion();
         }
         break;
       case MULTIPLE_DATA:
         {
-          uint16_t i = 0, length;
+          uint16_t i = 0, length, k;
           if (resultBufferLength - resultBufferIndex > 16) 
             length = 16;
           else
@@ -567,18 +574,20 @@ implementation
             *resultBuffer++ = call HplAdc12.getMem(i);
           } while (++i < length);
           resultBufferIndex += length;
-              
-          if (resultBufferLength - resultBufferIndex > 15)
+          if (overflow || resultBufferLength == resultBufferIndex){
+            stopConversion();
+            resultBuffer -= resultBufferIndex;
+            k = resultBufferIndex - length;
+            resultBufferIndex = 0;
+            signal SingleChannel.multipleDataReady[clientID](resultBuffer,
+               overflow ? k : resultBufferLength);
+          } else if (resultBufferLength - resultBufferIndex > 15)
             return;
-          else if (resultBufferLength - resultBufferIndex > 0){
+          else {
+            // last sequence < 16 samples
             adc12memctl_t memctl = call HplAdc12.getMCtl(0);
             memctl.eos = 1;
             call HplAdc12.setMCtl(resultBufferLength - resultBufferIndex, memctl);
-          } else {
-            stopConversion();
-            resultBuffer -= resultBufferLength;
-            resultBufferIndex = 0;
-            signal SingleChannel.multipleDataReady[clientID](resultBuffer, resultBufferLength);
           }
         }
         break;
@@ -591,7 +600,7 @@ implementation
           
           resultBuffer = signal SingleChannel.multipleDataReady[clientID](
               resultBuffer-resultBufferLength,
-                    resultBufferLength);
+              overflow ? 0 : resultBufferLength);
           if (!resultBuffer)  
             stopConversion();
           break;
index 0ded55e31e6ded9ea74f6907fd35be892e0388f2..38ff00c7551d7671f3d9a572fb92eef98985ebad 100644 (file)
@@ -74,13 +74,8 @@ interface Msp430Adc12MultiChannel
    * (numMemctl+1) must be zero. For example, to sample every channel twice use
    * numSamples = (numMemctl+1) * 2
    *
-   * @param jiffies Sampling period per sequence in terms of clock ticks of
-   * "sampcon_ssel" and input divider "sampcon_id". A sequence of (numMemctl+1)
-   * is always sampled as fast as possible and <code>jiffies</code> specifies
-   * the time between those sequences. For example, if numSamples =
-   * (numMemctl+1) * 5, then dataReady() will be signalled after (approx.)
-   * 5*jiffies clock ticks after the call to getData() and each set of
-   * numMemctl+1 channels was sampled at (almost) the same time.
+   * @param jiffies Sampling period in terms of clock ticks of "sampcon_ssel"
+   * and input divider "sampcon_id".
    *
    * @return SUCCESS means that the ADC was configured successfully and
    * <code>getData()</code> can be called to start the conversion.
index 6a6ca684983c1b08689fc42c5380063655601d0f..3f0d589a298bce9cb0a664971128053d80e82d57 100644 (file)
@@ -36,8 +36,8 @@ An application that is written for an MSP430-based platform like 'eyesIFX' or
 the Msp430Adc12SingleChannel allows to perform one or more ADC conversions on a
 single channel with a specified sampling frequency and (2) the
 Msp430Adc12MultiChannel allows to sample a group of up to 16 different ADC
-channels "at once" (with minimum latency) and in addition define a sampling
-frequency for the whole group (useful for multi-channel accelerometers, etc.).
+channels.
+
 On the MSP430 two additional hardware modules may play a role when the ADC12 is
 used: the internal reference voltage generator and the DMA controller. 
 
diff --git a/tos/chips/msp430/adc12/WireAdcStreamP.nc b/tos/chips/msp430/adc12/WireAdcStreamP.nc
new file mode 100644 (file)
index 0000000..7d9291d
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id$
+ * Copyright (c) 2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE     
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
+ * 94704.  Attention:  Intel License Inquiry.
+ */
+/**
+ * Support component for AdcReadStreamClientC.
+ *
+ * @author David Gay
+ * @author Jan Hauer 
+ */
+
+#include "Msp430Adc12.h"
+
+configuration WireAdcStreamP {
+  provides interface ReadStream<uint16_t>[uint8_t client];
+  uses {
+    interface AdcConfigure<const msp430adc12_channel_config_t*>[uint8_t client];
+    interface Msp430Adc12SingleChannel[uint8_t client];
+    interface Resource[uint8_t client];
+  }
+}
+implementation {
+  components AdcStreamP, MainC, new AlarmMilli32C() as Alarm, 
+    new ArbitratedReadStreamC(uniqueCount(ADCC_READ_STREAM_SERVICE), uint16_t) as ArbitrateReadStream;
+
+  ReadStream = ArbitrateReadStream;
+  AdcConfigure = AdcStreamP;
+  Resource = ArbitrateReadStream;
+
+  ArbitrateReadStream.Service -> AdcStreamP;
+
+  AdcStreamP.Init <- MainC;
+  Msp430Adc12SingleChannel = AdcStreamP.SingleChannel;
+  AdcStreamP.Alarm -> Alarm;
+}