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

📄 stm25pconfigp.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
/* * Copyright (c) 2005-2006 Arch Rock Corporation * 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 Arch Rock Corporation 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 * ARCHED ROCK OR ITS 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 *//** * @author Jonathan Hui <jhui@archrock.com> * @version $Revision: 1.4 $ $Date: 2006/12/12 18:23:12 $ */#include <Stm25p.h>module Stm25pConfigP {    provides interface Mount[ uint8_t client ];  provides interface ConfigStorage as Config[ uint8_t client ];    uses interface Stm25pSector as Sector[ uint8_t client ];  uses interface Resource as ClientResource[ uint8_t client ];  uses interface Leds;  }implementation {    enum {    NUM_CLIENTS = uniqueCount( "Stm25p.Config" ),    CONFIG_SIZE = 2048,    CHUNK_SIZE_LOG2 = 8,    CHUNK_SIZE = 1 << CHUNK_SIZE_LOG2,    NUM_CHUNKS = CONFIG_SIZE / CHUNK_SIZE,    BUF_SIZE = 16,    INVALID_VERSION = -1,  };    enum {    S_IDLE,    S_MOUNT,    S_READ,    S_WRITE,    S_COMMIT,  };  typedef struct {    uint16_t addr;    void* buf;    uint16_t len;    uint8_t req;  } config_state_t;  config_state_t m_config_state[ NUM_CLIENTS ];  config_state_t m_req;    typedef struct {    uint16_t chunk_addr[ NUM_CHUNKS ];    uint16_t write_addr;    int16_t version;    uint8_t cur_sector;    bool valid : 1;  } config_info_t;  config_info_t m_config_info[ NUM_CLIENTS ];  typedef struct {    int32_t version;    uint16_t crc;  } config_metadata_t;  config_metadata_t m_metadata[ 2 ];    uint8_t m_buf[ BUF_SIZE ];  uint16_t m_chunk;  uint16_t m_offset;  enum {    S_COPY_BEFORE,    S_COPY_AFTER,  };  uint8_t m_meta_state;    error_t newRequest( uint8_t client );  void continueMount( uint8_t id );  void continueWrite( uint8_t id );  void continueCommit( uint8_t id );  void signalDone( uint8_t id, error_t error );    command error_t Mount.mount[ uint8_t client ]() {        if ( call Sector.getNumSectors[ client ]() != 2 )      return ESIZE;    m_req.req = S_MOUNT;    return newRequest( client );      }    command error_t Config.read[ uint8_t client ]( storage_addr_t addr, 						 void* buf, 						 storage_len_t len ) {        if ( !m_config_info[ client ].valid )      return FAIL;    m_req.req = S_READ;    m_req.addr = addr;    m_req.buf = buf;    m_req.len = len;    return newRequest( client );      }    command error_t Config.write[ uint8_t client ]( storage_addr_t addr,						  void* buf,						  storage_len_t len ) {        m_req.req = S_WRITE;    m_req.addr = addr;    m_req.buf = buf;    m_req.len = len;    return newRequest( client );          }    command error_t Config.commit[ uint8_t client ]() {        m_req.req = S_COMMIT;    return newRequest( client );          }    command storage_len_t Config.getSize[ uint8_t client ]() {    return CONFIG_SIZE;  }    command bool Config.valid[ uint8_t client ]() {    return m_config_info[ client ].valid;  }  error_t newRequest( uint8_t client ) {    if ( m_config_state[ client ].req != S_IDLE )      return EBUSY;        call ClientResource.request[ client ]();    m_config_state[ client ] = m_req;        return SUCCESS;      }    stm25p_addr_t calcAddr( uint8_t id, uint16_t addr, bool current ) {    stm25p_addr_t result = addr;    if ( !(current ^ m_config_info[ id ].cur_sector) )      result += STM25P_SECTOR_SIZE;    return result;  }    event void ClientResource.granted[ uint8_t id ]() {    m_chunk = 0;    m_offset = 0;        switch( m_config_state[ id ].req ) {    case S_IDLE:      break;    case S_MOUNT:      continueMount( id );      break;    case S_READ:      call Sector.read[ id ]( calcAddr( id, m_config_state[ id ].addr, TRUE ),			      m_config_state[ id ].buf,			      m_config_state[ id ].len );      break;    case S_WRITE:      m_meta_state = S_COPY_BEFORE;      m_chunk = m_config_state[ id ].addr >> CHUNK_SIZE_LOG2;      continueWrite( id );      break;    case S_COMMIT:      continueCommit( id );      break;    }      }  void continueMount( uint8_t id ) {    uint32_t addr = 0;    uint8_t cur_sector = 0;    int i;    switch( m_chunk ) {    case 1:      addr = STM25P_SECTOR_SIZE;      // fall through    case 0:      addr += STM25P_SECTOR_SIZE - sizeof( config_metadata_t );      call Sector.read[ id ]( addr, (uint8_t*)&m_metadata[ m_chunk ],                              sizeof( config_metadata_t ) );      break;    case 3:      addr = STM25P_SECTOR_SIZE;      // fall through    case 2:      call Sector.computeCrc[ id ]( 0, addr, CONFIG_SIZE );      break;    case 4:      if ( m_metadata[ 0 ].version != INVALID_VERSION ||	   m_metadata[ 1 ].version != INVALID_VERSION ) {	m_config_info[ id ].valid = TRUE;	if ( m_metadata[ 0 ].version == INVALID_VERSION )	  cur_sector = 1;	else if ( m_metadata[ 1 ].version == INVALID_VERSION )	  cur_sector = 0;	else	  cur_sector = (( m_metadata[1].version - m_metadata[0].version ) > 0);      }      m_config_info[ id ].cur_sector = cur_sector;      m_config_info[ id ].version = m_metadata[ cur_sector ].version;      call Sector.erase[ id ]( !cur_sector, 1 );      break;    case 5:      // initialize chunk addrs      for ( i = 0; i < NUM_CHUNKS; i++ )	m_config_info[ id ].chunk_addr[ i ] = i << CHUNK_SIZE_LOG2;      m_config_info[ id ].write_addr = CONFIG_SIZE;      signalDone( id, SUCCESS );      break;    }        m_chunk++;      }    event void Sector.readDone[ uint8_t id ]( stm25p_addr_t addr, uint8_t* buf, 					    stm25p_len_t len, error_t error ) {    switch ( m_config_state[ id ].req ) {    case S_IDLE:      break;    case S_MOUNT:      continueMount( id );      break;    case S_READ:      signalDone( id, error );      break;    case S_WRITE:      addr = calcAddr( id, m_config_info[ id ].write_addr, FALSE );      call Sector.write[ id ]( addr, buf, len );      break;    case S_COMMIT:      addr = ((uint16_t)m_chunk << CHUNK_SIZE_LOG2) + m_offset;      addr = calcAddr( id, addr, FALSE );      call Sector.write[ id ]( addr, buf, len );      break;    }  }    void continueWrite( uint8_t id ) {        config_state_t* state = &m_config_state[ id ];    config_info_t* info = &m_config_info[ id ];    uint8_t chunk = m_chunk + (m_offset / CHUNK_SIZE);    uint8_t offset = m_offset & 0xff;    uint32_t addr;    uint16_t len;        // compute addr for copy    addr = info->chunk_addr[ chunk ] + offset;    addr = calcAddr( id, addr, info->chunk_addr[ chunk ] < CONFIG_SIZE );        switch( m_meta_state ) {          case S_COPY_BEFORE:      // copy old data before      if ( offset < (uint8_t)state->addr ) {	len = (uint8_t)state->addr - offset;	if ( len > sizeof( m_buf ) )	  len = sizeof( m_buf );	call Sector.read[ id ]( addr, m_buf, len );      }      // write new data      else if ( offset == (uint8_t)state->addr ) {	addr = calcAddr( id, info->write_addr, FALSE );	len = state->len;	call Sector.write[ id ]( addr, state->buf, len );	m_meta_state = S_COPY_AFTER;      }      break;    case S_COPY_AFTER:      // copy old data after      if ( offset != 0 ) {	len = CHUNK_SIZE - offset;	if ( len > sizeof( m_buf ) )	  len = sizeof( m_buf );	call Sector.read[ id ]( addr, m_buf, len );      }      // all done, update chunk addrs      else {	info->write_addr -= m_offset;	for ( chunk = 0; chunk < m_offset / CHUNK_SIZE; chunk++ ) {	  info->chunk_addr[ m_chunk+chunk ] = info->write_addr;	  info->write_addr += CHUNK_SIZE;	}	signalDone( id, SUCCESS );      }      break;    }  }    event void Sector.writeDone[ uint8_t id ]( stm25p_addr_t addr, uint8_t* buf, 					     stm25p_len_t len, error_t error ){    switch( m_config_state[ id ].req ) {    case S_WRITE:      m_config_info[ id ].write_addr += len;      m_offset += len;      continueWrite( id );      break;    case S_COMMIT:      m_offset += len;      continueCommit( id );      break;          }  }    event void Sector.eraseDone[ uint8_t id ]( uint8_t sector,					     uint8_t num_sectors,					     error_t error ) {    if ( m_config_state[ id ].req == S_MOUNT )      continueMount( id );    else      continueCommit( id );  }    void continueCommit( uint8_t id ) {        config_info_t* info = &m_config_info[ id ];    uint32_t addr;    uint16_t len;    int i;        // check if time to copy next chunk    if ( m_offset >= CHUNK_SIZE ) {      m_chunk++;      m_offset = 0;    }        // copy data    if ( m_chunk < NUM_CHUNKS ) {      // compute addr for copy      addr = info->chunk_addr[ m_chunk ] + m_offset;      addr = calcAddr( id, addr, info->chunk_addr[ m_chunk ] < CONFIG_SIZE );      len = sizeof( m_buf );      call Sector.read[ id ]( addr, m_buf, len );    }    // compute crc    else if ( m_chunk == NUM_CHUNKS ) {      addr = calcAddr( 0, 0, FALSE );      call Sector.computeCrc[ id ]( 0, addr, CONFIG_SIZE );      m_chunk++;    }    // swap and erase other sector    else if ( m_chunk == NUM_CHUNKS + 1 ) {      info->cur_sector ^= 1;      info->write_addr = CONFIG_SIZE;      // initialize chunks      for ( i = 0; i < NUM_CHUNKS; i++ )	info->chunk_addr[ i ] = (uint16_t)i << CHUNK_SIZE_LOG2;      call Sector.erase[ id ]( !info->cur_sector, 1 );      m_chunk++;    }    // signal done    else {      m_config_info[ id ].valid = TRUE;      signalDone( id, SUCCESS );    }      }  event void Sector.computeCrcDone[ uint8_t id ]( stm25p_addr_t addr, 						  stm25p_len_t len,						  uint16_t crc,						  error_t error ) {        // mount    if ( m_config_state[ id ].req == S_MOUNT ) {      uint8_t chunk = addr >> STM25P_SECTOR_SIZE_LOG2;      if ( m_metadata[ chunk ].crc != crc )	m_metadata[ chunk ].version = INVALID_VERSION;      continueMount( id );    }    // commit    else {      bool cur_sector = m_config_info[ id ].cur_sector;      m_config_info[ id ].version++;      m_metadata[ !cur_sector ].version = m_config_info[ id ].version;      m_metadata[ !cur_sector ].crc = crc;      addr += STM25P_SECTOR_SIZE - sizeof( config_metadata_t );      call Sector.write[ id ]( addr, (uint8_t*)&m_metadata[ !cur_sector ],			       sizeof( config_metadata_t ) );    }      }  void signalDone( uint8_t id, error_t error ) {        uint8_t req = m_config_state[ id ].req;        call ClientResource.release[ id ]();    m_config_state[ id ].req = S_IDLE;        switch( req ) {    case S_MOUNT:      signal Mount.mountDone[ id ]( error );      break;    case S_READ:      signal Config.readDone[ id ]( m_config_state[ id ].addr,				    m_config_state[ id ].buf,				    m_config_state[ id ].len, error );      break;    case S_WRITE:      signal Config.writeDone[ id ]( m_config_state[ id ].addr,				     m_config_state[ id ].buf,				     m_config_state[ id ].len, error );      break;    case S_COMMIT:      signal Config.commitDone[ id ]( error );      break;    }      }    default event void Mount.mountDone[ uint8_t id ]( error_t error ) {}  default event void Config.readDone[ uint8_t id ]( storage_addr_t addr, void* buf, storage_len_t len, error_t error ) {}  default event void Config.writeDone[ uint8_t id ]( storage_addr_t addr, void* buf, storage_len_t len, error_t error ) {}  default event void Config.commitDone[ uint8_t id ]( error_t error ) {}    default command storage_addr_t Sector.getPhysicalAddress[ uint8_t id ]( storage_addr_t addr ) { return 0xffffffff; }  default command uint8_t Sector.getNumSectors[ uint8_t id ]() { return 0; }  default command error_t Sector.read[ uint8_t id ]( storage_addr_t addr, uint8_t* buf, storage_len_t len ) { return FAIL; }  default command error_t Sector.write[ uint8_t id ]( storage_addr_t addr, uint8_t* buf, storage_len_t len ) { return FAIL; }  default command error_t Sector.erase[ uint8_t id ]( uint8_t sector, uint8_t num_sectors ) { return FAIL; }  default command error_t Sector.computeCrc[ uint8_t id ]( uint16_t crc, storage_addr_t addr, storage_len_t len ) { return FAIL; }  default async command error_t ClientResource.request[ uint8_t id ]() { return FAIL; }  default async command error_t ClientResource.release[ uint8_t id ]() { return FAIL; }  }

⌨️ 快捷键说明

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