stm25plogp.nc

来自「tinyos-2.x.rar」· NC 代码 · 共 533 行 · 第 1/2 页

NC
533
字号
    }
    
  }

  void continueReadOp( uint8_t client ) {
    
    stm25p_addr_t read_addr = m_log_info[ client ].read_addr;
    uint8_t* buf;
    uint8_t len;

    // check if all done
    if ( m_len == 0 || read_addr >= m_log_info[ client ].write_addr ) {
      signalDone( client, SUCCESS );
      return;
    }
    
    buf = &m_header;
    len = sizeof( m_header );

    if ( m_rw_state == S_DATA ) {
      // if header is invalid, move to next block
      if ( m_header == INVALID_HEADER ) {
	m_rw_state = S_HEADER;
	read_addr += BLOCK_SIZE;
	read_addr &= ~BLOCK_MASK;
      }
      else {
	buf = m_log_state[ client ].buf + m_log_state[ client ].len - m_len;
	// truncate if record is shorter than requested length
	if ( m_log_info[ client ].remaining < m_len )
	  len = m_log_info[ client ].remaining;
	else
	  len = m_len;
      }
    }
    
    // if on block boundary
    if ( !((uint16_t)read_addr & BLOCK_MASK ) )
      read_addr += sizeof( m_addr );
    
    m_log_info[ client ].read_addr = read_addr;
    call Sector.read[ client ]( calcAddr( client, read_addr ), buf, len );
    
  }
  
  event void Sector.readDone[ uint8_t id ]( stm25p_addr_t addr, uint8_t* buf,
					    stm25p_len_t len, error_t error ) {

    stm25p_log_info_t* log_info = &m_log_info[ id ];

    // searching for the first and last log blocks
    switch( m_rw_state ) {
    case S_SEARCH_BLOCKS: 
      {
	uint16_t block = addr >> BLOCK_SIZE_LOG2;
	// record potential starting and ending addresses
	if ( m_addr != STM25P_INVALID_ADDRESS ) {
	  if ( m_addr < log_info->read_addr )
	    log_info->read_addr = m_addr;
	  if ( m_addr > log_info->write_addr )
	    log_info->write_addr = m_addr;
	}
	// move on to next log block
	if (++block < (call Sector.getNumSectors[ id ]()*BLOCKS_PER_SECTOR)) {
	  addr += BLOCK_SIZE;
	  call Sector.read[ id ]( addr, (uint8_t*)&m_addr, sizeof( m_addr ) );
	}
	// if log is empty, continue operation
	else if ( log_info->read_addr == STM25P_INVALID_ADDRESS ) {
	  log_info->read_addr = 0;
	  log_info->write_addr = 0;
	  signal ClientResource.granted[ id ]();
	}
	// search for last record
	else {
	  log_info->write_addr += sizeof( m_addr );
	  m_rw_state = S_SEARCH_RECORDS;
	  call Sector.read[ id ]( calcAddr(id, log_info->write_addr), &m_header,
				  sizeof( m_header ) );
	}
      }
      break;

    case S_SEARCH_RECORDS: 
      {
	// searching for the last log record to write
	uint16_t cur_block = log_info->write_addr >> BLOCK_SIZE_LOG2;
	uint16_t new_block = ( log_info->write_addr + sizeof( m_header ) + 
			       m_header ) >> BLOCK_SIZE_LOG2;
	// if header is valid and is on same block, move to next record
	if ( m_header != INVALID_HEADER && cur_block == new_block ) {
	  log_info->write_addr += sizeof( m_header ) + m_header;
	  call Sector.read[ id ]( calcAddr( id, log_info->write_addr ), 
				  &m_header, sizeof( m_header ) );
	}
	// found last record
	else {
	  signal ClientResource.granted[ id ]();
	}
      }
      break;

    case S_SEARCH_SEEK:
      {
	// searching for last log record to read
	log_info->read_addr += sizeof( m_header ) + m_header;
	// if not yet at cookie, keep searching
	if ( log_info->read_addr < m_log_state[ id ].cookie ) {
	  call Sector.read[ id ]( calcAddr(id, log_info->read_addr), &m_header,
				  sizeof( m_header ) );
	}
	// at or passed cookie, stop
	else {
	  log_info->remaining = log_info->read_addr - m_log_state[ id ].cookie;
	  log_info->read_addr = m_log_state[ id ].cookie;
	  signalDone( id, error );
	}
      }
      break;

    case S_HEADER:
      {
	// if header is invalid, move to next block
	if ( m_header == INVALID_HEADER ) {
	  log_info->read_addr += BLOCK_SIZE;
	  log_info->read_addr &= ~BLOCK_MASK;
	}
	else {
	  log_info->read_addr += sizeof( m_header );
	  log_info->remaining = m_header;
	  m_rw_state = S_DATA;
	}
	continueReadOp( id );
      }
      break;

    case S_DATA:
      {
	log_info->read_addr += len;
	log_info->remaining -= len;
	m_len -= len;
	m_rw_state = S_HEADER;
	continueReadOp( id );
	break;
      }
      
    }
    
  }

  void continueAppendOp( uint8_t client ) {
    
    stm25p_addr_t write_addr = m_log_info[ client ].write_addr;
    void* buf;
    uint8_t len;
    
    if ( !(uint16_t)write_addr ) {
      m_records_lost = TRUE;
      call Sector.erase[ client ]( calcSector( client, write_addr ), 1 );
    }
    else {
      if ( !((uint16_t)write_addr & BLOCK_MASK) ) {
	buf = &m_log_info[ client ].write_addr;
	len = sizeof( m_addr );
      }
      else if ( m_rw_state == S_HEADER ) {
	buf = &m_log_state[ client ].len;
	len = sizeof( m_log_state[ client ].len );
      }
      else {
	buf = m_log_state[ client ].buf;
	len = m_log_state[ client ].len;
      }
      call Sector.write[ client ]( calcAddr( client, write_addr ), buf, len );
    }

  }

  event void Sector.eraseDone[ uint8_t id ]( uint8_t sector, 
					     uint8_t num_sectors,
					     error_t error ) {
    if ( m_log_state[ id ].req == S_ERASE ) {
      m_log_info[ id ].read_addr = 0;
      m_log_info[ id ].write_addr = 0;
      signalDone( id, error );
    }
    else {
      // advance read pointer if write pointer has gone too far ahead
      // (the log could have cycled around)
      stm25p_addr_t volume_size = 
	STM25P_SECTOR_SIZE * ( call Sector.getNumSectors[ id ]() - 1 );
      if ( m_log_info[ id ].write_addr > volume_size ) {
	stm25p_addr_t read_addr = m_log_info[ id ].write_addr - volume_size;
	if ( m_log_info[ id ].read_addr < read_addr )
	  m_log_info[ id ].read_addr = read_addr;
      }
      m_addr = m_log_info[ id ].write_addr;
      call Sector.write[ id ]( calcAddr( id, m_addr ), (uint8_t*)&m_addr, 
			      sizeof( m_addr ) );
    }
  }

  event void Sector.writeDone[ uint8_t id ]( storage_addr_t addr, 
					     uint8_t* buf, 
					     storage_len_t len, 
					     error_t error ) {
    m_log_info[ id ].write_addr += len;
    if ( m_rw_state == S_HEADER ) {
      if ( len == sizeof( m_header ) )
	m_rw_state = S_DATA;
      continueAppendOp( id );
    }
    else {
      signalDone( id, error );
    }
  }
  
  void signalDone( uint8_t id, error_t error ) {
    
    stm25p_log_req_t req = m_log_state[ id ].req;
    void* buf = m_log_state[ id ].buf;
    storage_len_t len = m_log_state[ id ].len;

    call ClientResource.release[ id ]();
    m_log_state[ id ].req = S_IDLE;
    switch( req ) {
    case S_IDLE:
      break;
    case S_READ:
      signal Read.readDone[ id ]( buf, len - m_len, error );
      break;
    case S_SEEK:
      signal Read.seekDone[ id ]( error );
      break;
    case S_ERASE:
      signal Write.eraseDone[ id ]( error );
      break;
    case S_APPEND:
      signal Write.appendDone[ id ]( buf, len, m_records_lost, error );
      break;
    case S_SYNC:
      signal Write.syncDone[ id ]( error );
      break;
    }
  }

  event void Sector.computeCrcDone[ uint8_t id ]( stm25p_addr_t addr, stm25p_len_t len, uint16_t crc, error_t error ) {}

  default event void Read.readDone[ uint8_t id ]( void* data, storage_len_t len, error_t error ) {}
  default event void Read.seekDone[ uint8_t id ]( error_t error ) {}
  default event void Write.eraseDone[ uint8_t id ]( error_t error ) {}
  default event void Write.appendDone[ uint8_t id ]( void* data, storage_len_t len, bool recordsLost, error_t error ) {}
  default event void Write.syncDone[ 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; }
  default command bool Circular.get[ uint8_t id ]() { return FALSE; }
  
}

⌨️ 快捷键说明

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