Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Further improvements #49

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions target/min.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ enum {
uint8_t payloads_ring_buffer[TRANSPORT_FIFO_MAX_FRAME_DATA];

static uint32_t now;
static void send_reset(struct min_context *self);
static bool send_reset(struct min_context *self);
#endif

static void crc32_init_context(struct crc32_context *context)
Expand Down Expand Up @@ -125,7 +125,7 @@ static void on_wire_bytes(struct min_context *self, uint8_t id_control, uint8_t

stuffed_tx_byte(self, payload_len, true);

for(i = 0, n = payload_len; n > 0; n--, i++) {
for((void)(i = 0), n = payload_len; n > 0; n--, i++) {
stuffed_tx_byte(self, payload_base[payload_offset], true);
payload_offset++;
payload_offset &= payload_mask;
Expand Down Expand Up @@ -236,12 +236,14 @@ static void send_ack(struct min_context *self)
}

// We don't queue an RESET frame - we send it straight away (if there's space to do so)
static void send_reset(struct min_context *self)
static bool send_reset(struct min_context *self)
{
min_debug_print("send RESET\n");
if(ON_WIRE_SIZE(0) <= min_tx_space(self->port)) {
on_wire_bytes(self, RESET, 0, 0, 0, 0, 0);
return true;
}
return false;
}

static void transport_fifo_reset(struct min_context *self)
Expand All @@ -262,16 +264,19 @@ static void transport_fifo_reset(struct min_context *self)
self->transport_fifo.last_received_frame_ms = 0;
}

void min_transport_reset(struct min_context *self, bool inform_other_side)
bool min_transport_reset(struct min_context *self, bool inform_other_side)
{
min_debug_print("Resetting %s other side\n", inform_other_side ? "and informing" : "without informing");
if (inform_other_side) {
// Tell the other end we have gone away
send_reset(self);
if(!send_reset(self)) {
return false;
}
}

// Throw our frames away
transport_fifo_reset(self);
return true;
}

// Queues a MIN ID / payload frame into the outgoing FIFO
Expand Down Expand Up @@ -385,9 +390,15 @@ static void valid_frame_received(struct min_context *self)
// Now retransmit the number of frames that were requested
for(i = 0; i < num_nacked; i++) {
struct transport_frame *retransmit_frame = &self->transport_fifo.frames[idx];
transport_fifo_send(self, retransmit_frame);
idx++;
idx &= TRANSPORT_FIFO_SIZE_FRAMES_MASK;
if(ON_WIRE_SIZE(retransmit_frame->payload_len) <= min_tx_space(self->port)) {
transport_fifo_send(self, retransmit_frame);
idx++;
idx &= TRANSPORT_FIFO_SIZE_FRAMES_MASK;
}
else {
min_debug_print("Not enough space to retransmit frame\n");
break;
}
}
}
else {
Expand Down
90 changes: 74 additions & 16 deletions target/min.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,50 +157,108 @@ struct min_context {

#ifdef TRANSPORT_PROTOCOL
// Queue a MIN frame in the transport queue
/**
* Queue a MIN frame in the transport queue
* @param self the min context
* @param min_id the ID of the frame
* @param payload the payload of the frame
* @param payload_len the length of the payload
* @return true if the frame was queued, false otherwise
*/
bool min_queue_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_t payload_len);

// Determine if MIN has space to queue a transport frame
/**
* Determine if MIN has space to queue a transport frame
* @param self the min context
* @param payload_len the length of the payload
* @return true if there is space, false otherwise
*/
bool min_queue_has_space_for_frame(struct min_context *self, uint8_t payload_len);
#endif

// Send a non-transport frame MIN frame
/**
* Send a MIN frame
* @param self the min context
* @param min_id the ID of the frame
* @param payload the payload of the frame
* @param payload_len the length of the payload
*/
void min_send_frame(struct min_context *self, uint8_t min_id, uint8_t const *payload, uint8_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
// this call must still be made in order to drive the state machine for retransmits.
/**
* Process incoming bytes or internal queue
* If using transport protocol, must be called regularly to drive the state machine for retransmits, even if there are no received bytes
* @param self the min context
* @param buf the buffer of bytes to process, or NULL
* @param buf_len the length of the buffer, or 0
*/
void min_poll(struct min_context *self, uint8_t const *buf, uint32_t buf_len);

// Reset the state machine and (optionally) tell the other side that we have done so
void min_transport_reset(struct min_context *self, bool inform_other_side);
/**
* Reset the state machine and (optionally) tell the other side that we have done so
* @param self the min context
* @param inform_other_side true if we should send a reset frame to the other side
* @return false if inform_other_side is true and there is no space to send the reset frame, true otherwise
*/
bool min_transport_reset(struct min_context *self, bool inform_other_side);

// CALLBACK. Handle incoming MIN frame
/**
* CALLBACK. Handle incoming MIN frame
* @param min_id the ID of the frame
* @param min_payload the payload of the frame
* @param len_payload the length of the payload
* @param port the port the frame was received on
*/
void min_application_handler(uint8_t min_id, uint8_t const *min_payload, uint8_t len_payload, uint8_t port);

#ifdef TRANSPORT_PROTOCOL
// CALLBACK. Must return current time in milliseconds.
// Typically a tick timer interrupt will increment a 32-bit variable every 1ms (e.g. SysTick on Cortex M ARM devices).
/**
* CALLBACK. Must return current time in milliseconds.
* @return the current time in milliseconds
*/
uint32_t min_time_ms(void);
#endif

// CALLBACK. Must return current buffer space in the given port. Used to check that a frame can be
// queued.
/**
* CALLBACK. Must return current buffer space in the given port. Used to check that a frame can be queued.
* @param port the port to check
* @return the number of bytes of space available. If sufficient space is available, data will be sent on the line.
*/
uint16_t min_tx_space(uint8_t port);

// CALLBACK. Send a byte on the given line.
/**
* CALLBACK. Send a byte on the given line.
* @param port the port to send the byte on
* @param byte the byte to send
*/
void min_tx_byte(uint8_t port, uint8_t byte);

// CALLBACK. Indcates when frame transmission is finished; useful for buffering bytes into a single serial call.
/**
* CALLBACK. Indicates when frame transmission is finished; useful for buffering bytes into a single serial call.
* @param port the port that is starting sending
*/
void min_tx_start(uint8_t port);
/**
* CALLBACK. Indicates when frame transmission is finished; useful for buffering bytes into a single serial call.
* @param port the port that has finished sending
*/
void min_tx_finished(uint8_t port);

// define to validate that MAX_PAYLOAD is defined the same value in calling code and min
#ifdef VALIDATE_MAX_PAYLOAD
void min_init_context_validate(struct min_context *self, uint8_t port, void * p_rx_frame_checksum);
/**
* Initialize a MIN context ready for receiving bytes from a serial link (can have multiple MIN contexts)
* @param self the min context
* @param port the port number associated with the context
*/
#define min_init_context(self, port) min_init_context_validate(self, port, &(self)->rx_frame_checksum)
#else
// Initialize a MIN context ready for receiving bytes from a serial link
// (Can have multiple MIN contexts)
/**
* Initialize a MIN context ready for receiving bytes from a serial link (can have multiple MIN contexts)
* @param self the min context
* @param port the port number associated with the context
*/
void min_init_context(struct min_context *self, uint8_t port);
#endif

Expand Down