📄 cc2420spip.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> * @author David Moss * @author Roman Lim * @version $Revision: 1.1 $ $Date: 2008/02/11 17:41:25 $ */module CC2420SpiP { provides { interface ChipSpiResource; interface Resource[ uint8_t id ]; interface CC2420Fifo as Fifo[ uint8_t id ]; interface CC2420Ram as Ram[ uint16_t id ]; interface CC2420Register as Reg[ uint8_t id ]; interface CC2420Strobe as Strobe[ uint8_t id ]; } uses { interface Resource as SpiResource; interface SpiByte; interface SpiPacket; interface State as WorkingState; interface Leds; }}implementation { enum { RESOURCE_COUNT = uniqueCount( "CC2420Spi.Resource" ), NO_HOLDER = 0xFF, }; /** WorkingStates */ enum { S_IDLE, S_BUSY, }; /** Address to read/write on the CC2420, also maintains caller's client id */ norace uint16_t m_addr; /** Each bit represents a client ID that is requesting SPI bus access */ uint8_t m_requests = 0; /** The current client that owns the SPI bus */ uint8_t m_holder = NO_HOLDER; /** TRUE if it is safe to release the SPI bus after all users say ok */ bool release; /***************** Prototypes ****************/ error_t attemptRelease(); task void grant(); /***************** ChipSpiResource Commands ****************/ /** * Abort the release of the SPI bus. This must be called only with the * releasing() event */ async command void ChipSpiResource.abortRelease() { atomic release = FALSE; } /** * Release the SPI bus if there are no objections */ async command error_t ChipSpiResource.attemptRelease() { return attemptRelease(); } /***************** Resource Commands *****************/ async command error_t Resource.request[ uint8_t id ]() { atomic { if ( call WorkingState.requestState(S_BUSY) == SUCCESS ) { m_holder = id; if(call SpiResource.isOwner()) { post grant(); } else { call SpiResource.request(); } } else { m_requests |= 1 << id; } } return SUCCESS; } async command error_t Resource.immediateRequest[ uint8_t id ]() { error_t error; atomic { if ( call WorkingState.requestState(S_BUSY) != SUCCESS ) { return EBUSY; } if(call SpiResource.isOwner()) { m_holder = id; error = SUCCESS; } else if ((error = call SpiResource.immediateRequest()) == SUCCESS ) { m_holder = id; } else { call WorkingState.toIdle(); } } return error; } async command error_t Resource.release[ uint8_t id ]() { uint8_t i; atomic { if ( m_holder != id ) { return FAIL; } m_holder = NO_HOLDER; if ( !m_requests ) { call WorkingState.toIdle(); attemptRelease(); } else { for ( i = m_holder + 1; ; i++ ) { i %= RESOURCE_COUNT; if ( m_requests & ( 1 << i ) ) { m_holder = i; m_requests &= ~( 1 << i ); post grant(); return SUCCESS; } } } } return SUCCESS; } async command uint8_t Resource.isOwner[ uint8_t id ]() { atomic return (m_holder == id); } /***************** SpiResource Events ****************/ event void SpiResource.granted() { post grant(); } /***************** Fifo Commands ****************/ async command cc2420_status_t Fifo.beginRead[ uint8_t addr ]( uint8_t* data, uint8_t len ) { cc2420_status_t status = 0; atomic { if(call WorkingState.isIdle()) { return status; } } m_addr = addr | 0x40; status = call SpiByte.write( m_addr ); call Fifo.continueRead[ addr ]( data, len ); return status; } async command error_t Fifo.continueRead[ uint8_t addr ]( uint8_t* data, uint8_t len ) { return call SpiPacket.send( NULL, data, len ); } async command cc2420_status_t Fifo.write[ uint8_t addr ]( uint8_t* data, uint8_t len ) { uint8_t status = 0; atomic { if(call WorkingState.isIdle()) { return status; } } m_addr = addr; status = call SpiByte.write( m_addr ); call SpiPacket.send( data, NULL, len ); return status; } /***************** RAM Commands ****************/ async command cc2420_status_t Ram.read[ uint16_t addr ]( uint8_t offset, uint8_t* data, uint8_t len ) { cc2420_status_t status = 0; atomic { if(call WorkingState.isIdle()) { return status; } } addr += offset; call SpiByte.write( addr | 0x80 ); status = call SpiByte.write( ( ( addr >> 1 ) & 0xc0 ) | 0x20 ); for ( ; len; len-- ) { *data++ = call SpiByte.write( 0 ); } return status; } async command cc2420_status_t Ram.write[ uint16_t addr ]( uint8_t offset, uint8_t* data, uint8_t len ) { cc2420_status_t status = 0; atomic { if(call WorkingState.isIdle()) { return status; } } addr += offset; call SpiByte.write( addr | 0x80 ); call SpiByte.write( ( addr >> 1 ) & 0xc0 ); for ( ; len; len-- ) { status = call SpiByte.write( *data++ ); } return status; } /***************** Register Commands ****************/ async command cc2420_status_t Reg.read[ uint8_t addr ]( uint16_t* data ) { cc2420_status_t status = 0; atomic { if(call WorkingState.isIdle()) { return status; } } status = call SpiByte.write( addr | 0x40 ); *data = (uint16_t)call SpiByte.write( 0 ) << 8; *data |= call SpiByte.write( 0 ); return status; } async command cc2420_status_t Reg.write[ uint8_t addr ]( uint16_t data ) { atomic { if(call WorkingState.isIdle()) { return 0; } } call SpiByte.write( addr ); call SpiByte.write( data >> 8 ); return call SpiByte.write( data & 0xff ); } /***************** Strobe Commands ****************/ async command cc2420_status_t Strobe.strobe[ uint8_t addr ]() { atomic { if(call WorkingState.isIdle()) { return 0; } } return call SpiByte.write( addr ); } /***************** SpiPacket Events ****************/ async event void SpiPacket.sendDone( uint8_t* tx_buf, uint8_t* rx_buf, uint16_t len, error_t error ) { if ( m_addr & 0x40 ) { signal Fifo.readDone[ m_addr & ~0x40 ]( rx_buf, len, error ); } else { signal Fifo.writeDone[ m_addr ]( tx_buf, len, error ); } } /***************** Functions ****************/ error_t attemptRelease() { atomic{ if(m_requests > 0 || m_holder != NO_HOLDER || !call WorkingState.isIdle()) { return FAIL; } } atomic release = TRUE; signal ChipSpiResource.releasing(); atomic { if(release) { call SpiResource.release(); return SUCCESS; } } return EBUSY; } task void grant() { uint8_t holder; atomic { holder = m_holder; } signal Resource.granted[ holder ](); } /***************** Defaults ****************/ default event void Resource.granted[ uint8_t id ]() { } default async event void Fifo.readDone[ uint8_t addr ]( uint8_t* rx_buf, uint8_t rx_len, error_t error ) { } default async event void Fifo.writeDone[ uint8_t addr ]( uint8_t* tx_buf, uint8_t tx_len, error_t error ) { } default async event void ChipSpiResource.releasing() { } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -