📄 stm25plogp.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.7 $ $Date: 2007/11/28 03:15:30 $ */#include <Stm25p.h>module Stm25pLogP { provides interface Init; provides interface LogRead as Read[ uint8_t id ]; provides interface LogWrite as Write[ uint8_t id ]; uses interface Stm25pSector as Sector[ uint8_t id ]; uses interface Resource as ClientResource[ uint8_t id ]; uses interface Get<bool> as Circular[ uint8_t id ]; uses interface Leds;}implementation { enum { NUM_LOGS = uniqueCount( "Stm25p.Log" ), BLOCK_SIZE = 4096, BLOCK_SIZE_LOG2 = 12, BLOCK_MASK = BLOCK_SIZE - 1, BLOCKS_PER_SECTOR = STM25P_SECTOR_SIZE / BLOCK_SIZE, MAX_RECORD_SIZE = 254, INVALID_HEADER = 0xff, }; typedef enum { S_IDLE, S_READ, S_SEEK, S_ERASE, S_APPEND, S_SYNC, } stm25p_log_req_t; typedef struct stm25p_log_state_t { storage_cookie_t cookie; void* buf; uint8_t len; stm25p_log_req_t req; } stm25p_log_state_t; typedef struct stm25p_log_info_t { stm25p_addr_t read_addr; stm25p_addr_t remaining; stm25p_addr_t write_addr; } stm25p_log_info_t; stm25p_log_state_t m_log_state[ NUM_LOGS ]; stm25p_log_state_t m_req; stm25p_log_info_t m_log_info[ NUM_LOGS ]; stm25p_addr_t m_addr; bool m_records_lost; uint8_t m_header; uint8_t m_len; typedef enum { S_SEARCH_BLOCKS, S_SEARCH_RECORDS, S_SEARCH_SEEK, S_HEADER, S_DATA, } stm25p_log_rw_state_t; stm25p_log_rw_state_t m_rw_state; error_t newRequest( uint8_t client ); void continueReadOp( uint8_t client ); void continueAppendOp( uint8_t client ); void signalDone( uint8_t id, error_t error ); command error_t Init.init() { int i; for ( i = 0; i < NUM_LOGS; i++ ) { m_log_info[ i ].read_addr = STM25P_INVALID_ADDRESS; m_log_info[ i ].write_addr = 0; } return SUCCESS; } command error_t Read.read[ uint8_t id ]( void* buf, storage_len_t len ) { m_req.req = S_READ; m_req.buf = buf; m_req.len = len; m_len = len; return newRequest( id ); } command error_t Read.seek[ uint8_t id ]( storage_addr_t cookie ) { if ( cookie > m_log_info[ id ].write_addr ) return FAIL; m_req.req = S_SEEK; m_req.cookie = cookie; return newRequest( id ); } command storage_cookie_t Read.currentOffset[ uint8_t id ]() { return m_log_info[ id ].read_addr; } command storage_cookie_t Read.getSize[ uint8_t id ]() { return ( (storage_len_t)call Sector.getNumSectors[ id ]() << STM25P_SECTOR_SIZE_LOG2 ); } command storage_cookie_t Write.currentOffset[ uint8_t id ]() { return m_log_info[ id ].write_addr; } command error_t Write.erase[ uint8_t id ]() { m_req.req = S_ERASE; return newRequest( id ); } command error_t Write.append[ uint8_t id ]( void* buf, storage_len_t len ) { uint16_t bytes_left = (uint16_t)m_log_info[ id ].write_addr % BLOCK_SIZE; bytes_left = BLOCK_SIZE - bytes_left; // don't allow appends larger than maximum record size if ( len > MAX_RECORD_SIZE ) return ESIZE; // move to next block if current block doesn't have enough space if ( sizeof( m_header ) + len > bytes_left ) m_log_info[ id ].write_addr += bytes_left; // if log is not circular, make sure it doesn't grow too large if ( !call Circular.get[ id ]() && ( (uint8_t)(m_log_info[ id ].write_addr >> STM25P_SECTOR_SIZE_LOG2) >= call Sector.getNumSectors[ id ]() ) ) return ESIZE; m_records_lost = FALSE; m_req.req = S_APPEND; m_req.buf = buf; m_req.len = len; return newRequest( id ); } command error_t Write.sync[ uint8_t id ]() { m_req.req = S_SYNC; return newRequest( id ); } error_t newRequest( uint8_t client ) { if ( m_log_state[ client ].req != S_IDLE ) return FAIL; call ClientResource.request[ client ](); m_log_state[ client ] = m_req; return SUCCESS; } uint8_t calcSector( uint8_t client, stm25p_addr_t addr ) { uint8_t sector = call Sector.getNumSectors[ client ](); return (uint8_t)( addr >> STM25P_SECTOR_SIZE_LOG2 ) % sector; } stm25p_addr_t calcAddr( uint8_t client, stm25p_addr_t addr ) { stm25p_addr_t result = calcSector( client, addr ); result <<= STM25P_SECTOR_SIZE_LOG2; result |= addr & STM25P_SECTOR_MASK; return result; } event void ClientResource.granted[ uint8_t id ]() { // log never used, need to find start and end of log if ( m_log_info[ id ].read_addr == STM25P_INVALID_ADDRESS && m_log_state[ id ].req != S_ERASE ) { m_rw_state = S_SEARCH_BLOCKS; call Sector.read[ id ]( 0, (uint8_t*)&m_addr, sizeof( m_addr ) ); } // start and end of log known, do the requested operation else { switch( m_log_state[ id ].req ) { case S_READ: m_rw_state = (m_log_info[ id ].remaining) ? S_DATA : S_HEADER; continueReadOp( id ); break; case S_SEEK: { // make sure the cookie is still within the range of valid data uint8_t numSectors = call Sector.getNumSectors[ id ](); uint8_t readSector = (m_log_state[ id ].cookie >> STM25P_SECTOR_SIZE_LOG2); uint8_t writeSector = ((m_log_info[ id ].write_addr-1)>>STM25P_SECTOR_SIZE_LOG2)+1; // if cookie is overwritten, advance to beginning of log if ( (writeSector - readSector) > numSectors ) { m_log_state[ id ].cookie = (storage_cookie_t)(writeSector-numSectors) <<STM25P_SECTOR_SIZE_LOG2; } m_log_info[ id ].read_addr = m_log_state[ id ].cookie & ~BLOCK_MASK; m_log_info[ id ].remaining = 0; m_rw_state = S_SEARCH_SEEK; if ( m_log_info[ id ].read_addr != m_log_state[ id ].cookie ) { m_log_info[ id ].read_addr += sizeof( m_addr ); call Sector.read[ id ]( calcAddr( id, m_log_info[ id ].read_addr ), &m_header, sizeof( m_header ) ); } else signalDone( id, SUCCESS ); } break; case S_ERASE: call Sector.erase[ id ]( 0, call Sector.getNumSectors[ id ]() ); break; case S_APPEND: m_rw_state = S_HEADER; continueAppendOp( id ); break; case S_SYNC: signalDone( id, SUCCESS ); break; case S_IDLE: break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -