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

📄 at45dbp.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
// $Id: At45dbP.nc,v 1.7 2008/06/11 00:46:23 razvanm Exp $/* * "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-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. */#include "crc.h"#include "At45db.h"#include "Timer.h"/** * Private componenent for the Atmel's AT45DB HAL. * * @author David Gay */module At45dbP {  provides {    interface Init;    interface At45db;  }  uses {    interface HplAt45db;    interface BusyWait<TMicro, uint16_t>;  }}implementation{#define CHECKARGS#if 0  uint8_t work[20];  uint8_t woffset;  void wdbg(uint8_t x) {    work[woffset++] = x;    if (woffset == sizeof work)      woffset = 0;  }#else#define wdbg(n)#endif  enum { // requests    IDLE,    R_READ,    R_READCRC,    R_WRITE,    R_ERASE,    R_COPY,    R_SYNC,    R_SYNCALL,    R_FLUSH,    R_FLUSHALL,    BROKEN // Write failed. Fail all subsequent requests.  };  uint8_t request;  at45pageoffset_t reqOffset, reqBytes;  uint8_t * COUNT_NOK(reqBytes) reqBuf;  at45page_t reqPage;  enum {    P_READ,    P_READCRC,    P_WRITE,    P_FLUSH,    P_FILL,    P_ERASE,    P_COMPARE,    P_COMPARE_CHECK  };    struct {    at45page_t page;    bool busy : 1;    bool clean : 1;    bool erased : 1;    uint8_t unchecked : 2;  } buffer[2];  uint8_t selected; // buffer used by the current op  uint8_t checking;  bool flashBusy;  // Select a command for the current buffer#define OPN(n, name) ((n) ? name ## 1 : name ## 2)#define OP(name) OPN(selected, name)  command error_t Init.init() {    request = IDLE;    flashBusy = TRUE;          // pretend we're on an invalid non-existent page    buffer[0].page = buffer[1].page = AT45_MAX_PAGES;    buffer[0].busy = buffer[1].busy = FALSE;    buffer[0].clean = buffer[1].clean = TRUE;    buffer[0].unchecked = buffer[1].unchecked = 0;    buffer[0].erased = buffer[1].erased = FALSE;    return SUCCESS;  }    void flashIdle() {    flashBusy = buffer[0].busy = buffer[1].busy = FALSE;  }  void requestDone(error_t result, uint16_t computedCrc, uint8_t newState);  void handleRWRequest();  task void taskSuccess() {    requestDone(SUCCESS, 0, IDLE);  }  task void taskFail() {    requestDone(FAIL, 0, IDLE);  }  void checkBuffer(uint8_t buf) {    if (flashBusy)      {	call HplAt45db.waitIdle();	return;      }    call HplAt45db.compare(OPN(buf, AT45_C_COMPARE_BUFFER), buffer[buf].page);    checking = buf;  }  void flushBuffer() {    if (flashBusy)      {	call HplAt45db.waitIdle();	return;      }    call HplAt45db.flush(buffer[selected].erased ?			 OP(AT45_C_QFLUSH_BUFFER) :			 OP(AT45_C_FLUSH_BUFFER), 			 buffer[selected].page);  }  event void HplAt45db.waitIdleDone() {    flashIdle();    // Eager compare - this steals the current command#if 0    if ((buffer[0].unchecked || buffer[1].unchecked) &&	cmdPhase != P_COMPARE)      checkBuffer(buffer[0].unchecked ? 0 : 1);    else#endif      handleRWRequest();  }  event void HplAt45db.waitCompareDone(bool ok) {    flashIdle();    if (ok)      buffer[checking].unchecked = 0;    else if (buffer[checking].unchecked < 2)      buffer[checking].clean = FALSE;    else      {	requestDone(FAIL, 0, BROKEN);	return;      }    handleRWRequest();  }  event void HplAt45db.readDone() {    requestDone(SUCCESS, 0, IDLE);  }  event void HplAt45db.writeDone() {    buffer[selected].clean = FALSE;    buffer[selected].unchecked = 0;    requestDone(SUCCESS, 0, IDLE);  }  event void HplAt45db.crcDone(uint16_t crc) {    requestDone(SUCCESS, crc, IDLE);  }  event void HplAt45db.flushDone() {    flashBusy = TRUE;    buffer[selected].clean = buffer[selected].busy = TRUE;    buffer[selected].unchecked++;    buffer[selected].erased = FALSE;    handleRWRequest();  }  event void HplAt45db.compareDone() {    flashBusy = TRUE;    buffer[checking].busy = TRUE;    // The 10us wait makes old mica motes (Atmega 103) happy, for    // some mysterious reason (w/o this wait, the first compare    // always fails, even though the compare after the rewrite    // succeeds...)    call BusyWait.wait(10);    call HplAt45db.waitCompare();  }  event void HplAt45db.fillDone() {    flashBusy = TRUE;    buffer[selected].page = reqPage;    buffer[selected].clean = buffer[selected].busy = TRUE;    buffer[selected].erased = FALSE;    handleRWRequest();  }  event void HplAt45db.eraseDone() {    flashBusy = TRUE;    // The buffer contains garbage, but we don't care about the state    // of bits on this page anyway (if we do, we'll perform a     // subsequent write)    buffer[selected].page = reqPage;    buffer[selected].clean = TRUE;    buffer[selected].erased = TRUE;    requestDone(SUCCESS, 0, IDLE);  }  void syncOrFlushAll(uint8_t newReq);  void handleRWRequest() {    if (reqPage == buffer[selected].page)      switch (request)	{	case R_ERASE:	  switch (reqOffset)	    {	    case AT45_ERASE:	      if (flashBusy)		call HplAt45db.waitIdle();	      else		call HplAt45db.erase(AT45_C_ERASE_PAGE, reqPage);	      break;	    case AT45_PREVIOUSLY_ERASED:	      // We believe the user...	      buffer[selected].erased = TRUE;	      /* Fallthrough */	    case AT45_DONT_ERASE:	      // The buffer contains garbage, but we don't care about the state	      // of bits on this page anyway (if we do, we'll perform a 	      // subsequent write)	      buffer[selected].clean = TRUE;	      requestDone(SUCCESS, 0, IDLE);	      break;	    }	  break;	case R_COPY:	  if (!buffer[selected].clean) // flush any modifications	    flushBuffer();	  else	    {	      // Just redesignate as destination page, and mark it dirty.	      // It will eventually be flushed, completing the copy.	      buffer[selected].page = reqOffset;	      buffer[selected].clean = FALSE;	      post taskSuccess();	    }	  break;	case R_SYNC: case R_SYNCALL:	  if (buffer[selected].clean && buffer[selected].unchecked)	    {	      checkBuffer(selected);	      return;	    }	  /* fall through */	case R_FLUSH: case R_FLUSHALL:	  if (!buffer[selected].clean)	    flushBuffer();	  else if (request == R_FLUSH || request == R_SYNC)	    post taskSuccess();	  else	    {	      // Check for more dirty pages	      uint8_t oreq = request;	      request = IDLE;	      syncOrFlushAll(oreq);	    }	  break;	case R_READ:	  if (buffer[selected].busy)	    call HplAt45db.waitIdle();	  else	    call HplAt45db.readBuffer(OP(AT45_C_READ_BUFFER), reqOffset,				      reqBuf, reqBytes);	  break;	case R_READCRC:	  if (buffer[selected].busy)	    call HplAt45db.waitIdle();	  else	    /* Hack: baseCrc was stored in reqBuf */	    call HplAt45db.crc(OP(AT45_C_READ_BUFFER), 0, reqOffset, reqBytes,			       (uint16_t)reqBuf);	  break;	case R_WRITE:	  if (buffer[selected].busy)	    call HplAt45db.waitIdle();	  else	    call HplAt45db.write(OP(AT45_C_WRITE_BUFFER), 0, reqOffset,				 reqBuf, reqBytes);	  break;	}    else if (!buffer[selected].clean)      flushBuffer();    else if (buffer[selected].unchecked)      checkBuffer(selected);    else      {	// just get the new page (except for erase)	if (request == R_ERASE)	  {	    buffer[selected].page = reqPage;	    handleRWRequest();	  }	else if (flashBusy)	  call HplAt45db.waitIdle();	else	  call HplAt45db.fill(OP(AT45_C_FILL_BUFFER), reqPage);      }  }  void requestDone(error_t result, uint16_t computedCrc, uint8_t newState) {    uint8_t orequest = request;    request = newState;    switch (orequest)      {      case R_READ: signal At45db.readDone(result); break;      case R_READCRC: signal At45db.computeCrcDone(result, computedCrc); break;      case R_WRITE: signal At45db.writeDone(result); break;      case R_SYNC: case R_SYNCALL: signal At45db.syncDone(result); break;      case R_FLUSH: case R_FLUSHALL: signal At45db.flushDone(result); break;      case R_ERASE: signal At45db.eraseDone(result); break;      case R_COPY: signal At45db.copyPageDone(result); break;      }  }  void newRequest(uint8_t req, at45page_t page, at45pageoffset_t offset,		  void * COUNT_NOK(n) reqdata, at45pageoffset_t n) {    request = req;    reqBuf = reqdata;    reqBytes = n;    reqPage = page;    reqOffset = offset;    if (page == buffer[0].page)      selected = 0;    else if (page == buffer[1].page)      selected = 1;    else      selected = !selected; // LRU with 2 buffers...#ifdef CHECKARGS    if (page >= AT45_MAX_PAGES || offset >= AT45_PAGE_SIZE ||	n > AT45_PAGE_SIZE || offset + n > AT45_PAGE_SIZE)      post taskFail();    else#endif      handleRWRequest();  }  command void At45db.read(at45page_t page, at45pageoffset_t offset,				   void *reqdata, at45pageoffset_t n) {    newRequest(R_READ, page, offset, reqdata, n);  }  command void At45db.computeCrc(at45page_t page,					at45pageoffset_t offset,					at45pageoffset_t n,					uint16_t baseCrc) {    /* This is a hack (store crc in reqBuf), but it saves 2 bytes of RAM */    reqBuf = TCAST(uint8_t * COUNT(baseCrc), baseCrc);    newRequest(R_READCRC, page, offset, reqBuf, n);  }  command void At45db.write(at45page_t page, at45pageoffset_t offset,				    void *reqdata, at45pageoffset_t n) {    newRequest(R_WRITE, page, offset, reqdata, n);  }  command void At45db.erase(at45page_t page, uint8_t eraseKind) {    newRequest(R_ERASE, page, eraseKind, NULL, 0);  }  command void At45db.copyPage(at45page_t from, at45page_t to) {    /* Assumes at45pageoffset_t can hold an at45page_t. A little icky */    newRequest(R_COPY, from, to, NULL, 0);  }  void syncOrFlush(at45page_t page, uint8_t newReq) {    request = newReq;    if (buffer[0].page == page)      selected = 0;    else if (buffer[1].page == page)      selected = 1;    else      {	post taskSuccess();	return;      }    buffer[selected].unchecked = 0;    handleRWRequest();  }  command void At45db.sync(at45page_t page) {    syncOrFlush(page, R_SYNC);  }  command void At45db.flush(at45page_t page) {    syncOrFlush(page, R_FLUSH);  }  void syncOrFlushAll(uint8_t newReq) {    request = newReq;    if (!buffer[0].clean)      selected = 0;    else if (!buffer[1].clean)      selected = 1;    else      {	post taskSuccess();	return;      }    buffer[selected].unchecked = 0;    handleRWRequest();  }  command void At45db.syncAll() {    syncOrFlushAll(R_SYNCALL);  }  command void At45db.flushAll() {    syncOrFlushAll(R_FLUSHALL);  }}

⌨️ 快捷键说明

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