⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 byteeepromc.nc

📁 传感器网络中的嵌入式操作系统源代码
💻 NC
字号:
// $Id: ByteEEPROMC.nc,v 1.4.2.2 2003/08/18 22:09:49 cssharp Exp $/*									tab:4 * "Copyright (c) 2000-2003 The Regents of the University  of California.   * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. *  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 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. *//*  --Initialization--  Each app that uses ByteEEPROM should call init() before Request  or RequestAddr.  It is safe to call init multiple times.  --Start--  Each app that uses ByteEEPROM should call start() in its own  start method. It is safe to call start multiple times.  --Interface Wiring--  apps that use this component should wire specific instances of AllocationReq,  SendDataToMapped, and ReadDataToMapped. The reason for having these interfaces  parameterized is so ByteEEPROM can communicate with each app separately.  For example, when an app requests a read, when the read completes, this ByteEEPROM  can then signal a readDone to only the application that requested it; similar is the  case for writes.  --Notes--  TOS_EEPROM_MAX_LINES = 0x80000 >> TOS_EEPROM_LOG2_LINE_SIZE is the maximum number of  lines. Therefore, (TOS_EEPROM_MAX_LINES - 1) << TOS_EEPROM_LOG2_LINE_SIZE is the last  line/page that can be requested.  */includes ByteEEPROMInternal;module ByteEEPROMC {  provides {    interface WriteData[uint8_t id];    interface LogData[uint8_t id];    interface ReadData[uint8_t id];  }  uses {    command RegionSpecifier *getRegion(uint8_t id);    interface PageEEPROM;    interface Leds;  }}implementation {  enum {    S_IDLE,    S_READ,    S_WRITE,    S_APPEND,    S_SYNC,    S_ERASE  };  uint8_t state;    uint8_t appID;  uint32_t startAddr;  uint32_t stopAddr;  uint32_t numBytes;  uint32_t dataBufferOffset;  uint8_t *dataBuffer;  bool writesLastByte;  enum {    NREGIONS = uniqueCount("ByteEEPROM"),    PAGE_SIZE = 1 << TOS_EEPROM_PAGE_SIZE_LOG2,    PAGE_SIZE_MASK = PAGE_SIZE - 1  };  // appendOffsets for the regions. They are stored as "real offset"+1 to  // provide easy handling of the "append offset" invalid condition  uint32_t appendOffset[NREGIONS];  RegionSpecifier *newRequest(uint8_t clientId) {    if (S_IDLE != state)      return NULL;    appID = clientId;    return call getRegion(clientId);  }    result_t newBufferRequest(uint8_t clientId, uint32_t offset,			    uint8_t *buffer, uint32_t count) {    RegionSpecifier *mappedRegion = newRequest(clientId);        if (mappedRegion == NULL)      return FAIL;        // the first byte actually read from    startAddr = mappedRegion->startByte + offset;    // the byte addr before stopAddr is the last byte we actually read    stopAddr = mappedRegion->startByte + offset + count;    //offset out of range, or trying to read too many bytes    if ((startAddr < mappedRegion->startByte) ||	(startAddr >= mappedRegion->stopByte))      return FAIL;    if ((stopAddr <= mappedRegion->startByte) ||	(stopAddr > mappedRegion->stopByte))      return FAIL;    // We note if we're writing the last byte (append needs to know this to    // avoid erasing the first page of the next region)    writesLastByte = stopAddr == mappedRegion->stopByte;        // Save the request data in our state vars    numBytes = count;    dataBuffer = buffer;    dataBufferOffset = 0;    return SUCCESS;  }    void completeOp(result_t success) {    uint8_t op = state;    state = S_IDLE;    switch (op)      {      case S_READ:	signal ReadData.readDone[appID](dataBuffer, numBytes, success);	break;      case S_WRITE:	signal WriteData.writeDone[appID](dataBuffer, numBytes, success);	break;      case S_APPEND:	if (success)	  appendOffset[appID] += numBytes;	signal LogData.appendDone[appID](dataBuffer, numBytes, success);	break;      case S_SYNC:	signal LogData.syncDone[appID](success); 	break;      case S_ERASE:	signal LogData.eraseDone[appID](success); 	break;      }  }  task void successTask() {    completeOp(SUCCESS);  }  task void failTask() {    completeOp(FAIL);  }  void check(result_t success) {    if (!success)      post failTask();  }  void continueOp() {    eeprompage_t sPage = startAddr >> TOS_EEPROM_PAGE_SIZE_LOG2;    eeprompage_t ePage = stopAddr >> TOS_EEPROM_PAGE_SIZE_LOG2;    eeprompageoffset_t offset, count;    if (startAddr == stopAddr)      {	post successTask();	return;      }    offset = startAddr & PAGE_SIZE_MASK;    if (sPage == ePage)      count = stopAddr - startAddr;    else      count = PAGE_SIZE - offset;    switch (state)      {      case S_READ:	check(call PageEEPROM.read(sPage, offset, dataBuffer + dataBufferOffset, count));	break;      case S_WRITE:  case S_APPEND:	check(call PageEEPROM.write(sPage, offset, dataBuffer + dataBufferOffset, count));	break;      }    dataBufferOffset += count;    startAddr += count;  }  event result_t PageEEPROM.readDone(result_t success) {    if (success == FAIL)      completeOp(FAIL);    else       continueOp();    return SUCCESS;  }  event result_t PageEEPROM.writeDone(result_t success) {    if (success == FAIL)      completeOp(FAIL);    else       {	if (state == S_APPEND && (startAddr & PAGE_SIZE_MASK) == 0 &&	    !(writesLastByte && startAddr == stopAddr))	  /* If an appending write filled the page, flush the last page and	     remind the EEPROM that the next page has been erased.	     Semi-hack: if this append is writing the last byte of a region	     whose size is the multiple of the page size, we don't want to	     erase the next page (as it belongs to another region). We	     detect this with the writesLastByte boolean... */	  check(call PageEEPROM.flush((startAddr >> TOS_EEPROM_PAGE_SIZE_LOG2) - 1));	else	  continueOp();      }    return SUCCESS;  }  event result_t PageEEPROM.flushDone(result_t result) {    check(call PageEEPROM.erase(startAddr >> TOS_EEPROM_PAGE_SIZE_LOG2,				TOS_EEPROM_PREVIOUSLY_ERASED));    return SUCCESS;  }  command result_t ReadData.read[uint8_t id](uint32_t offset, uint8_t *buffer, uint32_t numBytesRead) {    if (newBufferRequest(id, offset, buffer, numBytesRead) == FAIL)      return FAIL;    state = S_READ;    continueOp();    return SUCCESS;  }    command result_t WriteData.write[uint8_t id](uint32_t offset, uint8_t *buffer, uint32_t numBytesWrite) {    if (newBufferRequest(id, offset, buffer, numBytesWrite) == FAIL)      return FAIL;    state = S_WRITE;    continueOp();    return SUCCESS;  }    command result_t LogData.append[uint8_t id](uint8_t *buffer, uint32_t numBytesWrite) {    // The use of appendOffset - 1 will make newBufferRequest fail if    // appends are not currently allowed    if (newBufferRequest(id, appendOffset[id] - 1, buffer, numBytesWrite) == FAIL)      return FAIL;    state = S_APPEND;    continueOp();    return SUCCESS;  }  command uint32_t LogData.currentOffset[uint8_t id]() {    if (call getRegion(id))      return appendOffset[id] - 1;    else      return (uint32_t)-1;  }    command result_t LogData.sync[uint8_t clientId]() {    if (!newRequest(clientId))      return FAIL;    appendOffset[clientId] = 0; // disable append    state = S_SYNC;    check(call PageEEPROM.syncAll());    return SUCCESS;  }  event result_t PageEEPROM.syncDone(result_t result) {     completeOp(result);    return SUCCESS;  }  command result_t LogData.erase[uint8_t clientId]() {    RegionSpecifier *mappedRegion = newRequest(clientId);    if (!mappedRegion)      return FAIL;    /* We erase backwards so that the first page (where we will start       appending) is in the cache in an "erased" state */    state = S_ERASE;    startAddr = mappedRegion->startByte >> TOS_EEPROM_PAGE_SIZE_LOG2;    stopAddr = (mappedRegion->stopByte - 1) >> TOS_EEPROM_PAGE_SIZE_LOG2;    appendOffset[clientId] = 1; // start appending at offset 0    check(call PageEEPROM.erase(stopAddr, TOS_EEPROM_ERASE));    return SUCCESS;  }  event result_t PageEEPROM.eraseDone(result_t success) {    if (!success)      completeOp(success);    else if (state == S_APPEND)      continueOp();    else      {	if (startAddr == stopAddr)	  completeOp(SUCCESS);	else	  {	    stopAddr--;	    check(call PageEEPROM.erase(stopAddr, TOS_EEPROM_ERASE));	  }      }    return SUCCESS;  }    default event result_t WriteData.writeDone[uint8_t id](uint8_t *data, uint32_t numBytesWrite, result_t success) {    return SUCCESS;  }  default event result_t ReadData.readDone[uint8_t id](uint8_t *buffer, uint32_t numBytesRead, result_t success) {    return SUCCESS;  }  default event result_t LogData.appendDone[uint8_t id](uint8_t *data, uint32_t numBytesWrite, result_t success) {    return SUCCESS;  }  default event result_t LogData.eraseDone[uint8_t id](result_t success) {    return SUCCESS;  }  default event result_t LogData.syncDone[uint8_t id](result_t success) {    return SUCCESS;  }  event result_t PageEEPROM.computeCrcDone(result_t result, uint16_t crc) {    return SUCCESS;  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -