blob: 486544609135b8dc979e4821fd46b9759bfce475 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDER OR 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.
*/
/**
* @file
* This file contains definitions for a SPI interface to the OpenThread stack.
*/
#ifndef NCP_SPI_HPP_
#define NCP_SPI_HPP_
#include "openthread-core-config.h"
#include "ncp/ncp_base.hpp"
namespace ot {
namespace Ncp {
/**
* This class defines a SPI frame.
*
*/
class SpiFrame
{
public:
enum
{
kHeaderSize = 5, ///< SPI header size (in bytes).
};
/**
* This constructor initializes an `SpiFrame` instance.
*
* @param[in] aBuffer Pointer to buffer containing the frame.
*
*/
SpiFrame(uint8_t *aBuffer) : mBuffer(aBuffer) { }
/**
* This method gets a pointer to data portion in the SPI frame skipping the header.
*
* @returns A pointer to data in the SPI frame.
*
*/
uint8_t *GetData(void) { return mBuffer + kHeaderSize; }
/**
* This method indicates whether or not the frame is valid.
*
* In a valid frame the flag byte should contain the pattern bits.
*
* @returns TRUE if the frame is valid, FALSE otherwise.
*
*/
bool IsValid(void) const
{
return ((mBuffer[kIndexFlagByte] & kFlagPatternMask) == kFlagPattern);
}
/**
* This method sets the "flag byte" field in the SPI frame header.
*
* @param[in] aResetFalg The status of reset flag (TRUE to set the flag, FALSE to clear flag).
*
*/
void SetHeaderFlagByte(bool aResetFlag)
{
mBuffer[kIndexFlagByte] = kFlagPattern | (aResetFlag ? kFlagReset : 0);
}
/**
* This method sets the "accept len" field in the SPI frame header.
*
* "accept len" specifies number of bytes the sender of the SPI frame can receive.
*
* @param[in] aAcceptLen The accept length in bytes.
*
*/
void SetHeaderAcceptLen(uint16_t aAcceptLen)
{
Encoding::LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen);
}
/**
* This method gets the "accept len" field in the SPI frame header.
*
* @returns The accept length in bytes.
*
*/
uint16_t GetHeaderAcceptLen(void) const
{
return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen);
}
/**
* This method sets the "data len" field in the SPI frame header.
*
* "Data len" specifies number of data bytes in the transmitted SPI frame.
*
* @param[in] aDataLen The data length in bytes.
*
*/
void SetHeaderDataLen(uint16_t aDataLen)
{
Encoding::LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen);
}
/**
* This method gets the "data len" field in the SPI frame header.
*
* @returns The data length in bytes.
*
*/
uint16_t GetHeaderDataLen(void) const
{
return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexDataLen);
}
private:
enum
{
kIndexFlagByte = 0, // flag byte (uint8_t).
kIndexAcceptLen = 1, // accept len (uint16_t little-endian encoding).
kIndexDataLen = 3, // data len (uint16_t little-endian encoding).
kFlagReset = (1 << 7), // Flag byte RESET bit.
kFlagPattern = 0x02, // Flag byte PATTERN bits.
kFlagPatternMask = 0x03, // Flag byte PATTERN mask.
};
uint8_t *mBuffer;
};
class NcpSpi : public NcpBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A pointer to the OpenThread instance structure.
*
*/
NcpSpi(Instance *aInstance);
private:
enum
{
/**
* SPI tx and rx buffer size (should fit a max length frame + SPI header).
*
*/
kSpiBufferSize = OPENTHREAD_CONFIG_NCP_SPI_BUFFER_SIZE,
/**
* Size of the SPI header (in bytes).
*
*/
kSpiHeaderSize = SpiFrame::kHeaderSize,
};
enum TxState
{
kTxStateIdle, // No frame to send.
kTxStateSending, // A frame is ready to be sent.
kTxStateHandlingSendDone // The frame was sent successfully, waiting to prepare the next one (if any).
};
typedef uint8_t LargeFrameBuffer[kSpiBufferSize];
typedef uint8_t EmptyFrameBuffer[kSpiHeaderSize];
static bool SpiTransactionComplete(void * aContext,
uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen);
bool SpiTransactionComplete(uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen);
static void SpiTransactionProcess(void *aContext);
void SpiTransactionProcess(void);
static void HandleFrameAddedToTxBuffer(void * aContext,
NcpFrameBuffer::FrameTag aFrameTag,
NcpFrameBuffer::Priority aPriority,
NcpFrameBuffer * aNcpFrameBuffer);
static void PrepareTxFrame(Tasklet &aTasklet);
void PrepareTxFrame(void);
void HandleRxFrame(void);
void PrepareNextSpiSendFrame(void);
volatile TxState mTxState;
volatile bool mHandlingRxFrame;
volatile bool mResetFlag;
Tasklet mPrepareTxFrameTask;
uint16_t mSendFrameLength;
LargeFrameBuffer mSendFrame;
EmptyFrameBuffer mEmptySendFrameFullAccept;
EmptyFrameBuffer mEmptySendFrameZeroAccept;
LargeFrameBuffer mReceiveFrame;
EmptyFrameBuffer mEmptyReceiveFrame;
};
} // namespace Ncp
} // namespace ot
#endif // NCP_SPI_HPP_