[Tinyos-2-commits] CVS: tinyos-2.x/doc/txt tep103.txt, 1.1.2.9, 1.1.2.10

David Gay idgay at users.sourceforge.net
Tue Jun 13 17:08:52 PDT 2006


Update of /cvsroot/tinyos/tinyos-2.x/doc/txt
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv3381/txt

Modified Files:
      Tag: tinyos-2_0_devel-BRANCH
	tep103.txt 
Log Message:
major storage tep rewrite


Index: tep103.txt
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/doc/txt/Attic/tep103.txt,v
retrieving revision 1.1.2.9
retrieving revision 1.1.2.10
diff -C2 -d -r1.1.2.9 -r1.1.2.10
*** tep103.txt	9 Jun 2006 21:55:00 -0000	1.1.2.9
--- tep103.txt	14 Jun 2006 00:08:49 -0000	1.1.2.10
***************
*** 26,49 ****
  ====================================================================
  
! This memo documents a set of hardware-independent, non-volatile
! storage interfaces for TinyOS 2.x, and the HPL and HAL layers for
! various flash chips.
! 
  
  1. Introduction
  ====================================================================
  
! There are three different flash chip families under use or
! consideration for TinyOS platforms: the Atmel AT45DB family (Mica
! family, Telos rev. A), the ST M25P family (Telos rev. B, eyes) and the
! Intel Strataflash (Intel Mote2).  All three are "NOR" flash chips, but
! the AT45DB has fairly different characteristics (see below). There
! also "NAND" flash chips which have rather different tradeoffs from NOR
! flash. Compact flash/etc cards use NAND flash but present a disk-like
! block interface.
  
! A common restriction of flash technology is that each bit can only be
! written once between erases. The table below summarizes the
! differences between the various flash technologies::
  
  
--- 26,48 ----
  ====================================================================
  
! This memo documents a set of hardware-independent, non-volatile storage
! interfaces for TinyOS 2.x, and some principles for the HPL and HAL layers
! for various flash chips.
  
  1. Introduction
  ====================================================================
  
! Flash chips are a form of EEPROM (electrically-eraseable, programmable
! read-only memory), distinguished by a fast erase capability. However,
! erases can only be done in large units (from 256B to 128kB depending on the
! flash chip). Erases are the only way to switch bits from 0 to 1, the
! programming operation can only switch 1's to 0's. Additionally, some
! chips requires that programming only happen once between each erase,
! or that it be performed in relatively large units (e.g., 256B). 
  
! In the table below, we summarise these differences by categorising
! flash chips by their underlying technology (NOR vs NAND). We also
! include a column for Atmel's AT45DB flash chip family, as it has
! significantly different tradeoffs than other flash chips: ::
  
  
***************
*** 60,63 ****
--- 59,63 ----
    Erase cycles :  10^4 - 10^5         10^4 **        10^5 - 10^7
    Intended use :  Code storage        Data storage   Data storage
+   Energy/byte  :  1uJ                 1uJ            .01uJ
  
    *  Intel Mote2 NOR flash is memory mapped (reads are very fast and can
***************
*** 66,206 ****
       must be written every 10^4 writes within that sector
  
! From the power consumption for erasing and writing, we can derive an
! energy cost/byte written (for NAND flash, taken from a Samsung
! datasheet):
! 
!   Energy/byte:	  1uJ                 1uJ            .01uJ
! 
! Energy/byte for reads appears to depend mostly on how long the read
! takes (the power consumptions are comparable), i.e., on the efficiency
! of the bus + processor.
! 
! 2. Non-Volatile Storage Abstraction in TinyOS 2.x 
! ===================================================================
  
! The very significant differences between the flash chips used in TinyOS,
! and lack of RAM to hide these differences, preclude common, low-level HIL
! interfaces such as a disk-like block interface. Instead, we propose that
! the HIL interfaces correspond to high-level storage services useful for
! sensor network applications. We have identified three storage abstractions:
! large objects, small objects, and logs. We envision separate implementations
! of these abstractions for each class of storage chip; these implementations
! will be found in the tos/chips/CHIPNAME hierarchy.
  
! Rather than provide a general-purpose file system with variable-sized
! files, we assume the flash is divided into fixed-size volumes, with
! each volume dedicated to holding a single instance of one of the
! abstractions (a large object, a small object or a log). We believe this
! restrictive approach is practical in the single-application model of
! TinyOS.
  
! 2.1 Large objects:
! ------------------------------------------------------------------
  
! A large object ranges from a few kilobytes upwards. A large object
! must be erased before use. Each byte in a large object can only
! written once after each erase. A large object must be committed
! to ensure it survives a reboot or crash. After a commit, no more
! writes may be performed.
  
!   - Size: large
!   - Reads: random
!   - Writes: random (each byte written at most once)
!   - Failure model: no fault tolerance (crash before commit leads to
!     object loss)
!   - Other: a commit operation terminates writes, a validate operation
!     checks the object.
  
! Examples: program storage, message buffering in delay-tolerant-networking
  
! 2.2 Large sequential objects
! ------------------------------------------------------------------
!        
! Some applications (e.g., low-rate data collection) can use a large
! sequential object to save their results in a reliable fashion. A large
! sequential object can be circular.
  
!   - Size: large
!   - Reads: from memorized write points or beginning
!   - Writes: sequential, object is linear or circular
!   - Failure model: writes are atomic, failure during/between writes does
!     not lead to whole object loss, but may lead to loss of some entries
!     (but see sync)
!     Note: failure during write may lead to (minor) capacity reduction
!   - Other: sync: guarantees already written data will not be lost to
!     (crash-style) failure
  
! Example: logs.
  
! 2.3 Small objects:
! ------------------------------------------------------------------
  
- A small object may be only a few hundred bytes. Small objects support
- random reads and writes and simple transactional behaviour (each read is a
- separate transaction, all writes up to a commit form a single transaction).
  
!   - Size: small
!   - Reads: random, read data as of last commit
!   - Writes: random, rewrite ok
!   - Failure model: failure during/between writes does not lead to object 
!     loss (at reboot, object will contain state as of the most recent
!     successful commit)
!   - Other: commit operation ensures all writes since last commit become
!     permanent
  
! Example: configuration data.
  
! 3. HPL/HAL/HIL Architecture
! ====================================================================
  
- The proposed architecture aligns with the three-layer Hardware
- Abstraction Architecture (HAA). This document briefly presents
- the components and interfaces; for full details see the nesdoc
- comments in the referenced components and interfaces.
  
! 3.1 Hardware Presentation Layer (HPL)
  --------------------------------------------------------------------
  
  The flash HPL has a chip-dependent, system-independent interface. The
  implementation of this HPL is system-dependent. The flash HPL SHOULD be
! stateless. In many cases, families of flash chips can share a common HPL
! interface.
! 
! Some examples:
! 
! - The Atmel AT45DB family HPL is: ::
! 
!     configuration HplAt45dbC {
!       provides interface HplAt45db;
!     } ...
! 
!   The ``HplAt45db`` interface has flash->buffer, buffer->flash, compare
!   buffer to flash, erase page, read, compute CRC, and write operations.  A
!   generic, system-independent implementation of the HPL
!   (``HplAt45dbByteC``) is included allowing platforms to just provide SPI
!   and chip selection interfaces.
! 
!   Different members of the AT45DB family are supported by specifying a few
!   constants (number of pages, page size).
! 
! - The M25P family HPL is: ::
! 
!     configuration Stm25pSpiC {
!       provides interface Init;
!       provides interface Resource;
!       provides interface Stm25pSpi;
!     }
! 
!    The ``Stm25pSpi`` interface has read, write, compute CRC, sector erase
!    and block erase operations. The implementation of this HPL is
!    system-independent, built over a few system-dependent components
!    providing SPI and chip selection interfaces.
  
! Note that these two examples have different resource management policies:
! the AT45DB encapsulates resource acquisition and release within each
! operation, while the M25P family requires that HPL users acquire and
! release the resource itself.
  
! 3.2 Hardware Adaptation Layer (HAL)
  --------------------------------------------------------------------
  
--- 66,175 ----
       must be written every 10^4 writes within that sector
  
! The energy/byte is the per-byte cost of erasing plus programming. It is
! derived from the timing and power consumption of erase and write operations
! (for NOR flash, values are for the STMicroelectronics M25P family, for NAND
! flash, values are from a Samsung datasheet). Energy/byte for reads appears
! to depend mostly on how long the read takes (the power consumptions are
! comparable), i.e., on the efficiency of the bus + processor.
  
! Early motes used with TinyOS all used a flash chip from the AT45DB
! family. In TinyOS 1.x, this chip could be accessed through three
! different components:
  
! - Using a low-level interface (``PageEEPROMC``) which gave direct
!   access to per-page read, write and erase operations.
! - Using a high-level memory-like interface (``ByteEEPROMC``) with
!   read, write and logging operations.
! - Using a simple file system (``Matchbox``) with sequential-only
!   files.
  
! Some more recent motes use different flash chips: the ST M25P family (Telos
! rev. B, eyes) and the Intel Strataflash (Intel Mote2). None of the
! three components listed above are supported on these chips:
  
! - The ``PageEEPROMC`` component is (and was intended to be) AT45DB-specific
! - ``ByteEEPROMC`` allows arbitrary rewrites of sections of the flash.
!   This is not readily implementable on a flash chip with large erase units.
! - The ``Matchbox`` implementation was AT45DB-specific. It was not
!   reimplemented for these other chips, in part because it does not 
!   support some applications (e.g., network reprogramming) very well.
!   
! One approach to hiding the differences between different flash chips is to
! provide a disk-like, block interface (with, e.g., 512B blocks). This is the
! approach taken by compact flash cards. However, in the context of TinyOS,
! this approach has several drawbacks:
  
! - This approach is protected by patents, making it difficult to provide
!   in a free, open-source operating system.
! - To support arbitrary block writes where blocks are smaller than the
!   erase unit, and to deal with the limited number of erase cycles/block
!   requires remapping blocks. We believe that maintaining this remapping 
!   table is too expensive on many mote-class devices.
  
! Another approach to supporting multiple flash chips is to build a
! file system (like Matchbox) which can be implemented for multiple
! flash chips. However, TinyOS is currently targeted at running a 
! single application, and many applications know their storage needs
! in advance: for instance, a little space for configuration data, and
! everything else for a log of all sampled data. In such cases, the
! flexibility offered by a filing system (e.g., arbitrary numbers of
! files) is overkill, and may come at the expense of implementation
! and runtime complexity.
  
! Instead, in TinyOS 2.x, we divide flash chips into separate volumes (with
! sizes fixed at compile-time). Each volume is dedicated to a high-level
! storage services useful for sensor network applications. We have so far
! identified three such services: large objects written in a single session,
! small objects with arbitrary reads and writes, and logs. This approach
! has two advantages:
  
! - Each service is relatively easy to implement on a new flash chip, and
!   has relatively little overhead.
! - The problem of dealing with the limited number of erase cycles/block
!   is simplified: it is unlikely that user applications will need to
!   rewrite the same small object 100'000 times, or cycle 100'000 times
!   through their log. Thus the services can mostly ignore the need for
!   "wear levelling" (ensuring that each block of the flash is erased
!   the same number of time, to maximise flash chip lifetime).
  
! New services (including a filing system...) can easily be added to this
! framework.
  
! The rest of this TEP covers some principles for the organisation of
! flash chips (Section 2), then describes the flash volumes and
! storage services in detail (Section 3).
  
  
! 2. HPL/HAL/HIL Architecture
! ====================================================================
  
! The flash chip architecture aligns with the three-layer Hardware
! Abstraction Architecture (HAA), with each chip providing a presentation
! layer (HPL, Section 2.1), adaptation layer (HAL, Section 2.2) and
! platform-independent interface layer (the storage services described in
! Section 3). The implementation of these layers SHOULD be found in the
! ``tos/chips/CHIPNAME`` directory. If a flash chip is part of a larger
! family with a similar interface, the HAA SHOULD support all family members
! by relying, e.g., on platform-provided configuration information.
  
! Appendix A shows example HPL and HAL specifications for the AT45DB
! and ST M25P chip families.
  
  
! 2.1 Hardware Presentation Layer (HPL)
  --------------------------------------------------------------------
  
  The flash HPL has a chip-dependent, system-independent interface. The
  implementation of this HPL is system-dependent. The flash HPL SHOULD be
! stateless. 
  
! The flash chip's HPL SHOULD connect to platform-specific components
! providing access to the flash chip on a particular mote; these components
! SHOULD be placed in the ``tos/platforms/PLATFORM/chips/CHIPNAME``
! directory. If the flash chip implementation supports a family of 
! flash chips, this directory MAY also contain a file describing the
! particular flash chip found on the platform.
  
! 2.2 Hardware Adaptation Layer (HAL)
  --------------------------------------------------------------------
  
***************
*** 208,496 ****
  implementation. Flash families with a common HPL SHOULD have a common
  HAL. Flash HAL's SHOULD expose a ``Resource`` interface and automatically
! power-manage the underlying flash chip. Finally, the flash HAL SHOULD
  provide a way to access the volume information specified by the
! programmer (see Section 3.3a). This allows users to build new flash
! abstractions that interact cleanly with the rest of the flash system.
! Next, we show a couple of flash HAL's.
! 
! The AT45DB HAL has two components, one for chip access and the other
! providing volume information: ::
! 
!   component At45dbC
!   {
!     provides {
!       interface At45db;
!       interface Resource[uint8_t client];
!       interface ResourceController;
!       interface ArbiterInfo;
!     }
!   } ...
! 
!   configuration At45dbStorageManagerC {
!     provides interface At45dbVolume[volume_id_t volid];
!   } ...
! 
! 
! Note that the AT45DB HAL resource management is independent of the
! underlying HPL's power management. The motivation for this is that
! individual flash operations may take a long time, so it may be desirable to
! release the flash's bus during long-running operations. The ``At45db``
! and ``At45dbVolume`` interfaces are: ::
! 
!    interface At45db {
!      command void write(at45page_t page, at45pageoffset_t offset,
!                         void *PASS data, at45pageoffset_t n);
!      event void writeDone(error_t error);
  
-      command void erase(at45page_t page, uint8_t eraseKind);
-      event void eraseDone(error_t error);
  
!      command void copyPage(at45page_t from, at45page_t to);
!      event void copyPageDone(error_t error);
! 
!      command void sync(at45page_t page);
!      command void syncAll();
  
!      event void syncDone(error_t error);
  
!      command void flush(at45page_t page);
!      command void flushAll();
!      event void flushDone(error_t error);
  
!      command void read(at45page_t page, at45pageoffset_t offset,
!                        void *PASS data, at45pageoffset_t n);
!      event void readDone(error_t error);
  
!      command void computeCrc(at45page_t page, at45pageoffset_t offset,
!                              at45pageoffset_t n, uint16_t baseCrc);
!      event void computeCrcDone(error_t error, uint16_t crc);
!    }
  
!    interface At45dbVolume {
!      command at45page_t remap(at45page_t volumePage);
!      command at45page_t volumeSize();
!    }
  
! The STMicroelectronics M25P HAL is: ::
  
!   configuration Stm25pSectorC {
!     provides interface Resource as ClientResource[storage_volume_t volume];
!     provides interface Stm25pSector as Sector[storage_volume_t volume];
!     provides interface Stm25pVolume as Volume[storage_volume_t volume];
!   }
  
! and the ``Stm25pSector`` and ``Stm25pVolume`` interfaces are: ::
  
!    interface Stm25pSector {
!      command stm25p_addr_t getPhysicalAddress( stm25p_addr_t addr );
!      command uint8_t getNumSectors();
  
!      command error_t read(stm25p_addr_t addr, void* buf, stm25p_addr_t len);
!      event   error_t readDone(stm25p_addr_t addr, void* buf, stm25p_addr_t len,
!                               error_t error);
  
-      command error_t write(stm25p_addr_t addr, void* buf, 
-                            stm25p_addr_t len);
-      event   error_t writeDone(stm25p_addr_t addr, void* buf, 
-                                stm25p_addr_t len, error_t error);
  
!      command error_t erase(uint8_t sector, uint8_t num_sectors);
!      event   error_t eraseDone(uint8_t sector, uint8_t num_sectors, 
!                                error_t error);
  
!      command error_t computeCrc(uint16_t crc, stm25p_addr_t addr, 
!                                 stm25p_len_t len );
!      event void computeCrcDone(stm25p_addr_t addr, stm25p_len_t len, 
!                                uint16_t crc, error_t error);
!    }
  
!    interface Stm25pVolume {
!      async event volume_id_t getVolumeId();
!    }
  
! Note that the M25P HAL integrates volume management and chip access
! within the ``Stm25pSector`` interface.
  
! 3.3 Hardware Interface Layer (HIL)
! --------------------------------------------------------------------
  
! The HIL implementations are system-independent, but chip (family)
! dependent. They implement the three storage abstractions and
! volume structure discussed in Section 2.
  
! a. Volumes
  
!    The division of the flash chip into fixed-size volumes is specified by
!    an XML file that is placed in the application's directory (where one
!    types 'make'). The xml file specifies the allocation as follows: ::
  
!      <volume_table>
!        <volume name="DELUGE0" size="65536" />
!        <volume name="CONFIGLOG" size="65536" />
!        <volume name="DATALOG" size="131072" />
!        <volume name="GOLDENIMAGE" size="65536" base="983040" />
!      </volume_table>
  
!    The name and size parameters are required, while base is
!    optional. The name is a string containing one or more characters in
!    [a-zA-Z0-9\_], while size and base are in bytes. Each storage chip
!    MUST provide a compile-time tool that translates the allocation
!    specification to chip-specific nesC code. There is no constraint on
!    how this is done or what code is produced, except that the
!    specification to physical allocation MUST be one-to-one (i.e. a
!    given specification should always have the same resulting physical
!    allocation on a given chip) and the result MUST be placed in the
!    build directory. When not specified, the tool may give any suitable
!    physical location to a volume. If there is any reason that the
!    physical allocation cannot be satisfied, an error should be given
!    at compile time.
  
!    The compile-time tool MUST prepend 'VOLUME\_' to each volume name in
!    the xml file and '#define' each resulting name to map to a unique
!    integer. 
  
!    The storage abstractions are accessed by instantiating generic
!    components that take the volume macro as argument: ::
  
!      components new BlockStorageC(VOLUME_DELUGE0);
  
!    If the named volume is not in the specification, nesC will give a
!    compile-time error since the symbol will be undefined.
  
!    A volume MUST NOT be used with more than one storage abstraction
!    instance.
  
- b. Large object interface:
  
!   Large objects are accessed by instantiating a BlockStorageC component
!   which takes a volume id argument: ::
  
!     generic configuration BlockStorageC(volume_id_t volid) {
!       provides {
! 	interface BlockWrite;
! 	interface BlockRead;
!       }
!     } ...
  
!   The ``BlockRead`` and ``BlockWrite`` interfaces contain the following
!   operations: ::
  
!      interface BlockWrite {
!        command error_t write(storage_addr_t addr, void* buf, 
! 			     storage_len_t len);
!        event void writeDone(storage_addr_t addr, void* buf, 
! 			    storage_len_t len, error_t error);
  
!        command error_t erase();
!        event   void    eraseDone(error_t result);
  
!        command error_t commit();
! 	event  void    commitDone(error_t result);
!      }
  
!      interface BlockRead {
!        command error_t read(addr_t addr, void* dest, addr_t len);
!        event   void    readDone(storage_error_t result);
  
!        command error_t verify();
!        event   void    verifyDone(storage_error_t result);
  
!        command error_t computeCrc(storage_addr_t addr, storage_len_t len,
! 				  uint16_t baseCrc);
!        event   void    computeCrcDone(storage_addr_t addr, storage_len_t len, 
! 				      uint16_t crc, error_t error );
  
!        command storage_len_t getSize();
!      }
  
! c. Large sequential objects:
  
!   Large sequential objects are accessed by instantiating a LogStorageC
!   component which takes a volume id and a boolean argument: ::
  
!     generic configuration LogStorageC(volume_id_t volid, bool circular) {
!       provides {
! 	interface LogWrite;
! 	interface LogRead;
!       }
!     } ...
  
!   If the ``circular`` argument is TRUE, the log is circular; otherwise
!   it is linear.
  
!   The ``LogRead`` and ``LogWrite`` interfaces contain the following
!   operations: ::
  
!      interface LogWrite {
!        command error_t erase();
!        event   void    eraseDone(storage_error_t success);
  
!        command error_t append(void* buf, storage_len_t len);
!        event   void    appendDone(void* buf, storage_len_t len, error_t error);
  
!        command storage_cookie_t currentOffset();
  
-        command error_t sync();
-        event   void    syncDone(storage_error_t success);
-      }
  
-      interface LogRead {
-        command error_t read(void* buf, storage_len_t len);
-        event   void    readDone(void* buf, storage_len_t len, error_t error);
  
!        command storage_cookie_t currentOffset();
  
!        command error_t seek(storage_cookie_t cookie);
!        event   void    seekDone(error_t error);
  
!        command storage_len_t getSize();
!      }
  
! d. Small objects:
  
!   Small objects are accessed by instantiating a ConfigStorageC component
!   which takes a volume id argument: ::
  
!     generic configuration ConfigStorageC(volume_id_t volid) {
!       provides {
  	interface Mount;
  	interface ConfigStorage;
!       }
!     } ...
! 
!   A small object MUST be mounted (see the ``Mount`` interface) before 
!   the first use.
  
!   The ``Mount`` and ``ConfigStorage`` interfaces contain the following
!   operations: ::
  
!      interface Mount {
!        command error_t mount();
!        event void mountDone(error_t error);
!      }
  
!      interface ConfigStorage {
!        command error_t read(addr_t addr, void* dest, addr_t len);
!        event   void    readDone(storage_error_t result);
  
!        command error_t write(addr_t addr void* source, addr_t len);
!        event   void    writeDone(storage_error_t result);
  
!        command error_t commit();
!        event   void    commitDone(storage_error_t result);
  
!        command storage_len_t getSize();
  
!        command bool valid();
!      }
  
! 4. Implementation
! ====================================================================
  
! An AT45DB implementation can be found in tinyos-2.x/tos/chips/at45db.
  
! An STM25P implementation can be found in tinyos-2.x/tos/chips/stm25p.
!  
! 5. Authors' Addresses
  ====================================================================
  
--- 177,426 ----
  implementation. Flash families with a common HPL SHOULD have a common
  HAL. Flash HAL's SHOULD expose a ``Resource`` interface and automatically
! power-manage the underlying flash chip. Finally, the flash HAL MUST
  provide a way to access the volume information specified by the
! programmer (see Section 3). This allows users to build new flash
! services that interact cleanly with the rest of the flash system.
  
  
! 3. Non-Volatile Storage Services in TinyOS 2.x 
! ===================================================================
  
! The HIL implementations are system-independent, but chip (family)
! dependent. They implement the three storage services and
! volume structure discussed in the introduction.
  
! 3.1. Volumes
! -------------------------------------------------------------------
  
! The division of the flash chip into fixed-size volumes is specified by
! an XML file that is placed in the application's directory (where one
! types 'make'). The XML file specifies the allocation as follows: ::
  
!   <volume_table>
!     <volume name="DELUGE0" size="65536" />
!     <volume name="CONFIGLOG" size="65536" />
!     <volume name="DATALOG" size="131072" />
!     <volume name="GOLDENIMAGE" size="65536" base="983040" />
!   </volume_table>
  
! The name and size parameters are required, while base is optional. The name
! is a string containing one or more characters in [a-zA-Z0-9\_], while size
! and base are in bytes. Each storage chip MUST provide a compile-time tool
! that translates the allocation specification to chip-specific nesC
! code. There is no constraint on how this is done or what code is produced,
! except that the specification to physical allocation MUST be one-to-one
! (i.e. a given specification should always have the same resulting physical
! allocation on a given chip) and the result MUST be placed in the build
! directory. When not specified, the tool may give any suitable physical
! location to a volume. If there is any reason that the physical allocation
! cannot be satisfied, an error should be given at compile time. The tool
! SHOULD be named ``tos-storage-CHIPNAME`` and be distributed with the other
! tools supporting a platform.
  
! The compile-time tool MUST prepend 'VOLUME\_' to each volume name in
! the XML file and '#define' each resulting name to map to a unique
! integer. 
  
! The storage services are accessed by instantiating generic
! components that take the volume macro as argument: ::
  
!   components new BlockStorageC(VOLUME_DELUGE0);
  
! If the named volume is not in the specification, nesC will give a
! compile-time error since the symbol will be undefined.
  
! A volume MUST NOT be used with more than one storage service instance.
  
  
! 3.2 Large objects
! ------------------------------------------------------------------
  
! The motivating example for large objects is the transmission or long-term
! storage of large objects. For instance, programs in a network-reprogramming
! system, or large data-packets in a reliable data-transmission system. Such
! objects have two interesting characteristics: each byte in the object is
! written at most once, and a full object is written in a single "session"
! (i.e., without the mote rebooting).
  
! This leads to the definition of the ``BlockStorageC`` service for storing
! large objects:
  
! - A large object ranges from a few kilobytes upwards.
! - A large object must be erased before use.
! - A large object must be committed to ensure it survives a reboot or crash;
!   after a commit no more writes may be performed.
! - Random reads are allowed.
! - Random writes are allowed are allowed between erase and commit; data
!   cannot be overwritten.
  
! Large objects are accessed by instantiating a BlockStorageC component
! which takes a volume id argument: ::
  
!   generic configuration BlockStorageC(volume_id_t volid) {
!     provides {
! 	interface BlockWrite;
! 	interface BlockRead;
!     }
!   } ...
  
! The ``BlockRead`` and ``BlockWrite`` interfaces contain the following
! operations (all split-phase, except ``BlockRead.getSize``):
  
! - ``BlockWrite.erase``: erase the volume. After a reboot or a commit, a
!   volume must be erased before it can be written to.
  
! - ``BlockWrite.write``: write some bytes starting at a given offset. Each
!   byte can only be written once between an erase and the subsequent commit.
  
! - ``BlockWrite.commit``: commit all writes to a given volume. No writes can
!   be performed after a commit until a subsequent erase.
  
! - ``BlockRead.verify``: verify that the volume contains the results of a
!   successful commit.
  
! - ``BlockRead.read``: read some bytes starting at a given offset.
  
! - ``BlockRead.computeCrc``: compute the CRC of some bytes starting at a
!   given offset.
  
! - ``BlockRead.getSize``: return bytes available for large object storage in
!   volume.
  
! For full details on arguments, etc, see the comments in the interface
! definitions.
  
  
! 3.3 Logging
! ------------------------------------------------------------------
  
! Logging of results, events, etc is a common requirement in sensor
! networks. Such logging should be reliable (a mote crash should not
! lose data). It should also be easy to extract data from the log,
! either partially or fully. Some logs are *linear* (stop logging when
! the volume is full), others are *circular* (the oldest data is
! overwritten when the volume is full).
  
! The ``LogStorageC`` service supports these requirements.  The log is record
! based: each call to ``LogWrite.append`` (see below) creates a new
! record. On failure (crash or reboot), the log is guaranteed to only lose
! whole records from the end of the log. Additionally, once a circular log
! wraps around, calls to ``LogWrite.append`` only lose whole records from the
! beginning of the log. These guarantees mean that applications do not to
! have worry about incomplete or inconsistent log entries.
  
! Logs are accessed by instantiating a LogStorageC component which takes a
! volume id and a boolean argument: ::
  
!   generic configuration LogStorageC(volume_id_t volid, bool circular) {
!     provides {
! 	interface LogWrite;
! 	interface LogRead;
!     }
!   } ...
  
! If the ``circular`` argument is TRUE, the log is circular; otherwise
! it is linear.
  
! The ``LogRead`` and ``LogWrite`` interfaces contain the following
! operations (all split-phase except ``LogWrite.currentOffset``,
! ``LogRead.currentOffset`` and ``LogRead.getSize``):
  
! - ``LogWrite.erase``: erase the log.
  
! - ``LogWrite.append``: append some bytes to the log. In a circular log,
!   this may overwrite the current read position. In this case, the 
!   read position is implicitly advanced to the log's current beginning
!   (i.e., as if ``LogRead.seek`` had been called with ``SEEK_BEGINNING``).
  
!   Each append creates a separate record. Log implementations may have a
!   maximum record size; all implementations MUST support records of up
!   to 255 bytes.
  
! - ``LogWrite.sync``: guarantee that data written so far will not be lost to
!   a crash or reboot (it can still be overwritten when a circular log wraps
!   around). Using ``sync`` may waste some space in the log.
  
! - ``LogWrite.currentOffset``: return cookie representing current
!   append position (for use with ``LogRead.seek``).
  
! - ``LogRead.read``: read some bytes from the current read position in
!   the log and advance the read position.
  
! - ``LogRead.currentOffset``: return cookie representing current
!   read position (for use with ``LogRead.seek``).
  
! - ``LogRead.seek``: set the read position to a value returned by
!   a prior call to ``LogWrite.currentOffset`` or ``LogRead.currentOffset``,
!   or to the special ``SEEK_BEGINNING`` value. In a circular log, if
!   the specified position has been overwritten, behave as if 
!   ``SEEK_BEGINNING`` was requested.
  
!   ``SEEK_BEGINNING`` positions the read position at the beginning of
!   the oldest record still present in the log.
  
! - ``LogRead.getSize``: return an approximation of the log's capacity.
!   Uses of ``sync`` and other overhead may reduce this number.
  
! For full details on arguments, etc, see the comments in the interface
! definitions.
  
  
  
! 3.4 Small objects:
! ------------------------------------------------------------------
  
! Sensor network applications may need to store configuration data, e.g.,
! mote id, radio frequency, sample rates, etc. Such data is not large, but
! losing it may lead to a mote misbehaving or losing contact with the
! network.
  
! The ``ConfigStorageC`` service stores a single small object in a volume. It:
  
! - Assumes that configuration data is relatively small (a few
!   hundred bytes).
! - Allows random reads and writes.
! - Has simple transactional behaviour: each read is a separate transaction,
!   all writes up to a commit form a single transaction.
! - At reboot, the volume contains the data as of the most recent successful
!   commit.
  
! Small objects are accessed by instantiating a ConfigStorageC component
! which takes a volume id argument: ::
  
!   generic configuration ConfigStorageC(volume_id_t volid) {
!     provides {
  	interface Mount;
  	interface ConfigStorage;
!     }
!   } ...
  
! A small object MUST be mounted (via the ``Mount`` interface) before 
! the first use.
  
! The ``Mount`` and ``ConfigStorage`` interfaces contain the following
! operations (all split-phase except ``ConfigStorage.getSize`` and
! ``ConfigStorage.valid``):
  
! - ``Mount.mount``: mount the volume.
  
! - ``ConfigStorage.valid``: return TRUE if the volume contains a
!   valid small object.
  
! - ``ConfigStorage.read``: read some bytes starting at a given offset.
!   Fails if the small object is not valid. Note that this reads the
!   data as of the last successful commit.
  
! - ``ConfigStorage.write``: write some bytes to a given offset.
  
! - ``ConfigStorage.commit``: make the small object contents reflect all the
!   writes since the last commit.
  
! - ``ConfigStorage.getSize``: return the number of bytes that can be stored
!   in the small object.
  
! For full details on arguments, etc, see the comments in the interface
! definitions.
  
! 4. Authors' Addresses
  ====================================================================
  
***************
*** 511,512 ****
--- 441,543 ----
  | phone - +1 415 692 0828
  | email - jhui at archedrock.com
+ 
+ Appendix A. HAA implementations
+ ====================================================================
+ 
+ An AT45DB implementation can be found in tinyos-2.x/tos/chips/at45db.
+ 
+ An ST M25P implementation can be found in tinyos-2.x/tos/chips/stm25p.
+ 
+ A.1 AT45DB
+ ------------------------------------------------------------------
+  
+ The Atmel AT45DB family HPL is: ::
+ 
+   configuration HplAt45dbC {
+     provides interface HplAt45db;
+   } ...
+ 
+ The ``HplAt45db`` interface has flash->buffer, buffer->flash, compare
+ buffer to flash, erase page, read, compute CRC, and write operations.  Most
+ of these operations are asynchronous, i.e., their completion is signaled
+ before the flash chip has completed the operation. The HPL also includes 
+ operations to wait for asynchronous operations to complete.
+ 
+ A generic, system-independent implementation of the HPL
+ (``HplAt45dbByteC``) is included allowing platforms to just provide SPI and
+ chip selection interfaces.
+ 
+ Different members of the AT45DB family are supported by specifying a few
+ constants (number of pages, page size).
+ 
+ The AT45DB HAL has two components, one for chip access and the other
+ providing volume information: ::
+ 
+   component At45dbC
+   {
+     provides {
+       interface At45db;
+       interface Resource[uint8_t client];
+       interface ResourceController;
+       interface ArbiterInfo;
+     }
+   } ...
+ 
+   configuration At45dbStorageManagerC {
+     provides interface At45dbVolume[volume_id_t volid];
+   } ...
+ 
+ 
+ Note that the AT45DB HAL resource management is independent of the
+ underlying HPL's power management. The motivation for this is that
+ individual flash operations may take a long time, so it may be desirable to
+ release the flash's bus during long-running operations. 
+ 
+ The ``At45db`` interface abstracts from the low-level HPL operations by:
+ 
+ - using the flash's 2 RAM buffers as a cache to allow faster reads and
+   writes
+ - hiding the asynchronous nature of the HPL operations
+ - verifying that all writes were successful
+ 
+ It provides cached read, write and CRC computation, and page erase and
+ copy. It also includes flush and sync operations to manage the cache.
+ 
+ The ``At45dbVolume`` interface has operations to report volume size and
+ map volume-relative pages to absolute pages.
+ 
+ A.2 ST M25P
+ ------------------------------------------------------------------
+  
+ The ST M25P family HPL is: ::
+ 
+   configuration Stm25pSpiC {
+     provides interface Init;
+     provides interface Resource;
+     provides interface Stm25pSpi;
+   }
+ 
+ The ``Stm25pSpi`` interface has read, write, compute CRC, sector erase
+ and block erase operations. The implementation of this HPL is
+ system-independent, built over a few system-dependent components
+ providing SPI and chip selection interfaces.
+ 
+ Note that these two examples have different resource management policies:
+ the AT45DB encapsulates resource acquisition and release within each
+ operation, while the M25P family requires that HPL users acquire and
+ release the resource itself.
+ 
+ The ST M25P HAL is: ::
+ 
+   configuration Stm25pSectorC {
+     provides interface Resource as ClientResource[storage_volume_t volume];
+     provides interface Stm25pSector as Sector[storage_volume_t volume];
+     provides interface Stm25pVolume as Volume[storage_volume_t volume];
+   }
+ 
+ The ``Stm25pSector`` interface provides volume-relative operations similar
+ to those from the HPL interface: read, write, compute CRC and
+ erase. Additionally, it has operations to report volume size and remap
+ volume-relative addresses. Clients of the ST M25P HAL must implement the
+ ``getVolumeId`` event of the ``Stm25pVolume`` interface so that the HAL can
+ obtain the volume id of each of its clients.



More information about the Tinyos-2-commits mailing list