1*cfb92d14SAndroid Build Coastguard Worker /* 2*cfb92d14SAndroid Build Coastguard Worker * Copyright (c) 2023, The OpenThread Authors. 3*cfb92d14SAndroid Build Coastguard Worker * All rights reserved. 4*cfb92d14SAndroid Build Coastguard Worker * 5*cfb92d14SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 6*cfb92d14SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions are met: 7*cfb92d14SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright 8*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 9*cfb92d14SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright 10*cfb92d14SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the 11*cfb92d14SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution. 12*cfb92d14SAndroid Build Coastguard Worker * 3. Neither the name of the copyright holder nor the 13*cfb92d14SAndroid Build Coastguard Worker * names of its contributors may be used to endorse or promote products 14*cfb92d14SAndroid Build Coastguard Worker * derived from this software without specific prior written permission. 15*cfb92d14SAndroid Build Coastguard Worker * 16*cfb92d14SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17*cfb92d14SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18*cfb92d14SAndroid Build Coastguard Worker * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19*cfb92d14SAndroid Build Coastguard Worker * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20*cfb92d14SAndroid Build Coastguard Worker * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22*cfb92d14SAndroid Build Coastguard Worker * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23*cfb92d14SAndroid Build Coastguard Worker * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24*cfb92d14SAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25*cfb92d14SAndroid Build Coastguard Worker * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26*cfb92d14SAndroid Build Coastguard Worker */ 27*cfb92d14SAndroid Build Coastguard Worker 28*cfb92d14SAndroid Build Coastguard Worker /** 29*cfb92d14SAndroid Build Coastguard Worker * @file 30*cfb92d14SAndroid Build Coastguard Worker * This file contains definitions of the SPI frame. 31*cfb92d14SAndroid Build Coastguard Worker */ 32*cfb92d14SAndroid Build Coastguard Worker 33*cfb92d14SAndroid Build Coastguard Worker #ifndef SPINEL_SPI_FRAME_HPP_ 34*cfb92d14SAndroid Build Coastguard Worker #define SPINEL_SPI_FRAME_HPP_ 35*cfb92d14SAndroid Build Coastguard Worker 36*cfb92d14SAndroid Build Coastguard Worker #include <stdint.h> 37*cfb92d14SAndroid Build Coastguard Worker 38*cfb92d14SAndroid Build Coastguard Worker #include "lib/utils/endian.hpp" 39*cfb92d14SAndroid Build Coastguard Worker 40*cfb92d14SAndroid Build Coastguard Worker namespace ot { 41*cfb92d14SAndroid Build Coastguard Worker namespace Spinel { 42*cfb92d14SAndroid Build Coastguard Worker 43*cfb92d14SAndroid Build Coastguard Worker /* 44*cfb92d14SAndroid Build Coastguard Worker * SPI Framing Protocol 45*cfb92d14SAndroid Build Coastguard Worker * 46*cfb92d14SAndroid Build Coastguard Worker * Each SPI frame starts with a 5-byte frame header: 47*cfb92d14SAndroid Build Coastguard Worker * 48*cfb92d14SAndroid Build Coastguard Worker * +---------+-----+----------+----------+ 49*cfb92d14SAndroid Build Coastguard Worker * | Octets: | 1 | 2 | 2 | 50*cfb92d14SAndroid Build Coastguard Worker * +---------+-----+----------+----------+ 51*cfb92d14SAndroid Build Coastguard Worker * | Fields: | HDR | RECV_LEN | DATA_LEN | 52*cfb92d14SAndroid Build Coastguard Worker * +---------+-----+----------+----------+ 53*cfb92d14SAndroid Build Coastguard Worker * 54*cfb92d14SAndroid Build Coastguard Worker * - "HDR": The first byte is the header byte (defined below) 55*cfb92d14SAndroid Build Coastguard Worker * - "RECV_LEN": The second and third bytes indicate the largest frame 56*cfb92d14SAndroid Build Coastguard Worker * size that that device is ready to receive. If zero, then the 57*cfb92d14SAndroid Build Coastguard Worker * other device must not send any data. (Little endian) 58*cfb92d14SAndroid Build Coastguard Worker * - "DATA_LEN": The fourth and fifth bytes indicate the size of the 59*cfb92d14SAndroid Build Coastguard Worker * pending data frame to be sent to the other device. If this value 60*cfb92d14SAndroid Build Coastguard Worker * is equal-to or less-than the number of bytes that the other device 61*cfb92d14SAndroid Build Coastguard Worker * is willing to receive, then the data of the frame is immediately 62*cfb92d14SAndroid Build Coastguard Worker * after the header. (Little Endian) 63*cfb92d14SAndroid Build Coastguard Worker * 64*cfb92d14SAndroid Build Coastguard Worker * The "HDR" byte is defined as: 65*cfb92d14SAndroid Build Coastguard Worker * 66*cfb92d14SAndroid Build Coastguard Worker * 0 1 2 3 4 5 6 7 67*cfb92d14SAndroid Build Coastguard Worker * +---+---+---+---+---+---+---+---+ 68*cfb92d14SAndroid Build Coastguard Worker * |RST|CRC|CCF| RESERVED |PATTERN| 69*cfb92d14SAndroid Build Coastguard Worker * +---+---+---+---+---+---+---+---+ 70*cfb92d14SAndroid Build Coastguard Worker * 71*cfb92d14SAndroid Build Coastguard Worker * - "RST": This bit is set when that device has been reset since the 72*cfb92d14SAndroid Build Coastguard Worker * last time `CS` (chip select) was asserted. 73*cfb92d14SAndroid Build Coastguard Worker * - "CRC": This bit is set when that device supports writing a 16-bit 74*cfb92d14SAndroid Build Coastguard Worker * CRC at the end of the data. The CRC length is NOT included in 75*cfb92d14SAndroid Build Coastguard Worker * DATA_LEN. 76*cfb92d14SAndroid Build Coastguard Worker * - "CCF": "CRC Check Failure". Set if the CRC check on the last 77*cfb92d14SAndroid Build Coastguard Worker * received frame failed, cleared to zero otherwise. This bit is 78*cfb92d14SAndroid Build Coastguard Worker * only used if both sides support CRC. 79*cfb92d14SAndroid Build Coastguard Worker * - "RESERVED": These bits are all reserved for future used. They 80*cfb92d14SAndroid Build Coastguard Worker * MUST be cleared to zero and MUST be ignored if set. 81*cfb92d14SAndroid Build Coastguard Worker * - "PATTERN": These bits are set to a fixed value to help distinguish 82*cfb92d14SAndroid Build Coastguard Worker * valid SPI frames from garbage (by explicitly making "0xFF" and 83*cfb92d14SAndroid Build Coastguard Worker * "0x00" invalid values). Bit 6 MUST be set to be one and bit 7 84*cfb92d14SAndroid Build Coastguard Worker * MUST be cleared (0). A frame received that has any other values 85*cfb92d14SAndroid Build Coastguard Worker * for these bits MUST be dropped. 86*cfb92d14SAndroid Build Coastguard Worker * 87*cfb92d14SAndroid Build Coastguard Worker * Prior to a sending or receiving a frame, the master MAY send a 88*cfb92d14SAndroid Build Coastguard Worker * 5-octet frame with zeros for both the max receive frame size and the 89*cfb92d14SAndroid Build Coastguard Worker * the contained frame length. This will induce the slave device to 90*cfb92d14SAndroid Build Coastguard Worker * indicate the length of the frame it wants to send (if any) and 91*cfb92d14SAndroid Build Coastguard Worker * indicate the largest frame it is capable of receiving at the moment. 92*cfb92d14SAndroid Build Coastguard Worker * This allows the master to calculate the size of the next transaction. 93*cfb92d14SAndroid Build Coastguard Worker * Alternatively, if the master has a frame to send it can just go ahead 94*cfb92d14SAndroid Build Coastguard Worker * and send a frame of that length and determine if the frame was 95*cfb92d14SAndroid Build Coastguard Worker * accepted by checking that the "RECV_LEN" from the slave frame is 96*cfb92d14SAndroid Build Coastguard Worker * larger than the frame the master just tried to send. If the 97*cfb92d14SAndroid Build Coastguard Worker * "RECV_LEN" is smaller then the frame wasn't accepted and will need to 98*cfb92d14SAndroid Build Coastguard Worker * be transmitted again. 99*cfb92d14SAndroid Build Coastguard Worker * 100*cfb92d14SAndroid Build Coastguard Worker * This protocol can be used either unidirectionally or bidirectionally, 101*cfb92d14SAndroid Build Coastguard Worker * determined by the behavior of the master and the slave. 102*cfb92d14SAndroid Build Coastguard Worker * 103*cfb92d14SAndroid Build Coastguard Worker * If the the master notices "PATTERN" is not set correctly, the master 104*cfb92d14SAndroid Build Coastguard Worker * should consider the transaction to have failed and try again after 10 105*cfb92d14SAndroid Build Coastguard Worker * milliseconds, retrying up to 200 times. After unsuccessfully trying 106*cfb92d14SAndroid Build Coastguard Worker * 200 times in a row, the master MAY take appropriate remedial action 107*cfb92d14SAndroid Build Coastguard Worker * (like a NCP hardware reset, or indicating a communication failure to 108*cfb92d14SAndroid Build Coastguard Worker * a user interface). 109*cfb92d14SAndroid Build Coastguard Worker * 110*cfb92d14SAndroid Build Coastguard Worker * At the end of the data of a frame is an optional 16-bit CRC, support 111*cfb92d14SAndroid Build Coastguard Worker * for which is indicated by the "CRC" bit of the "HDR" byte being set. 112*cfb92d14SAndroid Build Coastguard Worker * If these bits are set for both the master and slave frames, then CRC 113*cfb92d14SAndroid Build Coastguard Worker * checking is enabled on both sides, effectively requiring that frame 114*cfb92d14SAndroid Build Coastguard Worker * sizes be two bytes longer than would be otherwise required. The CRC 115*cfb92d14SAndroid Build Coastguard Worker * is calculated using the same mechanism used for the CRC calculation 116*cfb92d14SAndroid Build Coastguard Worker * in HDLC-Lite (See Appendix A.1.2). When both of the "CRC" bits are 117*cfb92d14SAndroid Build Coastguard Worker * set, both sides must verify that the "CRC" is valid before accepting 118*cfb92d14SAndroid Build Coastguard Worker * the frame. If not enough bytes were clocked out for the CRC to be 119*cfb92d14SAndroid Build Coastguard Worker * read, then the frame must be ignored. If enough bytes were clocked 120*cfb92d14SAndroid Build Coastguard Worker * out to perform a CRC check, but the CRC check fails, then the frame 121*cfb92d14SAndroid Build Coastguard Worker * must be rejected and the "CRC_FAIL" bit on the next frame (and ONLY 122*cfb92d14SAndroid Build Coastguard Worker * the next frame) MUST be set. 123*cfb92d14SAndroid Build Coastguard Worker */ 124*cfb92d14SAndroid Build Coastguard Worker 125*cfb92d14SAndroid Build Coastguard Worker /** 126*cfb92d14SAndroid Build Coastguard Worker * Defines a SPI frame. 127*cfb92d14SAndroid Build Coastguard Worker * 128*cfb92d14SAndroid Build Coastguard Worker */ 129*cfb92d14SAndroid Build Coastguard Worker class SpiFrame 130*cfb92d14SAndroid Build Coastguard Worker { 131*cfb92d14SAndroid Build Coastguard Worker public: 132*cfb92d14SAndroid Build Coastguard Worker enum 133*cfb92d14SAndroid Build Coastguard Worker { 134*cfb92d14SAndroid Build Coastguard Worker kHeaderSize = 5, ///< SPI header size (in bytes). 135*cfb92d14SAndroid Build Coastguard Worker }; 136*cfb92d14SAndroid Build Coastguard Worker 137*cfb92d14SAndroid Build Coastguard Worker /** 138*cfb92d14SAndroid Build Coastguard Worker * Initializes an `SpiFrame` instance. 139*cfb92d14SAndroid Build Coastguard Worker * 140*cfb92d14SAndroid Build Coastguard Worker * @param[in] aBuffer Pointer to buffer containing the frame. 141*cfb92d14SAndroid Build Coastguard Worker * 142*cfb92d14SAndroid Build Coastguard Worker */ SpiFrame(uint8_t * aBuffer)143*cfb92d14SAndroid Build Coastguard Worker explicit SpiFrame(uint8_t *aBuffer) 144*cfb92d14SAndroid Build Coastguard Worker : mBuffer(aBuffer) 145*cfb92d14SAndroid Build Coastguard Worker { 146*cfb92d14SAndroid Build Coastguard Worker } 147*cfb92d14SAndroid Build Coastguard Worker 148*cfb92d14SAndroid Build Coastguard Worker /** 149*cfb92d14SAndroid Build Coastguard Worker * Gets a pointer to data portion in the SPI frame skipping the header. 150*cfb92d14SAndroid Build Coastguard Worker * 151*cfb92d14SAndroid Build Coastguard Worker * @returns A pointer to data in the SPI frame. 152*cfb92d14SAndroid Build Coastguard Worker * 153*cfb92d14SAndroid Build Coastguard Worker */ GetData(void)154*cfb92d14SAndroid Build Coastguard Worker uint8_t *GetData(void) { return mBuffer + kHeaderSize; } 155*cfb92d14SAndroid Build Coastguard Worker 156*cfb92d14SAndroid Build Coastguard Worker /** 157*cfb92d14SAndroid Build Coastguard Worker * Indicates whether or not the frame is valid. 158*cfb92d14SAndroid Build Coastguard Worker * 159*cfb92d14SAndroid Build Coastguard Worker * In a valid frame the flag byte should contain the pattern bits. 160*cfb92d14SAndroid Build Coastguard Worker * 161*cfb92d14SAndroid Build Coastguard Worker * @returns TRUE if the frame is valid, FALSE otherwise. 162*cfb92d14SAndroid Build Coastguard Worker * 163*cfb92d14SAndroid Build Coastguard Worker */ IsValid(void) const164*cfb92d14SAndroid Build Coastguard Worker bool IsValid(void) const { return ((mBuffer[kIndexFlagByte] & kFlagPatternMask) == kFlagPattern); } 165*cfb92d14SAndroid Build Coastguard Worker 166*cfb92d14SAndroid Build Coastguard Worker /** 167*cfb92d14SAndroid Build Coastguard Worker * Indicates whether or not the "RST" bit is set. 168*cfb92d14SAndroid Build Coastguard Worker * 169*cfb92d14SAndroid Build Coastguard Worker * @returns TRUE if the "RST" bit is set, FALSE otherwise. 170*cfb92d14SAndroid Build Coastguard Worker * 171*cfb92d14SAndroid Build Coastguard Worker */ IsResetFlagSet(void) const172*cfb92d14SAndroid Build Coastguard Worker bool IsResetFlagSet(void) const { return ((mBuffer[kIndexFlagByte] & kFlagReset) == kFlagReset); } 173*cfb92d14SAndroid Build Coastguard Worker 174*cfb92d14SAndroid Build Coastguard Worker /** 175*cfb92d14SAndroid Build Coastguard Worker * Sets the "flag byte" field in the SPI frame header. 176*cfb92d14SAndroid Build Coastguard Worker * 177*cfb92d14SAndroid Build Coastguard Worker * @param[in] aResetFlag The status of reset flag (TRUE to set the flag, FALSE to clear flag). 178*cfb92d14SAndroid Build Coastguard Worker * 179*cfb92d14SAndroid Build Coastguard Worker */ SetHeaderFlagByte(bool aResetFlag)180*cfb92d14SAndroid Build Coastguard Worker void SetHeaderFlagByte(bool aResetFlag) { mBuffer[kIndexFlagByte] = kFlagPattern | (aResetFlag ? kFlagReset : 0); } 181*cfb92d14SAndroid Build Coastguard Worker 182*cfb92d14SAndroid Build Coastguard Worker /** 183*cfb92d14SAndroid Build Coastguard Worker * Gets the "flag byte" field in the SPI frame header. 184*cfb92d14SAndroid Build Coastguard Worker * 185*cfb92d14SAndroid Build Coastguard Worker * @returns The flag byte. 186*cfb92d14SAndroid Build Coastguard Worker * 187*cfb92d14SAndroid Build Coastguard Worker */ GetHeaderFlagByte(void) const188*cfb92d14SAndroid Build Coastguard Worker uint8_t GetHeaderFlagByte(void) const { return mBuffer[kIndexFlagByte]; } 189*cfb92d14SAndroid Build Coastguard Worker 190*cfb92d14SAndroid Build Coastguard Worker /** 191*cfb92d14SAndroid Build Coastguard Worker * Sets the "accept len" field in the SPI frame header. 192*cfb92d14SAndroid Build Coastguard Worker * 193*cfb92d14SAndroid Build Coastguard Worker * "accept len" specifies number of bytes the sender of the SPI frame can receive. 194*cfb92d14SAndroid Build Coastguard Worker * 195*cfb92d14SAndroid Build Coastguard Worker * @param[in] aAcceptLen The accept length in bytes. 196*cfb92d14SAndroid Build Coastguard Worker * 197*cfb92d14SAndroid Build Coastguard Worker */ SetHeaderAcceptLen(uint16_t aAcceptLen)198*cfb92d14SAndroid Build Coastguard Worker void SetHeaderAcceptLen(uint16_t aAcceptLen) 199*cfb92d14SAndroid Build Coastguard Worker { 200*cfb92d14SAndroid Build Coastguard Worker Lib::Utils::LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen); 201*cfb92d14SAndroid Build Coastguard Worker } 202*cfb92d14SAndroid Build Coastguard Worker 203*cfb92d14SAndroid Build Coastguard Worker /** 204*cfb92d14SAndroid Build Coastguard Worker * Gets the "accept len" field in the SPI frame header. 205*cfb92d14SAndroid Build Coastguard Worker * 206*cfb92d14SAndroid Build Coastguard Worker * @returns The accept length in bytes. 207*cfb92d14SAndroid Build Coastguard Worker * 208*cfb92d14SAndroid Build Coastguard Worker */ GetHeaderAcceptLen(void) const209*cfb92d14SAndroid Build Coastguard Worker uint16_t GetHeaderAcceptLen(void) const { return Lib::Utils::LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen); } 210*cfb92d14SAndroid Build Coastguard Worker 211*cfb92d14SAndroid Build Coastguard Worker /** 212*cfb92d14SAndroid Build Coastguard Worker * Sets the "data len" field in the SPI frame header. 213*cfb92d14SAndroid Build Coastguard Worker * 214*cfb92d14SAndroid Build Coastguard Worker * "Data len" specifies number of data bytes in the transmitted SPI frame. 215*cfb92d14SAndroid Build Coastguard Worker * 216*cfb92d14SAndroid Build Coastguard Worker * @param[in] aDataLen The data length in bytes. 217*cfb92d14SAndroid Build Coastguard Worker * 218*cfb92d14SAndroid Build Coastguard Worker */ SetHeaderDataLen(uint16_t aDataLen)219*cfb92d14SAndroid Build Coastguard Worker void SetHeaderDataLen(uint16_t aDataLen) 220*cfb92d14SAndroid Build Coastguard Worker { 221*cfb92d14SAndroid Build Coastguard Worker Lib::Utils::LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen); 222*cfb92d14SAndroid Build Coastguard Worker } 223*cfb92d14SAndroid Build Coastguard Worker 224*cfb92d14SAndroid Build Coastguard Worker /** 225*cfb92d14SAndroid Build Coastguard Worker * Gets the "data len" field in the SPI frame header. 226*cfb92d14SAndroid Build Coastguard Worker * 227*cfb92d14SAndroid Build Coastguard Worker * @returns The data length in bytes. 228*cfb92d14SAndroid Build Coastguard Worker * 229*cfb92d14SAndroid Build Coastguard Worker */ GetHeaderDataLen(void) const230*cfb92d14SAndroid Build Coastguard Worker uint16_t GetHeaderDataLen(void) const { return Lib::Utils::LittleEndian::ReadUint16(mBuffer + kIndexDataLen); } 231*cfb92d14SAndroid Build Coastguard Worker 232*cfb92d14SAndroid Build Coastguard Worker private: 233*cfb92d14SAndroid Build Coastguard Worker enum 234*cfb92d14SAndroid Build Coastguard Worker { 235*cfb92d14SAndroid Build Coastguard Worker kIndexFlagByte = 0, // flag byte (uint8_t). 236*cfb92d14SAndroid Build Coastguard Worker kIndexAcceptLen = 1, // accept len (uint16_t little-endian encoding). 237*cfb92d14SAndroid Build Coastguard Worker kIndexDataLen = 3, // data len (uint16_t little-endian encoding). 238*cfb92d14SAndroid Build Coastguard Worker 239*cfb92d14SAndroid Build Coastguard Worker kFlagReset = (1 << 7), // Flag byte RESET bit. 240*cfb92d14SAndroid Build Coastguard Worker kFlagPattern = 0x02, // Flag byte PATTERN bits. 241*cfb92d14SAndroid Build Coastguard Worker kFlagPatternMask = 0x03, // Flag byte PATTERN mask. 242*cfb92d14SAndroid Build Coastguard Worker }; 243*cfb92d14SAndroid Build Coastguard Worker 244*cfb92d14SAndroid Build Coastguard Worker uint8_t *mBuffer; 245*cfb92d14SAndroid Build Coastguard Worker }; 246*cfb92d14SAndroid Build Coastguard Worker 247*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel 248*cfb92d14SAndroid Build Coastguard Worker } // namespace ot 249*cfb92d14SAndroid Build Coastguard Worker #endif // SPINEL_SPI_FRAME_HPP_ 250