Skip to content

Instantly share code, notes, and snippets.

@darconeous
Last active September 9, 2019 21:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darconeous/6403a99baab6b12c402aaa7573e27b7e to your computer and use it in GitHub Desktop.
Save darconeous/6403a99baab6b12c402aaa7573e27b7e to your computer and use it in GitHub Desktop.
Multiplexed Asynchronous Serial Reliability Protocol (MASRP)

Multiplexed Asynchronous Stream Reliability Protocol (MASRP)

Copyright (C) 2017 Nest Labs, All Rights Reserved

License

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.

Abstract

This document describes a reliability protocol for both stream and frame based protocols. It has the following design parameters:

  • Designed to be sent over a frame transport mechanism. May be encoded with HDLC-lite for UART, or using some sort of SPI framing protocol (like this one). This protocol makes the following assumptions about the upper framing layer:
    • The upper framing layer is best-effort.
    • The upper framing layer includes some sort of CRC checking. If the CRC fails, the packet is dropped and some sort of notification is sent to the MASRP layer.
  • Supports the transport of frames or streams.
  • No payload length. The length of the frame is implied by the framing mechanism.
  • Optional capability to support multiple independent asynchronous streams (multiplexing).
  • MTU discovery.

Frame Format

  • Control Byte:
    • 2-bits for Frame Type
    • 3-bits for OFC (Outbound Frame Counter)
    • 3-bits for AFC (Acknowledged Frame Counter)
  • Payload Bytes (defined by frame type)

 0               
 0 1 2 3 4 5 6 7 
+-+-+-+-+-+-+-+-+
|TYP| OFC | AFC |
+-+-+-+-+-+-+-+-+

The smallest possible frame is a single byte: A control byte with a zero-length payload.

Frame Types

The frame types are:

  • 0 - REQ - Control Request
  • 1 - RSP - Control Response
  • 2 - ACK - Acknowledgement (May rename to DAT)
  • 3 - NAK - Negative Acknowledgement (Bad CRC, flow control, etc)

For a control request/response, the payload is formatted as follows:

  • Control Request Info byte:
    • 1 bit (reserved for REQ, set-on-error for RSP)
    • 3 bits reserved (set to zero. Middle bit will always set to zero)
    • 4 bits request type:
      • 0 - RESET
      • All other values - RESERVED
  • Request-type-specific payload

For a RESET, the payload is formatted as follows:

  • 1 byte:
    • 4 bits for supported protocol version. (zero is experimental, one is the first published version of this protocol)
    • 4 bits for protocol reset reason:
      • 0: MASRP layer Reset
      • 1: Power-On Reset
      • 2: External Reset
      • 3: Software Reset
      • 4: System Crash
      • 5-15: Reserved
  • 1 byte for the maximum receivable frame size (calculated as MFS minus 16). Valid values are between 0-127, meaning the maximum frame size is between 16 and 143 bytes. Values larger than 127 are reserved: if encountered, assume a max receivable frame size of 143.

Reset packets indicate that the OFC is reset to the value of the OFC field.

For an ACK/NAK, (which contain actual stream content), the payload is formatted as follows:

  • 1 byte:
    • 3 bits reserved, set to zero.
    • 1 bit, FRAME_INCOMPLETE. This is used if the enclosed stream is frame-based. When this bit is not set, the entire frame is considered to be the concatenation of all of the prior subframes that have this bit set.
    • 1 bit, URG (urgent data flag. Used for things like sending CTRL-C, etc)
    • 3 bits for stream id (MUX support). If MUX is not supported, skip frames which have this set to a non-zero value and always set these bits to zero when sending.
  • Payload data

When an ACK/NAK has a payload, the OFC value is incremented. An ACK/NAK without a payload uses the largest previously sent OFC value. REQ and RSP have similar semantics to ACK/NAKs without a payload---they do not change the OFC or AFC.

All mathmatical operations performed on frame counters are modulo 8. I.E.:

$7 + 1 = 0 MOD 8$

Notes about reset

Valid AFC/OFC combinations for a control reset request:

  • RST_REQ_70: AFC:7, OFC:0 (Initial sender)
  • RST_REQ_01: AFC:0, OFC:1 (After having received and responded to a reset)

Valid AFC/OFC combinations for a control reset response:

  • RST_RSP_00: AFC:0, OFC:0 (Response sent before sending reset)
  • RST_RSP_01: AFC:0, OFC:1 (Response sent after sending reset, but before a response was received from other device)
  • RST_RSP_11: AFC:1, OFC:1 (Response sent after sending reset, after having received and responded to a reset)

No matter what path initialization goes through, once initialization is complete, the first data packet sent will have an AFC of 1 and an OFC of 1.

Upon receiving one of the reset messages, a device must behave in the following predefined ways:

  • Receiving RST_REQ_70:

    • If already sent RST_REQ_70,
      • Send RST_RSP_01
    • Otherwise RESET LOCAL STATE and send RST_RSP_00 and then RST_REQ_01
  • Receiving RST_RSP_00

    • If already sent RST_REQ_70,
      • WAIT FOR RST_REQ_01
    • Otherwise RESET LOCAL STATE and send RST_REQ_70
  • Receiving RST_REQ_01

    • If already RECEIVED RST_RSP_00
      • Send RST_RSP_11
      • You are now RUNNING.
    • Otherwise RESET LOCAL STATE and send RST_REQ_70
  • Receiving RST_RSP_01

    • If already sent RST_REQ_70
      • You are now RUNNING.
    • Otherwise RESET LOCAL STATE and send RST_REQ_70
  • Receiving RST_RSP_11

    • If already sent RST_REQ_01
      • You are now RUNNING.
    • Otherwise RESET LOCAL STATE and send RST_REQ_70

Initial Reset Example

Example 1 : Standard reset

Summary:

  • Device A sends RST_REQ_70
  • Device B sends RST_RSP_00
  • Device B sends RST_REQ_01
  • Device A sends RST_RSP_11

Details:

Device Type AFC OFC Payload Description State
Device A - - - - INIT
Device B - - - - INIT
Device A REQ 7 0 RESET, v0, maxRX:64, reason:1
Device B - - - - RESET_RECEIVED
Device B RSP 0 0 RESET, error: 0
Device A - - - - RESET_SENT
Device B REQ 0 1 RESET, v0, maxRX:64, reason:0
Device A - - - - RUNNING
Device A RSP 1 1 RESET, error: 0
Device B - - - - RUNNING
Device B ACK 1 1

Example 2 : Near simultaneous resets

  • A sends RST_REQ_70
  • B sends RST_REQ_70
  • A sends RST_RSP_01
  • B sends RST_RSP_01

Details:

Device Type AFC OFC Payload Description State
Device A - - - - INIT
Device B - - - - INIT
Device A REQ 7 0 RESET, v0, maxRX:64, reason:1
Device B REQ 7 0 RESET, v0, maxRX:64, reason:0
Device A - - - - RESET_RECEIVED
Device B - - - - RESET_RECEIVED
Device A RSP 0 1 RESET, error: 0
Device B RSP 0 1 RESET, error: 0
Device A - - - - RUNNING
Device B - - - - RUNNING
Device B ACK 1 1
Device B ACK 1 2 ...data...
Device A ACK 2 1

Example 3 : Failed reset, with recovery

  • Device A sends RST_REQ_70
  • Device B sends RST_RSP_00
  • Device B sends RST_REQ_01
  • Device A CRASHES!
  • Device A sends RST_REQ_70
  • Device B sends RST_RSP_00
  • Device B sends RST_REQ_01
  • Device A sends RST_RSP_11

Details:

Device Type AFC OFC Payload Description State
Device A - - - - INIT
Device B - - - - INIT
Device A REQ 7 0 RESET, v0, maxRX:64, reason:1
Device B - - - - RESET_RECEIVED
Device B RSP 0 0 RESET, error: 0
Device A - - - DEVICE A CRASHES AND RESTARTS INIT
Device B REQ 0 1 RESET, v0, maxRX:64, reason:0
Device A - - - Ignores previous packet because OFC was not zero
Device A REQ 7 0 RESET, v0, maxRX:64, reason:1
Device B - - - Resets itself, starting over RESET_RECEIVED
Device B RSP 0 0 RESET, error: 0
Device A - - - - RESET_SENT
Device B REQ 0 1 RESET, v0, maxRX:64, reason:0
Device A - - - - RUNNING
Device A RSP 1 1 RESET, error: 0
Device B - - - - RUNNING
Device B ACK 1 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment