[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/rincon/apps/FlashBridge/media/AT45DB FlashBridgeC.nc, NONE, 1.1 FlashSettings.h, NONE, 1.1 FlashBridgeM.nc, NONE, 1.1 readme.txt, NONE, 1.1 Makefile, NONE, 1.1

dmm rincon at users.sourceforge.net
Tue Jul 18 09:25:26 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/rincon/apps/FlashBridge/media/AT45DB
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv13205/contrib/rincon/apps/FlashBridge/media/AT45DB

Added Files:
	FlashBridgeC.nc FlashSettings.h FlashBridgeM.nc readme.txt 
	Makefile 
Log Message:
Extracted the FlashBridge component and test app from Blackbook5

--- NEW FILE: FlashBridgeC.nc ---
/*
 * Copyright (c) 2004-2006 Rincon Research Corporation.  
 * All rights reserved.
 * 
 * Rincon Research will permit distribution and use by others subject to
 * the restrictions of a licensing agreement which contains (among other things)
 * the following restrictions:
 * 
 *  1. No credit will be taken for the Work of others.
 *  2. It will not be resold for a price in excess of reproduction and 
 *      distribution costs.
 *  3. Others are not restricted from copying it or using it except as 
 *      set forward in the licensing agreement.
 *  4. Commented source code of any modifications or additions will be 
 *      made available to Rincon Research on the same terms.
 *  5. This notice will remain intact and displayed prominently.
 * 
 * Copies of the complete licensing agreement may be obtained by contacting 
 * Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
 * 
 * There is no warranty with this product, either expressed or implied.  
 * Use at your own risk.  Rincon Research is not liable or responsible for 
 * damage or loss incurred or resulting from the use or misuse of this software.
 */

/**
 * Blackbook to Flash bridge implementation 
 * For the AT45DB
 * 
 * Components using this interface should connect 
 * to the parameterized interface unique("FlashBridge")
 * @author David Moss (dmm at rincon.com)
 */

includes FlashSettings;

configuration FlashBridgeC {
  provides {
    interface FlashBridge[uint8_t id];
    interface StdControl; 
  }
}

implementation {
  components FlashBridgeM, PageEEPROMC, StateC, TimerC;
  
  StdControl = FlashBridgeM;
  StdControl = PageEEPROMC;
  StdControl = StateC;
  StdControl = TimerC;
  
  FlashBridge = FlashBridgeM;
  
  FlashBridgeM.Timer -> TimerC.Timer[unique("Timer")];
  FlashBridgeM.State -> StateC.State[unique("State")];
  FlashBridgeM.PageEEPROM -> PageEEPROMC.PageEEPROM[unique("PageEEPROM")];
}


--- NEW FILE: FlashSettings.h ---
/*
 * Copyright (c) 2004-2006 Rincon Research Corporation.  
 * All rights reserved.
 * 
 * Rincon Research will permit distribution and use by others subject to
 * the restrictions of a licensing agreement which contains (among other things)
 * the following restrictions:
 * 
 *  1. No credit will be taken for the Work of others.
 *  2. It will not be resold for a price in excess of reproduction and 
 *      distribution costs.
 *  3. Others are not restricted from copying it or using it except as 
 *      set forward in the licensing agreement.
 *  4. Commented source code of any modifications or additions will be 
 *      made available to Rincon Research on the same terms.
 *  5. This notice will remain intact and displayed prominently.
 * 
 * Copies of the complete licensing agreement may be obtained by contacting 
 * Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
 * 
 * There is no warranty with this product, either expressed or implied.  
 * Use at your own risk.  Rincon Research is not liable or responsible for 
 * damage or loss incurred or resulting from the use or misuse of this software.
 */


/*
 * Flash Information 
 * Atmel AT45DB041B 4Mb Flash on Mica2/Mica2Dot/MicaZ
 * 2048 pages
 * 264 bytes/page
 * 8 pages/block, 1 block = 2112 bytes
 * Sector 0 = 8 pages, 2112 bytes (2k+64)
 * Sector 1 = 248 pages, 65472 bytes (62k+64)
 * Sector 2 = 256 pages, 67584 bytes (64k+1984)
 * Sector 3 = 512 pages, 135168 bytes (128k + 4k)
 * Sector 4 = 512 pages, 135168 bytes (128k + 4k)
 * Sector 5 = 512 pages, 135168 bytes (128k + 4k)
 *
 * Even though the granularity of the sectors changes,
 * All sectors in Blackbook will use the same size -
 * 0x10000 (64kB) sectors since we can erase at the page
 * level.
 *
 * Total of 4,325,376 bits (0.5 megabyte)
 */
enum {
  FLASH_FIRST_BLACKBOOK_SECTOR = 0,
  FLASH_LAST_BLACKBOOK_SECTOR = 7,
  
  FLASH_PAGE_LENGTH = 0x100, 
  FLASH_SECTOR_LENGTH = 0x10000,
  FLASH_SECTOR_SIZE_LOG2 = 16,
  FLASH_TOTAL_SECTORS = 8,
  FLASH_PAGES_PER_SECTOR = 0x100,
  FLASH_PAGE_SIZE_LOG2 = 8,
}; 

--- NEW FILE: FlashBridgeM.nc ---
/*
 * Copyright (c) 2004-2006 Rincon Research Corporation.  
 * All rights reserved.
 * 
 * Rincon Research will permit distribution and use by others subject to
 * the restrictions of a licensing agreement which contains (among other things)
 * the following restrictions:
 * 
 *  1. No credit will be taken for the Work of others.
 *  2. It will not be resold for a price in excess of reproduction and 
 *      distribution costs.
 *  3. Others are not restricted from copying it or using it except as 
 *      set forward in the licensing agreement.
 *  4. Commented source code of any modifications or additions will be 
 *      made available to Rincon Research on the same terms.
 *  5. This notice will remain intact and displayed prominently.
 * 
 * Copies of the complete licensing agreement may be obtained by contacting 
 * Rincon Research, 101 N. Wilmot, Suite 101, Tucson, AZ 85711.
 * 
 * There is no warranty with this product, either expressed or implied.  
 * Use at your own risk.  Rincon Research is not liable or responsible for 
 * damage or loss incurred or resulting from the use or misuse of this software.
 */

/**
 * FlashBridge to AT45DB interface
 * through the PageEEPROM component
 * 
 * We add a Timer delay to the start because
 * the radio uses the same SPI bus as the Flash on
 * some motes.  This allows the radio time to startup
 * and then the flash kicks in so Blackbook can boot up
 *
 * TODO's
 * The AT45DB flash bridge uses the PageEEPROM component
 * to access the flash. One problem we ran into was with
 * sync and flush - when data is written to the flash, later
 * on we'd come back and the data wouldn't be there. 
 * The code works correctly because debug output and telos motes
 * proved it.  But the flash write was unreliable. This is because
 * the data would get written to the internal RAM buffer on the
 * AT45DB, but that data wouldn't get programmed to main memory.
 * This happened especially when programming to one page on flash
 * and then programming to another page on flash - the next page's
 * data would be lost.
 *
 * To try to solve these problems, after every flash write, the
 * AT45DB flash bridge component sync()'s, flush()'s, and completes.
 * This shouldn't be necessary, and it also wastes energy.
 * The code could be simplified with some better AT45DB low-level interfaces 
 * - i.e. type in a flash address and get it, instead of calculating pages.
 * Another question to ask Atmel is why the flash pages need to be erased
 * before being re-written.  If the answer is "so that your data
 * won't get corrupted" then it doesn't apply to us - Blackbook
 * takes care of not corrupting existing data. That should
 * double the data throughput to flash.
 *
 * Overall, this interface to the AT45DB needs a lot of work, especially
 * in the low-level hardware interface implementations.  A complete
 * re-write with better matching to the FlashBridge interface and
 * more efficiency would make a good project for someone.  I'm sure
 * the throughput and erasing can be performed much faster than what
 * we're seeing now.
 *
 * @author David Moss (dmm at rincon.com)
 */

includes FlashSettings;
includes PageEEPROM;

module FlashBridgeM {
  provides {
    interface FlashBridge[uint8_t id];
    interface StdControl;
  }
  
  uses {
    interface Timer;
    interface State;
    interface PageEEPROM;
  }
}

implementation {

  /** The current address we're working at */
  uint32_t currentAddr;
  
  /** The current pointer to our buffer */
  void *currentBuf;
  
  /** The current length we're dealing with */
  uint32_t currentLen;
  
  /** The current currentClient we're working with */
  uint8_t currentClient;
  
  /** Total amount of bytes read or written */
  uint32_t currentTotal;
  
  /** Total current CRC */
  uint16_t currentCrc;
  
  /** Amount of data to transact */  
  uint16_t amount;

  enum {
    S_IDLE = 0,
    S_READ,
    S_WRITE,
    S_ERASE,
    S_FLUSH, 
    S_GETCRC,
  };
  
  /***************** Prototypes ***************/
  /** Convert the given address and length into PageEEPROM parameters */
  task void calculateParams();
  
  /** Erase a sector */
  task void erase();
  
  /** Ensure data written is stored on flash */
  task void flush();
  task void sync();
  
  /***************** StdControl Commands ****************/
  command result_t StdControl.init() {
    return SUCCESS;
  }
  
  command result_t StdControl.start() {
    // Call a delay Timer to allow compatibility with the CC2420 and the CC1000
    call Timer.start(TIMER_ONE_SHOT, 128);
    return SUCCESS;
  }
  
  command result_t StdControl.stop() {
    return SUCCESS;
  }
  
  /***************** FlashBridge Commands ****************/
    /** 
   * Read bytes from flash
   * @param addr - the address to read from
   * @param *buf - the buffer to read into
   * @param len - the amount to read
   * @return SUCCESS if the bytes will be read
   */
  command result_t FlashBridge.read[uint8_t id](uint32_t addr, void *buf, uint32_t len) {
    if(addr + len > FLASH_SECTOR_LENGTH * FLASH_TOTAL_SECTORS) {
      return FAIL;
    }
    
    if(call State.requestState(S_READ)) {
      currentClient = id;
      currentAddr = addr;
      currentBuf = buf;
      currentLen = len;
      currentTotal = 0;
      post calculateParams();
      
    } else {
      return FAIL;
    }
    
    return SUCCESS;
  }
  
  
  /** 
   * Write bytes to flash
   * @param addr - the address to write to
   * @param *buf - the buffer to write from
   * @param len - the amount to write
   * @return SUCCESS if the bytes will be written
   */
  command result_t FlashBridge.write[uint8_t id](uint32_t addr, void *buf, uint32_t len) {
    if(addr + len  > FLASH_SECTOR_LENGTH * FLASH_TOTAL_SECTORS) {
      return FAIL;
    }
    
    if(call State.requestState(S_WRITE)) {
      currentClient = id;
      currentAddr = addr;
      currentBuf = buf;
      currentLen = len;
      currentTotal = 0;
      post calculateParams();
      
    } else {
      return FAIL;
    }
    
    return SUCCESS;
  }
  
  
  /**
   * Erase a sector in flash
   * Blackbook only erases in sector granularities, not pages.
   * Sector 0 should be the first sector existing at FS_START_ADDRESS
   * defined in FlashSettings.h
   * @param sector - the sector id to erase
   * @return SUCCESS if the sector will be erased
   */
  command result_t FlashBridge.erase[uint8_t id](uint16_t sector) {
    if(sector > FLASH_TOTAL_SECTORS - 1) {
      return FAIL;
    }
    
    if(call State.requestState(S_ERASE)) {
      currentClient = id;
      currentAddr = sector * FLASH_SECTOR_LENGTH;
      currentLen = FLASH_SECTOR_LENGTH;
      currentTotal = 0;
      post erase();
      
    } else {
      return FAIL;
    }
    
    return SUCCESS;
  }
  
  
  /**
   * Ensure the data written is stored to flash.
   * @return SUCCESS if the flash will be flushed
   */
  command result_t FlashBridge.flush[uint8_t id]() {
    if(call State.requestState(S_FLUSH)) {
      currentClient = id;
      post flush();
    
    } else {
      return FAIL;
    }
    
    return SUCCESS;
  }
  
  
  /**
   * Obtain the CRC of a chunk of data sitting on flash.
   * @param addr - the address to start the CRC computation
   * @param len - the amount of data to obtain the CRC for
   * @return SUCCESS if the CRC will be computed.
   */
  command result_t FlashBridge.crc[uint8_t id](uint32_t addr, uint32_t len) {
    if(addr + len  > FLASH_SECTOR_LENGTH * FLASH_TOTAL_SECTORS) {
      return FAIL;
    }
    
    if(call State.requestState(S_GETCRC)) {
      currentClient = id;
      currentAddr = addr;
      currentLen = len;
      currentTotal = 0;
      currentCrc = 0;
      post calculateParams();
      
    } else {
      return FAIL;
    }
    
    return SUCCESS;
  }
  
  
  /***************** PageEEPROM Events ****************/
  event result_t PageEEPROM.writeDone(result_t result) {
    if(call State.getState() == S_WRITE) {
      currentTotal += amount;
      post flush();
    }
    return SUCCESS; 
  }
  
  event result_t PageEEPROM.readDone(result_t result) {
    if(call State.getState() == S_READ) {
      currentTotal += amount;
      post calculateParams();
    }
    return SUCCESS; 
  }
  
  event result_t PageEEPROM.eraseDone(result_t result) {
    if(call State.getState() == S_ERASE) {
      post erase();
    }     
    return SUCCESS;  
  }
  
    
  event result_t PageEEPROM.flushDone(result_t result) {
    post sync();
    return SUCCESS; 
  }
  
  event result_t PageEEPROM.syncDone(result_t result) {
    if(call State.getState() == S_FLUSH) {
      call State.toIdle();
      signal FlashBridge.flushDone[currentClient](result);

    } else if(call State.getState() == S_ERASE) {
      call State.toIdle();
      signal FlashBridge.eraseDone[currentClient]((currentAddr >> FLASH_SECTOR_SIZE_LOG2), SUCCESS);
      
    } else if(call State.getState() == S_WRITE) {
      post calculateParams();
    }
    
    
    return SUCCESS; 
  }
  
  event result_t PageEEPROM.computeCrcDone(result_t result, uint16_t pageCrc) {
    if(call State.getState() == S_GETCRC) {
      currentTotal += amount;
      currentCrc = pageCrc;
      post calculateParams();
    }
    return SUCCESS;
  }
  
  
  /***************** Timer Events ****************/
  event result_t Timer.fired() {
    int i; 
    for(i = 0; i < uniqueCount("FlashBridge"); i++) { 
      signal FlashBridge.ready[i](SUCCESS);
    }
    return SUCCESS;
  }
  
  
  
  /***************** Tasks ****************/
  /**
   * Calculate the PageEEPROM parameters need to read or write 
   * to some address and length
   */
  task void calculateParams() {
    uint16_t offset;
    uint16_t startPage = ((currentAddr + currentTotal) >> FLASH_PAGE_SIZE_LOG2);

    if(currentTotal < currentLen) {
      // More data exists
      offset = (currentAddr + currentTotal) & 0xFF;
      if(startPage == ((currentAddr + currentLen) >> FLASH_PAGE_SIZE_LOG2)) {
        amount = currentLen - currentTotal;
      } else {
        amount = FLASH_PAGE_LENGTH - offset;
      }

      if(call State.getState() == S_READ) {
        if(!call PageEEPROM.read(startPage, offset, currentBuf + currentTotal, amount)) {
          post calculateParams();
          return;
        }
    
      } else if(call State.getState() == S_WRITE) {
        if(!call PageEEPROM.write(startPage, offset, currentBuf + currentTotal, amount)) {
          post calculateParams();
          return;
        }
        
      } else if(call State.getState() == S_GETCRC) {
        if(!call PageEEPROM.computeCrcContinue(startPage, offset, amount, currentCrc)) {
          post calculateParams();
          return;
        }
      }
    
    } else {
      // No more data exists
      if(call State.getState() == S_READ) {
        call State.toIdle();
        signal FlashBridge.readDone[currentClient](currentAddr, currentBuf, currentTotal, SUCCESS);
      
      } else if(call State.getState() == S_WRITE) {
        call State.toIdle();
        signal FlashBridge.writeDone[currentClient](currentAddr, currentBuf, currentTotal, SUCCESS);
      
      } else if(call State.getState() == S_GETCRC) {
        call State.toIdle();
        signal FlashBridge.crcDone[currentClient](currentCrc, currentAddr, currentLen, SUCCESS);
      }
    }
  }
  
  
  /**
   * Erase a given sector of pages starting at the currentAddr
   */
  task void erase() {
    if(currentTotal < FLASH_SECTOR_LENGTH) {
      // More pages to erase
      // TODO this should reliably erase from the END of the sector 
      //   to the BEGINNING of the sector to maintain fault tolerance.
      
      if(!call PageEEPROM.erase((currentAddr + currentTotal) >> FLASH_PAGE_SIZE_LOG2, TOS_EEPROM_ERASE)) {
        post erase();
      
      } else {
        currentTotal += FLASH_PAGE_LENGTH;
      }
      
    } else {
      // No more pages to erase
      post flush();
    }
  }
  
  
  /**
   * Ensure the data written is stored to flash
   * TODO not sure what the difference is between sync and flush
   * here, but we'll call them both anyway.
   */
  task void flush() {
    if(!call PageEEPROM.flushAll()) {
      post flush();
    }
  }
  
  task void sync() {
    if(!call PageEEPROM.syncAll()) {
      post sync();
    }
  }
  
  
  /***************** Defaults ****************/
  default event void FlashBridge.readDone[uint8_t id](uint32_t addr, void *buf, uint32_t len, result_t result) {
  }
  
  default event void FlashBridge.writeDone[uint8_t id](uint32_t addr, void *buf, uint32_t len, result_t result) {
  }
  
  default event void FlashBridge.eraseDone[uint8_t id](uint16_t sector, result_t result) {
  }
  
  default event void FlashBridge.flushDone[uint8_t id](result_t result) {
  }
  
  default event void FlashBridge.crcDone[uint8_t id](uint16_t calculatedCrc, uint32_t addr, uint32_t len, result_t result) {
  }
  
  default event void FlashBridge.ready[uint8_t id](result_t result) {
  }
  

}




--- NEW FILE: readme.txt ---
Compiling and installing the application in this directory
will format the AT45DB flash - erasing every sector allocated
to Blackbook on it.

So be careful.

@author David Moss (dmm at rincon.com)


--- NEW FILE: Makefile ---
COMPONENT=../Format/BlackbookFormatC
CFLAGS += -I../Format -I../../interfaces
CFLAGS += -I../../../../tos/lib/State
include $(MAKERULES)



More information about the Tinyos-contrib-commits mailing list