diff --git a/target/min.c b/target/min.c index d0d0a8e..9cc253f 100644 --- a/target/min.c +++ b/target/min.c @@ -8,8 +8,8 @@ #define TRANSPORT_FIFO_SIZE_FRAME_DATA_MASK ((uint16_t)((1U << TRANSPORT_FIFO_SIZE_FRAME_DATA_BITS) - 1U)) // Number of bytes needed for a frame with a given payload length, excluding stuff bytes -// 3 header bytes, ID/control byte, length byte, seq byte, 4 byte CRC, EOF byte -#define ON_WIRE_SIZE(p) ((p) + 11U) +// 3 header bytes, ID/control byte, 1 or 2 length bytes, seq byte, 4 byte CRC, EOF byte +#define ON_WIRE_SIZE(p) ((p) + 4U + sizeof(pl_len_t) + 6U) // Special protocol bytes enum { @@ -23,7 +23,8 @@ enum { SEARCHING_FOR_SOF, RECEIVING_ID_CONTROL, RECEIVING_SEQ, - RECEIVING_LENGTH, + RECEIVING_LENGTH_MSB, + RECEIVING_LENGTH_LSB, RECEIVING_PAYLOAD, RECEIVING_CHECKSUM_3, RECEIVING_CHECKSUM_2, @@ -101,9 +102,9 @@ static void stuffed_tx_byte(struct min_context *self, uint8_t byte, bool crc) } } -static void on_wire_bytes(struct min_context *self, uint8_t id_control, uint8_t seq, uint8_t const *payload_base, uint16_t payload_offset, uint16_t payload_mask, uint8_t payload_len) +static void on_wire_bytes(struct min_context *self, uint8_t id_control, uint8_t seq, uint8_t const *payload_base, uint16_t payload_offset, uint16_t payload_mask, pl_len_t payload_len) { - uint8_t n, i; + pl_len_t n, i; uint32_t checksum; self->tx_header_byte_countdown = 2U; @@ -122,7 +123,10 @@ static void on_wire_bytes(struct min_context *self, uint8_t id_control, uint8_t stuffed_tx_byte(self, seq, true); } - stuffed_tx_byte(self, payload_len, true); +#if (MAX_PAYLOAD > UINT8_MAX) + stuffed_tx_byte(self, payload_len >> 8, true); +#endif + stuffed_tx_byte(self, payload_len & 0xFF, true); for(i = 0, n = payload_len; n > 0; n--, i++) { stuffed_tx_byte(self, payload_base[payload_offset], true); @@ -276,7 +280,7 @@ void min_transport_reset(struct min_context *self, bool inform_other_side) // Queues a MIN ID / payload frame into the outgoing FIFO // API call. // Returns true if the frame was queued OK. -bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_t payload_len) +bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, pl_len_t payload_len) { struct transport_frame *frame = transport_fifo_push(self, payload_len); // Claim a FIFO slot, reserve space for payload @@ -301,7 +305,7 @@ bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *pa } } -bool min_queue_has_space_for_frame(struct min_context *self, uint8_t payload_len) { +bool min_queue_has_space_for_frame(struct min_context *self, pl_len_t payload_len) { return self->transport_fifo.n_frames < TRANSPORT_FIFO_MAX_FRAMES && self->transport_fifo.n_ring_buffer_bytes <= TRANSPORT_FIFO_MAX_FRAME_DATA - payload_len; } @@ -339,12 +343,12 @@ static struct transport_frame *find_retransmit_frame(struct min_context *self) // duplicates received, and handling RESET requests. static void valid_frame_received(struct min_context *self) { - uint8_t id_control = self->rx_frame_id_control; - uint8_t *payload = self->rx_frame_payload_buf; - uint8_t payload_len = self->rx_control; + const uint8_t id_control = self->rx_frame_id_control; + const uint8_t * const payload = self->rx_frame_payload_buf; + const pl_len_t payload_len = self->rx_length; #ifdef TRANSPORT_PROTOCOL - uint8_t seq = self->rx_frame_seq; + const uint8_t seq = self->rx_frame_seq; uint8_t num_acked; uint8_t num_nacked; uint8_t num_in_window; @@ -493,17 +497,29 @@ static void rx_byte(struct min_context *self, uint8_t byte) } else { self->rx_frame_seq = 0; - self->rx_frame_state = RECEIVING_LENGTH; + self->rx_frame_state = RECEIVING_LENGTH_MSB; } break; case RECEIVING_SEQ: self->rx_frame_seq = byte; crc32_step(&self->rx_checksum, byte); - self->rx_frame_state = RECEIVING_LENGTH; + self->rx_frame_state = RECEIVING_LENGTH_MSB; + break; + case RECEIVING_LENGTH_MSB: +#if (MAX_PAYLOAD > UINT8_MAX) + self->rx_frame_length = ((uint16_t)byte) << 8; + crc32_step(&self->rx_checksum, byte); + self->rx_frame_state = RECEIVING_LENGTH_LSB; break; - case RECEIVING_LENGTH: - self->rx_frame_length = byte; - self->rx_control = byte; +#else + // MSB == LSB if value is 8-bit + self->rx_frame_length = 0; + self->rx_frame_state = RECEIVING_LENGTH_LSB; +#endif + // FALLTHRU + case RECEIVING_LENGTH_LSB: + self->rx_frame_length |= byte; + self->rx_length = self->rx_frame_length; crc32_step(&self->rx_checksum, byte); if(self->rx_frame_length > 0) { // Can reduce the RAM size by compiling limits to frame sizes @@ -657,7 +673,7 @@ void min_init_context(struct min_context *self, uint8_t port) } // Sends an application MIN frame on the wire (do not put into the transport queue) -void min_send_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_t payload_len) +void min_send_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, pl_len_t payload_len) { if((ON_WIRE_SIZE(payload_len) <= min_tx_space(self->port))) { on_wire_bytes(self, min_id & (uint8_t) 0x3fU, 0, payload, 0, 0xffffU, payload_len); diff --git a/target/min.h b/target/min.h index 5c5879f..62d2839 100644 --- a/target/min.h +++ b/target/min.h @@ -86,8 +86,8 @@ #define TRANSPORT_FIFO_MAX_FRAMES (1U << TRANSPORT_FIFO_SIZE_FRAMES_BITS) #define TRANSPORT_FIFO_MAX_FRAME_DATA (1U << TRANSPORT_FIFO_SIZE_FRAME_DATA_BITS) -#if (MAX_PAYLOAD > 255) -#error "MIN frame payloads can be no bigger than 255 bytes" +#if (MAX_PAYLOAD > 0x7FFF) +#error "MIN frame payloads can be no bigger than 32767 (0x7FFF) bytes" #endif // Indices into the frames FIFO are uint8_t and so can't have more than 256 frames in a FIFO @@ -100,6 +100,12 @@ #error "Transport FIFO data allocated cannot exceed 64Kbytes" #endif +#if (MAX_PAYLOAD > UINT8_MAX) +typedef uint16_t pl_len_t; +#else +typedef uint8_t pl_len_t; +#endif + struct crc32_context { uint32_t crc; }; @@ -109,7 +115,7 @@ struct crc32_context { struct transport_frame { uint32_t last_sent_time_ms; // When frame was last sent (used for re-send timeouts) uint16_t payload_offset; // Where in the ring buffer the payload is - uint8_t payload_len; // How big the payload is + pl_len_t payload_len; // How big the payload is uint8_t min_id; // ID of frame uint8_t seq; // Sequence number of frame }; @@ -146,25 +152,25 @@ struct min_context { struct crc32_context tx_checksum; // Calculated checksum for sending frame uint8_t rx_header_bytes_seen; // Countdown of header bytes to reset state uint8_t rx_frame_state; // State of receiver - uint8_t rx_frame_payload_bytes; // Length of payload received so far + pl_len_t rx_frame_payload_bytes; // Length of payload received so far uint8_t rx_frame_id_control; // ID and control bit of frame being received uint8_t rx_frame_seq; // Sequence number of frame being received - uint8_t rx_frame_length; // Length of frame - uint8_t rx_control; // Control byte + pl_len_t rx_frame_length; // Remaining length of frame to be received + pl_len_t rx_length; // Original received length of the payload uint8_t tx_header_byte_countdown; // Count out the header bytes uint8_t port; // Number of the port associated with the context }; #ifdef TRANSPORT_PROTOCOL // Queue a MIN frame in the transport queue -bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_t payload_len); +bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, pl_len_t payload_len); // Determine if MIN has space to queue a transport frame -bool min_queue_has_space_for_frame(struct min_context *self, uint8_t payload_len); +bool min_queue_has_space_for_frame(struct min_context *self, pl_len_t payload_len); #endif // Send a non-transport frame MIN frame -void min_send_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_t payload_len); +void min_send_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, pl_len_t payload_len); // Must be regularly called, with the received bytes since the last call. // NB: if the transport protocol is being used then even if there are no bytes @@ -175,7 +181,7 @@ void min_poll(struct min_context *self, uint8_t const *buf, uint32_t buf_len); void min_transport_reset(struct min_context *self, bool inform_other_side); // CALLBACK. Handle incoming MIN frame -void min_application_handler(uint8_t min_id, uint8_t const *min_payload, uint8_t len_payload, uint8_t port); +void min_application_handler(uint8_t min_id, uint8_t const *min_payload, pl_len_t len_payload, uint8_t port); #ifdef TRANSPORT_PROTOCOL // CALLBACK. Must return current time in milliseconds.