From 3f737b9b39d53be0b27335908c94189593fae02c Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 28 Feb 2019 08:14:48 +0200 Subject: [PATCH 01/80] Initial incomplete proto state. --- README.md | 5 + am/mist_comm_am.c | 182 ++++++++++++++++++++++++++++++++ api/mist_comm_api.c | 209 +++++++++++++++++++++++++++++++++++++ include/mist_comm.h | 148 ++++++++++++++++++++++++++ include/mist_comm_am.h | 35 +++++++ include/mist_comm_am_msg.h | 31 ++++++ include/mist_comm_basics.h | 12 +++ include/mist_comm_eui.h | 20 ++++ include/mist_comm_iface.h | 83 +++++++++++++++ test/Makefile | 6 ++ test/main.c | 22 ++++ test/platform_msg.h | 12 +++ 12 files changed, 765 insertions(+) create mode 100644 am/mist_comm_am.c create mode 100644 api/mist_comm_api.c create mode 100644 include/mist_comm.h create mode 100644 include/mist_comm_am.h create mode 100644 include/mist_comm_am_msg.h create mode 100644 include/mist_comm_basics.h create mode 100644 include/mist_comm_eui.h create mode 100644 include/mist_comm_iface.h create mode 100644 test/Makefile create mode 100644 test/main.c create mode 100644 test/platform_msg.h diff --git a/README.md b/README.md index c08e197..0f6c3e4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # mist-comm Mist communications and security APIs. + + +# Features + +* address mapping diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c new file mode 100644 index 0000000..8a92b27 --- /dev/null +++ b/am/mist_comm_am.c @@ -0,0 +1,182 @@ + +#include "mist_comm.h" +#include "mist_comm_iface.h" +#include "mist_comm_am.h" + +#include + +static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { + if(comms != NULL) { + msg->layer = (comms_layer_t*)comms; + } +} + +static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + return COMMS_FAIL; +} + +static comms_receiver_id_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receive_f* func, void *user, am_id_t amid) { + return -1; +} +static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_id_t rid) { + return COMMS_FAIL; +} + +static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static void am_comms_set_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { +} +static void* am_comms_get_payload(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { + return NULL; +} + +static uint8_t am_comms_get_retries(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static comms_error_t am_comms_set_retries(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { + return COMMS_EINVAL; +} + +static uint8_t am_comms_get_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static comms_error_t am_comms_set_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { + return COMMS_EINVAL; +} + +static uint32_t am_comms_get_timeout(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timeout) { + return COMMS_EINVAL; +} + +static bool am_comms_is_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg) { + return false; +} +static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { + return COMMS_EINVAL; +} +static bool am_comms_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg) { + return false; +} + +static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { + return COMMS_EINVAL; +} +static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static bool am_comms_event_time_valid(comms_layer_iface_t* comms, comms_msg_t* msg) { + return false; +} + +static uint8_t am_comms_get_lqi(comms_layer_iface_t* comms, comms_msg_t* msg) { + return 0; +} +static void am_comms_set_lqi(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t lqi) { +} + +static int8_t am_comms_get_rssi(comms_layer_iface_t* comms, comms_msg_t* msg) { + return -128; +} +static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t rssi) { +} + + +static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, comms_msg_t* msg) { + return *((am_addr_t*)msg->body.destination); +} +static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { + *((am_addr_t*)msg->body.destination) = dest; +} + +static am_addr_t am_comms_get_source(comms_layer_am_t* comms, comms_msg_t* msg) { + return *((am_addr_t*)msg->body.source); +} +static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { + *((am_addr_t*)msg->body.source) = source; +} + +am_addr_t comms_am_get_destination(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; + return comms->am_get_destination(comms, msg); + } + } + return 0; +} +void comms_am_set_destination(comms_msg_t* msg, am_addr_t dest) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; + comms->am_set_destination(comms, msg, dest); + } + } +} + +am_addr_t comms_am_get_source(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; + return comms->am_get_source(comms, msg); + } + } + return 0; +} +void comms_am_set_source(comms_msg_t* msg, am_addr_t source) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; + comms->am_set_source(comms, msg, source); + } + } +} + +comms_error_t comms_am_create(comms_layer_t* layer) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; + comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; + + comms->init_message = &am_comms_init_message; + + comms->send = &am_comms_send; + comms->register_recv = &am_comms_register_recv; + comms->deregister_recv = &am_comms_deregister_recv; + + comms->get_payload_length = &am_comms_get_payload_length; + comms->set_payload_length = &am_comms_set_payload_length; + comms->get_payload = &am_comms_get_payload; + + comms->get_retries = &am_comms_get_retries; + comms->set_retries = &am_comms_set_retries; + + comms->get_retries_used = &am_comms_get_retries_used; + comms->set_retries_used = &am_comms_set_retries_used; + + comms->get_timeout = &am_comms_get_timeout; + comms->set_timeout = &am_comms_set_timeout; + + comms->is_ack_required = &am_comms_is_ack_required; + comms->set_ack_required = &am_comms_set_ack_required; + + comms->ack_received = &am_comms_ack_received; + + comms->set_event_time = &am_comms_set_event_time; + comms->get_event_time = &am_comms_get_event_time; + comms->event_time_valid = &am_comms_event_time_valid; + + comms->get_lqi = &am_comms_get_lqi; + comms->set_lqi = &am_comms_set_lqi; + + comms->get_rssi = &am_comms_get_rssi; + comms->set_rssi = &am_comms_set_rssi; + + amcomms->am_get_destination = &am_comms_get_destination; + amcomms->am_set_destination = &am_comms_set_destination; + amcomms->am_get_source = &am_comms_get_source; + amcomms->am_set_source = &am_comms_set_source; + + return COMMS_SUCCESS; +} diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c new file mode 100644 index 0000000..19e7ed6 --- /dev/null +++ b/api/mist_comm_api.c @@ -0,0 +1,209 @@ +#include "mist_comm.h" +#include "mist_comm_iface.h" + +#include + +void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { + if((comms != NULL)&&(msg != NULL)) { + ((comms_layer_iface_t*)comms)->init_message((comms_layer_iface_t*)comms, msg); + } +} + +comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + if(comms != NULL) { + return ((comms_layer_iface_t*)comms)->send((comms_layer_iface_t*)comms, msg, sdf, user); + } + return COMMS_EINVAL; +} + +comms_receiver_id_t comms_register_recv(comms_layer_t* comms, comms_receive_f* func, void *user, am_id_t amid) { + if(comms != NULL) { + return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, func, user, amid); + } + return -1; +} +comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t rid) { + if(comms != NULL) { + return ((comms_layer_iface_t*)comms)->deregister_recv((comms_layer_iface_t*)comms, rid); + } + return COMMS_EINVAL; +} + +uint8_t comms_get_payload_length(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_payload_length(comms, msg); + } + } + return 0; +} +void comms_set_payload_length(comms_msg_t* msg, uint8_t length) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + comms->set_payload_length(comms, msg, length); + } + } +} +void* comms_get_payload(comms_msg_t* msg, uint8_t length) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_payload(comms, msg, length); + } + } + return NULL; +} + +uint8_t comms_get_retries(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_retries(comms, msg); + } + } + return 0; +} +comms_error_t comms_set_retries(comms_msg_t* msg, uint8_t count) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->set_retries(comms, msg, count); + } + } + return COMMS_EINVAL; +} + +uint8_t comms_get_retries_used(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_retries_used(comms, msg); + } + } + return 0; +} +comms_error_t comms_set_retries_used(comms_msg_t* msg, uint8_t count) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->set_retries_used(comms, msg, count); + } + } + return COMMS_EINVAL; +} + +uint32_t comms_get_timeout(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_timeout(comms, msg); + } + } + return 0; +} +comms_error_t comms_set_timeout(comms_msg_t* msg, uint32_t timeout) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->set_timeout(comms, msg, timeout); + } + return COMMS_UNINITIALIZED; + } + return COMMS_EINVAL; +} + +bool comms_is_ack_required(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->is_ack_required(comms, msg); + } + } + return false; +} +comms_error_t comms_set_ack_required(comms_msg_t* msg, bool required) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->set_ack_required(comms, msg, required); + } + return COMMS_UNINITIALIZED; + } + return COMMS_EINVAL; +} +bool comms_ack_received(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->ack_received(comms, msg); + } + } + return false; +} + +comms_error_t comms_set_event_time(comms_msg_t* msg, uint32_t evt) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->set_event_time(comms, msg, evt); + } + return COMMS_UNINITIALIZED; + } + return COMMS_EINVAL; +} +uint32_t comms_get_event_time(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_event_time(comms, msg); + } + } + return 0; +} +bool comms_event_time_valid(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->event_time_valid(comms, msg); + } + } + return false; +} + +uint8_t comms_get_lqi(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_lqi(comms, msg); + } + } + return 0; +} +void comms_set_lqi(comms_msg_t* msg, uint8_t lqi) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + comms->set_lqi(comms, msg, lqi); + } + } +} + +int8_t comms_get_rssi(comms_msg_t* msg) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + return comms->get_rssi(comms, msg); + } + } + return -128; +} +void comms_set_rssi(comms_msg_t* msg, int8_t rssi) { + if(msg != NULL) { + if(msg->layer != NULL) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; + comms->set_rssi(comms, msg, rssi); + } + } +} diff --git a/include/mist_comm.h b/include/mist_comm.h new file mode 100644 index 0000000..7a2c879 --- /dev/null +++ b/include/mist_comm.h @@ -0,0 +1,148 @@ +#ifndef MIST_COMM_H_ +#define MIST_COMM_H_ +// Mist Communication API ------------------------------------------------------ + +#include +#include +#include + +#include "mist_comm_basics.h" + +#include "platform_msg.h" + +typedef enum CommsErrors { + COMMS_UNINITIALIZED = -127, + COMMS_NOT_SUPPORTED = -126, + + COMMS_NO_ADDR = -15, + COMMS_NO_KEY = -14, + COMMS_NO_ROUTE = -13, + + COMMS_ETIMEOUT = -12, + COMMS_ENOACK = -11, + COMMS_ENOMEM = -10, + COMMS_EALREADY = -9, // Would prefer to use positive COMMS_ALREADY instead + COMMS_ERESERVE = -8, + COMMS_ERETRY = -7, + COMMS_EINVAL = -6, + COMMS_EBUSY = -5, + COMMS_EOFF = -4, + COMMS_ECANCEL = -3, + COMMS_SIZE = -2, + COMMS_FAIL = -1, + + COMMS_SUCCESS = 0, + COMMS_ALREADY = 1 +} comms_error_t; + +typedef struct comms_layer { + uint8_t type; + // Everything else will embed at least this structure +} comms_layer_t; + +typedef struct comms_msg comms_msg_t; +typedef struct comms_msg { + comms_layer_t* layer; + struct { + uint16_t application; // AMID, port? + uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; + uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; + uint8_t header[COMMS_MSG_HEADER_SIZE]; + uint8_t payload[COMMS_MSG_PAYLOAD_SIZE]; + uint8_t footer[COMMS_MSG_FOOTER_SIZE]; + uint8_t metadata[COMMS_MSG_METADATA_SIZE]; + } body; + comms_msg_t* next; // ... maybe, could be very useful for transitioning through layers +} comms_msg_t; + +typedef int16_t comms_receiver_id_t; + +// Initialize a message structure for use on the specified communications +// layer. Must be called before any packet functions can be used. +void comms_init_message(comms_layer_t* comms, comms_msg_t* msg); + +// Callback definitions -------------------------------------------------------- + +// Signalled when message transmission is completed to return the message object +// to the client. A function of this type must be passed with every call to the +// comms_send function and the passed function will be called in the future if +// the comms_send returns a successful result (message is accepted). +typedef void comms_send_done_f(void* user, comms_msg_t* msg, comms_error_t result); + +// Signalled when a message is received. Functions of this type must first be +// registered with a communications layer with comms_register_recv. +typedef comms_msg_t* comms_receive_f(void* user, comms_msg_t* msg); + +// Send a message through the specified communications layer. +// The callback function specified with the send done function argument sdf will +// be called some time in the future if comms_send returns SUCCESS. The sdf +// argument is mandatory, the user argument may be NULL. +comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user); + +// Receiver and receiver registration ------------------------------------------ + +// returns a unique receiver ID, which can be used to deregister the receiver. +// Only non-negative receiver IDs are valid, a negative value indicates failure. +// The same receive function can be registered several times for different +// conditions and with a different user argument. +comms_receiver_id_t comms_register_recv(comms_layer_t* comms, comms_receive_f* func, void *user, am_id_t amid); +// ??? +// last param should be some form of generic args, but this is C ... are we ok +// to proceed with AM ID or should we expand and rename? 16 bit port? +// and what other filtering is needed for receives ... if any? +// ??? + +// Remove and already registered receive function. +comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t rid); + +// Message payload manipulation functions -------------------------------------- +uint8_t comms_get_payload_length(comms_msg_t* msg); +void comms_set_payload_length(comms_msg_t* msg, uint8_t length); + +void* comms_get_payload(comms_msg_t* msg, uint8_t length); +// ??? +// Do we want support for larger payloads - uint16_t length? +// ??? +// ----------------------------------------------------------------------------- + +// PacketLink & Acknowledgements +uint8_t comms_get_retries(comms_msg_t* msg); +comms_error_t comms_set_retries(comms_msg_t* msg, uint8_t count); + +uint8_t comms_get_retries_used(comms_msg_t* msg); +comms_error_t comms_set_retries_used(comms_msg_t* msg, uint8_t count); + +uint32_t comms_get_timeout(comms_msg_t* msg); +comms_error_t comms_set_timeout(comms_msg_t* msg, uint32_t timeout); + +bool comms_is_ack_required(comms_msg_t* msg); +comms_error_t comms_set_ack_required(comms_msg_t* msg, bool required); + +// Check delivery for both PacketLink and simple Ack use cases +bool comms_ack_received(comms_msg_t* msg); +// ----------------------------------------------------------------------------- + +// TimeSync messaging +// Event time is microseconds local clock + +// Set event time +comms_error_t comms_set_event_time(comms_msg_t* msg, uint32_t evt); + +// Check that event time is valid with comms_event_time_valid. +uint32_t comms_get_event_time(comms_msg_t* msg); + +// return TRUE if message has valid event time +bool comms_event_time_valid(comms_msg_t* msg); +// ----------------------------------------------------------------------------- + +// Message Quality +uint8_t comms_get_lqi(comms_msg_t* msg); +void comms_set_lqi(comms_msg_t* msg, uint8_t lqi); +// ??? standardize on 0-100 instead of 0-255, because for example CC1101 LQI goes from 0-127 and is inverse to Atmel RFX. + +// Value in dBm +int8_t comms_get_rssi(comms_msg_t* msg); +void comms_set_rssi(comms_msg_t* msg, int8_t rssi); +// ----------------------------------------------------------------------------- + +#endif//MIST_COMM_H_ diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h new file mode 100644 index 0000000..901ff14 --- /dev/null +++ b/include/mist_comm_am.h @@ -0,0 +1,35 @@ +#ifndef MIST_COMM_AM_H_ +#define MIST_COMM_AM_H_ + +#include "mist_comm.h" +#include "mist_comm_iface.h" + +typedef struct comms_layer_am comms_layer_am_t; + +typedef am_addr_t comms_am_get_destination_f(comms_layer_am_t*, comms_msg_t*); +typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); + +typedef am_addr_t comms_am_get_source_f(comms_layer_am_t*, comms_msg_t*); +typedef void comms_am_set_source_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); + +typedef struct comms_layer_am { + comms_layer_iface_t base; + + comms_am_get_destination_f* am_get_destination; + comms_am_set_destination_f* am_set_destination; + + comms_am_get_source_f* am_get_source; + comms_am_set_source_f* am_set_source; +} comms_layer_am_t; + +// Message manipulation functions for ActiveMessage layer ---------------------- +am_addr_t comms_am_get_destination(comms_msg_t* msg); +void comms_am_set_destination(comms_msg_t* msg, am_addr_t dest); + +am_addr_t comms_am_get_source(comms_msg_t* msg); +void comms_am_set_source(comms_msg_t* msg, am_addr_t source); +// ----------------------------------------------------------------------------- + +comms_error_t comms_am_create(comms_layer_t* layer); + +#endif//MIST_COMM_AM_H_ diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h new file mode 100644 index 0000000..5f3221c --- /dev/null +++ b/include/mist_comm_am_msg.h @@ -0,0 +1,31 @@ +#ifndef MIST_COMM_AM_MSG_H_ +#define MIST_COMM_AM_MSG_H_ + +#include "mist_comm_basics.h" + +typedef struct comms_am_msg_header { + am_addr_t source; + am_addr_t destination; + am_group_t group; + am_id_t amid; +} comms_am_msg_header_t; + +typedef struct comms_am_msg_footer { +} comms_am_msg_footer_t; + +typedef struct comms_am_msg_metadata { + int8_t rssi; + uint8_t lqi; + + uint8_t sent; + uint8_t retries; + uint32_t timeout; + + bool ack_requested; + bool ack_received; + + bool event_time_valid; + uint32_t event_time; +} comms_am_msg_metadata_t; + +#endif//MIST_COMM_AM_H_ diff --git a/include/mist_comm_basics.h b/include/mist_comm_basics.h new file mode 100644 index 0000000..b80367b --- /dev/null +++ b/include/mist_comm_basics.h @@ -0,0 +1,12 @@ +#ifndef MIST_COMM_BASICS +#define MIST_COMM_BASICS + +typedef uint8_t am_group_t; +typedef uint8_t am_id_t; +typedef uint16_t am_addr_t; + +typedef struct ieee_eui64 { + uint8_t data[8]; +} ieee_eui64_t; + +#endif//MIST_COMM_BASICS diff --git a/include/mist_comm_eui.h b/include/mist_comm_eui.h new file mode 100644 index 0000000..f090c67 --- /dev/null +++ b/include/mist_comm_eui.h @@ -0,0 +1,20 @@ +#ifndef MIST_COMM_EUI_H_ +#define MIST_COMM_EUI_H_ + +// Address manipulation functions for EUI communications layer ----------------- +ieee_eui64_t comms_get_destination(comms_msg_t* msg); +void comms_set_destination(comms_msg_t* msg, ieee_eui64_t dest); + +ieee_eui64_t comms_get_source(comms_msg_t* msg); +void comms_set_source(comms_msg_t* msg, ieee_eui64_t source); +// ??? +// consider using EUI pointers? +// ??? + +// +// TODO EUI registry functions will have to be defined +// + +// ----------------------------------------------------------------------------- + +#endif//MIST_COMM_EUI_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h new file mode 100644 index 0000000..7c22619 --- /dev/null +++ b/include/mist_comm_iface.h @@ -0,0 +1,83 @@ +#ifndef MIST_COMM_IFACE_H_ +#define MIST_COMM_IFACE_H_ + +#include "mist_comm.h" + +typedef struct comms_layer_iface comms_layer_iface_t; + +typedef void comms_init_message_f(comms_layer_iface_t*, comms_msg_t*); + +typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_send_done_f*, void*); +typedef comms_receiver_id_t comms_register_recv_f(comms_layer_iface_t*, comms_receive_f*, void*, am_id_t); +typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_id_t); + +typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, comms_msg_t*); +typedef void comms_set_payload_length_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); +typedef void* comms_get_payload_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); + +typedef uint8_t comms_get_retries_f(comms_layer_iface_t*, comms_msg_t*); +typedef comms_error_t comms_set_retries_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); + +typedef uint8_t comms_get_retries_used_f(comms_layer_iface_t*, comms_msg_t*); +typedef comms_error_t comms_set_retries_used_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); + +typedef uint32_t comms_get_timeout_f(comms_layer_iface_t*, comms_msg_t*); +typedef comms_error_t comms_set_timeout_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); + +typedef bool comms_is_ack_required_f(comms_layer_iface_t*, comms_msg_t*); +typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t*, bool); + +typedef bool comms_ack_received_f(comms_layer_iface_t*, comms_msg_t*); + +typedef comms_error_t comms_set_event_time_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); +typedef uint32_t comms_get_event_time_f(comms_layer_iface_t*, comms_msg_t*); +typedef bool comms_event_time_valid_f(comms_layer_iface_t*, comms_msg_t*); + +typedef uint8_t comms_get_lqi_f(comms_layer_iface_t*, comms_msg_t*); +typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); + +typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, comms_msg_t*); +typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); + +// ----------------------------------------------------------------------------- + +typedef struct comms_layer_iface { + comms_layer_t layer; // Type info + + comms_init_message_f* init_message; + + comms_send_f* send; + comms_register_recv_f* register_recv; + comms_deregister_recv_f* deregister_recv; + + comms_get_payload_length_f* get_payload_length; + comms_set_payload_length_f* set_payload_length; + comms_get_payload_f* get_payload; + + comms_get_retries_f* get_retries; + comms_set_retries_f* set_retries; + + comms_get_retries_used_f* get_retries_used; + comms_set_retries_used_f* set_retries_used; + + comms_get_timeout_f* get_timeout; + comms_set_timeout_f* set_timeout; + + comms_is_ack_required_f* is_ack_required; + comms_set_ack_required_f* set_ack_required; + + comms_ack_received_f* ack_received; + + comms_set_event_time_f* set_event_time; + comms_get_event_time_f* get_event_time; + comms_event_time_valid_f* event_time_valid; + + comms_get_lqi_f* get_lqi; + comms_set_lqi_f* set_lqi; + + comms_get_rssi_f* get_rssi; + comms_set_rssi_f* set_rssi; + +} comms_layer_iface_t; + +#endif//MIST_COMM_IFACE_H_ diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..c3af729 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,6 @@ +# Makefile + +CFLAGS = -I. -I../api -I../include -std=c99 + +all: + gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../am/mist_comm_am.c -o test diff --git a/test/main.c b/test/main.c new file mode 100644 index 0000000..18b1f71 --- /dev/null +++ b/test/main.c @@ -0,0 +1,22 @@ +#include + +#include "mist_comm.h" +#include "mist_comm_am.h" + +int main() { + comms_msg_t msg; + uint8_t m[256]; + comms_layer_t* comm = (comms_layer_t*)m; + + comms_error_t err = comms_am_create(comm); + printf("create=%d\n", err); + + comms_init_message(comm, &msg); + comms_am_set_destination(&msg, 0xFFFF); + comms_am_set_source(&msg, 0x0001); + + printf("%04X->%04X\n", comms_am_get_source(&msg), comms_am_get_destination(&msg)); + + return 0; +} + diff --git a/test/platform_msg.h b/test/platform_msg.h new file mode 100644 index 0000000..c828957 --- /dev/null +++ b/test/platform_msg.h @@ -0,0 +1,12 @@ +#ifndef PLATFORM_MSG_H_ +#define PLATFORM_MSG_H_ + +#include "mist_comm_am_msg.h" + +#define COMMS_MSG_ADDRESSING_SIZE 2 +#define COMMS_MSG_HEADER_SIZE 1 +#define COMMS_MSG_PAYLOAD_SIZE 128 +#define COMMS_MSG_FOOTER_SIZE 0 +#define COMMS_MSG_METADATA_SIZE sizeof(comms_am_msg_metadata_t) + +#endif//PLATFORM_MSG_H_ From 0b2e6041f4e5d2a55cd08741061443be157d69db Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 1 Mar 2019 09:32:21 +0200 Subject: [PATCH 02/80] Add dummy send example. --- am/mist_comm_am.c | 16 ++++++++++--- include/mist_comm.h | 3 +++ include/mist_comm_am.h | 2 +- test/main.c | 52 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 8a92b27..6272fbf 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -8,6 +8,7 @@ static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { if(comms != NULL) { msg->layer = (comms_layer_t*)comms; + msg->body.length = 0; } } @@ -23,11 +24,15 @@ static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_ } static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return msg->body.length; } static void am_comms_set_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { + msg->body.length = length; } static void* am_comms_get_payload(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { + if(length < sizeof(msg->body.payload)) { + return (void*)(msg->body.payload); + } return NULL; } @@ -135,13 +140,18 @@ void comms_am_set_source(comms_msg_t* msg, am_addr_t source) { } } -comms_error_t comms_am_create(comms_layer_t* layer) { +comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; comms->init_message = &am_comms_init_message; - comms->send = &am_comms_send; + if(sender != NULL) { + comms->send = sender; + } + else { + comms->send = &am_comms_send; + } comms->register_recv = &am_comms_register_recv; comms->deregister_recv = &am_comms_deregister_recv; diff --git a/include/mist_comm.h b/include/mist_comm.h index 7a2c879..7c3bc59 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -48,7 +48,10 @@ typedef struct comms_msg { uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; uint8_t header[COMMS_MSG_HEADER_SIZE]; + + uint8_t length; uint8_t payload[COMMS_MSG_PAYLOAD_SIZE]; + uint8_t footer[COMMS_MSG_FOOTER_SIZE]; uint8_t metadata[COMMS_MSG_METADATA_SIZE]; } body; diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 901ff14..ba02c35 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -30,6 +30,6 @@ am_addr_t comms_am_get_source(comms_msg_t* msg); void comms_am_set_source(comms_msg_t* msg, am_addr_t source); // ----------------------------------------------------------------------------- -comms_error_t comms_am_create(comms_layer_t* layer); +comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender); #endif//MIST_COMM_AM_H_ diff --git a/test/main.c b/test/main.c index 18b1f71..7e0cba4 100644 --- a/test/main.c +++ b/test/main.c @@ -1,22 +1,70 @@ #include +#include +#include +#include // sleep #include "mist_comm.h" #include "mist_comm_am.h" +static bool sent = false; + +const char hello[] = "HelloWorld!"; + +comms_msg_t* _msg = NULL; +comms_send_done_f* _sdf = NULL; +void* _user = NULL; + +comms_error_t fake_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + if(_msg == NULL) { + _msg = msg; + _sdf = sdf; + _user = user; + return COMMS_SUCCESS; + } + return COMMS_EBUSY; +} + +void send_done(void* user, comms_msg_t* msg, comms_error_t result) { + printf("sd %p, %p, %u\n", user, msg, result); + sent = true; +} + int main() { comms_msg_t msg; uint8_t m[256]; + uint8_t* payload; comms_layer_t* comm = (comms_layer_t*)m; - comms_error_t err = comms_am_create(comm); + comms_error_t err = comms_am_create(comm, &fake_comms_send); printf("create=%d\n", err); comms_init_message(comm, &msg); comms_am_set_destination(&msg, 0xFFFF); comms_am_set_source(&msg, 0x0001); + payload = comms_get_payload(&msg, strlen(hello)+1); + if(payload == NULL) { + printf("payload NULL\n"); + return 1; + } + strncpy(payload, hello, strlen(hello)+1); + printf("%04X->%04X\n", comms_am_get_source(&msg), comms_am_get_destination(&msg)); + err = comms_send(comm, &msg, &send_done, NULL); + printf("send(%p)=%d\n", &msg, err); + if(err != COMMS_SUCCESS) { + return 1; + } + + while(sent == false) { + sleep(1); + if(_msg != NULL) { + comms_msg_t* m = _msg; + _msg = NULL; + _sdf(_user, m, COMMS_SUCCESS); + } + } + return 0; } - From ddcb0a551b5ae72a701c8106f42a1353e51db3c1 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 1 Mar 2019 09:32:56 +0200 Subject: [PATCH 03/80] Add gitignore for test dir. --- test/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/.gitignore diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..9daeafb --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +test From 0a5545052804f608d3634cfd81f4b43c1f953ae1 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 4 Mar 2019 12:19:02 +0200 Subject: [PATCH 04/80] Decided msg should not carry a ref to layer. --- am/mist_comm_am.c | 51 ++++------ api/mist_comm_api.c | 197 ++++++++++++++++---------------------- include/mist_comm.h | 41 ++++---- include/mist_comm_am.h | 8 +- include/mist_comm_iface.h | 2 + test/main.c | 8 +- 6 files changed, 128 insertions(+), 179 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 6272fbf..041dc21 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -6,10 +6,7 @@ #include static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { - if(comms != NULL) { - msg->layer = (comms_layer_t*)comms; - msg->body.length = 0; - } + msg->body.length = 0; } static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { @@ -23,6 +20,9 @@ static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_ return COMMS_FAIL; } +static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* comms) { + return 114; +} static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg) { return msg->body.length; } @@ -104,40 +104,22 @@ static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_ad *((am_addr_t*)msg->body.source) = source; } -am_addr_t comms_am_get_destination(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; - return comms->am_get_destination(comms, msg); - } - } - return 0; +am_addr_t comms_am_get_destination(comms_layer_t* comms, comms_msg_t* msg) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + return amcomms->am_get_destination(amcomms, msg); } -void comms_am_set_destination(comms_msg_t* msg, am_addr_t dest) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; - comms->am_set_destination(comms, msg, dest); - } - } +void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + amcomms->am_set_destination(amcomms, msg, dest); } -am_addr_t comms_am_get_source(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; - return comms->am_get_source(comms, msg); - } - } - return 0; +am_addr_t comms_am_get_source(comms_layer_t* comms, comms_msg_t* msg) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + return amcomms->am_get_source(amcomms, msg); } -void comms_am_set_source(comms_msg_t* msg, am_addr_t source) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_am_t* comms = (comms_layer_am_t*)msg->layer; - comms->am_set_source(comms, msg, source); - } - } +void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + amcomms->am_set_source(amcomms, msg, source); } comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { @@ -155,6 +137,7 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { comms->register_recv = &am_comms_register_recv; comms->deregister_recv = &am_comms_deregister_recv; + comms->get_payload_max_length = &am_comms_get_payload_max_length; comms->get_payload_length = &am_comms_get_payload_length; comms->set_payload_length = &am_comms_set_payload_length; comms->get_payload = &am_comms_get_payload; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 19e7ed6..2a6669d 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -29,181 +29,144 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t ri return COMMS_EINVAL; } -uint8_t comms_get_payload_length(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_payload_length(comms, msg); - } +uint8_t comms_get_payload_max_length(comms_layer_t* comms) { + return ((comms_layer_iface_t*)comms)->get_payload_max_length((comms_layer_iface_t*)comms); +} + +uint8_t comms_get_payload_length(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_payload_length(cl, msg); } return 0; } -void comms_set_payload_length(comms_msg_t* msg, uint8_t length) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - comms->set_payload_length(comms, msg, length); - } +void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_payload_length(cl, msg, length); } } -void* comms_get_payload(comms_msg_t* msg, uint8_t length) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_payload(comms, msg, length); - } +void* comms_get_payload(comms_layer_t* comms, comms_msg_t* msg, uint8_t length) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_payload(cl, msg, length); } return NULL; } -uint8_t comms_get_retries(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_retries(comms, msg); - } +uint8_t comms_get_retries(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_retries(cl, msg); } return 0; } -comms_error_t comms_set_retries(comms_msg_t* msg, uint8_t count) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->set_retries(comms, msg, count); - } +comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_retries(cl, msg, count); } return COMMS_EINVAL; } -uint8_t comms_get_retries_used(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_retries_used(comms, msg); - } +uint8_t comms_get_retries_used(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_retries_used(cl, msg); } return 0; } -comms_error_t comms_set_retries_used(comms_msg_t* msg, uint8_t count) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->set_retries_used(comms, msg, count); - } +comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uint8_t count) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_retries_used(cl, msg, count); } return COMMS_EINVAL; } -uint32_t comms_get_timeout(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_timeout(comms, msg); - } +uint32_t comms_get_timeout(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_timeout(cl, msg); } return 0; } -comms_error_t comms_set_timeout(comms_msg_t* msg, uint32_t timeout) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->set_timeout(comms, msg, timeout); - } - return COMMS_UNINITIALIZED; +comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t timeout) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_timeout(cl, msg, timeout); } return COMMS_EINVAL; } -bool comms_is_ack_required(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->is_ack_required(comms, msg); - } +bool comms_is_ack_required(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->is_ack_required(cl, msg); } return false; } -comms_error_t comms_set_ack_required(comms_msg_t* msg, bool required) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->set_ack_required(comms, msg, required); - } - return COMMS_UNINITIALIZED; +comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_ack_required(cl, msg, required); } return COMMS_EINVAL; } -bool comms_ack_received(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->ack_received(comms, msg); - } +bool comms_ack_received(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->ack_received(cl, msg); } return false; } -comms_error_t comms_set_event_time(comms_msg_t* msg, uint32_t evt) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->set_event_time(comms, msg, evt); - } - return COMMS_UNINITIALIZED; +comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_event_time(cl, msg, evt); } return COMMS_EINVAL; } -uint32_t comms_get_event_time(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_event_time(comms, msg); - } +uint32_t comms_get_event_time(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_event_time(cl, msg); } return 0; } -bool comms_event_time_valid(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->event_time_valid(comms, msg); - } +bool comms_event_time_valid(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->event_time_valid(cl, msg); } return false; } -uint8_t comms_get_lqi(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_lqi(comms, msg); - } +uint8_t comms_get_lqi(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_lqi(cl, msg); } return 0; } -void comms_set_lqi(comms_msg_t* msg, uint8_t lqi) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - comms->set_lqi(comms, msg, lqi); - } +void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_lqi(cl, msg, lqi); } } -int8_t comms_get_rssi(comms_msg_t* msg) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - return comms->get_rssi(comms, msg); - } +int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_rssi(cl, msg); } return -128; } -void comms_set_rssi(comms_msg_t* msg, int8_t rssi) { - if(msg != NULL) { - if(msg->layer != NULL) { - comms_layer_iface_t* comms = (comms_layer_iface_t*)msg->layer; - comms->set_rssi(comms, msg, rssi); - } +void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_rssi(cl, msg, rssi); } } diff --git a/include/mist_comm.h b/include/mist_comm.h index 7c3bc59..24eafb0 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -42,7 +42,6 @@ typedef struct comms_layer { typedef struct comms_msg comms_msg_t; typedef struct comms_msg { - comms_layer_t* layer; struct { uint16_t application; // AMID, port? uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; @@ -99,53 +98,55 @@ comms_receiver_id_t comms_register_recv(comms_layer_t* comms, comms_receive_f* f comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t rid); // Message payload manipulation functions -------------------------------------- -uint8_t comms_get_payload_length(comms_msg_t* msg); -void comms_set_payload_length(comms_msg_t* msg, uint8_t length); +uint8_t comms_get_payload_max_length(comms_layer_t* comms); -void* comms_get_payload(comms_msg_t* msg, uint8_t length); +uint8_t comms_get_payload_length(comms_layer_t* comms, comms_msg_t* msg); +void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); + +void* comms_get_payload(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); // ??? // Do we want support for larger payloads - uint16_t length? // ??? // ----------------------------------------------------------------------------- // PacketLink & Acknowledgements -uint8_t comms_get_retries(comms_msg_t* msg); -comms_error_t comms_set_retries(comms_msg_t* msg, uint8_t count); +uint8_t comms_get_retries(comms_layer_t* comms, comms_msg_t* msg); +comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); -uint8_t comms_get_retries_used(comms_msg_t* msg); -comms_error_t comms_set_retries_used(comms_msg_t* msg, uint8_t count); +uint8_t comms_get_retries_used(comms_layer_t* comms, comms_msg_t* msg); +comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); -uint32_t comms_get_timeout(comms_msg_t* msg); -comms_error_t comms_set_timeout(comms_msg_t* msg, uint32_t timeout); +uint32_t comms_get_timeout(comms_layer_t* comms, comms_msg_t* msg); +comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t timeout); -bool comms_is_ack_required(comms_msg_t* msg); -comms_error_t comms_set_ack_required(comms_msg_t* msg, bool required); +bool comms_is_ack_required(comms_layer_t* comms, comms_msg_t* msg); +comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required); // Check delivery for both PacketLink and simple Ack use cases -bool comms_ack_received(comms_msg_t* msg); +bool comms_ack_received(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- // TimeSync messaging // Event time is microseconds local clock // Set event time -comms_error_t comms_set_event_time(comms_msg_t* msg, uint32_t evt); +comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt); // Check that event time is valid with comms_event_time_valid. -uint32_t comms_get_event_time(comms_msg_t* msg); +uint32_t comms_get_event_time(comms_layer_t* comms, comms_msg_t* msg); // return TRUE if message has valid event time -bool comms_event_time_valid(comms_msg_t* msg); +bool comms_event_time_valid(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- // Message Quality -uint8_t comms_get_lqi(comms_msg_t* msg); -void comms_set_lqi(comms_msg_t* msg, uint8_t lqi); +uint8_t comms_get_lqi(comms_layer_t* comms, comms_msg_t* msg); +void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); // ??? standardize on 0-100 instead of 0-255, because for example CC1101 LQI goes from 0-127 and is inverse to Atmel RFX. // Value in dBm -int8_t comms_get_rssi(comms_msg_t* msg); -void comms_set_rssi(comms_msg_t* msg, int8_t rssi); +int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg); +void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // ----------------------------------------------------------------------------- #endif//MIST_COMM_H_ diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index ba02c35..b2d6afd 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -23,11 +23,11 @@ typedef struct comms_layer_am { } comms_layer_am_t; // Message manipulation functions for ActiveMessage layer ---------------------- -am_addr_t comms_am_get_destination(comms_msg_t* msg); -void comms_am_set_destination(comms_msg_t* msg, am_addr_t dest); +am_addr_t comms_am_get_destination(comms_layer_t* comms, comms_msg_t* msg); +void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest); -am_addr_t comms_am_get_source(comms_msg_t* msg); -void comms_am_set_source(comms_msg_t* msg, am_addr_t source); +am_addr_t comms_am_get_source(comms_layer_t* comms, comms_msg_t* msg); +void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source); // ----------------------------------------------------------------------------- comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender); diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 7c22619..ed9eea6 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -11,6 +11,7 @@ typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_sen typedef comms_receiver_id_t comms_register_recv_f(comms_layer_iface_t*, comms_receive_f*, void*, am_id_t); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_id_t); +typedef uint8_t comms_get_payload_max_length_f(comms_layer_iface_t*); typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, comms_msg_t*); typedef void comms_set_payload_length_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); typedef void* comms_get_payload_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); @@ -50,6 +51,7 @@ typedef struct comms_layer_iface { comms_register_recv_f* register_recv; comms_deregister_recv_f* deregister_recv; + comms_get_payload_max_length_f* get_payload_max_length; comms_get_payload_length_f* get_payload_length; comms_set_payload_length_f* set_payload_length; comms_get_payload_f* get_payload; diff --git a/test/main.c b/test/main.c index 7e0cba4..2bb7e4c 100644 --- a/test/main.c +++ b/test/main.c @@ -39,17 +39,17 @@ int main() { printf("create=%d\n", err); comms_init_message(comm, &msg); - comms_am_set_destination(&msg, 0xFFFF); - comms_am_set_source(&msg, 0x0001); + comms_am_set_destination(comm, &msg, 0xFFFF); + comms_am_set_source(comm, &msg, 0x0001); - payload = comms_get_payload(&msg, strlen(hello)+1); + payload = comms_get_payload(comm, &msg, strlen(hello)+1); if(payload == NULL) { printf("payload NULL\n"); return 1; } strncpy(payload, hello, strlen(hello)+1); - printf("%04X->%04X\n", comms_am_get_source(&msg), comms_am_get_destination(&msg)); + printf("%04X->%04X\n", comms_am_get_source(comm, &msg), comms_am_get_destination(comm, &msg)); err = comms_send(comm, &msg, &send_done, NULL); printf("send(%p)=%d\n", &msg, err); From 2c3343974c4243056f0f3bb50fd95b122ee96c8c Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 4 Mar 2019 13:30:10 +0200 Subject: [PATCH 05/80] Receiver registration with memory provided by user. --- am/mist_comm_am.c | 6 ++-- api/mist_comm_api.c | 12 ++++---- include/mist_comm.h | 55 +++++++++++++++++-------------------- include/mist_comm_iface.h | 5 ++-- include/mist_comm_private.h | 29 +++++++++++++++++++ 5 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 include/mist_comm_private.h diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 041dc21..da92873 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -13,10 +13,10 @@ static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, return COMMS_FAIL; } -static comms_receiver_id_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receive_f* func, void *user, am_id_t amid) { - return -1; +static comms_error_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid) { + return COMMS_FAIL; } -static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_id_t rid) { +static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { return COMMS_FAIL; } diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 2a6669d..414b65c 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -16,15 +16,15 @@ comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done return COMMS_EINVAL; } -comms_receiver_id_t comms_register_recv(comms_layer_t* comms, comms_receive_f* func, void *user, am_id_t amid) { - if(comms != NULL) { - return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, func, user, amid); +comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { + if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { + return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid); } - return -1; + return COMMS_EINVAL; } -comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t rid) { +comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr) { if(comms != NULL) { - return ((comms_layer_iface_t*)comms)->deregister_recv((comms_layer_iface_t*)comms, rid); + return ((comms_layer_iface_t*)comms)->deregister_recv((comms_layer_iface_t*)comms, rcvr); } return COMMS_EINVAL; } diff --git a/include/mist_comm.h b/include/mist_comm.h index 24eafb0..e5e4944 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -41,27 +41,6 @@ typedef struct comms_layer { } comms_layer_t; typedef struct comms_msg comms_msg_t; -typedef struct comms_msg { - struct { - uint16_t application; // AMID, port? - uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; - uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; - uint8_t header[COMMS_MSG_HEADER_SIZE]; - - uint8_t length; - uint8_t payload[COMMS_MSG_PAYLOAD_SIZE]; - - uint8_t footer[COMMS_MSG_FOOTER_SIZE]; - uint8_t metadata[COMMS_MSG_METADATA_SIZE]; - } body; - comms_msg_t* next; // ... maybe, could be very useful for transitioning through layers -} comms_msg_t; - -typedef int16_t comms_receiver_id_t; - -// Initialize a message structure for use on the specified communications -// layer. Must be called before any packet functions can be used. -void comms_init_message(comms_layer_t* comms, comms_msg_t* msg); // Callback definitions -------------------------------------------------------- @@ -73,7 +52,16 @@ typedef void comms_send_done_f(void* user, comms_msg_t* msg, comms_error_t resul // Signalled when a message is received. Functions of this type must first be // registered with a communications layer with comms_register_recv. -typedef comms_msg_t* comms_receive_f(void* user, comms_msg_t* msg); +typedef comms_msg_t* comms_receive_f(comms_layer_t* comms, comms_msg_t* msg, void* user); +// ??? +// do we want to allow message swapping? +// ??? + +// ----------------------------------------------------------------------------- + +// Initialize a message structure for use on the specified communications +// layer. Must be called before any packet functions can be used. +void comms_init_message(comms_layer_t* comms, comms_msg_t* msg); // Send a message through the specified communications layer. // The callback function specified with the send done function argument sdf will @@ -81,21 +69,26 @@ typedef comms_msg_t* comms_receive_f(void* user, comms_msg_t* msg); // argument is mandatory, the user argument may be NULL. comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user); -// Receiver and receiver registration ------------------------------------------ +// Receiver registration ------------------------------------------ -// returns a unique receiver ID, which can be used to deregister the receiver. -// Only non-negative receiver IDs are valid, a negative value indicates failure. -// The same receive function can be registered several times for different -// conditions and with a different user argument. -comms_receiver_id_t comms_register_recv(comms_layer_t* comms, comms_receive_f* func, void *user, am_id_t amid); +typedef struct comms_receiver comms_receiver_t; + +// Receiver must pass an unused comms_receiver_t object, guaranteeing that the +// memory remains allocated and is not used elsewhere until deregister is called. +// One receiver object may not be used in multiple roles at the same time, but +// the same receive function can be registered several times with different +// conditions and/or with a different user argument. +comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid); // ??? // last param should be some form of generic args, but this is C ... are we ok // to proceed with AM ID or should we expand and rename? 16 bit port? // and what other filtering is needed for receives ... if any? // ??? -// Remove and already registered receive function. -comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_id_t rid); +// Remove an already registered receiver. +comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr); + +// ----------------------------------------------------------------------------- // Message payload manipulation functions -------------------------------------- uint8_t comms_get_payload_max_length(comms_layer_t* comms); @@ -149,4 +142,6 @@ int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg); void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // ----------------------------------------------------------------------------- +#include "mist_comm_private.h" + #endif//MIST_COMM_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index ed9eea6..9d2e391 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -8,8 +8,9 @@ typedef struct comms_layer_iface comms_layer_iface_t; typedef void comms_init_message_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_send_done_f*, void*); -typedef comms_receiver_id_t comms_register_recv_f(comms_layer_iface_t*, comms_receive_f*, void*, am_id_t); -typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_id_t); + +typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t); +typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); typedef uint8_t comms_get_payload_max_length_f(comms_layer_iface_t*); typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, comms_msg_t*); diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h new file mode 100644 index 0000000..9d5b641 --- /dev/null +++ b/include/mist_comm_private.h @@ -0,0 +1,29 @@ +#ifndef MIST_COMM_PRIVATE_H_ +#define MIST_COMM_PRIVATE_H_ + +#include "mist_comm.h" + +typedef struct comms_msg { + struct { + uint16_t application; // AMID, port? + uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; + uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; + uint8_t header[COMMS_MSG_HEADER_SIZE]; + + uint8_t length; + uint8_t payload[COMMS_MSG_PAYLOAD_SIZE]; + + uint8_t footer[COMMS_MSG_FOOTER_SIZE]; + uint8_t metadata[COMMS_MSG_METADATA_SIZE]; + } body; + comms_msg_t* next; // ... maybe, could be very useful for transitioning through layers +} comms_msg_t; + +typedef struct comms_receiver { // Members are private, should not be accessed + uint16_t application; + comms_receive_f* callback; + void* user; + comms_receiver_t* next; +} comms_receiver_t; + +#endif//MIST_COMM_PRIVATE_H_ From 048e2760392c8871a60879fa9a4af0a46c17e598 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 4 Mar 2019 15:58:14 +0200 Subject: [PATCH 06/80] Receiver / delivery + AM impl. --- am/mist_comm_am.c | 49 ++++++++++++++++----------- api/mist_comm_api.c | 8 ++--- api/mist_comm_rcv.c | 70 +++++++++++++++++++++++++++++++++++++++ include/mist_comm.h | 5 +++ include/mist_comm_iface.h | 11 +++--- include/mist_comm_ref.h | 7 ++++ test/Makefile | 2 +- 7 files changed, 123 insertions(+), 29 deletions(-) create mode 100644 api/mist_comm_rcv.c create mode 100644 include/mist_comm_ref.h diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index da92873..92e4d4d 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -1,6 +1,6 @@ -#include "mist_comm.h" #include "mist_comm_iface.h" +#include "mist_comm_ref.h" #include "mist_comm_am.h" #include @@ -14,9 +14,11 @@ static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, } static comms_error_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid) { + // there is a suitable implementation in mist_comm_rcv.c return COMMS_FAIL; } static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { + // there is a suitable implementation in mist_comm_rcv.c return COMMS_FAIL; } @@ -37,56 +39,62 @@ static void* am_comms_get_payload(comms_layer_iface_t* comms, comms_msg_t* msg, } static uint8_t am_comms_get_retries(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->retries; } static comms_error_t am_comms_set_retries(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { - return COMMS_EINVAL; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->retries = count; + return COMMS_SUCCESS; } static uint8_t am_comms_get_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->sent; } static comms_error_t am_comms_set_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { - return COMMS_EINVAL; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->sent = count; + return COMMS_SUCCESS; } static uint32_t am_comms_get_timeout(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timeout; } static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timeout) { - return COMMS_EINVAL; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->timeout = timeout; + return COMMS_SUCCESS; } -static bool am_comms_is_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg) { - return false; +static bool am_comms_is_ack_requested(comms_layer_iface_t* comms, comms_msg_t* msg) { + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested; } -static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { - return COMMS_EINVAL; +static comms_error_t am_comms_set_ack_requested(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested = required; + return COMMS_SUCCESS; } static bool am_comms_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg) { - return false; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { return COMMS_EINVAL; } static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time; } static bool am_comms_event_time_valid(comms_layer_iface_t* comms, comms_msg_t* msg) { - return false; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid; } static uint8_t am_comms_get_lqi(comms_layer_iface_t* comms, comms_msg_t* msg) { - return 0; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi; } static void am_comms_set_lqi(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t lqi) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi = lqi; } static int8_t am_comms_get_rssi(comms_layer_iface_t* comms, comms_msg_t* msg) { - return -128; + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi; } static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t rssi) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi = rssi; } @@ -134,8 +142,9 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { else { comms->send = &am_comms_send; } - comms->register_recv = &am_comms_register_recv; - comms->deregister_recv = &am_comms_deregister_recv; + //comms->register_recv = &am_comms_register_recv; + //comms->deregister_recv = &am_comms_deregister_recv; + comms_initialize_rcvr_management(comms); comms->get_payload_max_length = &am_comms_get_payload_max_length; comms->get_payload_length = &am_comms_get_payload_length; @@ -151,8 +160,8 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { comms->get_timeout = &am_comms_get_timeout; comms->set_timeout = &am_comms_set_timeout; - comms->is_ack_required = &am_comms_is_ack_required; - comms->set_ack_required = &am_comms_set_ack_required; + comms->is_ack_requested = &am_comms_is_ack_requested; + comms->set_ack_requested = &am_comms_set_ack_requested; comms->ack_received = &am_comms_ack_received; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 414b65c..69c9da1 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -99,17 +99,17 @@ comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t return COMMS_EINVAL; } -bool comms_is_ack_required(comms_layer_t* comms, comms_msg_t* msg) { +bool comms_is_ack_requested(comms_layer_t* comms, comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - return cl->is_ack_required(cl, msg); + return cl->is_ack_requested(cl, msg); } return false; } -comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required) { +comms_error_t comms_set_ack_requested(comms_layer_t* comms, comms_msg_t* msg, bool requested) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - return cl->set_ack_required(cl, msg, required); + return cl->set_ack_requested(cl, msg, requested); } return COMMS_EINVAL; } diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c new file mode 100644 index 0000000..9097cbb --- /dev/null +++ b/api/mist_comm_rcv.c @@ -0,0 +1,70 @@ +#include "mist_comm_iface.h" +#include + +static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { + rcvr->application = amid; + rcvr->callback = func; + rcvr->user = user; + rcvr->next = NULL; + if(comms->receivers == NULL) { + comms->receivers = rcvr; + } + else { + comms_receiver_t* receiver; + for(receiver=comms->receivers;receiver->next!=NULL;receiver=receiver->next); + receiver->next = rcvr; + } + return COMMS_SUCCESS; +} + +static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { + if(comms->receivers == NULL) { + return COMMS_FAIL; // Nothing registered + } + else if(comms->receivers == rcvr) { + comms->receivers = rcvr->next; + return COMMS_SUCCESS; + } + else { + comms_receiver_t* receiver; + comms_receiver_t* last = comms->receivers; + for(receiver=last->next;receiver!=NULL;receiver=receiver->next) { + if(receiver == rcvr) { + last->next = receiver->next; + return COMMS_SUCCESS; + } + last = receiver; + } + } + return COMMS_FAIL; +} + +comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + uint16_t application = msg->body.application; + + comms_msg_t copy; + bool copied = false; + + comms_receiver_t* receiver = cl->receivers; + for(receiver=cl->receivers;receiver!=NULL;receiver=receiver->next) { + if(receiver->application == application) { + if(copied) { // msg has been received from user and may be modified + memcpy(msg, ©, sizeof(comms_msg_t)); + } + else { // make a backup of msg + memcpy(©, msg, sizeof(comms_msg_t)); + copied = true; + } + msg = receiver->callback(comms, msg, receiver->user); + } + } + return msg; +} + +comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms) { + comms->receivers = NULL; + comms->register_recv = &rcv_comms_register_recv; + comms->deregister_recv = &rcv_comms_deregister_recv; + return COMMS_SUCCESS; +} diff --git a/include/mist_comm.h b/include/mist_comm.h index e5e4944..2fe1aef 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -142,6 +142,11 @@ int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg); void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // ----------------------------------------------------------------------------- +// Other functions ------------------------------------------------------------- +// Deliver a message to all registered receivers +comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg); +// ----------------------------------------------------------------------------- + #include "mist_comm_private.h" #endif//MIST_COMM_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 9d2e391..fd3d0e5 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -26,8 +26,8 @@ typedef comms_error_t comms_set_retries_used_f(comms_layer_iface_t*, comms_msg_t typedef uint32_t comms_get_timeout_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_set_timeout_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); -typedef bool comms_is_ack_required_f(comms_layer_iface_t*, comms_msg_t*); -typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t*, bool); +typedef bool comms_is_ack_requested_f(comms_layer_iface_t*, comms_msg_t*); +typedef comms_error_t comms_set_ack_requested_f(comms_layer_iface_t*, comms_msg_t*, bool); typedef bool comms_ack_received_f(comms_layer_iface_t*, comms_msg_t*); @@ -66,8 +66,8 @@ typedef struct comms_layer_iface { comms_get_timeout_f* get_timeout; comms_set_timeout_f* set_timeout; - comms_is_ack_required_f* is_ack_required; - comms_set_ack_required_f* set_ack_required; + comms_is_ack_requested_f* is_ack_requested; + comms_set_ack_requested_f* set_ack_requested; comms_ack_received_f* ack_received; @@ -81,6 +81,9 @@ typedef struct comms_layer_iface { comms_get_rssi_f* get_rssi; comms_set_rssi_f* set_rssi; + // Receivers + comms_receiver_t* receivers; // Linked list of registered receivers + } comms_layer_iface_t; #endif//MIST_COMM_IFACE_H_ diff --git a/include/mist_comm_ref.h b/include/mist_comm_ref.h new file mode 100644 index 0000000..258a2ea --- /dev/null +++ b/include/mist_comm_ref.h @@ -0,0 +1,7 @@ +#ifndef MIST_COMM_REF_H_ +#define MIST_COMM_REF_H_ + +// Add default receiver handling functionality to a layer implementation +comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms); + +#endif//MIST_COMM_REF_H_ diff --git a/test/Makefile b/test/Makefile index c3af729..29e67fc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,4 +3,4 @@ CFLAGS = -I. -I../api -I../include -std=c99 all: - gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../am/mist_comm_am.c -o test + gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../api/mist_comm_rcv.c ../am/mist_comm_am.c -o test From ede586a96981978b6f57bfe4cd81316c7f714117 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 5 Mar 2019 10:55:02 +0200 Subject: [PATCH 07/80] Packet type, send_done sig, send-rcv example. --- am/mist_comm_am.c | 10 ++++ api/mist_comm_api.c | 14 +++++ api/mist_comm_rcv.c | 6 +-- include/mist_comm.h | 7 ++- include/mist_comm_iface.h | 6 +++ include/mist_comm_private.h | 4 +- test/main.c | 104 ++++++++++++++++++++++++++---------- 7 files changed, 116 insertions(+), 35 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 92e4d4d..d8eb34f 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -22,6 +22,13 @@ static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_ return COMMS_FAIL; } +static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg) { + return msg->body.type; +} +static void am_comms_set_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg, am_id_t ptype) { + msg->body.type = ptype; +} + static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* comms) { return 114; } @@ -146,6 +153,9 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { //comms->deregister_recv = &am_comms_deregister_recv; comms_initialize_rcvr_management(comms); + comms->get_packet_type = &am_comms_get_packet_type; + comms->set_packet_type = &am_comms_set_packet_type; + comms->get_payload_max_length = &am_comms_get_payload_max_length; comms->get_payload_length = &am_comms_get_payload_length; comms->set_payload_length = &am_comms_set_payload_length; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 69c9da1..bb96cea 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -29,6 +29,20 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr return COMMS_EINVAL; } +am_id_t comms_get_packet_type(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_packet_type(cl, msg); + } + return 0; +} +void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_packet_type(cl, msg, ptype); + } +} + uint8_t comms_get_payload_max_length(comms_layer_t* comms) { return ((comms_layer_iface_t*)comms)->get_payload_max_length((comms_layer_iface_t*)comms); } diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 9097cbb..c7df7d5 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -2,7 +2,7 @@ #include static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { - rcvr->application = amid; + rcvr->type = amid; rcvr->callback = func; rcvr->user = user; rcvr->next = NULL; @@ -41,14 +41,14 @@ static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - uint16_t application = msg->body.application; + am_id_t ptype = comms_get_packet_type(comms, msg); comms_msg_t copy; bool copied = false; comms_receiver_t* receiver = cl->receivers; for(receiver=cl->receivers;receiver!=NULL;receiver=receiver->next) { - if(receiver->application == application) { + if(receiver->type == ptype) { if(copied) { // msg has been received from user and may be modified memcpy(msg, ©, sizeof(comms_msg_t)); } diff --git a/include/mist_comm.h b/include/mist_comm.h index 2fe1aef..9a87004 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -48,7 +48,7 @@ typedef struct comms_msg comms_msg_t; // to the client. A function of this type must be passed with every call to the // comms_send function and the passed function will be called in the future if // the comms_send returns a successful result (message is accepted). -typedef void comms_send_done_f(void* user, comms_msg_t* msg, comms_error_t result); +typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user); // Signalled when a message is received. Functions of this type must first be // registered with a communications layer with comms_register_recv. @@ -90,6 +90,11 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr // ----------------------------------------------------------------------------- +// Packet type ----------------------------------------------------------------- +am_id_t comms_get_packet_type(comms_layer_t* comms, comms_msg_t* msg); +void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype); +// ----------------------------------------------------------------------------- + // Message payload manipulation functions -------------------------------------- uint8_t comms_get_payload_max_length(comms_layer_t* comms); diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index fd3d0e5..7875b89 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -12,6 +12,9 @@ typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_sen typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); +typedef am_id_t comms_get_packet_type_f(comms_layer_iface_t*, comms_msg_t*); +typedef void comms_set_packet_type_f(comms_layer_iface_t*, comms_msg_t*, am_id_t); + typedef uint8_t comms_get_payload_max_length_f(comms_layer_iface_t*); typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, comms_msg_t*); typedef void comms_set_payload_length_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); @@ -52,6 +55,9 @@ typedef struct comms_layer_iface { comms_register_recv_f* register_recv; comms_deregister_recv_f* deregister_recv; + comms_get_packet_type_f* get_packet_type; + comms_set_packet_type_f* set_packet_type; + comms_get_payload_max_length_f* get_payload_max_length; comms_get_payload_length_f* get_payload_length; comms_set_payload_length_f* set_payload_length; diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 9d5b641..be6559e 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -5,7 +5,7 @@ typedef struct comms_msg { struct { - uint16_t application; // AMID, port? + am_id_t type; // AMID, port? uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; uint8_t header[COMMS_MSG_HEADER_SIZE]; @@ -20,7 +20,7 @@ typedef struct comms_msg { } comms_msg_t; typedef struct comms_receiver { // Members are private, should not be accessed - uint16_t application; + am_id_t type; comms_receive_f* callback; void* user; comms_receiver_t* next; diff --git a/test/main.c b/test/main.c index 2bb7e4c..ff668dd 100644 --- a/test/main.c +++ b/test/main.c @@ -6,63 +6,109 @@ #include "mist_comm.h" #include "mist_comm_am.h" -static bool sent = false; - const char hello[] = "HelloWorld!"; -comms_msg_t* _msg = NULL; -comms_send_done_f* _sdf = NULL; -void* _user = NULL; +comms_msg_t mmsg1; +comms_msg_t* mcopy1 = &mmsg1; +comms_msg_t* _msg1 = NULL; +comms_send_done_f* _sdf1 = NULL; +void* _user1 = NULL; + +comms_msg_t mmsg2; +comms_msg_t* mcopy2 = &mmsg2; +comms_msg_t* _msg2 = NULL; +comms_send_done_f* _sdf2 = NULL; +void* _user2 = NULL; -comms_error_t fake_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { - if(_msg == NULL) { - _msg = msg; - _sdf = sdf; - _user = user; +comms_error_t fake_comms_send1(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + if(_msg1 == NULL) { + _msg1 = msg; + _sdf1 = sdf; + _user1 = user; return COMMS_SUCCESS; } return COMMS_EBUSY; } -void send_done(void* user, comms_msg_t* msg, comms_error_t result) { - printf("sd %p, %p, %u\n", user, msg, result); - sent = true; +comms_error_t fake_comms_send2(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + if(_msg2 == NULL) { + _msg2 = msg; + _sdf2 = sdf; + _user2 = user; + return COMMS_SUCCESS; + } + return COMMS_EBUSY; +} + +comms_msg_t* fake_comms_receive(comms_layer_t* comms, comms_msg_t* msg, void* user) { + printf("rcv %p, %p, %p\n", comms, msg, user); + printf("%04X->%04X %s\n", comms_am_get_source(comms, msg), + comms_am_get_destination(comms, msg), + (char*)comms_get_payload(comms, msg, comms_get_payload_length(comms, msg))); + return msg; +} + +void send_done(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user) { + printf("sd %p, %p, %u, %p\n", comms, msg, result, user); } int main() { comms_msg_t msg; - uint8_t m[256]; + uint8_t r1[256]; + uint8_t r2[256]; uint8_t* payload; - comms_layer_t* comm = (comms_layer_t*)m; + comms_layer_t* radio1 = (comms_layer_t*)r1; + comms_layer_t* radio2 = (comms_layer_t*)r2; + comms_receiver_t rcv1; + comms_receiver_t rcv2; + comms_error_t err; + uint8_t length = strlen(hello)+1; - comms_error_t err = comms_am_create(comm, &fake_comms_send); - printf("create=%d\n", err); + err = comms_am_create(radio1, &fake_comms_send1); + printf("create1=%d\n", err); + err = comms_am_create(radio2, &fake_comms_send2); + printf("create2=%d\n", err); - comms_init_message(comm, &msg); - comms_am_set_destination(comm, &msg, 0xFFFF); - comms_am_set_source(comm, &msg, 0x0001); + comms_register_recv(radio1, &rcv1, &fake_comms_receive, NULL, 0xAB); + comms_register_recv(radio2, &rcv2, &fake_comms_receive, NULL, 0xAB); - payload = comms_get_payload(comm, &msg, strlen(hello)+1); + comms_init_message(radio1, &msg); + comms_set_packet_type(radio1, &msg, 0xAB); + comms_am_set_destination(radio1, &msg, 0xFFFF); + comms_am_set_source(radio1, &msg, 0x0001); + + payload = comms_get_payload(radio1, &msg, length); if(payload == NULL) { printf("payload NULL\n"); return 1; } - strncpy(payload, hello, strlen(hello)+1); + strncpy(payload, hello, length); + comms_set_payload_length(radio1, &msg, length); - printf("%04X->%04X\n", comms_am_get_source(comm, &msg), comms_am_get_destination(comm, &msg)); + //printf("%x\n", comms_am_get_source(radio1, &msg)); + //printf("%04X->%04X\n", comms_am_get_source(radio1, &msg), comms_am_get_destination(radio1, &msg)); - err = comms_send(comm, &msg, &send_done, NULL); + err = comms_send(radio1, &msg, &send_done, NULL); printf("send(%p)=%d\n", &msg, err); if(err != COMMS_SUCCESS) { return 1; } - while(sent == false) { + while(true) { sleep(1); - if(_msg != NULL) { - comms_msg_t* m = _msg; - _msg = NULL; - _sdf(_user, m, COMMS_SUCCESS); + if(_msg1 != NULL) { + comms_msg_t* m = _msg1; + _msg1 = NULL; + memcpy(mcopy1, m, sizeof(comms_msg_t)); + mcopy1 = comms_deliver(radio2, mcopy1); + _sdf1(radio1, m, COMMS_SUCCESS, _user1); + } + if(_msg2 != NULL) { + comms_msg_t* m = _msg2; + _msg2 = NULL; + memcpy(mcopy2, m, sizeof(comms_msg_t)); + mcopy2 = comms_deliver(radio1, mcopy2); + _sdf2(radio2, m, COMMS_SUCCESS, _user2); } } From 011b0e0253ff3f5b8e0b827dd07f0cce0cc35681 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 5 Mar 2019 13:32:29 +0200 Subject: [PATCH 08/80] Some notes. --- include/mist_comm_basics.h | 3 ++- open-issues.txt | 20 ++++++++++++++++++++ test/main.c | 12 ++++++------ 3 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 open-issues.txt diff --git a/include/mist_comm_basics.h b/include/mist_comm_basics.h index b80367b..8acd65c 100644 --- a/include/mist_comm_basics.h +++ b/include/mist_comm_basics.h @@ -1,12 +1,13 @@ #ifndef MIST_COMM_BASICS #define MIST_COMM_BASICS -typedef uint8_t am_group_t; +typedef uint8_t am_group_t; // This is actually PAN typedef uint8_t am_id_t; typedef uint16_t am_addr_t; typedef struct ieee_eui64 { uint8_t data[8]; } ieee_eui64_t; +// ??? this should come from some ieee_eui64.h header #endif//MIST_COMM_BASICS diff --git a/open-issues.txt b/open-issues.txt new file mode 100644 index 0000000..d3ea1fc --- /dev/null +++ b/open-issues.txt @@ -0,0 +1,20 @@ + +* Addressing needs to be generalized - EUI addressing at the core, but support + for link locals. Special union typedef? void* pointer seems unclear, where do + you get the size of the actual thing on your platform? + +* Should am group be exposed in some generic way - do we need this concept for something? + +* Think AM id is too short, but if we expand it, how do we handle compatibility + with legacy applications. Protocol / application / type / port ... what would + be the best term to use for the general concept? + +* Timestamping should really be marked somehow in packet, previously "special" + AM ID 0x3D was used, but does not seem like a good way forward. Perhaps just + reserve the timestamp area always? + +* Timestamping needs clock source - must be provided somehow. + +* Thoughts about where to implement retries ... + * further down the line we probably want an e2e "reliable" transport + diff --git a/test/main.c b/test/main.c index ff668dd..fbacfce 100644 --- a/test/main.c +++ b/test/main.c @@ -14,12 +14,6 @@ comms_msg_t* _msg1 = NULL; comms_send_done_f* _sdf1 = NULL; void* _user1 = NULL; -comms_msg_t mmsg2; -comms_msg_t* mcopy2 = &mmsg2; -comms_msg_t* _msg2 = NULL; -comms_send_done_f* _sdf2 = NULL; -void* _user2 = NULL; - comms_error_t fake_comms_send1(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { if(_msg1 == NULL) { _msg1 = msg; @@ -30,6 +24,12 @@ comms_error_t fake_comms_send1(comms_layer_iface_t* comms, comms_msg_t* msg, com return COMMS_EBUSY; } +comms_msg_t mmsg2; +comms_msg_t* mcopy2 = &mmsg2; +comms_msg_t* _msg2 = NULL; +comms_send_done_f* _sdf2 = NULL; +void* _user2 = NULL; + comms_error_t fake_comms_send2(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { if(_msg2 == NULL) { _msg2 = msg; From 4f8e5bf692d659ef621dde6839f615540ebe2a93 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 5 Mar 2019 13:36:43 +0200 Subject: [PATCH 09/80] More open questions. --- open-issues.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/open-issues.txt b/open-issues.txt index d3ea1fc..0b9d509 100644 --- a/open-issues.txt +++ b/open-issues.txt @@ -18,3 +18,7 @@ * Thoughts about where to implement retries ... * further down the line we probably want an e2e "reliable" transport +* Radio startup and shutdown generalization - multistart & all stop? + +* Radio channels - this seems like a link-layer issue and would be handled + specifically - most apps should have no bussiness changing the channel? From b2fa919dcc886941f96955ca6a2240749d027168 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 5 Mar 2019 16:22:15 +0200 Subject: [PATCH 10/80] Received message is now const and getters operate with const. --- am/mist_comm_am.c | 32 ++++++++++++++++---------------- api/mist_comm_api.c | 24 ++++++++++++------------ api/mist_comm_rcv.c | 14 ++------------ include/mist_comm.h | 29 +++++++++++++---------------- include/mist_comm_am.h | 8 ++++---- include/mist_comm_iface.h | 24 ++++++++++++------------ test/main.c | 3 +-- 7 files changed, 60 insertions(+), 74 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index d8eb34f..61592b2 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -22,7 +22,7 @@ static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_ return COMMS_FAIL; } -static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg) { +static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { return msg->body.type; } static void am_comms_set_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg, am_id_t ptype) { @@ -32,20 +32,20 @@ static void am_comms_set_packet_type(comms_layer_iface_t* comms, comms_msg_t* ms static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* comms) { return 114; } -static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, const comms_msg_t* msg) { return msg->body.length; } static void am_comms_set_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { msg->body.length = length; } -static void* am_comms_get_payload(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { +static void* am_comms_get_payload(comms_layer_iface_t* comms, const comms_msg_t* msg, uint8_t length) { if(length < sizeof(msg->body.payload)) { return (void*)(msg->body.payload); } return NULL; } -static uint8_t am_comms_get_retries(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint8_t am_comms_get_retries(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->retries; } static comms_error_t am_comms_set_retries(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { @@ -53,7 +53,7 @@ static comms_error_t am_comms_set_retries(comms_layer_iface_t* comms, comms_msg_ return COMMS_SUCCESS; } -static uint8_t am_comms_get_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint8_t am_comms_get_retries_used(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->sent; } static comms_error_t am_comms_set_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { @@ -61,7 +61,7 @@ static comms_error_t am_comms_set_retries_used(comms_layer_iface_t* comms, comms return COMMS_SUCCESS; } -static uint32_t am_comms_get_timeout(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint32_t am_comms_get_timeout(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timeout; } static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timeout) { @@ -69,35 +69,35 @@ static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_ return COMMS_SUCCESS; } -static bool am_comms_is_ack_requested(comms_layer_iface_t* comms, comms_msg_t* msg) { +static bool am_comms_is_ack_requested(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested; } static comms_error_t am_comms_set_ack_requested(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested = required; return COMMS_SUCCESS; } -static bool am_comms_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg) { +static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { return COMMS_EINVAL; } -static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time; } -static bool am_comms_event_time_valid(comms_layer_iface_t* comms, comms_msg_t* msg) { +static bool am_comms_event_time_valid(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid; } -static uint8_t am_comms_get_lqi(comms_layer_iface_t* comms, comms_msg_t* msg) { +static uint8_t am_comms_get_lqi(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi; } static void am_comms_set_lqi(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t lqi) { ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi = lqi; } -static int8_t am_comms_get_rssi(comms_layer_iface_t* comms, comms_msg_t* msg) { +static int8_t am_comms_get_rssi(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi; } static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t rssi) { @@ -105,21 +105,21 @@ static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8 } -static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, comms_msg_t* msg) { +static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { return *((am_addr_t*)msg->body.destination); } static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { *((am_addr_t*)msg->body.destination) = dest; } -static am_addr_t am_comms_get_source(comms_layer_am_t* comms, comms_msg_t* msg) { +static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* msg) { return *((am_addr_t*)msg->body.source); } static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { *((am_addr_t*)msg->body.source) = source; } -am_addr_t comms_am_get_destination(comms_layer_t* comms, comms_msg_t* msg) { +am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg) { comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; return amcomms->am_get_destination(amcomms, msg); } @@ -128,7 +128,7 @@ void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t amcomms->am_set_destination(amcomms, msg, dest); } -am_addr_t comms_am_get_source(comms_layer_t* comms, comms_msg_t* msg) { +am_addr_t comms_am_get_source(comms_layer_t* comms, const comms_msg_t* msg) { comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; return amcomms->am_get_source(amcomms, msg); } diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index bb96cea..a376418 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -29,7 +29,7 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr return COMMS_EINVAL; } -am_id_t comms_get_packet_type(comms_layer_t* comms, comms_msg_t* msg) { +am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_packet_type(cl, msg); @@ -47,7 +47,7 @@ uint8_t comms_get_payload_max_length(comms_layer_t* comms) { return ((comms_layer_iface_t*)comms)->get_payload_max_length((comms_layer_iface_t*)comms); } -uint8_t comms_get_payload_length(comms_layer_t* comms, comms_msg_t* msg) { +uint8_t comms_get_payload_length(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_payload_length(cl, msg); @@ -60,7 +60,7 @@ void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t le cl->set_payload_length(cl, msg, length); } } -void* comms_get_payload(comms_layer_t* comms, comms_msg_t* msg, uint8_t length) { +void* comms_get_payload(comms_layer_t* comms, const comms_msg_t* msg, uint8_t length) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_payload(cl, msg, length); @@ -68,7 +68,7 @@ void* comms_get_payload(comms_layer_t* comms, comms_msg_t* msg, uint8_t length) return NULL; } -uint8_t comms_get_retries(comms_layer_t* comms, comms_msg_t* msg) { +uint8_t comms_get_retries(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_retries(cl, msg); @@ -83,7 +83,7 @@ comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t return COMMS_EINVAL; } -uint8_t comms_get_retries_used(comms_layer_t* comms, comms_msg_t* msg) { +uint8_t comms_get_retries_used(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_retries_used(cl, msg); @@ -98,7 +98,7 @@ comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uin return COMMS_EINVAL; } -uint32_t comms_get_timeout(comms_layer_t* comms, comms_msg_t* msg) { +uint32_t comms_get_timeout(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_timeout(cl, msg); @@ -113,7 +113,7 @@ comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t return COMMS_EINVAL; } -bool comms_is_ack_requested(comms_layer_t* comms, comms_msg_t* msg) { +bool comms_is_ack_requested(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->is_ack_requested(cl, msg); @@ -127,7 +127,7 @@ comms_error_t comms_set_ack_requested(comms_layer_t* comms, comms_msg_t* msg, bo } return COMMS_EINVAL; } -bool comms_ack_received(comms_layer_t* comms, comms_msg_t* msg) { +bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->ack_received(cl, msg); @@ -142,14 +142,14 @@ comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint3 } return COMMS_EINVAL; } -uint32_t comms_get_event_time(comms_layer_t* comms, comms_msg_t* msg) { +uint32_t comms_get_event_time(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_event_time(cl, msg); } return 0; } -bool comms_event_time_valid(comms_layer_t* comms, comms_msg_t* msg) { +bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->event_time_valid(cl, msg); @@ -157,7 +157,7 @@ bool comms_event_time_valid(comms_layer_t* comms, comms_msg_t* msg) { return false; } -uint8_t comms_get_lqi(comms_layer_t* comms, comms_msg_t* msg) { +uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_lqi(cl, msg); @@ -171,7 +171,7 @@ void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi) { } } -int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg) { +int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_rssi(cl, msg); diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index c7df7d5..eae5331 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -42,21 +42,11 @@ static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; am_id_t ptype = comms_get_packet_type(comms, msg); - - comms_msg_t copy; - bool copied = false; - comms_receiver_t* receiver = cl->receivers; + for(receiver=cl->receivers;receiver!=NULL;receiver=receiver->next) { if(receiver->type == ptype) { - if(copied) { // msg has been received from user and may be modified - memcpy(msg, ©, sizeof(comms_msg_t)); - } - else { // make a backup of msg - memcpy(©, msg, sizeof(comms_msg_t)); - copied = true; - } - msg = receiver->callback(comms, msg, receiver->user); + receiver->callback(comms, msg, receiver->user); } } return msg; diff --git a/include/mist_comm.h b/include/mist_comm.h index 9a87004..2ce65da 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -52,10 +52,7 @@ typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_err // Signalled when a message is received. Functions of this type must first be // registered with a communications layer with comms_register_recv. -typedef comms_msg_t* comms_receive_f(comms_layer_t* comms, comms_msg_t* msg, void* user); -// ??? -// do we want to allow message swapping? -// ??? +typedef void comms_receive_f(comms_layer_t* comms, const comms_msg_t* msg, void* user); // ----------------------------------------------------------------------------- @@ -91,37 +88,37 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr // ----------------------------------------------------------------------------- // Packet type ----------------------------------------------------------------- -am_id_t comms_get_packet_type(comms_layer_t* comms, comms_msg_t* msg); +am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg); void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype); // ----------------------------------------------------------------------------- // Message payload manipulation functions -------------------------------------- uint8_t comms_get_payload_max_length(comms_layer_t* comms); -uint8_t comms_get_payload_length(comms_layer_t* comms, comms_msg_t* msg); +uint8_t comms_get_payload_length(comms_layer_t* comms, const comms_msg_t* msg); void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); -void* comms_get_payload(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); +void* comms_get_payload(comms_layer_t* comms, const comms_msg_t* msg, uint8_t length); // ??? // Do we want support for larger payloads - uint16_t length? // ??? // ----------------------------------------------------------------------------- // PacketLink & Acknowledgements -uint8_t comms_get_retries(comms_layer_t* comms, comms_msg_t* msg); +uint8_t comms_get_retries(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); -uint8_t comms_get_retries_used(comms_layer_t* comms, comms_msg_t* msg); +uint8_t comms_get_retries_used(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); -uint32_t comms_get_timeout(comms_layer_t* comms, comms_msg_t* msg); +uint32_t comms_get_timeout(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t timeout); -bool comms_is_ack_required(comms_layer_t* comms, comms_msg_t* msg); +bool comms_is_ack_required(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required); // Check delivery for both PacketLink and simple Ack use cases -bool comms_ack_received(comms_layer_t* comms, comms_msg_t* msg); +bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg); // ----------------------------------------------------------------------------- // TimeSync messaging @@ -131,19 +128,19 @@ bool comms_ack_received(comms_layer_t* comms, comms_msg_t* msg); comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt); // Check that event time is valid with comms_event_time_valid. -uint32_t comms_get_event_time(comms_layer_t* comms, comms_msg_t* msg); +uint32_t comms_get_event_time(comms_layer_t* comms, const comms_msg_t* msg); // return TRUE if message has valid event time -bool comms_event_time_valid(comms_layer_t* comms, comms_msg_t* msg); +bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg); // ----------------------------------------------------------------------------- // Message Quality -uint8_t comms_get_lqi(comms_layer_t* comms, comms_msg_t* msg); +uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); // ??? standardize on 0-100 instead of 0-255, because for example CC1101 LQI goes from 0-127 and is inverse to Atmel RFX. // Value in dBm -int8_t comms_get_rssi(comms_layer_t* comms, comms_msg_t* msg); +int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // ----------------------------------------------------------------------------- diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index b2d6afd..99be724 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -6,10 +6,10 @@ typedef struct comms_layer_am comms_layer_am_t; -typedef am_addr_t comms_am_get_destination_f(comms_layer_am_t*, comms_msg_t*); +typedef am_addr_t comms_am_get_destination_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); -typedef am_addr_t comms_am_get_source_f(comms_layer_am_t*, comms_msg_t*); +typedef am_addr_t comms_am_get_source_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_source_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); typedef struct comms_layer_am { @@ -23,10 +23,10 @@ typedef struct comms_layer_am { } comms_layer_am_t; // Message manipulation functions for ActiveMessage layer ---------------------- -am_addr_t comms_am_get_destination(comms_layer_t* comms, comms_msg_t* msg); +am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg); void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest); -am_addr_t comms_am_get_source(comms_layer_t* comms, comms_msg_t* msg); +am_addr_t comms_am_get_source(comms_layer_t* comms, const comms_msg_t* msg); void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source); // ----------------------------------------------------------------------------- diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 7875b89..fdaec40 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -12,36 +12,36 @@ typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_sen typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); -typedef am_id_t comms_get_packet_type_f(comms_layer_iface_t*, comms_msg_t*); +typedef am_id_t comms_get_packet_type_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_packet_type_f(comms_layer_iface_t*, comms_msg_t*, am_id_t); typedef uint8_t comms_get_payload_max_length_f(comms_layer_iface_t*); -typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_payload_length_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); -typedef void* comms_get_payload_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); +typedef void* comms_get_payload_f(comms_layer_iface_t*, const comms_msg_t*, uint8_t); -typedef uint8_t comms_get_retries_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint8_t comms_get_retries_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_retries_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); -typedef uint8_t comms_get_retries_used_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint8_t comms_get_retries_used_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_retries_used_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); -typedef uint32_t comms_get_timeout_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint32_t comms_get_timeout_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_timeout_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); -typedef bool comms_is_ack_requested_f(comms_layer_iface_t*, comms_msg_t*); +typedef bool comms_is_ack_requested_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_ack_requested_f(comms_layer_iface_t*, comms_msg_t*, bool); -typedef bool comms_ack_received_f(comms_layer_iface_t*, comms_msg_t*); +typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_event_time_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); -typedef uint32_t comms_get_event_time_f(comms_layer_iface_t*, comms_msg_t*); -typedef bool comms_event_time_valid_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint32_t comms_get_event_time_f(comms_layer_iface_t*, const comms_msg_t*); +typedef bool comms_event_time_valid_f(comms_layer_iface_t*, const comms_msg_t*); -typedef uint8_t comms_get_lqi_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint8_t comms_get_lqi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); -typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, comms_msg_t*); +typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); // ----------------------------------------------------------------------------- diff --git a/test/main.c b/test/main.c index fbacfce..d974612 100644 --- a/test/main.c +++ b/test/main.c @@ -40,12 +40,11 @@ comms_error_t fake_comms_send2(comms_layer_iface_t* comms, comms_msg_t* msg, com return COMMS_EBUSY; } -comms_msg_t* fake_comms_receive(comms_layer_t* comms, comms_msg_t* msg, void* user) { +void fake_comms_receive(comms_layer_t* comms, const comms_msg_t* msg, void* user) { printf("rcv %p, %p, %p\n", comms, msg, user); printf("%04X->%04X %s\n", comms_am_get_source(comms, msg), comms_am_get_destination(comms, msg), (char*)comms_get_payload(comms, msg, comms_get_payload_length(comms, msg))); - return msg; } void send_done(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user) { From 0cd3cf47a89028f30f58d83f1c444872bc0abdf5 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 6 Mar 2019 16:45:44 +0200 Subject: [PATCH 11/80] Separate tos basics and compat. --- include/{ => compat}/mist_comm_basics.h | 0 include/tos/mist_comm_basics.h | 15 +++++++++++++++ 2 files changed, 15 insertions(+) rename include/{ => compat}/mist_comm_basics.h (100%) create mode 100644 include/tos/mist_comm_basics.h diff --git a/include/mist_comm_basics.h b/include/compat/mist_comm_basics.h similarity index 100% rename from include/mist_comm_basics.h rename to include/compat/mist_comm_basics.h diff --git a/include/tos/mist_comm_basics.h b/include/tos/mist_comm_basics.h new file mode 100644 index 0000000..02554ba --- /dev/null +++ b/include/tos/mist_comm_basics.h @@ -0,0 +1,15 @@ +#ifndef MIST_COMM_BASICS +#define MIST_COMM_BASICS + +#include "AM.h" +#include "IeeeEui64.h" +//typedef uint8_t am_group_t; // This is actually PAN +//typedef uint8_t am_id_t; +//typedef uint16_t am_addr_t; + +//typedef struct ieee_eui64 { +// uint8_t data[8]; +//} ieee_eui64_t; +// ??? this should come from some ieee_eui64.h header + +#endif//MIST_COMM_BASICS From 22813d2fd0ddbddad0a04665b9ea132ff1db5f62 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 6 Mar 2019 16:46:02 +0200 Subject: [PATCH 12/80] Some gcc's will not accept typedef forward and real declr. --- include/mist_comm_private.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index be6559e..660e999 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -3,7 +3,7 @@ #include "mist_comm.h" -typedef struct comms_msg { +struct comms_msg { struct { am_id_t type; // AMID, port? uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; @@ -17,13 +17,13 @@ typedef struct comms_msg { uint8_t metadata[COMMS_MSG_METADATA_SIZE]; } body; comms_msg_t* next; // ... maybe, could be very useful for transitioning through layers -} comms_msg_t; +}; -typedef struct comms_receiver { // Members are private, should not be accessed +struct comms_receiver { // Members are private, should not be accessed am_id_t type; comms_receive_f* callback; void* user; comms_receiver_t* next; -} comms_receiver_t; +}; #endif//MIST_COMM_PRIVATE_H_ From 80324a5025e2c674a18641ba86cf5eeee0301ec1 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 11 Mar 2019 12:16:47 +0200 Subject: [PATCH 13/80] Change how am structs are typedef'd. --- include/mist_comm_am.h | 4 ++-- include/mist_comm_iface.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 99be724..812819d 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -12,7 +12,7 @@ typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr typedef am_addr_t comms_am_get_source_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_source_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); -typedef struct comms_layer_am { +struct comms_layer_am { comms_layer_iface_t base; comms_am_get_destination_f* am_get_destination; @@ -20,7 +20,7 @@ typedef struct comms_layer_am { comms_am_get_source_f* am_get_source; comms_am_set_source_f* am_set_source; -} comms_layer_am_t; +}; // Message manipulation functions for ActiveMessage layer ---------------------- am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg); diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index fdaec40..449a401 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -46,7 +46,7 @@ typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); // ----------------------------------------------------------------------------- -typedef struct comms_layer_iface { +struct comms_layer_iface { comms_layer_t layer; // Type info comms_init_message_f* init_message; @@ -90,6 +90,6 @@ typedef struct comms_layer_iface { // Receivers comms_receiver_t* receivers; // Linked list of registered receivers -} comms_layer_iface_t; +}; #endif//MIST_COMM_IFACE_H_ From db54702dff4818459b07f93a52dae8527b75fb80 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 11 Mar 2019 12:29:30 +0200 Subject: [PATCH 14/80] Requested->required --- am/mist_comm_am.c | 12 ++++++------ api/mist_comm_api.c | 8 ++++---- include/mist_comm_am_msg.h | 2 +- include/mist_comm_iface.h | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 61592b2..781ff48 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -69,11 +69,11 @@ static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_ return COMMS_SUCCESS; } -static bool am_comms_is_ack_requested(comms_layer_iface_t* comms, const comms_msg_t* msg) { - return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested; +static bool am_comms_is_ack_required(comms_layer_iface_t* comms, const comms_msg_t* msg) { + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_required; } -static comms_error_t am_comms_set_ack_requested(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { - ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_requested = required; +static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_required = required; return COMMS_SUCCESS; } static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* msg) { @@ -170,8 +170,8 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { comms->get_timeout = &am_comms_get_timeout; comms->set_timeout = &am_comms_set_timeout; - comms->is_ack_requested = &am_comms_is_ack_requested; - comms->set_ack_requested = &am_comms_set_ack_requested; + comms->is_ack_required = &am_comms_is_ack_required; + comms->set_ack_required = &am_comms_set_ack_required; comms->ack_received = &am_comms_ack_received; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index a376418..873a981 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -113,17 +113,17 @@ comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t return COMMS_EINVAL; } -bool comms_is_ack_requested(comms_layer_t* comms, const comms_msg_t* msg) { +bool comms_is_ack_required(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - return cl->is_ack_requested(cl, msg); + return cl->is_ack_required(cl, msg); } return false; } -comms_error_t comms_set_ack_requested(comms_layer_t* comms, comms_msg_t* msg, bool requested) { +comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - return cl->set_ack_requested(cl, msg, requested); + return cl->set_ack_required(cl, msg, required); } return COMMS_EINVAL; } diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index 5f3221c..8811970 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -21,7 +21,7 @@ typedef struct comms_am_msg_metadata { uint8_t retries; uint32_t timeout; - bool ack_requested; + bool ack_required; bool ack_received; bool event_time_valid; diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 449a401..932ab63 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -29,8 +29,8 @@ typedef comms_error_t comms_set_retries_used_f(comms_layer_iface_t*, comms_msg_t typedef uint32_t comms_get_timeout_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_timeout_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); -typedef bool comms_is_ack_requested_f(comms_layer_iface_t*, const comms_msg_t*); -typedef comms_error_t comms_set_ack_requested_f(comms_layer_iface_t*, comms_msg_t*, bool); +typedef bool comms_is_ack_required_f(comms_layer_iface_t*, const comms_msg_t*); +typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t*, bool); typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); @@ -72,8 +72,8 @@ struct comms_layer_iface { comms_get_timeout_f* get_timeout; comms_set_timeout_f* set_timeout; - comms_is_ack_requested_f* is_ack_requested; - comms_set_ack_requested_f* set_ack_requested; + comms_is_ack_required_f* is_ack_required; + comms_set_ack_required_f* set_ack_required; comms_ack_received_f* ack_received; From ef5a83007d2270aca00e6a43040e5983f576ce34 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 11 Mar 2019 14:04:14 +0200 Subject: [PATCH 15/80] Add activemessage self addres func. --- am/mist_comm_am.c | 14 +++++++++++++- include/mist_comm_am.h | 13 ++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 781ff48..f00ac49 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -5,6 +5,15 @@ #include +am_addr_t comms_am_address(comms_layer_t* comms) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + amcomms->am_address(amcomms); +} + +static am_addr_t am_comms_addr(comms_layer_am_t* comms) { + return comms->am_addr; +} + static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { msg->body.length = 0; } @@ -137,7 +146,7 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc amcomms->am_set_source(amcomms, msg, source); } -comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { +comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender) { comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; @@ -190,5 +199,8 @@ comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender) { amcomms->am_get_source = &am_comms_get_source; amcomms->am_set_source = &am_comms_set_source; + amcomms->am_address = &am_comms_addr; + amcomms->am_addr = address; + return COMMS_SUCCESS; } diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 812819d..6f8f152 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -6,6 +6,8 @@ typedef struct comms_layer_am comms_layer_am_t; +typedef am_addr_t comms_am_addr_f(comms_layer_am_t*); + typedef am_addr_t comms_am_get_destination_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); @@ -20,8 +22,15 @@ struct comms_layer_am { comms_am_get_source_f* am_get_source; comms_am_set_source_f* am_set_source; + + comms_am_addr_f* am_address; + am_addr_t am_addr; }; +// ActiveMessage address +am_addr_t comms_am_address(comms_layer_t* comms); +// ----------------------------------------------------------------------------- + // Message manipulation functions for ActiveMessage layer ---------------------- am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg); void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest); @@ -30,6 +39,8 @@ am_addr_t comms_am_get_source(comms_layer_t* comms, const comms_msg_t* msg); void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source); // ----------------------------------------------------------------------------- -comms_error_t comms_am_create(comms_layer_t* layer, comms_send_f* sender); +// Create an ActiveMessage comms layer ----------------------------------------- +comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender); +// ----------------------------------------------------------------------------- #endif//MIST_COMM_AM_H_ From 39b5440b4d9ec495673a0094b80ad2c32bebcf7c Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 12 Mar 2019 09:28:09 +0200 Subject: [PATCH 16/80] Update test app. --- test/Makefile | 2 +- test/main.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/Makefile b/test/Makefile index 29e67fc..f89cf69 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ # Makefile -CFLAGS = -I. -I../api -I../include -std=c99 +CFLAGS = -I. -I../api -I../include -I../include/compat -std=c99 all: gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../api/mist_comm_rcv.c ../am/mist_comm_am.c -o test diff --git a/test/main.c b/test/main.c index d974612..8a4efe9 100644 --- a/test/main.c +++ b/test/main.c @@ -63,9 +63,9 @@ int main() { comms_error_t err; uint8_t length = strlen(hello)+1; - err = comms_am_create(radio1, &fake_comms_send1); + err = comms_am_create(radio1, 1, &fake_comms_send1); printf("create1=%d\n", err); - err = comms_am_create(radio2, &fake_comms_send2); + err = comms_am_create(radio2, 2, &fake_comms_send2); printf("create2=%d\n", err); comms_register_recv(radio1, &rcv1, &fake_comms_receive, NULL, 0xAB); @@ -73,8 +73,8 @@ int main() { comms_init_message(radio1, &msg); comms_set_packet_type(radio1, &msg, 0xAB); - comms_am_set_destination(radio1, &msg, 0xFFFF); - comms_am_set_source(radio1, &msg, 0x0001); + comms_am_set_destination(radio1, &msg, 0xCDEF); + comms_am_set_source(radio1, &msg, 0x1234); payload = comms_get_payload(radio1, &msg, length); if(payload == NULL) { From 5216a7c9b1b0264ca41bb9dc23857a36dde17e73 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 13 Mar 2019 09:38:01 +0200 Subject: [PATCH 17/80] Timestamp was not set. --- am/mist_comm_am.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index f00ac49..429ec52 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -90,7 +90,9 @@ static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* } static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { - return COMMS_EINVAL; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time = evt; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid = true; + return COMMS_SUCCESS; } static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time; From e97000972899dfbd6fb376ff5684f1e8e3e4cc64 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 13 Mar 2019 10:14:34 +0200 Subject: [PATCH 18/80] Fix packet init. --- am/mist_comm_am.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 429ec52..7443c05 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -15,7 +15,16 @@ static am_addr_t am_comms_addr(comms_layer_am_t* comms) { } static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { + comms_am_msg_metadata_t* metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); msg->body.length = 0; + metadata->event_time_valid = false; + metadata->ack_required = false; + metadata->ack_received = false; + metadata->timeout = 0; + metadata->retries = 0; + metadata->sent = 0; + metadata->lqi= 0; + metadata->rssi = -128; } static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { @@ -206,3 +215,4 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_sen return COMMS_SUCCESS; } + From 1ac1b904bf2fe874677b92b415b41962f368bf20 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 13 Mar 2019 14:48:36 +0200 Subject: [PATCH 19/80] Fix address bug. --- am/mist_comm_am.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 7443c05..cb46b61 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -7,7 +7,7 @@ am_addr_t comms_am_address(comms_layer_t* comms) { comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; - amcomms->am_address(amcomms); + return amcomms->am_address(amcomms); } static am_addr_t am_comms_addr(comms_layer_am_t* comms) { From 9eea2ed02ba65708d72e993d6ce13d4fcdff7572 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 13 Mar 2019 18:36:32 +0200 Subject: [PATCH 20/80] Comment out unused functions (prototypes). --- am/mist_comm_am.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index cb46b61..4b821cd 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -31,14 +31,14 @@ static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, return COMMS_FAIL; } -static comms_error_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid) { - // there is a suitable implementation in mist_comm_rcv.c - return COMMS_FAIL; -} -static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { - // there is a suitable implementation in mist_comm_rcv.c - return COMMS_FAIL; -} +//static comms_error_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid) { +// // there is a suitable implementation in mist_comm_rcv.c +// return COMMS_FAIL; +//} +//static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { +// // there is a suitable implementation in mist_comm_rcv.c +// return COMMS_FAIL; +//} static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { return msg->body.type; From 8bb49d4c1f3f95ce8f65722efbc51f119f515d42 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 14 Mar 2019 10:00:16 +0200 Subject: [PATCH 21/80] Packet timestamping. --- am/mist_comm_am.c | 17 ++++++++++++++++ api/mist_comm_api.c | 22 +++++++++++++++++++++ include/mist_comm.h | 14 +++++++++++++ include/mist_comm_am_msg.h | 7 +++---- include/mist_comm_iface.h | 8 ++++++++ test/Makefile | 2 +- test/main.c | 40 ++++++++++++++++++++++++++++++++++---- 7 files changed, 101 insertions(+), 9 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 4b821cd..e57e200 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -17,6 +17,7 @@ static am_addr_t am_comms_addr(comms_layer_am_t* comms) { static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { comms_am_msg_metadata_t* metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); msg->body.length = 0; + metadata->timestamp_valid = false; metadata->event_time_valid = false; metadata->ack_required = false; metadata->ack_received = false; @@ -98,6 +99,18 @@ static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } +static comms_error_t am_comms_set_timestamp(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timestamp) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp = timestamp; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp_valid = true; + return COMMS_SUCCESS; +} +static uint32_t am_comms_get_timestamp(comms_layer_iface_t* comms, const comms_msg_t* msg) { + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp; +} +static bool am_comms_timestamp_valid(comms_layer_iface_t* comms, const comms_msg_t* msg) { + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp_valid; +} + static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time = evt; ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid = true; @@ -195,6 +208,10 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_sen comms->ack_received = &am_comms_ack_received; + comms->set_timestamp = &am_comms_set_timestamp; + comms->get_timestamp = &am_comms_get_timestamp; + comms->timestamp_valid = &am_comms_timestamp_valid; + comms->set_event_time = &am_comms_set_event_time; comms->get_event_time = &am_comms_get_event_time; comms->event_time_valid = &am_comms_event_time_valid; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 873a981..5449639 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -135,6 +135,28 @@ bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg) { return false; } +comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->set_timestamp(cl, msg, timestamp); + } + return COMMS_EINVAL; +} +uint32_t comms_get_timestamp(comms_layer_t* comms, const comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_timestamp(cl, msg); + } + return 0; +} +bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->timestamp_valid(cl, msg); + } + return false; +} + comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; diff --git a/include/mist_comm.h b/include/mist_comm.h index 2ce65da..5ec5018 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -121,6 +121,20 @@ comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, boo bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg); // ----------------------------------------------------------------------------- +// Message timestamping +// Timestamps are microseconds local clock. Indicate either message reception or +// transmission time. + +// Check that the timestamp is valid with comms_timestamp_valid. +uint32_t comms_get_timestamp(comms_layer_t* comms, const comms_msg_t* msg); + +// return TRUE if message has valid timestamp +bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg); + +// Set timestamp (low level - on receive and on send) +comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp); +// ----------------------------------------------------------------------------- + // TimeSync messaging // Event time is microseconds local clock diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index 8811970..6089ef3 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -4,10 +4,6 @@ #include "mist_comm_basics.h" typedef struct comms_am_msg_header { - am_addr_t source; - am_addr_t destination; - am_group_t group; - am_id_t amid; } comms_am_msg_header_t; typedef struct comms_am_msg_footer { @@ -24,6 +20,9 @@ typedef struct comms_am_msg_metadata { bool ack_required; bool ack_received; + bool timestamp_valid; + uint32_t timestamp; + bool event_time_valid; uint32_t event_time; } comms_am_msg_metadata_t; diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 932ab63..a74142c 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -34,6 +34,10 @@ typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); +typedef comms_error_t comms_set_timestamp_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); +typedef uint32_t comms_get_timestamp_f(comms_layer_iface_t*, const comms_msg_t*); +typedef bool comms_timestamp_valid_f(comms_layer_iface_t*, const comms_msg_t*); + typedef comms_error_t comms_set_event_time_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); typedef uint32_t comms_get_event_time_f(comms_layer_iface_t*, const comms_msg_t*); typedef bool comms_event_time_valid_f(comms_layer_iface_t*, const comms_msg_t*); @@ -77,6 +81,10 @@ struct comms_layer_iface { comms_ack_received_f* ack_received; + comms_set_timestamp_f* set_timestamp; + comms_get_timestamp_f* get_timestamp; + comms_timestamp_valid_f* timestamp_valid; + comms_set_event_time_f* set_event_time; comms_get_event_time_f* get_event_time; comms_event_time_valid_f* event_time_valid; diff --git a/test/Makefile b/test/Makefile index f89cf69..8586140 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ # Makefile -CFLAGS = -I. -I../api -I../include -I../include/compat -std=c99 +CFLAGS = -I. -I../api -I../include -I../include/compat -std=c99 -Wall all: gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../api/mist_comm_rcv.c ../am/mist_comm_am.c -o test diff --git a/test/main.c b/test/main.c index 8a4efe9..192c3ca 100644 --- a/test/main.c +++ b/test/main.c @@ -51,10 +51,40 @@ void send_done(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, voi printf("sd %p, %p, %u, %p\n", comms, msg, result, user); } +bool test(comms_layer_t* radio) { + comms_msg_t msg; + + comms_init_message(radio, &msg); + + if(comms_timestamp_valid(radio, &msg) == true) { + return false; + } + comms_set_timestamp(radio, &msg, 1234); + if(comms_timestamp_valid(radio, &msg) == false) { + return false; + } + if(comms_get_timestamp(radio, &msg) != 1234) { + return false; + } + + if(comms_event_time_valid(radio, &msg) == true) { + return false; + } + comms_set_event_time(radio, &msg, 5678); + if(comms_event_time_valid(radio, &msg) == false) { + return false; + } + if(comms_get_event_time(radio, &msg) != 5678) { + return false; + } + + return true; +} + int main() { comms_msg_t msg; - uint8_t r1[256]; - uint8_t r2[256]; + uint8_t r1[512]; + uint8_t r2[512]; uint8_t* payload; comms_layer_t* radio1 = (comms_layer_t*)r1; comms_layer_t* radio2 = (comms_layer_t*)r2; @@ -68,6 +98,8 @@ int main() { err = comms_am_create(radio2, 2, &fake_comms_send2); printf("create2=%d\n", err); + printf("tests = %d\n", test(radio1)); + comms_register_recv(radio1, &rcv1, &fake_comms_receive, NULL, 0xAB); comms_register_recv(radio2, &rcv2, &fake_comms_receive, NULL, 0xAB); @@ -81,11 +113,11 @@ int main() { printf("payload NULL\n"); return 1; } - strncpy(payload, hello, length); + memcpy(payload, hello, length); comms_set_payload_length(radio1, &msg, length); //printf("%x\n", comms_am_get_source(radio1, &msg)); - //printf("%04X->%04X\n", comms_am_get_source(radio1, &msg), comms_am_get_destination(radio1, &msg)); + printf("snd %04X->%04X\n", comms_am_get_source(radio1, &msg), comms_am_get_destination(radio1, &msg)); err = comms_send(radio1, &msg, &send_done, NULL); printf("send(%p)=%d\n", &msg, err); From 18eaadc309d0ffdeeace25497767e7c03e547fd2 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 14 Mar 2019 11:32:40 +0200 Subject: [PATCH 22/80] Add ack_received setter. --- am/mist_comm_am.c | 5 ++++- api/mist_comm_api.c | 6 ++++++ include/mist_comm.h | 2 ++ include/mist_comm_iface.h | 3 ++- test/main.c | 16 ++++++++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index e57e200..cdbe8cf 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -98,6 +98,9 @@ static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } +static void am_comms_set_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received = true; +} static comms_error_t am_comms_set_timestamp(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timestamp) { ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp = timestamp; @@ -205,8 +208,8 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_sen comms->is_ack_required = &am_comms_is_ack_required; comms->set_ack_required = &am_comms_set_ack_required; - comms->ack_received = &am_comms_ack_received; + comms->set_ack_received = &am_comms_set_ack_received; comms->set_timestamp = &am_comms_set_timestamp; comms->get_timestamp = &am_comms_get_timestamp; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 5449639..30fc407 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -134,6 +134,12 @@ bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg) { } return false; } +void _comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_ack_received(cl, msg); + } +} comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { if((msg != NULL)&&(comms != NULL)) { diff --git a/include/mist_comm.h b/include/mist_comm.h index 5ec5018..5246bd4 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -119,6 +119,8 @@ comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, boo // Check delivery for both PacketLink and simple Ack use cases bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg); + +void _comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- // Message timestamping diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index a74142c..ec33fe9 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -33,6 +33,7 @@ typedef bool comms_is_ack_required_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t*, bool); typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); +typedef void comms_set_ack_received_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_set_timestamp_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); typedef uint32_t comms_get_timestamp_f(comms_layer_iface_t*, const comms_msg_t*); @@ -78,8 +79,8 @@ struct comms_layer_iface { comms_is_ack_required_f* is_ack_required; comms_set_ack_required_f* set_ack_required; - comms_ack_received_f* ack_received; + comms_set_ack_received_f* set_ack_received; comms_set_timestamp_f* set_timestamp; comms_get_timestamp_f* get_timestamp; diff --git a/test/main.c b/test/main.c index 192c3ca..6737e9f 100644 --- a/test/main.c +++ b/test/main.c @@ -78,6 +78,22 @@ bool test(comms_layer_t* radio) { return false; } + if(comms_is_ack_required(radio, &msg) != false) { + return false; + } + comms_set_ack_required(radio, &msg, true); + if(comms_is_ack_required(radio, &msg) != true) { + return false; + } + + if(comms_ack_received(radio, &msg) != false) { + return false; + } + _comms_set_ack_received(radio, &msg); + if(comms_ack_received(radio, &msg) != true) { + return false; + } + return true; } From e7db040fad0277143379f67a4280c1aaeb1027b9 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 19 Jul 2019 17:56:11 +0300 Subject: [PATCH 23/80] Add bcast addr to basics header. --- include/compat/mist_comm_basics.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 8acd65c..27e89eb 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -5,6 +5,8 @@ typedef uint8_t am_group_t; // This is actually PAN typedef uint8_t am_id_t; typedef uint16_t am_addr_t; +#define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) + typedef struct ieee_eui64 { uint8_t data[8]; } ieee_eui64_t; From ea9166880b15af37c55ae698cd7bee4771fb90c9 Mon Sep 17 00:00:00 2001 From: Tarmo Kuuse Date: Mon, 2 Sep 2019 17:30:30 +0300 Subject: [PATCH 24/80] DEV-2311 Listen for mist rules and data packets --- include/mist_comm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mist_comm.h b/include/mist_comm.h index 5246bd4..3bc8923 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -48,7 +48,7 @@ typedef struct comms_msg comms_msg_t; // to the client. A function of this type must be passed with every call to the // comms_send function and the passed function will be called in the future if // the comms_send returns a successful result (message is accepted). -typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user); +typedef void comms_send_done_f(comms_layer_t* comms, const comms_msg_t* msg, comms_error_t result, void* user); // Signalled when a message is received. Functions of this type must first be // registered with a communications layer with comms_register_recv. From 77b9272d765bf95c7b53892dc371a6e319c9c70a Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 19 Sep 2019 16:11:40 +0300 Subject: [PATCH 25/80] Fix error code typo. --- include/mist_comm.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/mist_comm.h b/include/mist_comm.h index 5246bd4..143505d 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -28,7 +28,7 @@ typedef enum CommsErrors { COMMS_EBUSY = -5, COMMS_EOFF = -4, COMMS_ECANCEL = -3, - COMMS_SIZE = -2, + COMMS_ESIZE = -2, COMMS_FAIL = -1, COMMS_SUCCESS = 0, @@ -162,6 +162,7 @@ void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // Other functions ------------------------------------------------------------- // Deliver a message to all registered receivers +// TODO the return value does not make sense any more comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- From 7d6289c2067b451d537ba6c726208d6d8b4f6bc1 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 19 Sep 2019 16:11:53 +0300 Subject: [PATCH 26/80] Missing include. --- include/compat/mist_comm_basics.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 27e89eb..9b1a2e1 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -1,15 +1,17 @@ #ifndef MIST_COMM_BASICS #define MIST_COMM_BASICS +#include + typedef uint8_t am_group_t; // This is actually PAN typedef uint8_t am_id_t; typedef uint16_t am_addr_t; -#define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) - typedef struct ieee_eui64 { uint8_t data[8]; } ieee_eui64_t; // ??? this should come from some ieee_eui64.h header +#define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) + #endif//MIST_COMM_BASICS From cbdcd9431d0ab2a86427cd2dcee8c58c4f21dd0f Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 20 Sep 2019 09:41:55 +0300 Subject: [PATCH 27/80] Add snoopers, refactor receiver registration to be more tasty. --- api/mist_comm_api.c | 13 ++++++++ api/mist_comm_rcv.c | 67 +++++++++++++++++++++++++-------------- include/mist_comm.h | 6 ++++ include/mist_comm_iface.h | 8 +++++ 4 files changed, 70 insertions(+), 24 deletions(-) diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 30fc407..d5b4849 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -29,6 +29,19 @@ comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr return COMMS_EINVAL; } +comms_error_t comms_register_snooper(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user) { + if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { + return ((comms_layer_iface_t*)comms)->register_snooper((comms_layer_iface_t*)comms, rcvr, func, user); + } + return COMMS_EINVAL; +} +comms_error_t comms_deregister_snooper(comms_layer_t* comms, comms_receiver_t* rcvr) { + if(comms != NULL) { + return ((comms_layer_iface_t*)comms)->deregister_snooper((comms_layer_iface_t*)comms, rcvr); + } + return COMMS_EINVAL; +} + am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index eae5331..0002895 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -2,38 +2,48 @@ #include static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { + comms_receiver_t** indirect; + for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)); + *indirect = rcvr; + rcvr->type = amid; rcvr->callback = func; rcvr->user = user; rcvr->next = NULL; - if(comms->receivers == NULL) { - comms->receivers = rcvr; - } - else { - comms_receiver_t* receiver; - for(receiver=comms->receivers;receiver->next!=NULL;receiver=receiver->next); - receiver->next = rcvr; - } + + return COMMS_SUCCESS; +} + +static comms_error_t rcv_comms_register_snooper(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user) { + comms_receiver_t** indirect; + for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)); + *indirect = rcvr; + + rcvr->type = 0; // Not used + rcvr->callback = func; + rcvr->user = user; + rcvr->next = NULL; + return COMMS_SUCCESS; } static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { - if(comms->receivers == NULL) { - return COMMS_FAIL; // Nothing registered - } - else if(comms->receivers == rcvr) { - comms->receivers = rcvr->next; - return COMMS_SUCCESS; + comms_receiver_t** indirect; + for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)) { + if(*indirect == rcvr) { + *indirect = rcvr->next; + return COMMS_SUCCESS; + } } - else { - comms_receiver_t* receiver; - comms_receiver_t* last = comms->receivers; - for(receiver=last->next;receiver!=NULL;receiver=receiver->next) { - if(receiver == rcvr) { - last->next = receiver->next; - return COMMS_SUCCESS; - } - last = receiver; + return COMMS_FAIL; +} + +static comms_error_t rcv_comms_deregister_snooper(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { + comms_receiver_t** indirect; + for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)) { + if(*indirect == rcvr) { + *indirect = rcvr->next; + return COMMS_SUCCESS; } } return COMMS_FAIL; @@ -42,13 +52,20 @@ static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; am_id_t ptype = comms_get_packet_type(comms, msg); - comms_receiver_t* receiver = cl->receivers; + comms_receiver_t* receiver; + // Receivers filter based on type for(receiver=cl->receivers;receiver!=NULL;receiver=receiver->next) { if(receiver->type == ptype) { receiver->callback(comms, msg, receiver->user); } } + + // Snoopers get everyting + for(receiver=cl->snoopers;receiver!=NULL;receiver=receiver->next) { + receiver->callback(comms, msg, receiver->user); + } + return msg; } @@ -56,5 +73,7 @@ comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms) { comms->receivers = NULL; comms->register_recv = &rcv_comms_register_recv; comms->deregister_recv = &rcv_comms_deregister_recv; + comms->register_snooper = &rcv_comms_register_snooper; + comms->deregister_snooper = &rcv_comms_deregister_snooper; return COMMS_SUCCESS; } diff --git a/include/mist_comm.h b/include/mist_comm.h index 143505d..5853531 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -85,6 +85,12 @@ comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, // Remove an already registered receiver. comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr); +// Snoopers don't look at the type (amid) +comms_error_t comms_register_snooper(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user); + +// Remove an already registered snooper. +comms_error_t comms_deregister_snooper(comms_layer_t* comms, comms_receiver_t* rcvr); + // ----------------------------------------------------------------------------- // Packet type ----------------------------------------------------------------- diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index ec33fe9..9105191 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -12,6 +12,9 @@ typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_sen typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); +typedef comms_error_t comms_register_snooper_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*); +typedef comms_error_t comms_deregister_snooper_f(comms_layer_iface_t*, comms_receiver_t*); + typedef am_id_t comms_get_packet_type_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_packet_type_f(comms_layer_iface_t*, comms_msg_t*, am_id_t); @@ -59,6 +62,8 @@ struct comms_layer_iface { comms_send_f* send; comms_register_recv_f* register_recv; comms_deregister_recv_f* deregister_recv; + comms_register_snooper_f* register_snooper; + comms_deregister_snooper_f* deregister_snooper; comms_get_packet_type_f* get_packet_type; comms_set_packet_type_f* set_packet_type; @@ -99,6 +104,9 @@ struct comms_layer_iface { // Receivers comms_receiver_t* receivers; // Linked list of registered receivers + // Snoopers + comms_receiver_t* snoopers; // Linked list of registered snoopers + }; #endif//MIST_COMM_IFACE_H_ From 2b36dd0443e4429608082d9b174222652eccbd27 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 17 Oct 2019 11:13:28 +0300 Subject: [PATCH 28/80] Add start/stop to API. --- am/mist_comm_am.c | 8 +++++++- api/mist_comm_api.c | 18 ++++++++++++++++++ include/mist_comm.h | 13 +++++++++++++ include/mist_comm_am.h | 3 ++- include/mist_comm_iface.h | 6 ++++++ test/main.c | 4 ++-- 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index cdbe8cf..a7f93de 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -173,10 +173,16 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc amcomms->am_set_source(amcomms, msg, source); } -comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender) { +comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, + comms_send_f* sender, + comms_start_f* startf, comms_stop_f* stopf) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; + comms->start = startf; + comms->stop = stopf; + comms->init_message = &am_comms_init_message; if(sender != NULL) { diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index d5b4849..079502c 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -3,6 +3,24 @@ #include +comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { + if(NULL != comms) { + if(NULL != ((comms_layer_iface_t*)comms)->start) { + return ((comms_layer_iface_t*)comms)->start((comms_layer_iface_t*)comms, start_done, user); + } + } + return COMMS_EINVAL; +} + +comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user) { + if(NULL != comms) { + if(NULL != ((comms_layer_iface_t*)comms)->stop) { + return ((comms_layer_iface_t*)comms)->stop((comms_layer_iface_t*)comms, stop_done, user); + } + } + return COMMS_EINVAL; +} + void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { if((comms != NULL)&&(msg != NULL)) { ((comms_layer_iface_t*)comms)->init_message((comms_layer_iface_t*)comms, msg); diff --git a/include/mist_comm.h b/include/mist_comm.h index 5853531..8176a14 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -35,11 +35,24 @@ typedef enum CommsErrors { COMMS_ALREADY = 1 } comms_error_t; +typedef enum CommsStatus { + COMMS_STOPPING = -2, + COMMS_STARTING = -1, + COMMS_STOPPED = 0, + COMMS_STARTED = 1 +} comms_status_t; + typedef struct comms_layer { uint8_t type; // Everything else will embed at least this structure } comms_layer_t; +typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, void* user); + +comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user); + +comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user); + typedef struct comms_msg comms_msg_t; // Callback definitions -------------------------------------------------------- diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 6f8f152..3cfd694 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -40,7 +40,8 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc // ----------------------------------------------------------------------------- // Create an ActiveMessage comms layer ----------------------------------------- -comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender); +comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender, + comms_start_f* startf, comms_stop_f* stopf); // ----------------------------------------------------------------------------- #endif//MIST_COMM_AM_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 9105191..32f280e 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -5,6 +5,9 @@ typedef struct comms_layer_iface comms_layer_iface_t; +typedef comms_error_t comms_start_f(comms_layer_iface_t*, comms_status_change_f*, void*); +typedef comms_error_t comms_stop_f(comms_layer_iface_t*, comms_status_change_f*, void*); + typedef void comms_init_message_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_send_done_f*, void*); @@ -57,6 +60,9 @@ typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); struct comms_layer_iface { comms_layer_t layer; // Type info + comms_start_f* start; + comms_stop_f* stop; + comms_init_message_f* init_message; comms_send_f* send; diff --git a/test/main.c b/test/main.c index 6737e9f..5e2a7b3 100644 --- a/test/main.c +++ b/test/main.c @@ -109,9 +109,9 @@ int main() { comms_error_t err; uint8_t length = strlen(hello)+1; - err = comms_am_create(radio1, 1, &fake_comms_send1); + err = comms_am_create(radio1, 1, &fake_comms_send1, NULL, NULL); printf("create1=%d\n", err); - err = comms_am_create(radio2, 2, &fake_comms_send2); + err = comms_am_create(radio2, 2, &fake_comms_send2, NULL, NULL); printf("create2=%d\n", err); printf("tests = %d\n", test(radio1)); From a5155bbfc158603bbed886c69fa6e5128cafc0b2 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 8 Nov 2019 13:05:41 +0200 Subject: [PATCH 29/80] Add bridge component proto. --- bridge/mist_comm_bridge.c | 110 +++++++++++++++++++++++++++++++++++++ include/mist_comm_bridge.h | 46 ++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 bridge/mist_comm_bridge.c create mode 100644 include/mist_comm_bridge.h diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c new file mode 100644 index 0000000..ea20558 --- /dev/null +++ b/bridge/mist_comm_bridge.c @@ -0,0 +1,110 @@ +/** + * MistComm bridge implementation. + * Bridge messages between 2 mist-comm communication interfaces. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + * @author Raido Pahtma + */ + +#include + +#include "cmsis_os2.h" +#include "mist_comm.h" +#include "mist_comm_am.h" +#include "mist_comm_bridge.h" + +#include "loglevels.h" +#define __MODUUL__ "bridge" +#define __LOG_LEVEL__ (LOG_LEVEL_bridge & BASE_LOG_LEVEL) +#include "log.h" + +static void bridge_thread(void * param); +static void bridge_send_done(comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); +static void bridge_am_snoop(comms_layer_t* comms, const comms_msg_t* msg, void* user); + +comms_error_t comms_bridge_init (comms_bridge_t * bridge, + comms_layer_t * a, + comms_layer_t * b) +{ + bridge->t1.rxqueue = osMessageQueueNew(10, sizeof(comms_msg_t), NULL); + bridge->t1.txqueue = osMessageQueueNew(10, sizeof(comms_msg_t), NULL); + bridge->t2.rxqueue = bridge->t1.txqueue; + bridge->t2.txqueue = bridge->t1.rxqueue; + + const osThreadAttr_t bridge_thread_1_attr = { .name = "bt1" }; + bridge->t1.thread = osThreadNew(bridge_thread, &(bridge->t1), &bridge_thread_1_attr); + + const osThreadAttr_t bridge_thread_2_attr = { .name = "bt2" }; + bridge->t2.thread = osThreadNew(bridge_thread, &(bridge->t2), &bridge_thread_2_attr); + + bridge->t1.layer = a; + bridge->t2.layer = b; + + // set up snoopers + comms_register_snooper(bridge->t1.layer, &(bridge->t1.receiver), &bridge_am_snoop, &(bridge->t1)); + comms_register_snooper(bridge->t2.layer, &(bridge->t2.receiver), &bridge_am_snoop, &(bridge->t2)); + + return COMMS_SUCCESS; +} + +static void bridge_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) +{ + comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; + logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "%p snt %d", msg, result); + osThreadFlagsSet(bt->thread, 0x00000001U); +} + +static void bridge_am_snoop (comms_layer_t* comms, const comms_msg_t* msg, void* user) +{ + comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; + + #if (__LOG_LEVEL__ & LOG_DEBUG4) + uint8_t plen = comms_get_payload_length(comms, msg); + uint8_t* payload = comms_get_payload(comms, msg, plen); + debugb4("rcv %d", payload, plen, (unsigned int)plen); + #endif//debug + + if(osMessageQueuePut(bt->rxqueue, msg, 0, 0) != osOK) + { + warn1("drop"); + } +} + +static void bridge_thread (void * param) +{ + comms_bridge_thread_t * bt = (comms_bridge_thread_t*)param; + + for(;;) + { + if (osOK == osMessageQueueGet(bt->txqueue, &(bt->msg), NULL, osWaitForever)) + { + #if (__LOG_LEVEL__ & LOG_DEBUG4) + uint8_t plen = comms_get_payload_length(bt->layer, &(bt->msg)); + uint8_t* payload = comms_get_payload(bt->layer, &(bt->msg), plen); + //debugb1("snd %d", payload, plen, (unsigned int)plen); + + debugb4("tx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", + payload, plen, + DEFAULT_PAN_ID, + comms_am_get_source(bt->layer, &(bt->msg)), + comms_am_get_destination(bt->layer, &(bt->msg)), + comms_get_packet_type(bt->layer, &(bt->msg))); + #endif//debug + + if(COMMS_SUCCESS == comms_send(bt->layer, &(bt->msg), bridge_send_done, bt)) + { + osThreadFlagsWait(0x00000001U, osFlagsWaitAny, osWaitForever); + debug1("snt"); + } + else + { + warn1("snd"); + } + } + else + { + err1("q"); + } + } +} diff --git a/include/mist_comm_bridge.h b/include/mist_comm_bridge.h new file mode 100644 index 0000000..154caa0 --- /dev/null +++ b/include/mist_comm_bridge.h @@ -0,0 +1,46 @@ +/** + * MistComm bridge. + * Bridge messages between 2 mist-comm communication interfaces. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + * @author Raido Pahtma + */ + +#ifndef MIST_COMM_BRIDGE_H_ +#define MIST_COMM_BRIDGE_H_ + +#include "cmsis_os2.h" +#include "mist_comm.h" + +typedef struct comms_bridge_thread +{ + osThreadId_t thread; + + comms_receiver_t receiver; + comms_layer_t * layer; + + osMessageQueueId_t rxqueue; + osMessageQueueId_t txqueue; + comms_msg_t msg; +} comms_bridge_thread_t; + +typedef struct comms_bridge +{ + comms_bridge_thread_t t1; + comms_bridge_thread_t t2; +} comms_bridge_t; + +/** + * Initialize and start a bridge. + * + * @param bridge The bridge to initialize. + * @param a The first communications interface. + * @param b The second communications interface. + * @return COMMS_SUCCESS for success. + */ +comms_error_t comms_bridge_init (comms_bridge_t * bridge, + comms_layer_t * a, + comms_layer_t * b); + +#endif//MIST_COMM_BRIDGE_H_ From f82396df124dba2cdcb783177fc90ef76c632045 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 26 Nov 2019 18:56:37 +0200 Subject: [PATCH 30/80] Add initial AM routing info callback support. --- include/mist_comm_routing.h | 39 ++++++++++++++++++++++ routing/mist_comm_routing.c | 66 +++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 include/mist_comm_routing.h create mode 100644 routing/mist_comm_routing.c diff --git a/include/mist_comm_routing.h b/include/mist_comm_routing.h new file mode 100644 index 0000000..4c51b88 --- /dev/null +++ b/include/mist_comm_routing.h @@ -0,0 +1,39 @@ +/** + * Routing info callbacks for the MistComm API. + * + * Copyright Thinnect Inc. 2019 + * + * @license MIT + * @author Raido Pahtma + */ + +#include "mist_comm_am.h" +#include + +typedef struct comms_layer_am_mh comms_layer_am_mh_t; +typedef struct comms_routing_info_handler comms_routing_info_handler_t; + +comms_error_t comms_init_routing_result_callbacks (comms_layer_am_mh_t * comms); + +void comms_routing_notify_routed (comms_layer_t * comms, am_addr_t dest, uint16_t cost, comms_error_t status); + +typedef void comms_am_routed_f(comms_layer_t *, am_addr_t, uint16_t, comms_error_t, void*); + +comms_error_t comms_routing_register_result_callback (comms_layer_am_mh_t * comms, + comms_routing_info_handler_t * rih, + comms_am_routed_f * func, void * user); + +comms_error_t comms_routing_deregister_result_callback (comms_layer_am_mh_t * comms, + comms_routing_info_handler_t * rih); + +struct comms_routing_info_handler +{ + comms_am_routed_f * callback; + void * user; + comms_routing_info_handler_t * next; +}; + +struct comms_layer_am_mh { + comms_layer_am_t base; + comms_routing_info_handler_t * routing_info_handlers; +}; diff --git a/routing/mist_comm_routing.c b/routing/mist_comm_routing.c new file mode 100644 index 0000000..be0abb7 --- /dev/null +++ b/routing/mist_comm_routing.c @@ -0,0 +1,66 @@ +/** + * Routing info callback handlers for the MistComm API. + * + * Copyright Thinnect Inc. 2019 + * + * @license MIT + * @author Raido Pahtma + */ + +#include "mist_comm_routing.h" +#include + +comms_error_t comms_routing_register_result_callback ( + comms_layer_am_mh_t* comms, + comms_routing_info_handler_t* rih, + comms_am_routed_f* func, void* user) +{ + comms_routing_info_handler_t** indirect; + for (indirect=&(comms->routing_info_handlers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if (*indirect == rih) + { + return COMMS_FAIL; + } + } + *indirect = rih; + + rih->callback = func; + rih->user = user; + rih->next = NULL; + + return COMMS_SUCCESS; +} + +comms_error_t comms_routing_deregister_result_callback ( + comms_layer_am_mh_t* comms, + comms_routing_info_handler_t* rih) +{ + comms_routing_info_handler_t** indirect; + for (indirect=&(comms->routing_info_handlers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if (*indirect == rih) + { + *indirect = rih->next; + return COMMS_SUCCESS; + } + } + return COMMS_FAIL; +} + +void comms_routing_notify_routed (comms_layer_t* comms, am_addr_t dest, uint16_t cost, comms_error_t status) +{ + comms_layer_am_mh_t * cl = (comms_layer_am_mh_t*)comms; + comms_routing_info_handler_t * rih; + + for (rih=cl->routing_info_handlers; NULL != rih; rih=rih->next) + { + rih->callback(comms, dest, cost, status, rih->user); + } +} + +comms_error_t comms_init_routing_result_callbacks (comms_layer_am_mh_t * comms) +{ + comms->routing_info_handlers = NULL; + return COMMS_SUCCESS; +} From d33e6caedc27b398feeb04603d7494294ac9728e Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 5 Dec 2019 17:19:42 +0200 Subject: [PATCH 31/80] Reject already registered receivers. --- api/mist_comm_rcv.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 0002895..28d059b 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -3,7 +3,11 @@ static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { comms_receiver_t** indirect; - for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)); + for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)) { + if(*indirect == rcvr) { + return COMMS_ALREADY; + } + } *indirect = rcvr; rcvr->type = amid; @@ -16,7 +20,11 @@ static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_r static comms_error_t rcv_comms_register_snooper(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user) { comms_receiver_t** indirect; - for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)); + for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)) { + if(*indirect == rcvr) { + return COMMS_ALREADY; + } + } *indirect = rcvr; rcvr->type = 0; // Not used From 73c2eca123fa7b0e4fd99fbf54d35e7db81b4b20 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 6 Dec 2019 10:16:18 +0200 Subject: [PATCH 32/80] Add tests for new start/stop. --- .gitmodules | 3 + .travis.yml | 9 +++ api/mist_comm_api.c | 45 ++++++++++++-- include/mist_comm.h | 2 + include/mist_comm_iface.h | 9 ++- test/startstop/.gitignore | 2 + test/startstop/Makefile | 31 ++++++++++ test/startstop/test_startstop.c | 106 ++++++++++++++++++++++++++++++++ test/zoo/ThrowTheSwitch.Unity | 1 + 9 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 .gitmodules create mode 100644 .travis.yml create mode 100644 test/startstop/.gitignore create mode 100644 test/startstop/Makefile create mode 100644 test/startstop/test_startstop.c create mode 160000 test/zoo/ThrowTheSwitch.Unity diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4aae019 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test/zoo/ThrowTheSwitch.Unity"] + path = test/zoo/ThrowTheSwitch.Unity + url = https://github.com/ThrowTheSwitch/Unity.git diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e9cd2b4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: c +sudo: false +addons: + apt: + packages: + - ruby + +script: + - make -C test/startstop diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 079502c..f6d5ddd 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -3,10 +3,30 @@ #include +static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->status = status; + cl->status_change_user_cb(comms, status, cl->status_change_user); + cl->status_change_user_cb = NULL; + cl->status_change_user = NULL; +} + comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { if(NULL != comms) { - if(NULL != ((comms_layer_iface_t*)comms)->start) { - return ((comms_layer_iface_t*)comms)->start((comms_layer_iface_t*)comms, start_done, user); + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + if(NULL != cl->start) { + if(NULL != cl->status_change_user_cb) { + return COMMS_EBUSY; + } + else { + comms_error_t err = cl->start(cl, &comms_status_change_callback, NULL); + if(COMMS_SUCCESS == err) { + cl->status = COMMS_STARTING; + cl->status_change_user_cb = start_done; + cl->status_change_user = user; + } + return err; + } } } return COMMS_EINVAL; @@ -14,13 +34,30 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user) { if(NULL != comms) { - if(NULL != ((comms_layer_iface_t*)comms)->stop) { - return ((comms_layer_iface_t*)comms)->stop((comms_layer_iface_t*)comms, stop_done, user); + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + if(NULL != cl->stop) { + if(NULL != cl->status_change_user_cb) { + return COMMS_EBUSY; + } + else { + comms_error_t err = cl->stop(cl, &comms_status_change_callback, NULL); + if(COMMS_SUCCESS == err) { + cl->status = COMMS_STOPPING; + cl->status_change_user_cb = stop_done; + cl->status_change_user = user; + } + return err; + } } } return COMMS_EINVAL; } +comms_status_t comms_status(comms_layer_t* comms) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->status; +} + void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { if((comms != NULL)&&(msg != NULL)) { ((comms_layer_iface_t*)comms)->init_message((comms_layer_iface_t*)comms, msg); diff --git a/include/mist_comm.h b/include/mist_comm.h index 8176a14..99abc82 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -53,6 +53,8 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user); +comms_status_t comms_status(comms_layer_t* comms); + typedef struct comms_msg comms_msg_t; // Callback definitions -------------------------------------------------------- diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 32f280e..fb9da13 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -5,6 +5,7 @@ typedef struct comms_layer_iface comms_layer_iface_t; +typedef comms_status_t comms_status_f(comms_layer_iface_t*); typedef comms_error_t comms_start_f(comms_layer_iface_t*, comms_status_change_f*, void*); typedef comms_error_t comms_stop_f(comms_layer_iface_t*, comms_status_change_f*, void*); @@ -62,6 +63,8 @@ struct comms_layer_iface { comms_start_f* start; comms_stop_f* stop; + comms_status_change_f* status_change_user_cb; + void* status_change_user; comms_init_message_f* init_message; @@ -108,11 +111,13 @@ struct comms_layer_iface { comms_set_rssi_f* set_rssi; // Receivers - comms_receiver_t* receivers; // Linked list of registered receivers + comms_receiver_t* receivers; // List of registered receivers // Snoopers - comms_receiver_t* snoopers; // Linked list of registered snoopers + comms_receiver_t* snoopers; // List of registered snoopers + // Standard variables + comms_status_t status; }; #endif//MIST_COMM_IFACE_H_ diff --git a/test/startstop/.gitignore b/test/startstop/.gitignore new file mode 100644 index 0000000..ace99d2 --- /dev/null +++ b/test/startstop/.gitignore @@ -0,0 +1,2 @@ +test_runners +test_startstop.out diff --git a/test/startstop/Makefile b/test/startstop/Makefile new file mode 100644 index 0000000..e4a1c01 --- /dev/null +++ b/test/startstop/Makefile @@ -0,0 +1,31 @@ +UNITY_ROOT=../zoo/ThrowTheSwitch.Unity + +CFLAGS = -std=c99 +CFLAGS += -Wall + +SRC_FILES = $(UNITY_ROOT)/src/unity.c test_startstop.c +SRC_FILES += test_runners/TestProductionCode_Runner.c +SRC_FILES += ../../api/mist_comm_api.c + +CFLAGS = -I. -I../../api -I../../include -I../include/compat + +INC_DIRS = -I. -I$(UNITY_ROOT)/src + +INC_DIRS += -I.. +INC_DIRS += -I../../include +INC_DIRS += -I../../include/compat + +TARGET = test_startstop.out + +all: clean default + +default: $(SRC_FILES) + gcc $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES) -o $(TARGET) + - ./$(TARGET) + +test_runners/TestProductionCode_Runner.c: test_startstop.c + mkdir -p test_runners + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test_startstop.c test_runners/TestProductionCode_Runner.c + +clean: + rm -f $(TARGET) diff --git a/test/startstop/test_startstop.c b/test/startstop/test_startstop.c new file mode 100644 index 0000000..85d0ded --- /dev/null +++ b/test/startstop/test_startstop.c @@ -0,0 +1,106 @@ +/** + * Unit-Tests for the MistComm start-stop functionality. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + */ + +#include "unity.h" +#include "string.h" + +#include "mist_comm.h" +#include "mist_comm_iface.h" + +static bool m_start_requested = false; +static bool m_stop_requested = false; +static bool m_started_called = false; +static bool m_stopped_called = false; +static comms_status_t m_status = COMMS_UNINITIALIZED; + +static void * m_start_user = NULL; +static void * m_stop_user = NULL; +static comms_status_change_f * m_start_cb = NULL; +static comms_status_change_f * m_stop_cb = NULL; + + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +comms_error_t comms_dummy_start (comms_layer_iface_t* lyr, comms_status_change_f * cb, void * user) +{ + m_start_requested = true; + m_start_cb = cb; + m_start_user = user; + return COMMS_SUCCESS; +} + +comms_error_t comms_dummy_stop (comms_layer_iface_t* lyr, comms_status_change_f * cb, void * user) +{ + m_stop_requested = true; + m_stop_cb = cb; + m_stop_user = user; + return COMMS_SUCCESS; +} + +void comms_start_done (comms_layer_t* comms, comms_status_t status, void* user) +{ + m_started_called = true; + m_status = status; +} + +void comms_stop_done (comms_layer_t* comms, comms_status_t status, void* user) +{ + m_stopped_called = true; + m_status = status; +} + +void test_StartAndStop() +{ + comms_layer_iface_t base; + + base.start = &comms_dummy_start; + base.stop = &comms_dummy_stop; + + // Test starting + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_start((comms_layer_t*)&base, &comms_start_done, NULL)); + + TEST_ASSERT_EQUAL(true, m_start_requested); + TEST_ASSERT_EQUAL(false, m_stop_requested); + TEST_ASSERT_EQUAL_INT(COMMS_STARTING, comms_status((comms_layer_t*)&base)); + + m_start_cb((comms_layer_t*)&base, COMMS_STARTED, m_start_user); + + TEST_ASSERT_EQUAL(true, m_started_called); + TEST_ASSERT_EQUAL(false, m_stopped_called); + TEST_ASSERT_EQUAL_INT(COMMS_STARTED, m_status); + TEST_ASSERT_EQUAL_INT(COMMS_STARTED, comms_status((comms_layer_t*)&base)); + TEST_ASSERT_NOT_EQUAL(NULL, m_start_cb); + + // Reset flags + m_start_cb = NULL; + m_stop_cb = NULL; + m_start_requested = false; + m_stop_requested = false; + m_started_called = false; + m_stopped_called = false; + + // Test stopping + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_stop((comms_layer_t*)&base, &comms_stop_done, NULL)); + + TEST_ASSERT_EQUAL(false, m_start_requested); + TEST_ASSERT_EQUAL(true, m_stop_requested); + TEST_ASSERT_EQUAL_INT(COMMS_STOPPING, comms_status((comms_layer_t*)&base)); + TEST_ASSERT_NOT_EQUAL(NULL, m_stop_cb); + + m_stop_cb((comms_layer_t*)&base, COMMS_STOPPED, m_stop_user); + + TEST_ASSERT_EQUAL(false, m_started_called); + TEST_ASSERT_EQUAL(true, m_stopped_called); + TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, m_status); + TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); +} diff --git a/test/zoo/ThrowTheSwitch.Unity b/test/zoo/ThrowTheSwitch.Unity new file mode 160000 index 0000000..e3132cd --- /dev/null +++ b/test/zoo/ThrowTheSwitch.Unity @@ -0,0 +1 @@ +Subproject commit e3132cdddd779cb5a813887b2d0d7facb7f3f90a From 70e9bb78758754f03f45d1224f7dc2243c7b4e96 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 6 Dec 2019 16:37:50 +0200 Subject: [PATCH 33/80] Sleep controller implementation and tests. --- .travis.yml | 1 + am/mist_comm_am.c | 4 + api/mist_comm_api.c | 13 ++ cmsis/mist_comm_defer.c | 35 +++++ cmsis/mist_comm_mutex.c | 25 ++++ control/mist_comm_controller.c | 265 +++++++++++++++++++++++++++++++++ include/mist_comm.h | 104 +++++++++++-- include/mist_comm_iface.h | 11 ++ include/mist_comm_private.h | 34 ++++- test/sleep/.gitignore | 2 + test/sleep/Makefile | 32 ++++ test/sleep/log.h | 6 + test/sleep/loglevels.h | 0 test/sleep/test_sleep.c | 215 ++++++++++++++++++++++++++ test/startstop/Makefile | 4 +- 15 files changed, 739 insertions(+), 12 deletions(-) create mode 100644 cmsis/mist_comm_defer.c create mode 100644 cmsis/mist_comm_mutex.c create mode 100644 control/mist_comm_controller.c create mode 100644 test/sleep/.gitignore create mode 100644 test/sleep/Makefile create mode 100644 test/sleep/log.h create mode 100644 test/sleep/loglevels.h create mode 100644 test/sleep/test_sleep.c diff --git a/.travis.yml b/.travis.yml index e9cd2b4..638bfe6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,3 +7,4 @@ addons: script: - make -C test/startstop + - make -C test/sleep diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index a7f93de..c5ddb6a 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -195,6 +195,10 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, //comms->deregister_recv = &am_comms_deregister_recv; comms_initialize_rcvr_management(comms); + _comms_mutex_init(layer); + + comms->sleep_controller_deferred = NULL; + comms->get_packet_type = &am_comms_get_packet_type; comms->set_packet_type = &am_comms_set_packet_type; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index f6d5ddd..db2e9c0 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -280,3 +280,16 @@ void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { cl->set_rssi(cl, msg, rssi); } } + +void _comms_mutex_acquire(comms_layer_t* comms) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + if(NULL != cl->mutex) { + cl->mutex_acquire(cl); + } +} +void _comms_mutex_release(comms_layer_t* comms) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + if(NULL != cl->mutex) { + cl->mutex_release(cl); + } +} diff --git a/cmsis/mist_comm_defer.c b/cmsis/mist_comm_defer.c new file mode 100644 index 0000000..5fd3c8d --- /dev/null +++ b/cmsis/mist_comm_defer.c @@ -0,0 +1,35 @@ +/** + * MistComm deferred implementation on CMSIS with a timer. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + * @author Raido Pahtma + */ + +#include "mist_comm_private.h" + +/** + * Initialize a deferred. In this case deferreds are implemented through an + * os timer. + */ +void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferred_f * cb) +{ + *deferred = osTimerNew(cb, osTimerOnce, (void*)comms, NULL); +} + +/** + * This is a slow implementation, will take at least a millisecond to run + * the deferred. + */ +void _comms_defer(void * deferred) +{ + osTimerStart((osTimerId_t)deferred, 1); +} + +/** + * Free the resources allocated for the deferred. + */ +void _comms_deferred_deinit(void * deferred) +{ + osTimerDelete((osTimerId_t)deferred); +} diff --git a/cmsis/mist_comm_mutex.c b/cmsis/mist_comm_mutex.c new file mode 100644 index 0000000..93bbb7f --- /dev/null +++ b/cmsis/mist_comm_mutex.c @@ -0,0 +1,25 @@ +/** + * MistComm locking implementation with CMSIS mutexes. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + * @author Raido Pahtma + */ + +#include "mist_comm_private.h" +#include "cmsis_os2.h" + +void _comms_mutex_init(comms_layer_t * comms) +{ + comms->mutex = (void*)osMutexNew(NULL); +} + +void _comms_mutex_acquire(comms_layer_t * comms) +{ + osMutexAcquire((osMutexId_t)(comms->mutex), osWaitForever); +} + +void _comms_mutex_release(comms_layer_t * comms) +{ + osMutexRelease((osMutexId_t)(comms->mutex)); +} diff --git a/control/mist_comm_controller.c b/control/mist_comm_controller.c new file mode 100644 index 0000000..4628938 --- /dev/null +++ b/control/mist_comm_controller.c @@ -0,0 +1,265 @@ +/** + * Sleep controller implementation. + * + * Copyright Thinnect Inc. 2019 + * @author Raido Pahtma + * @license MIT + */ + +#include "mist_comm.h" +#include "mist_comm_iface.h" + +#include "loglevels.h" +#define __MODUUL__ "mctrl" +#define __LOG_LEVEL__ (LOG_LEVEL_mist_comm_controller & BASE_LOG_LEVEL) +#include "log.h" + +static bool unsafe_update_state(comms_layer_t * comms); +static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t status); + +static void status_change_callback(comms_layer_t * comms, comms_status_t status, void * user) +{ + bool ok; + _comms_mutex_acquire(comms); + ok = unsafe_service_callbacks(comms, status); + _comms_mutex_release(comms); + if (!ok) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + _comms_defer(cl->sleep_controller_deferred); + } +} + +static void deferred_callback(void * arg) +{ + bool ok; + comms_layer_t * comms = (comms_layer_t*)arg; + _comms_mutex_acquire(comms); + ok = unsafe_update_state(comms); + _comms_mutex_release(comms); + if (!ok) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + _comms_defer(cl->sleep_controller_deferred); + } +} + +/** + * Cannot defer here, as mutex must be released. + * + * @return true if current state is good, false if state needs to be changed. + */ +static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t status) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + comms_sleep_controller_t** indirect; + for (indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if ((*indirect)->pending) + { + if (COMMS_STARTED == status) + { + (*indirect)->cb(comms, status, (*indirect)->user); + (*indirect)->pending = false; + } + else + { + return false; + } + } + if ((*indirect)->block) + { + if (COMMS_STOPPED == status) + { + return false; + } + } + } + return true; +} + +/** + * Cannot defer here, as mutex must be released. + * + * @return true if current state is good, false if state needs to be changed. + */ +static bool unsafe_update_state(comms_layer_t * comms) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + comms_status_t status = comms_status(comms); + comms_sleep_controller_t ** indirect; + for (indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if ((*indirect)->block) // Somebody wants it to be ON + { + if (COMMS_STOPPED == status) + { + if (COMMS_SUCCESS != comms_start(comms, &status_change_callback, NULL)) + { + err1("start"); // Not really expecting resistance here, try again? + return false; + } + } + return true; // Can make decision based on first block encountered + } + } + + // Nobody actually wants it to be ON, so turn it OFF + if (COMMS_SUCCESS != comms_stop(comms, &status_change_callback, NULL)) + { + err1("stop"); // Not really expecting resistance here, try again? + return false; + } + + return true; +} + +comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl, + comms_status_change_f * start_done, void * user) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + comms_error_t err = COMMS_SUCCESS; + comms_sleep_controller_t** indirect; + + _comms_mutex_acquire(comms); + + if (NULL == cl->sleep_controller_deferred) + { + _comms_deferred_init(comms, &(cl->sleep_controller_deferred), deferred_callback); + } + + for (indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if (*indirect == ctrl) + { + err = COMMS_ALREADY; + break; + } + } + + if (COMMS_SUCCESS == err) + { + *indirect = ctrl; + + ctrl->comms = comms; + ctrl->block = false; + ctrl->pending = false; + ctrl->user = user; + ctrl->cb = start_done; + ctrl->next = NULL; + } + + _comms_mutex_release(comms); + + return err; +} + +comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + comms_error_t err = COMMS_FAIL; + comms_sleep_controller_t** indirect; + + _comms_mutex_acquire(comms); + + for(indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) + { + if(*indirect == ctrl) + { + *indirect = ctrl->next; + + ctrl->comms = NULL; + err = COMMS_SUCCESS; + if (true != unsafe_update_state(comms)) + { + err1("panic"); + // TODO actual panic + } + break; + } + } + + _comms_mutex_release(comms); + + return err; +} + +// Block may be asynchronous, wakeup may take time, or EALREADY may be returned +comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl) +{ + comms_error_t err = COMMS_EINVAL; + if ((NULL != ctrl)&&(NULL != ctrl->comms)) + { + _comms_mutex_acquire(ctrl->comms); + + if(ctrl->pending) + { + err = COMMS_EBUSY; + } + else if (true == ctrl->block) + { + err = COMMS_ALREADY; + } + else + { + ctrl->block = true; + if (COMMS_STARTED == comms_status(ctrl->comms)) + { + err = COMMS_ALREADY; + } + else + { + err = COMMS_SUCCESS; + ctrl->pending = true; + if (true != unsafe_update_state(ctrl->comms)) + { + ctrl->pending = false; + err = COMMS_ERETRY; + } + } + } + + _comms_mutex_release(ctrl->comms); + } + return err; +} + +// Allow is synchronous, sleep is not guaranteed, but block is released immediately +comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl) +{ + comms_error_t err = COMMS_EINVAL; + if ((NULL != ctrl)&&(NULL != ctrl->comms)) + { + _comms_mutex_acquire(ctrl->comms); + + if(false == ctrl->block) + { + err = COMMS_ALREADY; + } + else + { + bool pending = ctrl->pending; + err = COMMS_SUCCESS; + ctrl->block = false; + ctrl->pending = false; + if (true != unsafe_update_state(ctrl->comms)) + { + ctrl->block = true; + ctrl->pending = pending; + err = COMMS_ERETRY; + } + } + + _comms_mutex_release(ctrl->comms); + } + return err; +} + +bool comms_sleep_blocked(comms_sleep_controller_t * ctrl) +{ + bool blocked; + _comms_mutex_acquire(ctrl->comms); + blocked = ctrl->block; + _comms_mutex_release(ctrl->comms); + return blocked; +} diff --git a/include/mist_comm.h b/include/mist_comm.h index 99abc82..19a5e67 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -43,18 +43,13 @@ typedef enum CommsStatus { } comms_status_t; typedef struct comms_layer { - uint8_t type; + uint8_t type; // TODO type definitions // Everything else will embed at least this structure } comms_layer_t; -typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, void* user); - -comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user); - -comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user); - -comms_status_t comms_status(comms_layer_t* comms); - +/* + * The comms message structure. Should only be manipulated through comms APIs. + */ typedef struct comms_msg comms_msg_t; // Callback definitions -------------------------------------------------------- @@ -69,6 +64,35 @@ typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_err // registered with a communications layer with comms_register_recv. typedef void comms_receive_f(comms_layer_t* comms, const comms_msg_t* msg, void* user); +// Signalled when a status change is requested and completed. +typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, void* user); + +// ----------------------------------------------------------------------------- + +/** + * Start a comms layer. Use this or sleep controllers, not both. + * @param comms A comms layer to start. + * @param start_done Status change callback. + * @param user Argument passed to the callback. + * @return COMMS_SUCCESS if the callback will be called in the future. + */ +comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user); + +/** + * Stop a comms layer. Use this or sleep controllers, not both. + * @param comms A comms layer to stop. + * @param start_done Status change callback. + * @param user Argument passed to the callback. + * @return COMMS_SUCCESS if the callback will be called in the future. + */ +comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user); + +/** + * Get current status of the comms layer. + * @return Current status. + */ +comms_status_t comms_status(comms_layer_t* comms); + // ----------------------------------------------------------------------------- // Initialize a message structure for use on the specified communications @@ -187,6 +211,68 @@ void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Sleep management controller +// If a sleep controller is registered for a comms layer, it will entirely take +// over start-stop management, the comms_start and comms_stop functions should +// be ignored altogether and only comms_sleep_block and comms_sleep_allow +// should be used. +// ----------------------------------------------------------------------------- +typedef struct comms_sleep_controller comms_sleep_controller_t; + +/** + * Register a sleep controller. + * @param comms Layer to register controller to. + * @param ctrl An unused controller. + * @param start_done Callback function called when a sleep block starts the comms layer. + * @param user User parameter passed with the callback. + */ +comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl, + comms_status_change_f * start_done, void * user); + +/** + * De-register a sleep controller. + * @param comms Layer to remove the controller from. + * @param ctrl A registered ccontroller. + * @return COMMS_SUCCESS when controller was removed. + */ +comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl); + +// Block may be asynchronous, wakeup may take time, or EALREADY may be returned + +/** + * Request a sleep block and the layer to be started. May return COMMS_ALREADY if + * the block takes effect immediately or COMMS_SUCCESS if the layer needs to be + * started and therefore a state change callback will be called once ready. + * + * @param ctrl A registered ccontroller. + * @return COMMS_SUCCESS when callback will be called in the future, COMMS_ALREADY if block immediately successful. + */ +comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl); + +/** + * Release a sleep block. The block is released immediately but the layer shutdown + * will only happen if other blocks are not present ... it will also take time. + * No callback will be fired, it is ok to request another block immediately. + * + * @param ctrl A registered ccontroller. + * @return COMMS_SUCCESS when block was released, COMMS_ALREADY if it was not event active. + */ +comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl); + +/** + * Query current block status. Use comms_status to get actual status. + * + * @param ctrl A registered ccontroller. + * @return true if block is active or pending. + */ +bool comms_sleep_blocked(comms_sleep_controller_t * ctrl); + + +// ----------------------------------------------------------------------------- +// Include implementation details. +// ----------------------------------------------------------------------------- #include "mist_comm_private.h" #endif//MIST_COMM_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index fb9da13..196c10e 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -56,6 +56,9 @@ typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); +typedef void comms_mutex_acquire_f(comms_layer_iface_t*); +typedef void comms_mutex_release_f(comms_layer_iface_t*); + // ----------------------------------------------------------------------------- struct comms_layer_iface { @@ -110,14 +113,22 @@ struct comms_layer_iface { comms_get_rssi_f* get_rssi; comms_set_rssi_f* set_rssi; + comms_mutex_acquire_f* mutex_acquire; + comms_mutex_release_f* mutex_release; + // Receivers comms_receiver_t* receivers; // List of registered receivers // Snoopers comms_receiver_t* snoopers; // List of registered snoopers + // Sleep controllers + comms_sleep_controller_t* sleep_controllers; // List of sleep controllers + void * sleep_controller_deferred; + // Standard variables comms_status_t status; + void * mutex; }; #endif//MIST_COMM_IFACE_H_ diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 660e999..5106154 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -16,9 +16,9 @@ struct comms_msg { uint8_t footer[COMMS_MSG_FOOTER_SIZE]; uint8_t metadata[COMMS_MSG_METADATA_SIZE]; } body; - comms_msg_t* next; // ... maybe, could be very useful for transitioning through layers }; +// Receiver structure ---------------------------------------------------------- struct comms_receiver { // Members are private, should not be accessed am_id_t type; comms_receive_f* callback; @@ -26,4 +26,36 @@ struct comms_receiver { // Members are private, should not be accessed comms_receiver_t* next; }; +// Sleep controller structure -------------------------------------------------- +struct comms_sleep_controller { + comms_layer_t* comms; + + bool block; + bool pending; + + comms_status_change_f* cb; + void* user; + + comms_sleep_controller_t* next; +}; + +// Internal locking ------------------------------------------------------------ + +void _comms_mutex_init(comms_layer_t* comms); + +void _comms_mutex_acquire(comms_layer_t* comms); + +void _comms_mutex_release(comms_layer_t* comms); + + +// Deferred calls -------------------------------------------------------------- + +typedef void comms_deferred_f(void * argument); + +void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferred_f * cb); + +void _comms_defer(void * deferred); + +void _comms_deferred_deinit(void * deferred); + #endif//MIST_COMM_PRIVATE_H_ diff --git a/test/sleep/.gitignore b/test/sleep/.gitignore new file mode 100644 index 0000000..0977986 --- /dev/null +++ b/test/sleep/.gitignore @@ -0,0 +1,2 @@ +test_runners +test_sleep.out diff --git a/test/sleep/Makefile b/test/sleep/Makefile new file mode 100644 index 0000000..56ef767 --- /dev/null +++ b/test/sleep/Makefile @@ -0,0 +1,32 @@ +UNITY_ROOT=../zoo/ThrowTheSwitch.Unity + +CFLAGS = -std=c99 -g +CFLAGS += -Wall + +SRC_FILES = $(UNITY_ROOT)/src/unity.c test_sleep.c +SRC_FILES += test_runners/TestProductionCode_Runner.c +SRC_FILES += ../../api/mist_comm_api.c +SRC_FILES += ../../control/mist_comm_controller.c + +CFLAGS += -I. -I../../api -I../../include -I../include/compat + +INC_DIRS = -I. -I$(UNITY_ROOT)/src + +INC_DIRS += -I.. +INC_DIRS += -I../../include +INC_DIRS += -I../../include/compat + +TARGET = test_sleep.out + +all: clean default + +default: $(SRC_FILES) + gcc $(CFLAGS) $(INC_DIRS) $(SYMBOLS) $(SRC_FILES) -o $(TARGET) + - ./$(TARGET) + +test_runners/TestProductionCode_Runner.c: test_sleep.c + mkdir -p test_runners + ruby $(UNITY_ROOT)/auto/generate_test_runner.rb test_sleep.c test_runners/TestProductionCode_Runner.c + +clean: + rm -f $(TARGET) diff --git a/test/sleep/log.h b/test/sleep/log.h new file mode 100644 index 0000000..1fc2669 --- /dev/null +++ b/test/sleep/log.h @@ -0,0 +1,6 @@ +#ifndef LOG_H_ +#define LOG_H_ + +void err1(char * s, ...); + +#endif//LOG_H_ diff --git a/test/sleep/loglevels.h b/test/sleep/loglevels.h new file mode 100644 index 0000000..e69de29 diff --git a/test/sleep/test_sleep.c b/test/sleep/test_sleep.c new file mode 100644 index 0000000..c55db56 --- /dev/null +++ b/test/sleep/test_sleep.c @@ -0,0 +1,215 @@ +/** + * Unit-Tests for the MistComm start-stop functionality. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + */ + +#include "unity.h" +#include "string.h" + +#include "mist_comm.h" +#include "mist_comm_iface.h" + +static int m_start_requested = 0; +static int m_stop_requested = 0; +static int m_change_called = 0; +static int m_errors = 0; +static comms_status_t m_status = COMMS_UNINITIALIZED; + +static void * m_start_user = NULL; +static void * m_stop_user = NULL; +static comms_status_change_f * m_start_cb = NULL; +static comms_status_change_f * m_stop_cb = NULL; + + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +comms_error_t comms_dummy_start (comms_layer_iface_t* lyr, comms_status_change_f * cb, void * user) +{ + m_start_requested = true; + m_start_cb = cb; + m_start_user = user; + return COMMS_SUCCESS; +} + +comms_error_t comms_dummy_stop (comms_layer_iface_t* lyr, comms_status_change_f * cb, void * user) +{ + m_stop_requested = true; + m_stop_cb = cb; + m_stop_user = user; + return COMMS_SUCCESS; +} + +void comms_status_changed (comms_layer_t* comms, comms_status_t status, void* user) +{ + m_change_called++; + m_status = status; +} + +typedef struct mocked_deferred +{ + comms_deferred_f * cb; + void * arg; + bool pending; +} mocked_deferred_t; + +mocked_deferred_t m_deferred = {NULL, NULL, false}; + +void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferred_f * cb) +{ + *deferred = &m_deferred; + m_deferred.cb = cb; + m_deferred.arg = comms; + m_deferred.pending = false; +} + +void _comms_defer(void * deferred) +{ + ((mocked_deferred_t*)deferred)->pending = true; +} + +void _comms_deferred_deinit(void * deferred) +{ + ((mocked_deferred_t*)deferred)->pending = false; + ((mocked_deferred_t*)deferred)->arg = NULL; + ((mocked_deferred_t*)deferred)->cb = NULL; +} + +void err1(char * s, ...) +{ + m_errors++; +} + +void test_SleepControllers() +{ + comms_layer_iface_t base; + comms_sleep_controller_t scs[3]; + + base.start = &comms_dummy_start; + base.stop = &comms_dummy_stop; + base.status = COMMS_STOPPED; + base.sleep_controllers = NULL; + base.sleep_controller_deferred = NULL; + base.mutex = NULL; + + TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); + + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_register_sleep_controller( + (comms_layer_t*)&base, + &(scs[0]), + comms_status_changed, + &(scs[0]))); + + TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); + + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_block(&(scs[0]))); + + TEST_ASSERT_EQUAL(1, m_start_requested); + TEST_ASSERT_NOT_EQUAL(NULL, m_start_cb); + + m_start_cb((comms_layer_t*)&base, COMMS_STARTED, m_start_user); + + TEST_ASSERT_EQUAL(1, m_change_called); + TEST_ASSERT_EQUAL(COMMS_STARTED, m_status); + TEST_ASSERT_EQUAL_INT(COMMS_STARTED, comms_status((comms_layer_t*)&base)); + + // Add another and stop and start both + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_register_sleep_controller( + (comms_layer_t*)&base, + &(scs[1]), + comms_status_changed, + &(scs[1]))); + + m_change_called = 0; + TEST_ASSERT_EQUAL_INT(COMMS_ALREADY, comms_sleep_block(&(scs[1]))); + TEST_ASSERT_EQUAL(0, m_change_called); + + m_change_called = 0; + m_stop_requested = 0; + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_allow(&(scs[0]))); + TEST_ASSERT_EQUAL(0, m_change_called); + TEST_ASSERT_EQUAL(0, m_stop_requested); + + m_change_called = 0; + m_stop_requested = false; + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_allow(&(scs[1]))); + TEST_ASSERT_EQUAL(0, m_change_called); + TEST_ASSERT_EQUAL(1, m_stop_requested); + + m_change_called = 0; + m_stop_cb((comms_layer_t*)&base, COMMS_STOPPED, m_stop_user); + TEST_ASSERT_EQUAL(0, m_change_called); + TEST_ASSERT_EQUAL(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); + + m_change_called = 0; + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_block(&(scs[1]))); + TEST_ASSERT_EQUAL(0, m_change_called); + + TEST_ASSERT_EQUAL(1, m_start_requested); + TEST_ASSERT_NOT_EQUAL(NULL, m_start_cb); + + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_block(&(scs[0]))); + TEST_ASSERT_EQUAL(0, m_change_called); + + TEST_ASSERT_EQUAL(1, m_start_requested); // Should not be called multiple times + + m_start_cb((comms_layer_t*)&base, COMMS_STARTED, m_start_user); + TEST_ASSERT_EQUAL(2, m_change_called); + TEST_ASSERT_EQUAL_INT(COMMS_STARTED, comms_status((comms_layer_t*)&base)); + + // Stop the current ones, add a third one and start it before the ongoing stop completes + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_register_sleep_controller( + (comms_layer_t*)&base, + &(scs[2]), + comms_status_changed, + &(scs[2]))); + + m_start_requested = 0; + m_stop_requested = 0; + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_allow(&(scs[0]))); + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_allow(&(scs[1]))); + TEST_ASSERT_EQUAL(1, m_stop_requested); + + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_sleep_block(&(scs[2]))); + TEST_ASSERT_EQUAL(0, m_start_requested); // Should not start, as still stopping + + m_change_called = 0; + m_stop_cb((comms_layer_t*)&base, COMMS_STOPPED, m_stop_user); + TEST_ASSERT_EQUAL(0, m_change_called); + + TEST_ASSERT_EQUAL(true, m_deferred.pending); + m_deferred.cb(m_deferred.arg); + + TEST_ASSERT_EQUAL(1, m_start_requested); + TEST_ASSERT_NOT_EQUAL(NULL, m_start_cb); + m_start_cb((comms_layer_t*)&base, COMMS_STARTED, m_start_user); + + TEST_ASSERT_EQUAL(1, m_change_called); + TEST_ASSERT_EQUAL(COMMS_STARTED, m_status); + TEST_ASSERT_EQUAL_INT(COMMS_STARTED, comms_status((comms_layer_t*)&base)); + + // Deregister all controllers, layer should be stopped + m_stop_requested = 0; + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_deregister_sleep_controller( + (comms_layer_t*)&base, + &(scs[0]))); + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_deregister_sleep_controller( + (comms_layer_t*)&base, + &(scs[1]))); + TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_deregister_sleep_controller( + (comms_layer_t*)&base, + &(scs[2]))); + TEST_ASSERT_EQUAL(1, m_stop_requested); + m_stop_cb((comms_layer_t*)&base, COMMS_STOPPED, m_stop_user); + TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); + + // Make sure we did not pick up any errors during the test + TEST_ASSERT_EQUAL(0, m_errors); +} diff --git a/test/startstop/Makefile b/test/startstop/Makefile index e4a1c01..0144b71 100644 --- a/test/startstop/Makefile +++ b/test/startstop/Makefile @@ -1,13 +1,13 @@ UNITY_ROOT=../zoo/ThrowTheSwitch.Unity -CFLAGS = -std=c99 +CFLAGS = -std=c99 -g CFLAGS += -Wall SRC_FILES = $(UNITY_ROOT)/src/unity.c test_startstop.c SRC_FILES += test_runners/TestProductionCode_Runner.c SRC_FILES += ../../api/mist_comm_api.c -CFLAGS = -I. -I../../api -I../../include -I../include/compat +CFLAGS += -I. -I../../api -I../../include -I../include/compat INC_DIRS = -I. -I$(UNITY_ROOT)/src From 5f8ba02a484e5ca4de9a49c9921568176f30e8ed Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 6 Dec 2019 18:29:07 +0200 Subject: [PATCH 34/80] Fix deferreds and mutexes with CMSIS. --- cmsis/mist_comm_defer.c | 2 ++ cmsis/mist_comm_mutex.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cmsis/mist_comm_defer.c b/cmsis/mist_comm_defer.c index 5fd3c8d..6fcce79 100644 --- a/cmsis/mist_comm_defer.c +++ b/cmsis/mist_comm_defer.c @@ -8,6 +8,8 @@ #include "mist_comm_private.h" +#include "cmsis_os2.h" + /** * Initialize a deferred. In this case deferreds are implemented through an * os timer. diff --git a/cmsis/mist_comm_mutex.c b/cmsis/mist_comm_mutex.c index 93bbb7f..958dc9c 100644 --- a/cmsis/mist_comm_mutex.c +++ b/cmsis/mist_comm_mutex.c @@ -6,20 +6,26 @@ * @author Raido Pahtma */ +#include "mist_comm_iface.h" #include "mist_comm_private.h" #include "cmsis_os2.h" -void _comms_mutex_init(comms_layer_t * comms) +static void mutex_acquire(comms_layer_iface_t * cl) { - comms->mutex = (void*)osMutexNew(NULL); + osMutexAcquire((osMutexId_t)(cl->mutex), osWaitForever); } -void _comms_mutex_acquire(comms_layer_t * comms) +static void mutex_release(comms_layer_iface_t * cl) { - osMutexAcquire((osMutexId_t)(comms->mutex), osWaitForever); + osMutexRelease((osMutexId_t)(cl->mutex)); } -void _comms_mutex_release(comms_layer_t * comms) + +void _comms_mutex_init(comms_layer_t * comms) { - osMutexRelease((osMutexId_t)(comms->mutex)); + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + cl->mutex = (void*)osMutexNew(NULL); + cl->mutex_acquire = mutex_acquire; + cl->mutex_release = mutex_release; } + From a1642d6204e920b8e0dbe372a7d2a846dee57d9b Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 8 Jan 2020 14:17:39 +0200 Subject: [PATCH 35/80] Update according to send_done signature change. --- bridge/mist_comm_bridge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index ea20558..21dd768 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -20,7 +20,7 @@ #include "log.h" static void bridge_thread(void * param); -static void bridge_send_done(comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); +static void bridge_send_done(comms_layer_t * comms, const comms_msg_t * msg, comms_error_t result, void * user); static void bridge_am_snoop(comms_layer_t* comms, const comms_msg_t* msg, void* user); comms_error_t comms_bridge_init (comms_bridge_t * bridge, @@ -48,7 +48,7 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, return COMMS_SUCCESS; } -static void bridge_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) +static void bridge_send_done (comms_layer_t * comms, const comms_msg_t * msg, comms_error_t result, void * user) { comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "%p snt %d", msg, result); From f6fda14028c6a139affb0fa7efdfe7e9b908c0ba Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 8 Jan 2020 18:33:58 +0200 Subject: [PATCH 36/80] Tweak bridge logging. --- bridge/mist_comm_bridge.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index 21dd768..aa6e25c 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -51,7 +51,7 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, static void bridge_send_done (comms_layer_t * comms, const comms_msg_t * msg, comms_error_t result, void * user) { comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; - logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "%p snt %d", msg, result); + logger(result == COMMS_SUCCESS ? LOG_DEBUG3: LOG_WARN1, "%p snt %d", msg, result); osThreadFlagsSet(bt->thread, 0x00000001U); } @@ -59,10 +59,10 @@ static void bridge_am_snoop (comms_layer_t* comms, const comms_msg_t* msg, void* { comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; - #if (__LOG_LEVEL__ & LOG_DEBUG4) + #if (__LOG_LEVEL__ & LOG_DEBUG2) uint8_t plen = comms_get_payload_length(comms, msg); uint8_t* payload = comms_get_payload(comms, msg, plen); - debugb4("rcv %d", payload, plen, (unsigned int)plen); + debugb2("rcv %d", payload, plen, (unsigned int)plen); #endif//debug if(osMessageQueuePut(bt->rxqueue, msg, 0, 0) != osOK) @@ -79,12 +79,12 @@ static void bridge_thread (void * param) { if (osOK == osMessageQueueGet(bt->txqueue, &(bt->msg), NULL, osWaitForever)) { - #if (__LOG_LEVEL__ & LOG_DEBUG4) + #if (__LOG_LEVEL__ & LOG_DEBUG1) uint8_t plen = comms_get_payload_length(bt->layer, &(bt->msg)); uint8_t* payload = comms_get_payload(bt->layer, &(bt->msg), plen); //debugb1("snd %d", payload, plen, (unsigned int)plen); - debugb4("tx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", + debugb1("{%02X}%04"PRIX16"->%04"PRIX16"[%02X]", payload, plen, DEFAULT_PAN_ID, comms_am_get_source(bt->layer, &(bt->msg)), @@ -95,7 +95,7 @@ static void bridge_thread (void * param) if(COMMS_SUCCESS == comms_send(bt->layer, &(bt->msg), bridge_send_done, bt)) { osThreadFlagsWait(0x00000001U, osFlagsWaitAny, osWaitForever); - debug1("snt"); + debug4("snt"); } else { From d6454dd7d27acb5c09cb81d2e9dba9420eab8b61 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 8 Jan 2020 18:34:07 +0200 Subject: [PATCH 37/80] Add checks on required args. --- api/mist_comm_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index db2e9c0..c41d3f5 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -12,7 +12,7 @@ static void comms_status_change_callback(comms_layer_t* comms, comms_status_t st } comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { - if(NULL != comms) { + if((NULL != comms)&&(NULL != start_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->start) { if(NULL != cl->status_change_user_cb) { @@ -33,7 +33,7 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don } comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user) { - if(NULL != comms) { + if((NULL != comms)&&(NULL != stop_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->stop) { if(NULL != cl->status_change_user_cb) { From 0a269f7debe4cc3960afaa255052b8dce2511c51 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 4 Feb 2020 14:44:13 +0200 Subject: [PATCH 38/80] Drop the const in send_done, because it's your own pointer. --- include/mist_comm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mist_comm.h b/include/mist_comm.h index 6f2e7fe..19a5e67 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -58,7 +58,7 @@ typedef struct comms_msg comms_msg_t; // to the client. A function of this type must be passed with every call to the // comms_send function and the passed function will be called in the future if // the comms_send returns a successful result (message is accepted). -typedef void comms_send_done_f(comms_layer_t* comms, const comms_msg_t* msg, comms_error_t result, void* user); +typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user); // Signalled when a message is received. Functions of this type must first be // registered with a communications layer with comms_register_recv. From 04d0f1db9144f450070b46a475d85ccfcbcb66ab Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 7 Feb 2020 23:48:15 +0200 Subject: [PATCH 39/80] Implement mutex for state changes. --- api/mist_comm_api.c | 56 +++++++++++++++++++++++++++++++++-------- cmsis/mist_comm_mutex.c | 9 ++++--- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index c41d3f5..b15f1f7 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -5,25 +5,43 @@ static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - cl->status = status; + cl->status_change_user_cb(comms, status, cl->status_change_user); + + _comms_mutex_acquire(comms); + cl->status = status; cl->status_change_user_cb = NULL; cl->status_change_user = NULL; + _comms_mutex_release(comms); } comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { if((NULL != comms)&&(NULL != start_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->start) { + _comms_mutex_acquire(comms); if(NULL != cl->status_change_user_cb) { + _comms_mutex_release(comms); return COMMS_EBUSY; } + else if(COMMS_STARTED == cl->status) { + _comms_mutex_release(comms); + return COMMS_ALREADY; + } else { + comms_status_t status = cl->status; + cl->status = COMMS_STARTING; + cl->status_change_user_cb = start_done; + cl->status_change_user = user; + _comms_mutex_release(comms); + comms_error_t err = cl->start(cl, &comms_status_change_callback, NULL); - if(COMMS_SUCCESS == err) { - cl->status = COMMS_STARTING; - cl->status_change_user_cb = start_done; - cl->status_change_user = user; + if(COMMS_SUCCESS != err) { + _comms_mutex_acquire(comms); + cl->status = status; + cl->status_change_user_cb = NULL; + cl->status_change_user = NULL; + _comms_mutex_release(comms); } return err; } @@ -36,15 +54,29 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, if((NULL != comms)&&(NULL != stop_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->stop) { + _comms_mutex_acquire(comms); if(NULL != cl->status_change_user_cb) { + _comms_mutex_release(comms); return COMMS_EBUSY; } + else if(COMMS_STOPPED == cl->status) { + _comms_mutex_release(comms); + return COMMS_ALREADY; + } else { + comms_status_t status = cl->status; + cl->status = COMMS_STOPPING; + cl->status_change_user_cb = stop_done; + cl->status_change_user = user; + _comms_mutex_release(comms); + comms_error_t err = cl->stop(cl, &comms_status_change_callback, NULL); - if(COMMS_SUCCESS == err) { - cl->status = COMMS_STOPPING; - cl->status_change_user_cb = stop_done; - cl->status_change_user = user; + if(COMMS_SUCCESS != err) { + _comms_mutex_acquire(comms); + cl->status = status; + cl->status_change_user_cb = NULL; + cl->status_change_user = NULL; + _comms_mutex_release(comms); } return err; } @@ -55,7 +87,11 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, comms_status_t comms_status(comms_layer_t* comms) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - return cl->status; + comms_status_t status; + _comms_mutex_acquire(comms); + status = cl->status; + _comms_mutex_release(comms); + return status; } void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { diff --git a/cmsis/mist_comm_mutex.c b/cmsis/mist_comm_mutex.c index 958dc9c..7675914 100644 --- a/cmsis/mist_comm_mutex.c +++ b/cmsis/mist_comm_mutex.c @@ -10,9 +10,11 @@ #include "mist_comm_private.h" #include "cmsis_os2.h" +static const osMutexAttr_t attr = {"comms", osMutexRecursive|osMutexPrioInherit, NULL, 0U}; + static void mutex_acquire(comms_layer_iface_t * cl) { - osMutexAcquire((osMutexId_t)(cl->mutex), osWaitForever); + while(osOK != osMutexAcquire((osMutexId_t)(cl->mutex), osWaitForever)); } static void mutex_release(comms_layer_iface_t * cl) @@ -20,12 +22,11 @@ static void mutex_release(comms_layer_iface_t * cl) osMutexRelease((osMutexId_t)(cl->mutex)); } - void _comms_mutex_init(comms_layer_t * comms) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; - cl->mutex = (void*)osMutexNew(NULL); + + cl->mutex = (void*)osMutexNew(&attr); cl->mutex_acquire = mutex_acquire; cl->mutex_release = mutex_release; } - From 3888dcd6d1a0e5c1c3bccd02ad3bf627cc31079f Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Fri, 14 Feb 2020 13:51:32 +0200 Subject: [PATCH 40/80] Remove const cast from senddone. --- bridge/mist_comm_bridge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index aa6e25c..5396d85 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -20,7 +20,7 @@ #include "log.h" static void bridge_thread(void * param); -static void bridge_send_done(comms_layer_t * comms, const comms_msg_t * msg, comms_error_t result, void * user); +static void bridge_send_done(comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); static void bridge_am_snoop(comms_layer_t* comms, const comms_msg_t* msg, void* user); comms_error_t comms_bridge_init (comms_bridge_t * bridge, @@ -48,7 +48,7 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, return COMMS_SUCCESS; } -static void bridge_send_done (comms_layer_t * comms, const comms_msg_t * msg, comms_error_t result, void * user) +static void bridge_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) { comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; logger(result == COMMS_SUCCESS ? LOG_DEBUG3: LOG_WARN1, "%p snt %d", msg, result); From 16270f18d76c6e627d81781afea62f9920427cf2 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 2 Mar 2020 22:01:06 +0200 Subject: [PATCH 41/80] Rework for separate mutexes. --- am/mist_comm_am.c | 18 ++++--------- api/mist_comm_api.c | 46 ++++++++++++---------------------- api/mist_comm_rcv.c | 40 +++++++++++++++++++++++------ cmsis/mist_comm_mutex.c | 18 ++++++------- cmsis/mist_comm_mutex.h | 15 +++++++++++ control/mist_comm_controller.c | 16 ++++++------ include/mist_comm.h | 22 ++++++++++++++++ include/mist_comm_iface.h | 11 +++----- include/mist_comm_private.h | 9 ------- 9 files changed, 110 insertions(+), 85 deletions(-) create mode 100644 cmsis/mist_comm_mutex.h diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index c5ddb6a..2fc899e 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -32,15 +32,6 @@ static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, return COMMS_FAIL; } -//static comms_error_t am_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid) { -// // there is a suitable implementation in mist_comm_rcv.c -// return COMMS_FAIL; -//} -//static comms_error_t am_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { -// // there is a suitable implementation in mist_comm_rcv.c -// return COMMS_FAIL; -//} - static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { return msg->body.type; } @@ -191,11 +182,12 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, else { comms->send = &am_comms_send; } - //comms->register_recv = &am_comms_register_recv; - //comms->deregister_recv = &am_comms_deregister_recv; - comms_initialize_rcvr_management(comms); - _comms_mutex_init(layer); + comms->start_stop_mutex = comms_mutex_create(); + comms->controller_mutex = comms_mutex_create(); + comms->receiver_mutex = comms_mutex_create(); + + comms_initialize_rcvr_management(comms); comms->sleep_controller_deferred = NULL; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index b15f1f7..7b73e87 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -6,26 +6,25 @@ static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + comms_mutex_acquire(cl->start_stop_mutex); cl->status_change_user_cb(comms, status, cl->status_change_user); - - _comms_mutex_acquire(comms); cl->status = status; cl->status_change_user_cb = NULL; cl->status_change_user = NULL; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); } comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { if((NULL != comms)&&(NULL != start_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->start) { - _comms_mutex_acquire(comms); + comms_mutex_acquire(cl->start_stop_mutex); if(NULL != cl->status_change_user_cb) { - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); return COMMS_EBUSY; } else if(COMMS_STARTED == cl->status) { - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); return COMMS_ALREADY; } else { @@ -33,15 +32,15 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don cl->status = COMMS_STARTING; cl->status_change_user_cb = start_done; cl->status_change_user = user; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); comms_error_t err = cl->start(cl, &comms_status_change_callback, NULL); if(COMMS_SUCCESS != err) { - _comms_mutex_acquire(comms); + comms_mutex_acquire(cl->start_stop_mutex); cl->status = status; cl->status_change_user_cb = NULL; cl->status_change_user = NULL; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); } return err; } @@ -54,13 +53,13 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, if((NULL != comms)&&(NULL != stop_done)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; if(NULL != cl->stop) { - _comms_mutex_acquire(comms); + comms_mutex_acquire(cl->start_stop_mutex); if(NULL != cl->status_change_user_cb) { - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); return COMMS_EBUSY; } else if(COMMS_STOPPED == cl->status) { - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); return COMMS_ALREADY; } else { @@ -68,15 +67,15 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, cl->status = COMMS_STOPPING; cl->status_change_user_cb = stop_done; cl->status_change_user = user; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); comms_error_t err = cl->stop(cl, &comms_status_change_callback, NULL); if(COMMS_SUCCESS != err) { - _comms_mutex_acquire(comms); + comms_mutex_acquire(cl->start_stop_mutex); cl->status = status; cl->status_change_user_cb = NULL; cl->status_change_user = NULL; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); } return err; } @@ -88,9 +87,9 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, comms_status_t comms_status(comms_layer_t* comms) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; comms_status_t status; - _comms_mutex_acquire(comms); + comms_mutex_acquire(cl->start_stop_mutex); status = cl->status; - _comms_mutex_release(comms); + comms_mutex_release(cl->start_stop_mutex); return status; } @@ -316,16 +315,3 @@ void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { cl->set_rssi(cl, msg, rssi); } } - -void _comms_mutex_acquire(comms_layer_t* comms) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - if(NULL != cl->mutex) { - cl->mutex_acquire(cl); - } -} -void _comms_mutex_release(comms_layer_t* comms) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - if(NULL != cl->mutex) { - cl->mutex_release(cl); - } -} diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 28d059b..3539ff7 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -3,8 +3,12 @@ static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { comms_receiver_t** indirect; + + comms_mutex_acquire(comms->receiver_mutex); + for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)) { if(*indirect == rcvr) { + comms_mutex_release(comms->receiver_mutex); return COMMS_ALREADY; } } @@ -15,13 +19,18 @@ static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_r rcvr->user = user; rcvr->next = NULL; + comms_mutex_release(comms->receiver_mutex); return COMMS_SUCCESS; } static comms_error_t rcv_comms_register_snooper(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user) { comms_receiver_t** indirect; + + comms_mutex_acquire(comms->receiver_mutex); + for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)) { if(*indirect == rcvr) { + comms_mutex_release(comms->receiver_mutex); return COMMS_ALREADY; } } @@ -32,56 +41,73 @@ static comms_error_t rcv_comms_register_snooper(comms_layer_iface_t* comms, comm rcvr->user = user; rcvr->next = NULL; + comms_mutex_release(comms->receiver_mutex); return COMMS_SUCCESS; } static comms_error_t rcv_comms_deregister_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { comms_receiver_t** indirect; + + comms_mutex_acquire(comms->receiver_mutex); + for(indirect=&(comms->receivers); NULL != *indirect; indirect = &((*indirect)->next)) { if(*indirect == rcvr) { *indirect = rcvr->next; + comms_mutex_release(comms->receiver_mutex); return COMMS_SUCCESS; } } + comms_mutex_release(comms->receiver_mutex); return COMMS_FAIL; } static comms_error_t rcv_comms_deregister_snooper(comms_layer_iface_t* comms, comms_receiver_t* rcvr) { comms_receiver_t** indirect; + + comms_mutex_acquire(comms->receiver_mutex); + for(indirect=&(comms->snoopers); NULL != *indirect; indirect = &((*indirect)->next)) { if(*indirect == rcvr) { *indirect = rcvr->next; + comms_mutex_release(comms->receiver_mutex); return COMMS_SUCCESS; } } + comms_mutex_release(comms->receiver_mutex); return COMMS_FAIL; } -comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - am_id_t ptype = comms_get_packet_type(comms, msg); +comms_msg_t* comms_deliver(comms_layer_t* layer, comms_msg_t* msg) { + comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; + am_id_t ptype = comms_get_packet_type(layer, msg); comms_receiver_t* receiver; + comms_mutex_acquire(comms->receiver_mutex); + // Receivers filter based on type - for(receiver=cl->receivers;receiver!=NULL;receiver=receiver->next) { + for(receiver=comms->receivers;receiver!=NULL;receiver=receiver->next) { if(receiver->type == ptype) { - receiver->callback(comms, msg, receiver->user); + receiver->callback(layer, msg, receiver->user); } } // Snoopers get everyting - for(receiver=cl->snoopers;receiver!=NULL;receiver=receiver->next) { - receiver->callback(comms, msg, receiver->user); + for(receiver=comms->snoopers;receiver!=NULL;receiver=receiver->next) { + receiver->callback(layer, msg, receiver->user); } + comms_mutex_release(comms->receiver_mutex); + return msg; } comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms) { + comms_mutex_acquire(comms->receiver_mutex); comms->receivers = NULL; comms->register_recv = &rcv_comms_register_recv; comms->deregister_recv = &rcv_comms_deregister_recv; comms->register_snooper = &rcv_comms_register_snooper; comms->deregister_snooper = &rcv_comms_deregister_snooper; + comms_mutex_release(comms->receiver_mutex); return COMMS_SUCCESS; } diff --git a/cmsis/mist_comm_mutex.c b/cmsis/mist_comm_mutex.c index 7675914..16f43f4 100644 --- a/cmsis/mist_comm_mutex.c +++ b/cmsis/mist_comm_mutex.c @@ -10,23 +10,19 @@ #include "mist_comm_private.h" #include "cmsis_os2.h" -static const osMutexAttr_t attr = {"comms", osMutexRecursive|osMutexPrioInherit, NULL, 0U}; +static const osMutexAttr_t attr = {"comms", osMutexPrioInherit, NULL, 0U}; -static void mutex_acquire(comms_layer_iface_t * cl) +void comms_mutex_acquire(commsMutexId_t mutex) { - while(osOK != osMutexAcquire((osMutexId_t)(cl->mutex), osWaitForever)); + while(osOK != osMutexAcquire((osMutexId_t)(mutex), osWaitForever)); } -static void mutex_release(comms_layer_iface_t * cl) +void comms_mutex_release(commsMutexId_t mutex) { - osMutexRelease((osMutexId_t)(cl->mutex)); + osMutexRelease((osMutexId_t)mutex); } -void _comms_mutex_init(comms_layer_t * comms) +commsMutexId_t comms_mutex_create() { - comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; - - cl->mutex = (void*)osMutexNew(&attr); - cl->mutex_acquire = mutex_acquire; - cl->mutex_release = mutex_release; + return (commsMutexId_t)osMutexNew(&attr); } diff --git a/cmsis/mist_comm_mutex.h b/cmsis/mist_comm_mutex.h new file mode 100644 index 0000000..6b330ac --- /dev/null +++ b/cmsis/mist_comm_mutex.h @@ -0,0 +1,15 @@ +/** + * MistComm locking with CMSIS mutexes. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + * @author Raido Pahtma + */ +#ifndef MIST_COMM_MUTEX_H_ +#define MIST_COMM_MUTEX_H_ + +#include "cmsis_os2.h" + +typedef osMutexId_t commsMutexId_t; + +#endif//MIST_COMM_MUTEX_H_ diff --git a/control/mist_comm_controller.c b/control/mist_comm_controller.c index 4628938..2612c09 100644 --- a/control/mist_comm_controller.c +++ b/control/mist_comm_controller.c @@ -20,9 +20,9 @@ static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t statu static void status_change_callback(comms_layer_t * comms, comms_status_t status, void * user) { bool ok; - _comms_mutex_acquire(comms); + comms_mutex_acquire(comms->controller_mutex); ok = unsafe_service_callbacks(comms, status); - _comms_mutex_release(comms); + comms_mutex_release(comms->controller_mutex); if (!ok) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; @@ -34,9 +34,9 @@ static void deferred_callback(void * arg) { bool ok; comms_layer_t * comms = (comms_layer_t*)arg; - _comms_mutex_acquire(comms); + comms_mutex_acquire(comms->controller_mutex); ok = unsafe_update_state(comms); - _comms_mutex_release(comms); + comms_mutex_release(comms->controller_mutex); if (!ok) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; @@ -121,7 +121,7 @@ comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep comms_error_t err = COMMS_SUCCESS; comms_sleep_controller_t** indirect; - _comms_mutex_acquire(comms); + comms_mutex_acquire(comms->controller_mutex); if (NULL == cl->sleep_controller_deferred) { @@ -149,7 +149,7 @@ comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep ctrl->next = NULL; } - _comms_mutex_release(comms); + comms_mutex_release(comms->controller_mutex); return err; } @@ -160,7 +160,7 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle comms_error_t err = COMMS_FAIL; comms_sleep_controller_t** indirect; - _comms_mutex_acquire(comms); + comms_mutex_acquire(comms->controller_mutex); for(indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) { @@ -179,7 +179,7 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle } } - _comms_mutex_release(comms); + comms_mutex_release(comms->controller_mutex); return err; } diff --git a/include/mist_comm.h b/include/mist_comm.h index 19a5e67..000c020 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -7,6 +7,7 @@ #include #include "mist_comm_basics.h" +#include "mist_comm_mutex.h" #include "platform_msg.h" @@ -269,6 +270,27 @@ comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl); */ bool comms_sleep_blocked(comms_sleep_controller_t * ctrl); +// ----------------------------------------------------------------------------- +// Locking, for internal use mostly -------------------------------------------- +// ----------------------------------------------------------------------------- + +/** + * Create a mutex. + * @return NULL for failure. + */ +commsMutexId_t comms_mutex_create(); + +/** + * Acquire the specified mutex. Blocks until aquired. + * @param mutex - The mutex to acquire. + */ +void comms_mutex_acquire(commsMutexId_t mutex); + +/** + * Release the specified mutex. Returns "immediately". + * @param mutex - The mutex to release. + */ +void comms_mutex_release(commsMutexId_t mutex); // ----------------------------------------------------------------------------- // Include implementation details. diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 196c10e..4ce5c32 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -56,9 +56,6 @@ typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); -typedef void comms_mutex_acquire_f(comms_layer_iface_t*); -typedef void comms_mutex_release_f(comms_layer_iface_t*); - // ----------------------------------------------------------------------------- struct comms_layer_iface { @@ -113,9 +110,6 @@ struct comms_layer_iface { comms_get_rssi_f* get_rssi; comms_set_rssi_f* set_rssi; - comms_mutex_acquire_f* mutex_acquire; - comms_mutex_release_f* mutex_release; - // Receivers comms_receiver_t* receivers; // List of registered receivers @@ -128,7 +122,10 @@ struct comms_layer_iface { // Standard variables comms_status_t status; - void * mutex; + + commsMutexId_t controller_mutex; + commsMutexId_t start_stop_mutex; + commsMutexId_t receiver_mutex; }; #endif//MIST_COMM_IFACE_H_ diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 5106154..8493570 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -39,15 +39,6 @@ struct comms_sleep_controller { comms_sleep_controller_t* next; }; -// Internal locking ------------------------------------------------------------ - -void _comms_mutex_init(comms_layer_t* comms); - -void _comms_mutex_acquire(comms_layer_t* comms); - -void _comms_mutex_release(comms_layer_t* comms); - - // Deferred calls -------------------------------------------------------------- typedef void comms_deferred_f(void * argument); From 1c2394a2ada90136dadf787c2b370093f25cf8fe Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 3 Mar 2020 07:52:13 +0200 Subject: [PATCH 42/80] Add mock mutex, fix tests. --- control/mist_comm_controller.c | 37 ++++++++++++++++++--------------- mock/mist_comm_mutex.c | 30 ++++++++++++++++++++++++++ mock/mist_comm_mutex.h | 13 ++++++++++++ test/Makefile | 4 ++-- test/sleep/Makefile | 4 ++-- test/sleep/test_sleep.c | 6 +++++- test/startstop/Makefile | 5 ++--- test/startstop/test_startstop.c | 5 +++++ 8 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 mock/mist_comm_mutex.c create mode 100644 mock/mist_comm_mutex.h diff --git a/control/mist_comm_controller.c b/control/mist_comm_controller.c index 2612c09..46c85ff 100644 --- a/control/mist_comm_controller.c +++ b/control/mist_comm_controller.c @@ -19,27 +19,27 @@ static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t statu static void status_change_callback(comms_layer_t * comms, comms_status_t status, void * user) { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; bool ok; - comms_mutex_acquire(comms->controller_mutex); + comms_mutex_acquire(cl->controller_mutex); ok = unsafe_service_callbacks(comms, status); - comms_mutex_release(comms->controller_mutex); + comms_mutex_release(cl->controller_mutex); if (!ok) { - comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; _comms_defer(cl->sleep_controller_deferred); } } static void deferred_callback(void * arg) { - bool ok; comms_layer_t * comms = (comms_layer_t*)arg; - comms_mutex_acquire(comms->controller_mutex); + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + bool ok; + comms_mutex_acquire(cl->controller_mutex); ok = unsafe_update_state(comms); - comms_mutex_release(comms->controller_mutex); + comms_mutex_release(cl->controller_mutex); if (!ok) { - comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; _comms_defer(cl->sleep_controller_deferred); } } @@ -121,7 +121,7 @@ comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep comms_error_t err = COMMS_SUCCESS; comms_sleep_controller_t** indirect; - comms_mutex_acquire(comms->controller_mutex); + comms_mutex_acquire(cl->controller_mutex); if (NULL == cl->sleep_controller_deferred) { @@ -149,7 +149,7 @@ comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep ctrl->next = NULL; } - comms_mutex_release(comms->controller_mutex); + comms_mutex_release(cl->controller_mutex); return err; } @@ -160,7 +160,7 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle comms_error_t err = COMMS_FAIL; comms_sleep_controller_t** indirect; - comms_mutex_acquire(comms->controller_mutex); + comms_mutex_acquire(cl->controller_mutex); for(indirect=&(cl->sleep_controllers); NULL != *indirect; indirect = &((*indirect)->next)) { @@ -179,7 +179,7 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle } } - comms_mutex_release(comms->controller_mutex); + comms_mutex_release(cl->controller_mutex); return err; } @@ -190,7 +190,8 @@ comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl) comms_error_t err = COMMS_EINVAL; if ((NULL != ctrl)&&(NULL != ctrl->comms)) { - _comms_mutex_acquire(ctrl->comms); + comms_layer_iface_t * cl = (comms_layer_iface_t*)(ctrl->comms); + comms_mutex_acquire(cl->controller_mutex); if(ctrl->pending) { @@ -219,7 +220,7 @@ comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl) } } - _comms_mutex_release(ctrl->comms); + comms_mutex_release(cl->controller_mutex); } return err; } @@ -230,7 +231,8 @@ comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl) comms_error_t err = COMMS_EINVAL; if ((NULL != ctrl)&&(NULL != ctrl->comms)) { - _comms_mutex_acquire(ctrl->comms); + comms_layer_iface_t * cl = (comms_layer_iface_t*)(ctrl->comms); + comms_mutex_acquire(cl->controller_mutex); if(false == ctrl->block) { @@ -250,16 +252,17 @@ comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl) } } - _comms_mutex_release(ctrl->comms); + comms_mutex_release(cl->controller_mutex); } return err; } bool comms_sleep_blocked(comms_sleep_controller_t * ctrl) { + comms_layer_iface_t * cl = (comms_layer_iface_t*)(ctrl->comms); bool blocked; - _comms_mutex_acquire(ctrl->comms); + comms_mutex_acquire(cl->controller_mutex); blocked = ctrl->block; - _comms_mutex_release(ctrl->comms); + comms_mutex_release(cl->controller_mutex); return blocked; } diff --git a/mock/mist_comm_mutex.c b/mock/mist_comm_mutex.c new file mode 100644 index 0000000..6e3119b --- /dev/null +++ b/mock/mist_comm_mutex.c @@ -0,0 +1,30 @@ +/** + * MistComm locking implementation with mock mutexes. + * + * Copyright Thinnect Inc. 2019 + * @license MIT + * @author Raido Pahtma + */ + +#include "mist_comm_iface.h" +#include "mist_comm_private.h" + +static volatile bool m_mutexes[8]; +static int m_mutex_count = 0; + +void comms_mutex_acquire(commsMutexId_t mutex) +{ + while(m_mutexes[mutex]); + m_mutexes[mutex] = true; +} + +void comms_mutex_release(commsMutexId_t mutex) +{ + m_mutexes[mutex] = false; +} + +commsMutexId_t comms_mutex_create() +{ + m_mutexes[m_mutex_count] = false; + return m_mutex_count++; +} diff --git a/mock/mist_comm_mutex.h b/mock/mist_comm_mutex.h new file mode 100644 index 0000000..f092d9c --- /dev/null +++ b/mock/mist_comm_mutex.h @@ -0,0 +1,13 @@ +/** + * MistComm locking with mock mutexes. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + * @author Raido Pahtma + */ +#ifndef MIST_COMM_MUTEX_H_ +#define MIST_COMM_MUTEX_H_ + +typedef int commsMutexId_t; + +#endif//MIST_COMM_MUTEX_H_ diff --git a/test/Makefile b/test/Makefile index 8586140..d3d6acf 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ # Makefile -CFLAGS = -I. -I../api -I../include -I../include/compat -std=c99 -Wall +CFLAGS = -I. -I../mock -I../api -I../include -I../include/compat -std=c99 -Wall all: - gcc ${CFLAGS} main.c ../api/mist_comm_api.c ../api/mist_comm_rcv.c ../am/mist_comm_am.c -o test + gcc ${CFLAGS} main.c ../mock/mist_comm_mutex.c ../api/mist_comm_api.c ../api/mist_comm_rcv.c ../am/mist_comm_am.c -o test diff --git a/test/sleep/Makefile b/test/sleep/Makefile index 56ef767..07bdd83 100644 --- a/test/sleep/Makefile +++ b/test/sleep/Makefile @@ -7,12 +7,12 @@ SRC_FILES = $(UNITY_ROOT)/src/unity.c test_sleep.c SRC_FILES += test_runners/TestProductionCode_Runner.c SRC_FILES += ../../api/mist_comm_api.c SRC_FILES += ../../control/mist_comm_controller.c +SRC_FILES += ../../mock/mist_comm_mutex.c -CFLAGS += -I. -I../../api -I../../include -I../include/compat INC_DIRS = -I. -I$(UNITY_ROOT)/src - INC_DIRS += -I.. +INC_DIRS += -I../../mock INC_DIRS += -I../../include INC_DIRS += -I../../include/compat diff --git a/test/sleep/test_sleep.c b/test/sleep/test_sleep.c index c55db56..1dd440d 100644 --- a/test/sleep/test_sleep.c +++ b/test/sleep/test_sleep.c @@ -10,6 +10,7 @@ #include "mist_comm.h" #include "mist_comm_iface.h" +#include "mist_comm_mutex.h" static int m_start_requested = 0; static int m_stop_requested = 0; @@ -97,7 +98,10 @@ void test_SleepControllers() base.status = COMMS_STOPPED; base.sleep_controllers = NULL; base.sleep_controller_deferred = NULL; - base.mutex = NULL; + base.status_change_user_cb = NULL; + base.controller_mutex = comms_mutex_create(); + base.start_stop_mutex = comms_mutex_create(); + base.receiver_mutex = comms_mutex_create(); TEST_ASSERT_EQUAL_INT(COMMS_STOPPED, comms_status((comms_layer_t*)&base)); diff --git a/test/startstop/Makefile b/test/startstop/Makefile index 0144b71..9699e2a 100644 --- a/test/startstop/Makefile +++ b/test/startstop/Makefile @@ -6,11 +6,10 @@ CFLAGS += -Wall SRC_FILES = $(UNITY_ROOT)/src/unity.c test_startstop.c SRC_FILES += test_runners/TestProductionCode_Runner.c SRC_FILES += ../../api/mist_comm_api.c - -CFLAGS += -I. -I../../api -I../../include -I../include/compat +SRC_FILES += ../../mock/mist_comm_mutex.c INC_DIRS = -I. -I$(UNITY_ROOT)/src - +INC_DIRS += -I../../mock INC_DIRS += -I.. INC_DIRS += -I../../include INC_DIRS += -I../../include/compat diff --git a/test/startstop/test_startstop.c b/test/startstop/test_startstop.c index 85d0ded..e33797b 100644 --- a/test/startstop/test_startstop.c +++ b/test/startstop/test_startstop.c @@ -66,6 +66,11 @@ void test_StartAndStop() base.start = &comms_dummy_start; base.stop = &comms_dummy_stop; + base.status_change_user_cb = NULL; + base.controller_mutex = comms_mutex_create(); + base.start_stop_mutex = comms_mutex_create(); + base.receiver_mutex = comms_mutex_create(); + // Test starting TEST_ASSERT_EQUAL_INT(COMMS_SUCCESS, comms_start((comms_layer_t*)&base, &comms_start_done, NULL)); From 0e7c252ab218204f87a05c67a8dabe9b93ef3f02 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Sun, 22 Mar 2020 16:27:00 +0200 Subject: [PATCH 43/80] Bring over serial_activemessage from node platform. --- serial/serial_activemessage.c | 323 ++++++++++++++++++++++++++++++++++ serial/serial_activemessage.h | 84 +++++++++ 2 files changed, 407 insertions(+) create mode 100644 serial/serial_activemessage.c create mode 100644 serial/serial_activemessage.h diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c new file mode 100644 index 0000000..282dec1 --- /dev/null +++ b/serial/serial_activemessage.c @@ -0,0 +1,323 @@ +/** +* MistComm SerialActiveMessage layer implementation. +* +* @author Raido Pahtma +* @license MIT +*/ +#include +#include +#include +#include + +#include "cmsis_os2.h" + +#include "endianness.h" + +#include "mist_comm.h" +#include "serial_protocol.h" +#include "serial_activemessage.h" + +#include "loglevels.h" +#define __MODUUL__ "sam" +#define __LOG_LEVEL__ (LOG_LEVEL_serial_activemessage & BASE_LOG_LEVEL) +#include "log.h" + +#pragma pack(push, 1) +typedef struct tos_serial_message +{ + uint16_t destination; + uint16_t source; + uint8_t payload_length; // payload[] length + uint8_t group; + uint8_t amid; + uint8_t payload[]; + // footer with lqi/rssi +} tos_serial_message_t; +#pragma pack(pop) + +static comms_error_t serial_activemessage_send (comms_layer_iface_t * iface, + comms_msg_t * msg, + comms_send_done_f * send_done, void * user); +static bool serial_am_receive(uint8_t dspch, const uint8_t data[], uint8_t length, void* user); +static void serial_am_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); +static void serial_am_timer_cb(void * argument); + +comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_protocol_t * spr) +{ + sam->mutex = osMutexNew(NULL); + sam->timer = osTimerNew(&serial_am_timer_cb, osTimerOnce, sam, NULL); + + // Initialize send queueing system + sam->send_busy = false; + sam->sending = NULL; + sam->send_queue = NULL; + sam->free_queue = &(sam->queue_memory[0]); + sam->free_queue->next = NULL; + for (uint8_t i=1; iqueue_memory)/sizeof(sam_queue_element_t); i++) + { + sam->queue_memory[i].next = sam->free_queue; + sam->free_queue = &(sam->queue_memory[i]); + } + + // Set up dispatcher + sam->protocol = spr; + serial_protocol_add_dispatcher(sam->protocol, 0x00, + &(sam->dispatcher), + &serial_am_receive, &serial_am_senddone, + sam); + + // Set up the mist-comm layer + // TODO should we be passing 0 as default address? + // TODO start-stop handlers + comms_am_create((comms_layer_t *)sam, 0, &serial_activemessage_send, NULL, NULL); + + // serial_activemessage_t is a valid comms_layer_t + return (comms_layer_t *)sam; +} + +bool serial_activemessage_deinit (serial_activemessage_t* sam) +{ + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + + if ((1 == osTimerIsRunning(sam->timer)) + ||(NULL != sam->sending)) + { + osMutexRelease(sam->mutex); + return false; + } + + serial_protocol_remove_dispatcher(sam->protocol, &(sam->dispatcher)); + osTimerDelete(sam->timer); + + osMutexRelease(sam->mutex); + osMutexDelete(sam->mutex); + + return true; +} + +static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t length, void * user) +{ + serial_activemessage_t * sam = (serial_activemessage_t*)user; + comms_layer_t * lyr = (comms_layer_t*)sam; + debugb1("%p data", data, length, sam); + + if (sizeof(tos_serial_message_t) > length) + { + warn1("short"); // Message is too short + return false; + } + + tos_serial_message_t * m = (tos_serial_message_t*)data; + if(length - sizeof(tos_serial_message_t) < m->payload_length) + { + warn1("p len big"); // Payload is listed as larger than available data + return false; + } + + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + + comms_msg_t msg; + comms_init_message(lyr, &msg); + + uint8_t* payload = comms_get_payload(lyr, &msg, m->payload_length); + if (NULL == payload) + { + osMutexRelease(sam->mutex); + err1("pl %d", m->payload_length); + return false; + } + + comms_set_packet_type(lyr, &msg, m->amid); + comms_set_payload_length(lyr, &msg, m->payload_length); + memcpy(payload, (const void *)m->payload, m->payload_length); + + // comms_set_timestamp(lyr, &msg, timestamp); // TODO Set to now? Make the lowest layer register frame starts ...? + + comms_am_set_destination(lyr, &msg, ntoh16(m->destination)); + comms_am_set_source(lyr, &msg, ntoh16(m->source)); + + // TODO DEFAULT_PAN_ID variable + debugb1("rx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", + payload, comms_get_payload_length(lyr, &msg), + DEFAULT_PAN_ID, + comms_am_get_source(lyr, &msg), + comms_am_get_destination(lyr, &msg), + comms_get_packet_type(lyr, &msg)); + + comms_deliver(lyr, &msg); + + osMutexRelease(sam->mutex); + + return true; +} + +/* +* Convert a comms message to a serial-protocol message buffer +* @param buffer - the buffer to store the message +* @param length - the length of the buffer +* @param msg - the message to convert +* @param lyr - the layer to use for interpreting the message +* @return length of the prepared message or 0 for errors +*/ +static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_t * msg, comms_layer_t * lyr) +{ + uint8_t plen = comms_get_payload_length(lyr, msg); + + if(plen + sizeof(tos_serial_message_t) <= length) + { + void * payload = comms_get_payload(lyr, msg, plen); + if (NULL != payload) + { + tos_serial_message_t* m = (tos_serial_message_t*)buffer; + + m->destination = hton16(comms_am_get_destination(lyr, msg)); + m->source = hton16(comms_am_get_source(lyr, msg)); + m->group = DEFAULT_PAN_ID; // TODO variable + m->amid = comms_get_packet_type(lyr, msg); + m->payload_length = plen; + memcpy(m->payload, payload, plen); + + // TODO check if LQI/RSSI is set in the packet + m->payload[plen] = comms_get_lqi(lyr, msg); + m->payload[plen+1] = comms_get_rssi(lyr, msg); + + return sizeof(tos_serial_message_t) + plen + 2; // + 2 for LQI/RSSI + } + else // Should not happen, unless platform configured incorrectly + { + err1("null pl"); + } + } + else + { + err1("pl size %d", (unsigned int)plen); + } + return 0; +} + +static void serial_am_senddone(uint8_t dispatch, const uint8_t data[], uint8_t length, bool acked, void * user) +{ + serial_activemessage_t * sam = (serial_activemessage_t*)user; + comms_layer_t * lyr = (comms_layer_t*)sam; + + debugb1("snt(a:%d) %02X", data, length, (int)acked, (unsigned int)dispatch); + + // Set flags on the message that was just sent + //comms_set_timestamp(lyr, sam->sending->msg, now()); + if (acked) + { + _comms_set_ack_received(lyr, sam->sending->msg); + } + + // Signal send done events + sam->sending->send_done(lyr, sam->sending->msg, COMMS_SUCCESS, sam->sending->user); + sam->sending->msg = NULL; + + // Mark sent and defer to send other pending messages + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + sam->send_busy = false; + osMutexRelease(sam->mutex); + osTimerStart(sam->timer, 1UL); +} + +static void serial_am_timer_cb(void * argument) +{ + serial_activemessage_t * sam = (serial_activemessage_t*)argument; + comms_layer_t * lyr = (comms_layer_t*)sam; + + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + if(sam->send_busy) + { + debug1("bsy"); // Must wait for last send to complete + osMutexRelease(sam->mutex); + return; + } + + if (NULL != sam->sending) + { + // Return the queue element to the free queue + sam->sending->next = sam->free_queue; + sam->free_queue = sam->sending; + sam->sending = NULL; + } + + if (NULL != sam->send_queue) + { + sam->sending = sam->send_queue; + sam->send_queue = sam->send_queue->next; + sam->send_busy = true; + } + osMutexRelease(sam->mutex); + + if (NULL != sam->sending) + { + uint16_t length = prepare_sp_message(sam->send_buffer, sizeof(sam->send_buffer), sam->sending->msg, lyr); + if(length > 0) + { + if(true == serial_protocol_send(&(sam->dispatcher), sam->send_buffer, length, false)) + { + debug1("snd %p %p %p", sam->sending, sam->send_queue, sam->free_queue); + return; + } + else + { + err1("busy?"); + } + } + else + { + err1("prep"); + } + + // Something bad has happened, return message to user with error + sam->sending->send_done(lyr, sam->sending->msg, COMMS_EINVAL, sam->sending->user); + sam->sending->msg = NULL; // Pointer has been returned + + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + sam->send_busy = false; + osMutexRelease(sam->mutex); + osTimerStart(sam->timer, 1L); // Try next message + } + else + { + debug1("idle"); + } +} + +static comms_error_t serial_activemessage_send (comms_layer_iface_t * iface, + comms_msg_t * msg, + comms_send_done_f * send_done, void * user) +{ + comms_error_t result = COMMS_SUCCESS; + serial_activemessage_t * sam = (serial_activemessage_t*)iface; + while (osOK != osMutexAcquire(sam->mutex, osWaitForever)); + + debug1("snd %p %p", sam->send_queue, sam->free_queue); + if (NULL != sam->free_queue) + { + sam_queue_element_t ** qe = &(sam->send_queue); + while (NULL != *qe) + { + qe = &((*qe)->next); + } + + *qe = sam->free_queue; + sam->free_queue = sam->free_queue->next; + + (*qe)->msg = msg; + (*qe)->send_done = send_done; + (*qe)->user = user; + (*qe)->next = NULL; + + debug1("q %p %p", sam->send_queue, sam->free_queue); + osTimerStart(sam->timer, 1UL); + } + else // Queue full + { + result = COMMS_EBUSY; + } + + osMutexRelease(sam->mutex); + + return result; +} diff --git a/serial/serial_activemessage.h b/serial/serial_activemessage.h new file mode 100644 index 0000000..b26b361 --- /dev/null +++ b/serial/serial_activemessage.h @@ -0,0 +1,84 @@ +/** +* MistComm SerialActiveMessage layer. +* +* Many instances can be created, each needs a serial_protocol. +* Instances will set up a dispatcher with dispatch ID 0x00. +* +* @author Raido Pahtma +* @license MIT +*/ +#ifndef SERIAL_ACTIVEMESSAGE_H_ +#define SERIAL_ACTIVEMESSAGE_H_ + +#include "mist_comm_am.h" +#include "mist_comm.h" +#include "serial_protocol.h" + +#include "cmsis_os2.h" + +// The serial_activemessage instance structure +typedef struct serial_activemessage serial_activemessage_t; + +/** + * Initialize the SerialActiveMessage layer, providing it memory and access + * to a lower layer SerialProtocol. + * + * @param sam - The SerialActiveMessage to initialize, a pointer to a persistent + * memory structure. + * @param spr - Pointer to an initialized SerialProtocol layer. + * + * @return a MistComm instance that can be used for sending/receiving messages + * or NULL for failure. + */ +comms_layer_t* serial_activemessage_init (serial_activemessage_t * sam, + serial_protocol_t * spr); + +/** + * Deinitialize the SerialActiveMessage layer. The memory used by the instance + * may be freed after this. + * + * @param sam - An initialized SerialActiveMessage + * @return true if successful, false if busy + */ +bool serial_activemessage_deinit (serial_activemessage_t * sam); + + +// Internal details to allow memory allocation---------------------------------- + +// send queue structure +typedef struct sam_queue_element sam_queue_element_t; +struct sam_queue_element +{ + comms_msg_t* msg; + comms_send_done_f *send_done; + void *user; + sam_queue_element_t* next; +}; + +#ifndef SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH +#define SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH 3 +#endif//SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH + +#ifndef SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH +#define SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH 128 +#endif//SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH + +struct serial_activemessage +{ + comms_layer_am_t base; + serial_dispatcher_t dispatcher; + serial_protocol_t* protocol; + + osMutexId_t mutex; + osTimerId_t timer; + + sam_queue_element_t * sending; + sam_queue_element_t * send_queue; + sam_queue_element_t * free_queue; + sam_queue_element_t queue_memory[SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH]; + + bool send_busy; + uint8_t send_buffer[SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH]; +}; + +#endif//SERIAL_ACTIVEMESSAGE_H_ From ea504cf0f917d9455048a54e252b3de6ae768866 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 23 Mar 2020 22:20:50 +0200 Subject: [PATCH 44/80] Add serial basicmessage implementation. --- serial/serial_basicmessage.c | 247 +++++++++++++++++++++++++++++++++++ serial/serial_basicmessage.h | 81 ++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 serial/serial_basicmessage.c create mode 100644 serial/serial_basicmessage.h diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c new file mode 100644 index 0000000..8168973 --- /dev/null +++ b/serial/serial_basicmessage.c @@ -0,0 +1,247 @@ +/** +* MistComm SerialBasicMessage layer implementation. +* +* @author Raido Pahtma +* @license MIT +*/ +#include +#include +#include +#include + +#include "cmsis_os2.h" + +#include "mist_comm.h" +#include "serial_protocol.h" +#include "serial_basicmessage.h" + +#include "loglevels.h" +#define __MODUUL__ "sbm" +#define __LOG_LEVEL__ (LOG_LEVEL_serial_basicmessage & BASE_LOG_LEVEL) +#include "log.h" + +static comms_error_t serial_basicmessage_send (comms_layer_iface_t * iface, + comms_msg_t * msg, + comms_send_done_f * send_done, void * user); +static bool serial_bm_receive(uint8_t dspch, const uint8_t data[], uint8_t length, void* user); +static void serial_bm_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); +static void serial_bm_timer_cb(void * argument); + +comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, uint8_t dispatch) +{ + sbm->mutex = osMutexNew(NULL); + sbm->timer = osTimerNew(&serial_bm_timer_cb, osTimerOnce, sbm, NULL); + + // Initialize send queueing system + sbm->send_busy = false; + sbm->sending = NULL; + sbm->send_queue = NULL; + sbm->free_queue = &(sbm->queue_memory[0]); + sbm->free_queue->next = NULL; + for (uint8_t i=1; iqueue_memory)/sizeof(sbm_queue_element_t); i++) + { + sbm->queue_memory[i].next = sbm->free_queue; + sbm->free_queue = &(sbm->queue_memory[i]); + } + + // Set up dispatcher + sbm->protocol = spr; + serial_protocol_add_dispatcher(sbm->protocol, dispatch, + &(sbm->dispatcher), + &serial_bm_receive, &serial_bm_senddone, + sbm); + + // Set up the mist-comm layer + // TODO start-stop handlers + comms_am_create((comms_layer_t *)sbm, 0, &serial_basicmessage_send, NULL, NULL); + + // serial_basicmessage_t is a semi-valid comms_layer_t + return (comms_layer_t *)sbm; +} + +bool serial_basicmessage_deinit (serial_basicmessage_t* sbm) +{ + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + + if ((1 == osTimerIsRunning(sbm->timer)) + ||(NULL != sbm->sending)) + { + osMutexRelease(sbm->mutex); + return false; + } + + serial_protocol_remove_dispatcher(sbm->protocol, &(sbm->dispatcher)); + osTimerDelete(sbm->timer); + + osMutexRelease(sbm->mutex); + osMutexDelete(sbm->mutex); + + return true; +} + +static bool serial_bm_receive(uint8_t dispatch, const uint8_t data[], uint8_t length, void * user) +{ + serial_basicmessage_t * sbm = (serial_basicmessage_t*)user; + comms_layer_t * lyr = (comms_layer_t*)sbm; + debugb1("%p data", data, length, sbm); + + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + + comms_msg_t msg; + comms_init_message(lyr, &msg); + + uint8_t* payload = comms_get_payload(lyr, &msg, length); + if (NULL == payload) + { + osMutexRelease(sbm->mutex); + err1("pl %d", length); + return false; + } + + comms_set_packet_type(lyr, &msg, 0); + comms_set_payload_length(lyr, &msg, length); + memcpy(payload, data, length); + + // comms_set_timestamp(lyr, &msg, timestamp); // TODO Set to now? Make the lowest layer register frame starts ...? + + comms_am_set_destination(lyr, &msg, 0); + comms_am_set_source(lyr, &msg, 0); + + debugb1("rx {%02"PRIX8"}", + payload, comms_get_payload_length(lyr, &msg), + dispatch); + + comms_deliver(lyr, &msg); + + osMutexRelease(sbm->mutex); + + return true; +} + +static void serial_bm_senddone(uint8_t dispatch, const uint8_t data[], uint8_t length, bool acked, void * user) +{ + serial_basicmessage_t * sbm = (serial_basicmessage_t*)user; + comms_layer_t * lyr = (comms_layer_t*)sbm; + + debugb1("snt(a:%d) %02X", data, length, (int)acked, (unsigned int)dispatch); + + // Set flags on the message that was just sent + //comms_set_timestamp(lyr, sbm->sending->msg, now()); + if (acked) + { + _comms_set_ack_received(lyr, sbm->sending->msg); + } + + // Signal send done events + sbm->sending->send_done(lyr, sbm->sending->msg, COMMS_SUCCESS, sbm->sending->user); + sbm->sending->msg = NULL; + + // Mark sent and defer to send other pending messages + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + sbm->send_busy = false; + osMutexRelease(sbm->mutex); + osTimerStart(sbm->timer, 1UL); +} + +static void serial_bm_timer_cb(void * argument) +{ + serial_basicmessage_t * sbm = (serial_basicmessage_t*)argument; + comms_layer_t * lyr = (comms_layer_t*)sbm; + + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + if(sbm->send_busy) + { + debug1("bsy"); // Must wait for last send to complete + osMutexRelease(sbm->mutex); + return; + } + + if (NULL != sbm->sending) + { + // Return the queue element to the free queue + sbm->sending->next = sbm->free_queue; + sbm->free_queue = sbm->sending; + sbm->sending = NULL; + } + + if (NULL != sbm->send_queue) + { + sbm->sending = sbm->send_queue; + sbm->send_queue = sbm->send_queue->next; + sbm->send_busy = true; + } + osMutexRelease(sbm->mutex); + + if (NULL != sbm->sending) + { + uint16_t length = comms_get_payload_length(lyr, sbm->sending->msg); + void * payload = comms_get_payload(lyr, sbm->sending->msg, length); + if (NULL != payload) + { + if(true == serial_protocol_send(&(sbm->dispatcher), payload, length, false)) + { + debug1("snd %p %p %p", sbm->sending, sbm->send_queue, sbm->free_queue); + return; + } + else + { + err1("busy?"); + } + } + else + { + err1("payload"); + } + + // Something bad has happened, return message to user with error + sbm->sending->send_done(lyr, sbm->sending->msg, COMMS_EINVAL, sbm->sending->user); + sbm->sending->msg = NULL; // Pointer has been returned + + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + sbm->send_busy = false; + osMutexRelease(sbm->mutex); + osTimerStart(sbm->timer, 1L); // Try next message + } + else + { + debug1("idle"); + } +} + +static comms_error_t serial_basicmessage_send (comms_layer_iface_t * iface, + comms_msg_t * msg, + comms_send_done_f * send_done, void * user) +{ + comms_error_t result = COMMS_SUCCESS; + serial_basicmessage_t * sbm = (serial_basicmessage_t*)iface; + while (osOK != osMutexAcquire(sbm->mutex, osWaitForever)); + + debug1("snd %p %p", sbm->send_queue, sbm->free_queue); + if (NULL != sbm->free_queue) + { + sbm_queue_element_t ** qe = &(sbm->send_queue); + while (NULL != *qe) + { + qe = &((*qe)->next); + } + + *qe = sbm->free_queue; + sbm->free_queue = sbm->free_queue->next; + + (*qe)->msg = msg; + (*qe)->send_done = send_done; + (*qe)->user = user; + (*qe)->next = NULL; + + debug1("q %p %p", sbm->send_queue, sbm->free_queue); + osTimerStart(sbm->timer, 1UL); + } + else // Queue full + { + result = COMMS_EBUSY; + } + + osMutexRelease(sbm->mutex); + + return result; +} diff --git a/serial/serial_basicmessage.h b/serial/serial_basicmessage.h new file mode 100644 index 0000000..10ab4e4 --- /dev/null +++ b/serial/serial_basicmessage.h @@ -0,0 +1,81 @@ +/** +* MistComm SerialBasicMessage layer. +* +* Many instances can be created, each needs a serial_protocol. +* +* Copyright Thinnect Inc. 2020 +* @author Raido Pahtma +* @license MIT +*/ +#ifndef SERIAL_BASICMESSAGE_H_ +#define SERIAL_BASICMESSAGE_H_ + +#include "mist_comm_am.h" +#include "mist_comm.h" +#include "serial_protocol.h" + +#include "cmsis_os2.h" + +// The serial_basicmessage instance structure +typedef struct serial_basicmessage serial_basicmessage_t; + +/** + * Initialize the SerialbasicMessage layer, providing it memory and access + * to a lower layer SerialProtocol. + * + * @param sbm - The SerialBasicMessage to initialize, a pointer to a persistent + * memory structure. + * @param spr - Pointer to an initialized SerialProtocol layer. + * @param dispatch - The SerialProtocol dispatch ID to use. + * + * @return a MistComm instance that can be used for sending/receiving messages + * or NULL for failure. + */ +comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, + serial_protocol_t * spr, + uint8_t dispatch); + +/** + * Deinitialize the SerialbasicMessage layer. The memory used by the instance + * may be freed after this. + * + * @param sbm - An initialized SerialbasicMessage + * @return true if successful, false if busy + */ +bool serial_basicmessage_deinit (serial_basicmessage_t * sbm); + + +// Internal details to allow memory allocation---------------------------------- + +// send queue structure +typedef struct sbm_queue_element sbm_queue_element_t; +struct sbm_queue_element +{ + comms_msg_t* msg; + comms_send_done_f *send_done; + void *user; + sbm_queue_element_t* next; +}; + +#ifndef SERIAL_BASICMESSAGE_QUEUE_LENGTH +#define SERIAL_BASICMESSAGE_QUEUE_LENGTH 2 +#endif//SERIAL_BASICMESSAGE_QUEUE_LENGTH + +struct serial_basicmessage +{ + comms_layer_am_t base; + serial_dispatcher_t dispatcher; + serial_protocol_t* protocol; + + osMutexId_t mutex; + osTimerId_t timer; + + sbm_queue_element_t * sending; + sbm_queue_element_t * send_queue; + sbm_queue_element_t * free_queue; + sbm_queue_element_t queue_memory[SERIAL_BASICMESSAGE_QUEUE_LENGTH]; + + bool send_busy; +}; + +#endif//SERIAL_BASICMESSAGE_H_ From e06a8545d6cef984e08c468031456fb63d478d9d Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Tue, 7 Apr 2020 22:28:19 +0300 Subject: [PATCH 45/80] Add bridge de-initialization. --- bridge/mist_comm_bridge.c | 56 +++++++++++++++++++++++++++++++++----- include/mist_comm_bridge.h | 9 ++++++ 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index 5396d85..0882ec7 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -19,6 +19,9 @@ #define __LOG_LEVEL__ (LOG_LEVEL_bridge & BASE_LOG_LEVEL) #include "log.h" +#define MIST_COMM_BRIDGE_FLAG_SEND_DONE (1 << 0) +#define MIST_COMM_BRIDGE_FLAG_TERMINATE (1 << 1) + static void bridge_thread(void * param); static void bridge_send_done(comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); static void bridge_am_snoop(comms_layer_t* comms, const comms_msg_t* msg, void* user); @@ -28,8 +31,8 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, comms_layer_t * b) { bridge->t1.rxqueue = osMessageQueueNew(10, sizeof(comms_msg_t), NULL); - bridge->t1.txqueue = osMessageQueueNew(10, sizeof(comms_msg_t), NULL); - bridge->t2.rxqueue = bridge->t1.txqueue; + bridge->t2.rxqueue = osMessageQueueNew(10, sizeof(comms_msg_t), NULL); + bridge->t1.txqueue = bridge->t2.rxqueue; bridge->t2.txqueue = bridge->t1.rxqueue; const osThreadAttr_t bridge_thread_1_attr = { .name = "bt1" }; @@ -48,11 +51,46 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, return COMMS_SUCCESS; } +void comms_bridge_deinit (comms_bridge_t * bridge) +{ + // remove snoopers + comms_deregister_snooper(bridge->t1.layer, &(bridge->t1.receiver)); + comms_deregister_snooper(bridge->t2.layer, &(bridge->t2.receiver)); + + // stop threads + osThreadFlagsSet(bridge->t1.thread, MIST_COMM_BRIDGE_FLAG_TERMINATE); + osThreadFlagsSet(bridge->t2.thread, MIST_COMM_BRIDGE_FLAG_TERMINATE); + + // wait for threads to exit + while (osThreadTerminated != osThreadGetState(bridge->t1.thread)) + { + osDelay(1); + } + while (osThreadTerminated != osThreadGetState(bridge->t2.thread)) + { + osDelay(1); + } + + // empty the queues + while (osOK == osMessageQueueGet(bridge->t1.rxqueue, &(bridge->t1.msg), NULL, 0)) + { + // it has been removed, nothing else to do with it now, memory is handled by queue + } + while (osOK == osMessageQueueGet(bridge->t2.rxqueue, &(bridge->t2.msg), NULL, 0)) + { + // it has been removed, nothing else to do with it now, memory is handled by queue + } + + // delete the queues + osMessageQueueDelete(bridge->t1.rxqueue); + osMessageQueueDelete(bridge->t2.rxqueue); +} + static void bridge_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) { comms_bridge_thread_t * bt = (comms_bridge_thread_t*)user; logger(result == COMMS_SUCCESS ? LOG_DEBUG3: LOG_WARN1, "%p snt %d", msg, result); - osThreadFlagsSet(bt->thread, 0x00000001U); + osThreadFlagsSet(bt->thread, MIST_COMM_BRIDGE_FLAG_SEND_DONE); } static void bridge_am_snoop (comms_layer_t* comms, const comms_msg_t* msg, void* user) @@ -77,7 +115,8 @@ static void bridge_thread (void * param) for(;;) { - if (osOK == osMessageQueueGet(bt->txqueue, &(bt->msg), NULL, osWaitForever)) + uint32_t flags = 0; + if (osOK == osMessageQueueGet(bt->txqueue, &(bt->msg), NULL, 5000)) { #if (__LOG_LEVEL__ & LOG_DEBUG1) uint8_t plen = comms_get_payload_length(bt->layer, &(bt->msg)); @@ -94,7 +133,7 @@ static void bridge_thread (void * param) if(COMMS_SUCCESS == comms_send(bt->layer, &(bt->msg), bridge_send_done, bt)) { - osThreadFlagsWait(0x00000001U, osFlagsWaitAny, osWaitForever); + flags = osThreadFlagsWait(MIST_COMM_BRIDGE_FLAG_SEND_DONE, osFlagsWaitAny, osWaitForever); debug4("snt"); } else @@ -102,9 +141,12 @@ static void bridge_thread (void * param) warn1("snd"); } } - else + + // Check for termination, may have been(?) set already in previous flag wait, so keep existing flags + flags |= osThreadFlagsWait(MIST_COMM_BRIDGE_FLAG_TERMINATE, osFlagsWaitAny, 0); + if(flags & MIST_COMM_BRIDGE_FLAG_TERMINATE) { - err1("q"); + osThreadExit(); } } } diff --git a/include/mist_comm_bridge.h b/include/mist_comm_bridge.h index 154caa0..e2f5a24 100644 --- a/include/mist_comm_bridge.h +++ b/include/mist_comm_bridge.h @@ -43,4 +43,13 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, comms_layer_t * a, comms_layer_t * b); +/** + * Deinitialize a bridge, freeing all resources. + * + * MAY TAKE SOME TIME (10-15 seconds)! + * + * @param bridge The bridge to initialize. + */ +void comms_bridge_deinit (comms_bridge_t * bridge); + #endif//MIST_COMM_BRIDGE_H_ From fcd283880a14c9129fabfa6e87178c1ce2aeebef Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 23 Apr 2020 09:34:49 +0300 Subject: [PATCH 46/80] Initial implementation of EUI discovery-addressing-caching. --- addrcache/mist_comm_addrcache.c | 150 ++++++++++++++++++ addrcache/mist_comm_addrcache.h | 64 ++++++++ am/mist_comm_am.c | 97 ++++++++++-- am/mist_comm_am_addrdisco.c | 221 +++++++++++++++++++++++++++ am/mist_comm_am_addrdisco.h | 58 +++++++ am/mist_comm_am_addrdisco_private.h | 28 ++++ am/mist_comm_am_addrdisco_protocol.h | 34 +++++ api/mist_comm_api.c | 35 ++++- api/mist_comm_rcv.c | 35 ++++- include/compat/mist_comm_basics.h | 7 +- include/mist_comm.h | 134 ++++++++++++---- include/mist_comm_am.h | 9 ++ include/mist_comm_eui.h | 20 --- include/mist_comm_iface.h | 8 +- include/mist_comm_private.h | 8 +- include/mist_comm_ref.h | 3 + serial/serial_activemessage.c | 1 + serial/serial_activemessage.h | 1 + serial/serial_basicmessage.c | 1 + 19 files changed, 833 insertions(+), 81 deletions(-) create mode 100644 addrcache/mist_comm_addrcache.c create mode 100644 addrcache/mist_comm_addrcache.h create mode 100644 am/mist_comm_am_addrdisco.c create mode 100644 am/mist_comm_am_addrdisco.h create mode 100644 am/mist_comm_am_addrdisco_private.h create mode 100644 am/mist_comm_am_addrdisco_protocol.h delete mode 100644 include/mist_comm_eui.h diff --git a/addrcache/mist_comm_addrcache.c b/addrcache/mist_comm_addrcache.c new file mode 100644 index 0000000..c096a58 --- /dev/null +++ b/addrcache/mist_comm_addrcache.c @@ -0,0 +1,150 @@ +/** + * EUI-local address cache. + * + * Will discard older elements when it runs out of space. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#include "mist_comm_addrcache.h" + +#include "cmsis_os2_ext.h" // osCounterGetSecond, but should probably use an alternative time-source + +#include + +#include "loglevels.h" +#define __MODUUL__ "addrc" +#define __LOG_LEVEL__ (LOG_LEVEL_mist_comm_addrcache & BASE_LOG_LEVEL) +#include "log.h" + +bool comms_cache_get_local (comms_addr_cache_t * cache, const ieee_eui64_t * eui, comms_local_addr_t * local) +{ + if (NULL == cache) + { + return false; + } + + comms_mutex_acquire(cache->mutex); + for (int i=0;ieuis[i]), sizeof(ieee_eui64_t))) + { + memcpy(local, &(cache->locals[i]), sizeof(comms_local_addr_t)); + comms_mutex_release(cache->mutex); + return true; + } + } + comms_mutex_release(cache->mutex); + return false; +} + +bool comms_cache_get_eui (comms_addr_cache_t * cache, const comms_local_addr_t * local, ieee_eui64_t * eui) +{ + if (NULL == cache) + { + return false; + } + + comms_mutex_acquire(cache->mutex); + for (int i=0;ilocals[i]), sizeof(comms_local_addr_t))) + { + memcpy(eui, &(cache->euis[i]), sizeof(ieee_eui64_t)); + comms_mutex_release(cache->mutex); + return true; + } + } + comms_mutex_release(cache->mutex); + return false; +} + +void comms_cache_update (comms_addr_cache_t * cache, const ieee_eui64_t * eui, const comms_local_addr_t * local) +{ + int free_slot = -1; + + if (NULL == cache) + { + return; + } + + debugb1("update", eui->data, IEEE_EUI64_LENGTH); + + comms_mutex_acquire(cache->mutex); + + // Look for local address match, delete if different eui, otherwise update, can be only 1 + for (int i=0;ilocals[i]), sizeof(comms_local_addr_t))) + { + if (0 == memcmp(eui, &(cache->euis[i]), sizeof(ieee_eui64_t))) + { + debug("exists"); + cache->updated[i] = osCounterGetSecond(); + comms_mutex_release(cache->mutex); + return; + } + else + { + debug("eui change"); + memset(&(cache->euis[i]), 0, sizeof(ieee_eui64_t)); + memset(&(cache->locals[i]), 0, sizeof(comms_local_addr_t)); + cache->updated[i] = 0; + free_slot = i; + break; + } + } + } + + // Look for eui address match + for (int i=0;ieuis[i]), sizeof(ieee_eui64_t))) + { + debug("loc change"); + memcpy(&(cache->locals[i]), local, sizeof(comms_local_addr_t)); + cache->updated[i] = osCounterGetSecond(); + + comms_mutex_release(cache->mutex); + return; + } + } + + // Look for an empty or oldest entry + if(free_slot < 0) + { + uint32_t updated = UINT32_MAX; + for (int i=0;ieuis[i]))) + { + free_slot = i; + break; + } + else if(cache->updated[i] < updated) + { + updated = cache->updated[i]; + free_slot = i; + } + } + } + + debug("add"); + // Store the information in the slot that was found + memcpy(&(cache->euis[free_slot]), eui, sizeof(ieee_eui64_t)); + memcpy(&(cache->locals[free_slot]), local, sizeof(comms_local_addr_t)); + cache->updated[free_slot] = osCounterGetSecond(); + + comms_mutex_release(cache->mutex); +} + +void comms_cache_init (comms_addr_cache_t * cache) +{ + cache->mutex = comms_mutex_create(); + for(int i=0;ieuis[i]), 0, sizeof(ieee_eui64_t)); + memset(&(cache->locals[i]), 0, sizeof(comms_local_addr_t)); + cache->updated[i] = 0; + } +} diff --git a/addrcache/mist_comm_addrcache.h b/addrcache/mist_comm_addrcache.h new file mode 100644 index 0000000..42975ad --- /dev/null +++ b/addrcache/mist_comm_addrcache.h @@ -0,0 +1,64 @@ +/** + * EUI64<->local address cache. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#ifndef MIST_COMM_ADDRCACHE_H_ +#define MIST_COMM_ADDRCACHE_H_ + +#include "mist_comm.h" + +#ifndef MIST_COMM_ADDRCACHE_SIZE +#define MIST_COMM_ADDRCACHE_SIZE 32 +#endif//MIST_COMM_ADDRCACHE_SIZE + +typedef struct comms_addr_cache comms_addr_cache_t; + +/** + * Initialize the cache structure. + */ +void comms_cache_init(comms_addr_cache_t * cache); + +/** + * Get the local address for the EUI. + * + * @param cache Pointer to the cache. + * @param eui EUI64 address. + * @param local Storage space for the local address. + * @return true if an address was available. + */ +bool comms_cache_get_local(comms_addr_cache_t * cache, const ieee_eui64_t * eui, comms_local_addr_t * local); + +/** + * Get the EUI for the local address. + * + * @param cache Pointer to the cache. + * @param local Local address. + * @param eui Storage space for the EUI64 address. + * @return true if an address was available. + */ +bool comms_cache_get_eui(comms_addr_cache_t * cache, const comms_local_addr_t * local, ieee_eui64_t * eui); + +/** + * Update the cached mapping. + * + * Only 1:1 possible, any conflicting mappings will get thrown out. + * + * @param cache Pointer to the cache. + * @param eui EUI64 address. + * @param local Local address. + */ +void comms_cache_update(comms_addr_cache_t * cache, const ieee_eui64_t * eui, const comms_local_addr_t * local); + + +//------------------------------------------------------------------------------ +struct comms_addr_cache +{ + commsMutexId_t mutex; + comms_local_addr_t locals[MIST_COMM_ADDRCACHE_SIZE]; + ieee_eui64_t euis[MIST_COMM_ADDRCACHE_SIZE]; + uint32_t updated[MIST_COMM_ADDRCACHE_SIZE]; +}; + +#endif//MIST_COMM_ADDRCACHE_H_ diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 2fc899e..e868195 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -1,9 +1,17 @@ +/** + * TinyOS ActiveMessage transport layer implementation. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ #include "mist_comm_iface.h" #include "mist_comm_ref.h" #include "mist_comm_am.h" +#include "mist_comm_addrcache.h" #include +#include am_addr_t comms_am_address(comms_layer_t* comms) { comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; @@ -16,6 +24,8 @@ static am_addr_t am_comms_addr(comms_layer_am_t* comms) { static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { comms_am_msg_metadata_t* metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); + memset(&(msg->body.destination), 0, sizeof(msg->body.destination)); + memset(&(msg->body.source), 0, sizeof(msg->body.source)); msg->body.length = 0; metadata->timestamp_valid = false; metadata->event_time_valid = false; @@ -28,8 +38,62 @@ static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) metadata->rssi = -128; } -static comms_error_t am_comms_send(comms_layer_iface_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { - return COMMS_FAIL; +static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { + comms_layer_t* comms = (comms_layer_t*)iface; + comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; + am_addr_t dest = comms_am_get_destination(comms, msg); + comms_error_t result; + + // Attach the eui address of the source + if(false == comms_cache_get_eui(amcomms->cache, + &(msg->body.source.local), &(msg->body.source.eui))) + { + eui64_set_zeros(&(msg->body.destination.eui)); + } + + // Attach the eui address of the destination + if(AM_BROADCAST_ADDR == dest) + { + eui64_set_ones(&(msg->body.destination.eui)); + } + else if(amcomms->am_addr == dest) + { + memcpy(&(msg->body.destination.eui), &(comms->eui), sizeof(ieee_eui64_t)); + } + else if(false == comms_cache_get_eui(amcomms->cache, + &(msg->body.destination.local), &(msg->body.destination.eui))) + { + eui64_set_zeros(&(msg->body.destination.eui)); + } + + result = comms_basic_deliver(comms, msg); + + // Request eui source address discovery, if it was necessary for receiver + if(COMMS_NO_ADDR == result) + { + comms_am_addrdisco_discover_eui(amcomms->disco, comms_am_get_source(comms, msg)); + } + + return result == COMMS_SUCCESS; +} + +static comms_error_t am_comms_send(comms_layer_iface_t* iface, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { + comms_layer_t* comms = (comms_layer_t*)iface; + comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; + + if(0 == comms_am_get_destination(comms, msg)) // Need to see if there is something in the address cache + { + if(eui64_is_ones(&(msg->body.destination.eui))) + { + comms_am_set_destination(comms, msg, AM_BROADCAST_ADDR); + } + else if(false == comms_cache_get_local(amcomms->cache, + &(msg->body.destination.eui), &(msg->body.destination.local))) + { + return COMMS_NO_ADDR; // Nothing retrieved from cache + } + } + return amcomms->link_sendf(iface, msg, sdf, user); } static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { @@ -131,19 +195,22 @@ static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8 ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi = rssi; } - static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { - return *((am_addr_t*)msg->body.destination); + return *((am_addr_t*)msg->body.destination.local.data); } static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { - *((am_addr_t*)msg->body.destination) = dest; + *((am_addr_t*)msg->body.destination.local.data) = dest; + *((am_addr_t*)msg->body.destination.updated) = 0; + // *((am_addr_t*)msg->body.destination.updated) = now_s(); } static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* msg) { - return *((am_addr_t*)msg->body.source); + return *((am_addr_t*)msg->body.source.local.data); } static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { - *((am_addr_t*)msg->body.source) = source; + *((am_addr_t*)msg->body.source.local.data) = source; + *((am_addr_t*)msg->body.source.updated) = 0; + // *((am_addr_t*)msg->body.source.updated) = now_s(); } am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg) { @@ -165,8 +232,7 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc } comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, - comms_send_f* sender, - comms_start_f* startf, comms_stop_f* stopf) { + comms_send_f* sendf, comms_start_f* startf, comms_stop_f* stopf) { comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; @@ -176,12 +242,10 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms->init_message = &am_comms_init_message; - if(sender != NULL) { - comms->send = sender; - } - else { - comms->send = &am_comms_send; - } + amcomms->link_sendf = sendf; + comms->sendf = &am_comms_send; + + comms->deliverf = &am_comms_deliver; comms->start_stop_mutex = comms_mutex_create(); comms->controller_mutex = comms_mutex_create(); @@ -235,6 +299,7 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, amcomms->am_address = &am_comms_addr; amcomms->am_addr = address; + amcomms->cache = NULL; + return COMMS_SUCCESS; } - diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c new file mode 100644 index 0000000..1e7e268 --- /dev/null +++ b/am/mist_comm_am_addrdisco.c @@ -0,0 +1,221 @@ +/** + * EUI and link-local address discovery implementation for + * the TinyOS ActiveMessage transport layer. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ + +#include "mist_comm_am_addrdisco_protocol.h" +#include "mist_comm_am_addrdisco.h" +#include "mist_comm_am.h" + +#include + +#include "loglevels.h" +#define __MODUUL__ "addrd" +#define __LOG_LEVEL__ (LOG_LEVEL_mist_comm_am_addrdisco & BASE_LOG_LEVEL) +#include "log.h" +#include "sys_panic.h" + +#define AM_ADDRDISCO_FLAG_RESPOND (1 << 0) +#define AM_ADDRDISCO_FLAG_DISCOVER (1 << 1) +#define AM_ADDRDISCO_FLAG_SENT (1 << 2) +#define AM_ADDRDISCO_FLAGS (7) + +static void receive_message (comms_layer_t * comms, const comms_msg_t * msg, void * user) +{ + am_addrdisco_t * disco = (am_addrdisco_t*)user; + + uint8_t length = comms_get_payload_length(comms, msg); + if (length >= sizeof(am_addrdisco_packet_t)) + { + am_addrdisco_packet_t * packet = (am_addrdisco_packet_t*)comms_get_payload(comms, msg, sizeof(am_addrdisco_packet_t)); + + debugb1("rcv", packet, sizeof(am_addrdisco_packet_t)); + + switch(packet->header) + { + case GUIDDISCOVERY_REQUEST: + { + am_addr_t dest = comms_am_get_destination(comms, msg); + ieee_eui64_t eui; + eui64_set(&eui, packet->guid); + if ( // Broadcast and my EUI64 + ((AM_BROADCAST_ADDR == dest)&&(0 == eui64_compare(&eui, &(comms->eui)))) + || // My address and FFFFFFFFFFFFFFFF + ((comms_am_address(comms) == dest)&&eui64_is_ones(&eui)) + || // My address and my EUI64 + ((comms_am_address(comms) == dest)&&(0 == eui64_compare(&eui, &(comms->eui)))) + ) + { + // Must respond + am_addr_t source = comms_am_get_source(comms, msg); + if((0 != disco->respond)&&(source != disco->respond)) + { + // A response is pending for someone else, might as well send to broadcast + disco->respond = AM_BROADCAST_ADDR; + } + else + { + disco->respond = source; + } + + debug1("rq %04X", (unsigned int)disco->respond); + + osThreadFlagsSet(disco->thread, 1); + } + } + break; + + case GUIDDISCOVERY_RESPONSE: + { + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; + comms_address_t source; + ieee_eui64_t eui; + comms_get_source(comms, msg, &source); + eui64_set(&eui, packet->guid); + + debugb1("rp %04X", packet->guid, IEEE_EUI64_LENGTH, comms_am_get_source(comms, msg)); + + comms_cache_update(amcomms->cache, &eui, &(source.local)); + } + break; + + default: + warnb1("?", packet, length); + break; + } + } + else warn1("size %d", (unsigned int)comms_get_payload_length(comms, msg)); +} + +static void radio_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) +{ + am_addrdisco_t * disco = (am_addrdisco_t*)user; + logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snt %u", result); + osThreadFlagsSet(disco->thread, AM_ADDRDISCO_FLAG_SENT); +} + +static void addrdisco_loop (void * arg) +{ + am_addrdisco_t * disco = (am_addrdisco_t*)arg; + + for(;;) + { + am_addr_t dest = 0; + + comms_init_message(disco->comms, &(disco->msg)); + am_addrdisco_packet_t * packet = comms_get_payload(disco->comms, &(disco->msg), sizeof(am_addrdisco_packet_t)); + + if (NULL == packet) + { + sys_panic("pckt"); + } + + while (osOK != osMutexAcquire(disco->mutex, osWaitForever)); + + if(0 != disco->respond) + { + dest = disco->respond; + packet->header = GUIDDISCOVERY_RESPONSE; + eui64_get(&(disco->comms->eui), packet->guid); + disco->respond = 0; + } + else if(0 != disco->query_addr) + { + dest = disco->query_addr; + packet->header = GUIDDISCOVERY_REQUEST; + memset(packet->guid, 0xff, sizeof(packet->guid)); + disco->query_addr = 0; + } + else if(false == eui64_is_zeros(&(disco->query_eui))) + { + dest = AM_BROADCAST_ADDR; + packet->header = GUIDDISCOVERY_REQUEST; + eui64_get(&(disco->query_eui), packet->guid); + eui64_set_zeros(&(disco->query_eui)); + } + + osMutexRelease(disco->mutex); + + if (0 != dest) + { + comms_am_set_destination(disco->comms, &(disco->msg), dest); + + comms_set_packet_type(disco->comms, &(disco->msg), AMID_ADDRESS_DISCOVERY); + comms_set_payload_length(disco->comms, &(disco->msg), sizeof(am_addrdisco_packet_t)); + + comms_error_t result = comms_send(disco->comms, &(disco->msg), radio_send_done, disco); + logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snd %u", result); + if (COMMS_SUCCESS == result) + { + osThreadFlagsWait(AM_ADDRDISCO_FLAG_SENT, osFlagsWaitAny, osWaitForever); + } + + // Message has been sent, now take a break for a bit + osDelay(ADDRDISCO_BACKOFF_MS); + } + else // No pending activities, wait for something to happen + { + osThreadFlagsWait(AM_ADDRDISCO_FLAGS, osFlagsWaitAny, osWaitForever); + } + } +} + +void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, comms_addr_cache_t * cache) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; + disco->comms = comms; + disco->respond = 0; + + amcomms->disco = disco; + + comms_cache_init(cache); + amcomms->cache = cache; + + comms_register_recv(comms, &(disco->rcvr), receive_message, disco, AMID_ADDRESS_DISCOVERY); + + const osMutexAttr_t app_mutex_attr = { .attr_bits = osMutexPrioInherit }; + disco->mutex = osMutexNew(&app_mutex_attr); + + const osThreadAttr_t app_thread_attr = { .name = "disco" }; + disco->thread = osThreadNew(addrdisco_loop, disco, &app_thread_attr); +} + +void comms_am_addrdisco_deinit (comms_layer_t * comms) +{ + // TODO implement deinit + // Stop the thread, wait out any ongoing send + // Free the mutex + // Remove the receiver + sys_panic("TODO"); +} + +void comms_am_addrdisco_discover_eui (am_addrdisco_t * disco, am_addr_t local) +{ + if (NULL != disco) + { + while(osOK != osMutexAcquire(disco->mutex, osWaitForever)); + if(0 == disco->query_addr) + { + disco->query_addr = local; + } + osMutexRelease(disco->mutex); + osThreadFlagsSet(disco->thread, AM_ADDRDISCO_FLAG_DISCOVER); + } +} + +void comms_am_addrdisco_discover_local (am_addrdisco_t * disco, ieee_eui64_t * eui) +{ + if (NULL != disco) + { + while(osOK != osMutexAcquire(disco->mutex, osWaitForever)); + if(eui64_is_zeros(&(disco->query_eui))) + { + memcpy(&(disco->query_eui), eui, sizeof(ieee_eui64_t)); + } + osMutexRelease(disco->mutex); + osThreadFlagsSet(disco->thread, AM_ADDRDISCO_FLAG_DISCOVER); + } +} diff --git a/am/mist_comm_am_addrdisco.h b/am/mist_comm_am_addrdisco.h new file mode 100644 index 0000000..2db5cbc --- /dev/null +++ b/am/mist_comm_am_addrdisco.h @@ -0,0 +1,58 @@ +/** + * EUI and link-local address discovery for the TinyOS ActiveMessage transport layer. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#ifndef MIST_COMM_AM_ADDRDISCO_H_ +#define MIST_COMM_AM_ADDRDISCO_H_ + +#include "mist_comm.h" +#include "mist_comm_iface.h" +#include "mist_comm_addrcache.h" + +#ifndef ADDRDISCO_BACKOFF_MS +#define ADDRDISCO_BACKOFF_MS 30000UL +#endif//ADDRDISCO_BACKOFF_MS + +typedef struct am_addrdisco am_addrdisco_t; + +/** + * Initialize address discovery and address cache. + * Should be called only once for a single comms layer. + * + * @param comms The comms layer for which to initialize discovery and cache. + * Needs to be of the AM type or a derivative. + * @param disco Memory for the discovery module. + * @param cache Memory for the cache module. + */ +void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, comms_addr_cache_t * cache); + +/** + * Remove from layer and deinitialize address discovery and address cache. + * + * @param comms The comms layer from which to remove disco and cache modules. + */ +void comms_am_addrdisco_deinit (comms_layer_t * comms); + +/** + * Request that the EUI be discovered for the local address. + * + * @param disco The discovery component to use. + * @param local The local ActiveMessage address for which the EUI is needed. + */ +void comms_am_addrdisco_discover_eui (am_addrdisco_t * disco, am_addr_t local); + +/** + * Request that the local address be discovered for the EUI. + * + * @param disco The discovery component to use. + * @param local The EUI address for which the local address is needed. + */ +void comms_am_addrdisco_discover_local (am_addrdisco_t * disco, ieee_eui64_t * eui); + + +// Include implementation details (size info for allocation) +#include "mist_comm_am_addrdisco_private.h" + +#endif//MIST_COMM_AM_ADDRDISCO_H_ diff --git a/am/mist_comm_am_addrdisco_private.h b/am/mist_comm_am_addrdisco_private.h new file mode 100644 index 0000000..aba9070 --- /dev/null +++ b/am/mist_comm_am_addrdisco_private.h @@ -0,0 +1,28 @@ +/** + * Active Message address discovery object structure. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#ifndef MIST_COMM_AM_ADDRDISCO_PRIVATE_H_ +#define MIST_COMM_AM_ADDRDISCO_PRIVATE_H_ + +struct am_addrdisco +{ + comms_layer_t * comms; + + comms_receiver_t rcvr; + + comms_msg_t msg; // Memory for sending message + + am_addr_t respond; // Who to respond with my EUI + + // TODO Discoveries should probably have a queue + am_addr_t query_addr; // Whose EUI needs to be discovered + ieee_eui64_t query_eui; // Whose local address needs to be discovered + + osMutexId_t mutex; + osThreadId_t thread; // TODO having a dedicated thread here is wasteful +}; + +#endif//MIST_COMM_AM_ADDRDISCO_PRIVATE_H_ diff --git a/am/mist_comm_am_addrdisco_protocol.h b/am/mist_comm_am_addrdisco_protocol.h new file mode 100644 index 0000000..623496a --- /dev/null +++ b/am/mist_comm_am_addrdisco_protocol.h @@ -0,0 +1,34 @@ +/** + * EUI vs link-local address discovery protocol for Mist over ActiveMessage. + * + * The message is sent to broadcast with a specific EUI64 in the payload + * to discover the link-local ActiveMessage address. + * The message is sent to unicast with the guid field set to all ones, to + * discover the EUI64 address. + * A broadcast message with the guid field set to all ones is forbidden. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#ifndef MIST_COMM_AM_ADDRDISCO_PROTOCOL_H_ +#define MIST_COMM_AM_ADDRDISCO_PROTOCOL_H_ + +#include "eui64.h" + +#define AMID_ADDRESS_DISCOVERY 0xFC + +enum GuidDiscoveryHeaders +{ + GUIDDISCOVERY_REQUEST = 1, + GUIDDISCOVERY_RESPONSE = 2 +}; + +#pragma pack(push, 1) +typedef struct am_addrdisco_packet +{ + uint8_t header; + uint8_t guid[IEEE_EUI64_LENGTH]; +} am_addrdisco_packet_t; +#pragma pack(pop) + +#endif//MIST_COMM_AM_ADDRDISCO_PROTOCOL_H_ diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 7b73e87..d842441 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -2,6 +2,7 @@ #include "mist_comm_iface.h" #include +#include static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; @@ -99,16 +100,46 @@ void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { } } +void comms_get_destination(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* destination) { + memcpy(destination, &(msg->body.destination), sizeof(comms_address_t)); +} + +void comms_set_destination(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* destination) { + memcpy(&(msg->body.destination), destination, sizeof(comms_address_t)); +} + +void comms_get_source(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* source) { + memcpy(source, &(msg->body.source), sizeof(comms_address_t)); +} + +void comms_set_source(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* source) { + memcpy(&(msg->body.source), source, sizeof(comms_address_t)); +} + comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { if(comms != NULL) { - return ((comms_layer_iface_t*)comms)->send((comms_layer_iface_t*)comms, msg, sdf, user); + return ((comms_layer_iface_t*)comms)->sendf((comms_layer_iface_t*)comms, msg, sdf, user); } return COMMS_EINVAL; } +bool comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { + comms_layer_iface_t* iface = (comms_layer_iface_t*)comms; + if((iface != NULL)&&(iface->deliverf != NULL)) { + return iface->deliverf(iface, msg); + } + return false; +} + comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { - return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid); + return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid, false); + } + return COMMS_EINVAL; +} +comms_error_t comms_register_recv_eui(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { + if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { + return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid, true); } return COMMS_EINVAL; } diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 3539ff7..542dd28 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -1,7 +1,10 @@ #include "mist_comm_iface.h" #include -static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { +static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, + comms_receiver_t* rcvr, + comms_receive_f* func, void* user, + am_id_t amid, bool require_eui) { comms_receiver_t** indirect; comms_mutex_acquire(comms->receiver_mutex); @@ -17,6 +20,7 @@ static comms_error_t rcv_comms_register_recv(comms_layer_iface_t* comms, comms_r rcvr->type = amid; rcvr->callback = func; rcvr->user = user; + rcvr->eui = require_eui; rcvr->next = NULL; comms_mutex_release(comms->receiver_mutex); @@ -39,6 +43,7 @@ static comms_error_t rcv_comms_register_snooper(comms_layer_iface_t* comms, comm rcvr->type = 0; // Not used rcvr->callback = func; rcvr->user = user; + rcvr->eui = false; rcvr->next = NULL; comms_mutex_release(comms->receiver_mutex); @@ -77,28 +82,50 @@ static comms_error_t rcv_comms_deregister_snooper(comms_layer_iface_t* comms, co return COMMS_FAIL; } -comms_msg_t* comms_deliver(comms_layer_t* layer, comms_msg_t* msg) { +comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg) { comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; am_id_t ptype = comms_get_packet_type(layer, msg); comms_receiver_t* receiver; + bool delivered = false; + bool resolve = false; comms_mutex_acquire(comms->receiver_mutex); // Receivers filter based on type for(receiver=comms->receivers;receiver!=NULL;receiver=receiver->next) { if(receiver->type == ptype) { + // Receiver needs the packet to have an EUI64 source + if(receiver->eui) + { + comms_address_t source; + comms_get_source(layer, msg, &source); + if(eui64_is_zeros(&(source.eui))) + { + resolve = true; + continue; // Cannot deliver if source identity not known + } + } + delivered = true; receiver->callback(layer, msg, receiver->user); } } - // Snoopers get everyting + // Snoopers get everyting and don't mark delivered to true for(receiver=comms->snoopers;receiver!=NULL;receiver=receiver->next) { receiver->callback(layer, msg, receiver->user); } comms_mutex_release(comms->receiver_mutex); - return msg; + if(resolve) + { + return COMMS_NO_ADDR; + } + if(delivered) + { + return COMMS_SUCCESS; + } + return COMMS_FAIL; } comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms) { diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 9b1a2e1..4a8ed6b 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -3,15 +3,12 @@ #include +#include "eui64.h" + typedef uint8_t am_group_t; // This is actually PAN typedef uint8_t am_id_t; typedef uint16_t am_addr_t; -typedef struct ieee_eui64 { - uint8_t data[8]; -} ieee_eui64_t; -// ??? this should come from some ieee_eui64.h header - #define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) #endif//MIST_COMM_BASICS diff --git a/include/mist_comm.h b/include/mist_comm.h index 000c020..bbdc6bf 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -6,6 +6,8 @@ #include #include +#include "eui64.h" + #include "mist_comm_basics.h" #include "mist_comm_mutex.h" @@ -44,28 +46,65 @@ typedef enum CommsStatus { } comms_status_t; typedef struct comms_layer { - uint8_t type; // TODO type definitions + uint8_t type; // TODO type definitions for reflection + ieee_eui64_t eui; // Everything else will embed at least this structure } comms_layer_t; +/** + * The comms local address structure. This carries a link-local address which + * may take different forms. + */ +typedef struct comms_local_addr { + uint8_t data[COMMS_MSG_ADDRESSING_SIZE]; +} comms_local_addr_t; + +/** + * The comms address structure. + */ +typedef struct comms_address { + ieee_eui64_t eui; + comms_local_addr_t local; + uint32_t updated; // Timestamp, seconds +} comms_address_t; + /* - * The comms message structure. Should only be manipulated through comms APIs. + * The comms message structure. Should only be manipulated through the APIs. */ typedef struct comms_msg comms_msg_t; // Callback definitions -------------------------------------------------------- -// Signalled when message transmission is completed to return the message object -// to the client. A function of this type must be passed with every call to the -// comms_send function and the passed function will be called in the future if -// the comms_send returns a successful result (message is accepted). +/** + * Signalled when message transmission is completed to return the message object + * to the client. A function of this type must be passed with every call to the + * comms_send function and the passed function will be called in the future if + * the comms_send returns COMMS_SUCCESS (message is accepted). + * + * @param comms The layer that was used to send the message. + * @param msg The message that was sent. + * @param result The result of the transmission. + * @param user The user pointer provided to comms_send. + */ typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user); -// Signalled when a message is received. Functions of this type must first be -// registered with a communications layer with comms_register_recv. +/** + * Signalled when a message is received. Functions of this type must first be + * registered with a communications layer with comms_register_recv. + * + * @param comms The layer where the message was received. + * @param msg The message, only valid while this call is running. + * @param user The user pointer given to comms_register_recv. + */ typedef void comms_receive_f(comms_layer_t* comms, const comms_msg_t* msg, void* user); -// Signalled when a status change is requested and completed. +/** + * Signalled when a status change is requested and completed. + * + * @param comms The layer for which the status change took place. + * @param status The new status (may not be what was actually requested). + * @param user The user pointer. + */ typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, void* user); // ----------------------------------------------------------------------------- @@ -110,16 +149,39 @@ comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done typedef struct comms_receiver comms_receiver_t; -// Receiver must pass an unused comms_receiver_t object, guaranteeing that the -// memory remains allocated and is not used elsewhere until deregister is called. -// One receiver object may not be used in multiple roles at the same time, but -// the same receive function can be registered several times with different -// conditions and/or with a different user argument. -comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user, am_id_t amid); -// ??? -// last param should be some form of generic args, but this is C ... are we ok -// to proceed with AM ID or should we expand and rename? 16 bit port? -// and what other filtering is needed for receives ... if any? +/** + * Register to receive messages. + * + * Must pass an unused comms_receiver_t object, guaranteeing that the + * memory remains allocated and is not used elsewhere until deregister is called. + * One receiver object may not be used in multiple roles at the same time, but + * the same receive function can be registered several times with different + * conditions and/or with a different user argument. + */ +comms_error_t comms_register_recv(comms_layer_t* comms, + comms_receiver_t* rcvr, + comms_receive_f* func, void *user, + am_id_t amid); + +/** + * Register to receive messages, require the EUI64 addresses to be resolved. + * + * Must pass an unused comms_receiver_t object, guaranteeing that the + * memory remains allocated and is not used elsewhere until deregister is called. + * One receiver object may not be used in multiple roles at the same time, but + * the same receive function can be registered several times with different + * conditions and/or with a different user argument. + */ +comms_error_t comms_register_recv_eui(comms_layer_t* comms, + comms_receiver_t* rcvr, + comms_receive_f* func, void *user, + am_id_t amid); + + +// ??? Open questions regarding receivers and their registration: +// AMID param should be some form of generic args, but this is C ... are we ok +// to only have the 8-bit AM ID or should we expand and rename? 16 bit port? +// Are any other filtering options needed for receiveres? // ??? // Remove an already registered receiver. @@ -138,6 +200,14 @@ am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg); void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype); // ----------------------------------------------------------------------------- +// Addressing ------------------------------------------------------------------ +void comms_get_destination(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* destination); +void comms_set_destination(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* destination); + +void comms_get_source(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* source); +void comms_set_source(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* source); +// ----------------------------------------------------------------------------- + // Message payload manipulation functions -------------------------------------- uint8_t comms_get_payload_max_length(comms_layer_t* comms); @@ -145,12 +215,12 @@ uint8_t comms_get_payload_length(comms_layer_t* comms, const comms_msg_t* msg); void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); void* comms_get_payload(comms_layer_t* comms, const comms_msg_t* msg, uint8_t length); -// ??? -// Do we want support for larger payloads - uint16_t length? +// ??? Open questions regarding payload: +// Do we want support larger payloads - uint16_t length? // ??? // ----------------------------------------------------------------------------- -// PacketLink & Acknowledgements +// PacketLink & Acknowledgements ----------------------------------------------- uint8_t comms_get_retries(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); @@ -169,7 +239,7 @@ bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- -// Message timestamping +// Message timestamping -------------------------------------------------------- // Timestamps are microseconds local clock. Indicate either message reception or // transmission time. @@ -183,7 +253,7 @@ bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg); comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp); // ----------------------------------------------------------------------------- -// TimeSync messaging +// TimeSync messaging ---------------------------------------------------------- // Event time is microseconds local clock // Set event time @@ -196,7 +266,7 @@ uint32_t comms_get_event_time(comms_layer_t* comms, const comms_msg_t* msg); bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg); // ----------------------------------------------------------------------------- -// Message Quality +// Message Quality ------------------------------------------------------------- uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); // ??? standardize on 0-100 instead of 0-255, because for example CC1101 LQI goes from 0-127 and is inverse to Atmel RFX. @@ -206,13 +276,17 @@ int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); // ----------------------------------------------------------------------------- -// Other functions ------------------------------------------------------------- -// Deliver a message to all registered receivers -// TODO the return value does not make sense any more -comms_msg_t* comms_deliver(comms_layer_t* comms, comms_msg_t* msg); +// Received message delivery --------------------------------------------------- +/** + * Deliver a message to all registered receivers. + * + * @param comms The later to use. + * @param msg The message to deliver. + * @return true if the message was delivered to at least one receiver +*/ +bool comms_deliver(comms_layer_t* comms, comms_msg_t* msg); // ----------------------------------------------------------------------------- - // ----------------------------------------------------------------------------- // Sleep management controller // If a sleep controller is registered for a comms layer, it will entirely take diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 3cfd694..1ec01cc 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -3,6 +3,8 @@ #include "mist_comm.h" #include "mist_comm_iface.h" +#include "mist_comm_addrcache.h" +#include "mist_comm_am_addrdisco.h" typedef struct comms_layer_am comms_layer_am_t; @@ -24,7 +26,14 @@ struct comms_layer_am { comms_am_set_source_f* am_set_source; comms_am_addr_f* am_address; + + comms_send_f* link_sendf; + am_addr_t am_addr; + + comms_addr_cache_t * cache; + + am_addrdisco_t * disco; }; // ActiveMessage address diff --git a/include/mist_comm_eui.h b/include/mist_comm_eui.h deleted file mode 100644 index f090c67..0000000 --- a/include/mist_comm_eui.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MIST_COMM_EUI_H_ -#define MIST_COMM_EUI_H_ - -// Address manipulation functions for EUI communications layer ----------------- -ieee_eui64_t comms_get_destination(comms_msg_t* msg); -void comms_set_destination(comms_msg_t* msg, ieee_eui64_t dest); - -ieee_eui64_t comms_get_source(comms_msg_t* msg); -void comms_set_source(comms_msg_t* msg, ieee_eui64_t source); -// ??? -// consider using EUI pointers? -// ??? - -// -// TODO EUI registry functions will have to be defined -// - -// ----------------------------------------------------------------------------- - -#endif//MIST_COMM_EUI_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 4ce5c32..3215a72 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -12,8 +12,9 @@ typedef comms_error_t comms_stop_f(comms_layer_iface_t*, comms_status_change_f*, typedef void comms_init_message_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_send_done_f*, void*); +typedef bool comms_deliver_f(comms_layer_iface_t*, comms_msg_t*); -typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t); +typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t, bool); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); typedef comms_error_t comms_register_snooper_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*); @@ -68,7 +69,10 @@ struct comms_layer_iface { comms_init_message_f* init_message; - comms_send_f* send; + comms_send_f* sendf; + + comms_deliver_f* deliverf; + comms_register_recv_f* register_recv; comms_deregister_recv_f* deregister_recv; comms_register_snooper_f* register_snooper; diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 8493570..bb53f69 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -3,11 +3,14 @@ #include "mist_comm.h" +// Message structure ----------------------------------------------------------- struct comms_msg { struct { am_id_t type; // AMID, port? - uint8_t source[COMMS_MSG_ADDRESSING_SIZE]; - uint8_t destination[COMMS_MSG_ADDRESSING_SIZE]; + + comms_address_t source; + comms_address_t destination; + uint8_t header[COMMS_MSG_HEADER_SIZE]; uint8_t length; @@ -23,6 +26,7 @@ struct comms_receiver { // Members are private, should not be accessed am_id_t type; comms_receive_f* callback; void* user; + bool eui; comms_receiver_t* next; }; diff --git a/include/mist_comm_ref.h b/include/mist_comm_ref.h index 258a2ea..2155de6 100644 --- a/include/mist_comm_ref.h +++ b/include/mist_comm_ref.h @@ -4,4 +4,7 @@ // Add default receiver handling functionality to a layer implementation comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms); +// Deliver to registered receivers. No further actions taken on the message. +comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg); + #endif//MIST_COMM_REF_H_ diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index 282dec1..9294592 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -1,6 +1,7 @@ /** * MistComm SerialActiveMessage layer implementation. * +* Copyright Thinnect Inc. 2020 * @author Raido Pahtma * @license MIT */ diff --git a/serial/serial_activemessage.h b/serial/serial_activemessage.h index b26b361..5d0198b 100644 --- a/serial/serial_activemessage.h +++ b/serial/serial_activemessage.h @@ -4,6 +4,7 @@ * Many instances can be created, each needs a serial_protocol. * Instances will set up a dispatcher with dispatch ID 0x00. * +* Copyright Thinnect Inc. 2020 * @author Raido Pahtma * @license MIT */ diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index 8168973..771db83 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -1,6 +1,7 @@ /** * MistComm SerialBasicMessage layer implementation. * +* Copyright Thinnect Inc. 2020 * @author Raido Pahtma * @license MIT */ From 10999dd479107225bbe0b525f746e09216979811 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 23 Apr 2020 10:09:31 +0300 Subject: [PATCH 47/80] Fix existing tests. --- .gitmodules | 3 +++ test/sleep/Makefile | 2 ++ test/startstop/Makefile | 2 ++ test/zoo/thinnect.node-platform | 1 + 4 files changed, 8 insertions(+) create mode 160000 test/zoo/thinnect.node-platform diff --git a/.gitmodules b/.gitmodules index 4aae019..48944a2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "test/zoo/ThrowTheSwitch.Unity"] path = test/zoo/ThrowTheSwitch.Unity url = https://github.com/ThrowTheSwitch/Unity.git +[submodule "test/zoo/thinnect.node-platform"] + path = test/zoo/thinnect.node-platform + url = git@github.com:thinnect/node-platform.git diff --git a/test/sleep/Makefile b/test/sleep/Makefile index 07bdd83..15e2369 100644 --- a/test/sleep/Makefile +++ b/test/sleep/Makefile @@ -16,6 +16,8 @@ INC_DIRS += -I../../mock INC_DIRS += -I../../include INC_DIRS += -I../../include/compat +INC_DIRS += -I../zoo/thinnect.node-platform/include + TARGET = test_sleep.out all: clean default diff --git a/test/startstop/Makefile b/test/startstop/Makefile index 9699e2a..3f1811e 100644 --- a/test/startstop/Makefile +++ b/test/startstop/Makefile @@ -14,6 +14,8 @@ INC_DIRS += -I.. INC_DIRS += -I../../include INC_DIRS += -I../../include/compat +INC_DIRS += -I../zoo/thinnect.node-platform/include + TARGET = test_startstop.out all: clean default diff --git a/test/zoo/thinnect.node-platform b/test/zoo/thinnect.node-platform new file mode 160000 index 0000000..5f76d7c --- /dev/null +++ b/test/zoo/thinnect.node-platform @@ -0,0 +1 @@ +Subproject commit 5f76d7cccb4cd63a0ec9e700da9a9199fd00c3c8 From 5a82dc7bae8b003f1cf2651d2f26a113140db39f Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 23 Apr 2020 10:15:02 +0300 Subject: [PATCH 48/80] Update submodule URL to use HTTPS. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 48944a2..5abbd22 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,4 +3,4 @@ url = https://github.com/ThrowTheSwitch/Unity.git [submodule "test/zoo/thinnect.node-platform"] path = test/zoo/thinnect.node-platform - url = git@github.com:thinnect/node-platform.git + url = https://github.com/thinnect/node-platform.git From 4de4466773d9ebd839574b93df64ed886e7e0c59 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Sat, 30 May 2020 17:58:15 +0300 Subject: [PATCH 49/80] Fix caching failure. --- addrcache/mist_comm_addrcache.c | 4 ++-- am/mist_comm_am.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/addrcache/mist_comm_addrcache.c b/addrcache/mist_comm_addrcache.c index c096a58..850cbeb 100644 --- a/addrcache/mist_comm_addrcache.c +++ b/addrcache/mist_comm_addrcache.c @@ -116,7 +116,7 @@ void comms_cache_update (comms_addr_cache_t * cache, const ieee_eui64_t * eui, c uint32_t updated = UINT32_MAX; for (int i=0;ieuis[i]))) + if (eui64_is_zeros(&(cache->euis[i]))) { free_slot = i; break; @@ -129,7 +129,7 @@ void comms_cache_update (comms_addr_cache_t * cache, const ieee_eui64_t * eui, c } } - debug("add"); + debug("add %d", free_slot); // Store the information in the slot that was found memcpy(&(cache->euis[free_slot]), eui, sizeof(ieee_eui64_t)); memcpy(&(cache->locals[free_slot]), local, sizeof(comms_local_addr_t)); diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index e868195..09dfce8 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -46,7 +46,7 @@ static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { // Attach the eui address of the source if(false == comms_cache_get_eui(amcomms->cache, - &(msg->body.source.local), &(msg->body.source.eui))) + &(msg->body.source.local), &(msg->body.source.eui))) { eui64_set_zeros(&(msg->body.destination.eui)); } @@ -61,7 +61,7 @@ static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { memcpy(&(msg->body.destination.eui), &(comms->eui), sizeof(ieee_eui64_t)); } else if(false == comms_cache_get_eui(amcomms->cache, - &(msg->body.destination.local), &(msg->body.destination.eui))) + &(msg->body.destination.local), &(msg->body.destination.eui))) { eui64_set_zeros(&(msg->body.destination.eui)); } @@ -199,6 +199,7 @@ static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_m return *((am_addr_t*)msg->body.destination.local.data); } static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { + memset(&(msg->body.destination.local), 0, sizeof(msg->body.destination.local)); *((am_addr_t*)msg->body.destination.local.data) = dest; *((am_addr_t*)msg->body.destination.updated) = 0; // *((am_addr_t*)msg->body.destination.updated) = now_s(); @@ -208,6 +209,7 @@ static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* return *((am_addr_t*)msg->body.source.local.data); } static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { + memset(&(msg->body.source.local), 0, sizeof(msg->body.source.local)); *((am_addr_t*)msg->body.source.local.data) = source; *((am_addr_t*)msg->body.source.updated) = 0; // *((am_addr_t*)msg->body.source.updated) = now_s(); From 6d7beec04ac8a493e622a58d64ad5277368be5a1 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Mon, 6 Jul 2020 23:38:55 +0300 Subject: [PATCH 50/80] Fix basicmessage compatibility with addr caching. --- serial/serial_basicmessage.c | 11 +++++++---- serial/serial_basicmessage.h | 6 +++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index 771db83..aa81996 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -28,7 +28,8 @@ static bool serial_bm_receive(uint8_t dspch, const uint8_t data[], uint8_t lengt static void serial_bm_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_bm_timer_cb(void * argument); -comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, uint8_t dispatch) +comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, + uint8_t dispatch, am_id_t amid) { sbm->mutex = osMutexNew(NULL); sbm->timer = osTimerNew(&serial_bm_timer_cb, osTimerOnce, sbm, NULL); @@ -44,6 +45,7 @@ comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_pro sbm->queue_memory[i].next = sbm->free_queue; sbm->free_queue = &(sbm->queue_memory[i]); } + sbm->amid = amid; // Set up dispatcher sbm->protocol = spr; @@ -99,14 +101,15 @@ static bool serial_bm_receive(uint8_t dispatch, const uint8_t data[], uint8_t le return false; } - comms_set_packet_type(lyr, &msg, 0); + comms_set_packet_type(lyr, &msg, sbm->amid); // Set to specified amid as it needs to pass through deliver comms_set_payload_length(lyr, &msg, length); memcpy(payload, data, length); // comms_set_timestamp(lyr, &msg, timestamp); // TODO Set to now? Make the lowest layer register frame starts ...? - comms_am_set_destination(lyr, &msg, 0); - comms_am_set_source(lyr, &msg, 0); + // Addresses are set to broadcast, as mist-comm may complain about 0 addresses + comms_am_set_destination(lyr, &msg, AM_BROADCAST_ADDR); + comms_am_set_source(lyr, &msg, AM_BROADCAST_ADDR); debugb1("rx {%02"PRIX8"}", payload, comms_get_payload_length(lyr, &msg), diff --git a/serial/serial_basicmessage.h b/serial/serial_basicmessage.h index 10ab4e4..7e5423c 100644 --- a/serial/serial_basicmessage.h +++ b/serial/serial_basicmessage.h @@ -27,13 +27,15 @@ typedef struct serial_basicmessage serial_basicmessage_t; * memory structure. * @param spr - Pointer to an initialized SerialProtocol layer. * @param dispatch - The SerialProtocol dispatch ID to use. + * @param amid - The AM ID to use for RX messages (for compatibility). * * @return a MistComm instance that can be used for sending/receiving messages * or NULL for failure. */ comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, - uint8_t dispatch); + uint8_t dispatch, + am_id_t amid); /** * Deinitialize the SerialbasicMessage layer. The memory used by the instance @@ -75,6 +77,8 @@ struct serial_basicmessage sbm_queue_element_t * free_queue; sbm_queue_element_t queue_memory[SERIAL_BASICMESSAGE_QUEUE_LENGTH]; + am_id_t amid; + bool send_busy; }; From cd739cce962d5d801e6ba4f1d37fbcd8cdcdd017 Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Thu, 16 Jul 2020 09:05:37 +0300 Subject: [PATCH 51/80] Fix some log strings. --- am/mist_comm_am_addrdisco.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index 1e7e268..6de23de 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -87,13 +87,13 @@ static void receive_message (comms_layer_t * comms, const comms_msg_t * msg, voi break; } } - else warn1("size %d", (unsigned int)comms_get_payload_length(comms, msg)); + else warn1("size %u", (unsigned int)comms_get_payload_length(comms, msg)); } static void radio_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) { am_addrdisco_t * disco = (am_addrdisco_t*)user; - logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snt %u", result); + logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snt %d", (int)result); osThreadFlagsSet(disco->thread, AM_ADDRDISCO_FLAG_SENT); } @@ -147,7 +147,7 @@ static void addrdisco_loop (void * arg) comms_set_payload_length(disco->comms, &(disco->msg), sizeof(am_addrdisco_packet_t)); comms_error_t result = comms_send(disco->comms, &(disco->msg), radio_send_done, disco); - logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snd %u", result); + logger(result == COMMS_SUCCESS ? LOG_DEBUG1: LOG_WARN1, "snd %d", (int)result); if (COMMS_SUCCESS == result) { osThreadFlagsWait(AM_ADDRDISCO_FLAG_SENT, osFlagsWaitAny, osWaitForever); From 10beb9e7888c7ec69468242646a7a688f5739abd Mon Sep 17 00:00:00 2001 From: Raido Pahtma Date: Wed, 29 Jul 2020 09:04:22 +0300 Subject: [PATCH 52/80] Address and group id for serial activemessage. --- serial/serial_activemessage.c | 25 ++++++++++++++++--------- serial/serial_activemessage.h | 6 +++++- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index 9294592..1367af8 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -43,11 +43,13 @@ static bool serial_am_receive(uint8_t dspch, const uint8_t data[], uint8_t lengt static void serial_am_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_am_timer_cb(void * argument); -comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_protocol_t * spr) +comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_protocol_t * spr, uint16_t pan_id, uint16_t address) { sam->mutex = osMutexNew(NULL); sam->timer = osTimerNew(&serial_am_timer_cb, osTimerOnce, sam, NULL); + sam->group_id = pan_id; + // Initialize send queueing system sam->send_busy = false; sam->sending = NULL; @@ -68,9 +70,8 @@ comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_pr sam); // Set up the mist-comm layer - // TODO should we be passing 0 as default address? // TODO start-stop handlers - comms_am_create((comms_layer_t *)sam, 0, &serial_activemessage_send, NULL, NULL); + comms_am_create((comms_layer_t *)sam, address, &serial_activemessage_send, NULL, NULL); // serial_activemessage_t is a valid comms_layer_t return (comms_layer_t *)sam; @@ -137,10 +138,9 @@ static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t le comms_am_set_destination(lyr, &msg, ntoh16(m->destination)); comms_am_set_source(lyr, &msg, ntoh16(m->source)); - // TODO DEFAULT_PAN_ID variable debugb1("rx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", payload, comms_get_payload_length(lyr, &msg), - DEFAULT_PAN_ID, + (int)m->group_id, // TODO grop variable stored in the packet comms_am_get_source(lyr, &msg), comms_am_get_destination(lyr, &msg), comms_get_packet_type(lyr, &msg)); @@ -160,8 +160,9 @@ static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t le * @param lyr - the layer to use for interpreting the message * @return length of the prepared message or 0 for errors */ -static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_t * msg, comms_layer_t * lyr) +static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_t * msg, serial_activemessage_t * sam) { + comms_layer_t * lyr = (comms_layer_t*)sam; uint8_t plen = comms_get_payload_length(lyr, msg); if(plen + sizeof(tos_serial_message_t) <= length) @@ -170,10 +171,16 @@ static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_ if (NULL != payload) { tos_serial_message_t* m = (tos_serial_message_t*)buffer; + uint16_t src = comms_am_get_source(lyr, msg); + + if (0 == src) + { + src = comms_am_address(lyr); + } m->destination = hton16(comms_am_get_destination(lyr, msg)); - m->source = hton16(comms_am_get_source(lyr, msg)); - m->group = DEFAULT_PAN_ID; // TODO variable + m->source = hton16(src); + m->group = sam->group_id; // TODO variable m->amid = comms_get_packet_type(lyr, msg); m->payload_length = plen; memcpy(m->payload, payload, plen); @@ -252,7 +259,7 @@ static void serial_am_timer_cb(void * argument) if (NULL != sam->sending) { - uint16_t length = prepare_sp_message(sam->send_buffer, sizeof(sam->send_buffer), sam->sending->msg, lyr); + uint16_t length = prepare_sp_message(sam->send_buffer, sizeof(sam->send_buffer), sam->sending->msg, sam); if(length > 0) { if(true == serial_protocol_send(&(sam->dispatcher), sam->send_buffer, length, false)) diff --git a/serial/serial_activemessage.h b/serial/serial_activemessage.h index 5d0198b..bc2c299 100644 --- a/serial/serial_activemessage.h +++ b/serial/serial_activemessage.h @@ -32,7 +32,8 @@ typedef struct serial_activemessage serial_activemessage_t; * or NULL for failure. */ comms_layer_t* serial_activemessage_init (serial_activemessage_t * sam, - serial_protocol_t * spr); + serial_protocol_t * spr, + uint16_t pan_id, uint16_t address); /** * Deinitialize the SerialActiveMessage layer. The memory used by the instance @@ -78,6 +79,9 @@ struct serial_activemessage sam_queue_element_t * free_queue; sam_queue_element_t queue_memory[SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH]; + am_addr_t am_addr; + am_group_t group_id; + bool send_busy; uint8_t send_buffer[SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH]; }; From 1d2609ba0388c4cc9f151b25f6dcb3d5512fa602 Mon Sep 17 00:00:00 2001 From: Raido Date: Wed, 21 Oct 2020 00:22:50 +0300 Subject: [PATCH 53/80] Add a mock radio for testing. --- mock/mist_mock_radio_cmsis.c | 75 ++++++++++++++++++++++++++++++++++++ mock/mist_mock_radio_cmsis.h | 21 ++++++++++ 2 files changed, 96 insertions(+) create mode 100644 mock/mist_mock_radio_cmsis.c create mode 100644 mock/mist_mock_radio_cmsis.h diff --git a/mock/mist_mock_radio_cmsis.c b/mock/mist_mock_radio_cmsis.c new file mode 100644 index 0000000..3ba9d5c --- /dev/null +++ b/mock/mist_mock_radio_cmsis.c @@ -0,0 +1,75 @@ +/** + * MistComm mock radio layer. + * Exports outgoing messages, giving send done events to users. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#include "mist_comm_am.h" + +#include "mist_mock_radio_cmsis.h" + +#include "cmsis_os2.h" + +static comms_layer_am_t m_radio_iface; + +static osThreadId_t m_thread; +static osMutexId_t m_mutex; + +static bool m_send_busy = false; +static comms_msg_t * mp_send_msg; +static comms_send_done_f * mf_send_done; +static void * mp_send_user; + +static comms_send_f * mf_send_copy; + + +static comms_error_t radio_send (comms_layer_iface_t * iface, comms_msg_t * msg, + comms_send_done_f * send_done, void * user) +{ + while (osOK != osMutexAcquire(m_mutex, osWaitForever)); + if (false == m_send_busy) + { + m_send_busy = true; + mp_send_msg = msg; + mf_send_done = send_done; + mp_send_user = user; + osThreadFlagsSet(m_thread, 1); + osMutexRelease(m_mutex); + return COMMS_SUCCESS; + } + osMutexRelease(m_mutex); + return COMMS_EBUSY; +} + + +static void mock_radio_loop (void * arg) +{ + for (;;) + { + osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); + while (osOK != osMutexAcquire(m_mutex, osWaitForever)); + if (m_send_busy) + { + m_send_busy = false; + mf_send_copy((comms_layer_iface_t *)&m_radio_iface, mp_send_msg, NULL, mp_send_user); + mf_send_done((comms_layer_t *)&m_radio_iface, mp_send_msg, COMMS_SUCCESS, mp_send_user); + } + osMutexRelease(m_mutex); + } +} + + +comms_layer_t * mist_mock_cmsis_radio_init (am_addr_t address, comms_send_f * send_copy) +{ + mf_send_copy = send_copy; + + comms_am_create((comms_layer_t *)&m_radio_iface, address, radio_send, NULL, NULL); + + m_mutex = osMutexNew(NULL); + + const osThreadAttr_t thread_attr = { .name = "radio", .stack_size = 3072 }; + m_thread = osThreadNew(mock_radio_loop, NULL, &thread_attr); + + return (comms_layer_t*)&m_radio_iface; +} diff --git a/mock/mist_mock_radio_cmsis.h b/mock/mist_mock_radio_cmsis.h new file mode 100644 index 0000000..6f0aba3 --- /dev/null +++ b/mock/mist_mock_radio_cmsis.h @@ -0,0 +1,21 @@ +/** + * MistComm mock radio layer. + * Exports outgoing messages, giving send done events to users. + * + * Copyright Thinnect Inc. 2020 + * @license MIT + */ +#ifndef MIST_MOCK_RADIO_CMSIS_H_ +#define MIST_MOCK_RADIO_CMSIS_H_ + +#include "mist_comm_am.h" + +/** + * Create a mock radio. + * @param address - radio address. + * @param send_copy - function to call with outgoing messages. + * @return Mock radio pointer. + */ +comms_layer_t * mist_mock_cmsis_radio_init (am_addr_t address, comms_send_f * send_copy); + +#endif//MIST_MOCK_RADIO_CMSIS_H_ From 7a9d2d0600511a19d38e6ba5e2951ec36e2082e5 Mon Sep 17 00:00:00 2001 From: Raido Date: Thu, 29 Oct 2020 10:26:32 +0200 Subject: [PATCH 54/80] Fix logline in sam. --- serial/serial_activemessage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index 1367af8..3e86ca2 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -140,7 +140,7 @@ static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t le debugb1("rx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", payload, comms_get_payload_length(lyr, &msg), - (int)m->group_id, // TODO grop variable stored in the packet + (int)m->group, comms_am_get_source(lyr, &msg), comms_am_get_destination(lyr, &msg), comms_get_packet_type(lyr, &msg)); From eb9c3836489330060f25b3da4d136df9b5215513 Mon Sep 17 00:00:00 2001 From: Konstantin Bilozor Date: Wed, 18 Nov 2020 17:13:39 +0200 Subject: [PATCH 55/80] Decreased stack size for addrdisco thread. --- am/mist_comm_am_addrdisco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index 6de23de..d0b6805 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -179,7 +179,7 @@ void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, com const osMutexAttr_t app_mutex_attr = { .attr_bits = osMutexPrioInherit }; disco->mutex = osMutexNew(&app_mutex_attr); - const osThreadAttr_t app_thread_attr = { .name = "disco" }; + const osThreadAttr_t app_thread_attr = { .name = "disco", stack_size = 512 }; disco->thread = osThreadNew(addrdisco_loop, disco, &app_thread_attr); } From b4d8585cc307d20220f2c55bdb95b3e7f5e696cc Mon Sep 17 00:00:00 2001 From: Konstantin Bilozor Date: Wed, 18 Nov 2020 17:58:59 +0200 Subject: [PATCH 56/80] Fix typo. --- am/mist_comm_am_addrdisco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index d0b6805..c1d4693 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -179,7 +179,7 @@ void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, com const osMutexAttr_t app_mutex_attr = { .attr_bits = osMutexPrioInherit }; disco->mutex = osMutexNew(&app_mutex_attr); - const osThreadAttr_t app_thread_attr = { .name = "disco", stack_size = 512 }; + const osThreadAttr_t app_thread_attr = { .name = "disco", .stack_size = 512 }; disco->thread = osThreadNew(addrdisco_loop, disco, &app_thread_attr); } From 0815c6a8cdc999eb31191c3c2fe7eae88229f834 Mon Sep 17 00:00:00 2001 From: Konstantin Bilozor Date: Fri, 20 Nov 2020 08:25:07 +0200 Subject: [PATCH 57/80] Increase heap size for addrdisco. --- am/mist_comm_am_addrdisco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index c1d4693..eba33df 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -179,7 +179,7 @@ void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, com const osMutexAttr_t app_mutex_attr = { .attr_bits = osMutexPrioInherit }; disco->mutex = osMutexNew(&app_mutex_attr); - const osThreadAttr_t app_thread_attr = { .name = "disco", .stack_size = 512 }; + const osThreadAttr_t app_thread_attr = { .name = "disco", .stack_size = 2048 }; disco->thread = osThreadNew(addrdisco_loop, disco, &app_thread_attr); } From 395ee7de7cd2246e0f339dd2174a6e7c9bdb003e Mon Sep 17 00:00:00 2001 From: Raido Date: Fri, 11 Dec 2020 13:22:54 +0200 Subject: [PATCH 58/80] Improve bridge logging. --- bridge/mist_comm_bridge.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index 0882ec7..2a02534 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -37,9 +37,11 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, const osThreadAttr_t bridge_thread_1_attr = { .name = "bt1" }; bridge->t1.thread = osThreadNew(bridge_thread, &(bridge->t1), &bridge_thread_1_attr); + debug1("bt1 %p", bridge->t1.thread); const osThreadAttr_t bridge_thread_2_attr = { .name = "bt2" }; bridge->t2.thread = osThreadNew(bridge_thread, &(bridge->t2), &bridge_thread_2_attr); + debug1("bt1 %p", bridge->t2.thread); bridge->t1.layer = a; bridge->t2.layer = b; @@ -105,7 +107,7 @@ static void bridge_am_snoop (comms_layer_t* comms, const comms_msg_t* msg, void* if(osMessageQueuePut(bt->rxqueue, msg, 0, 0) != osOK) { - warn1("drop"); + warn1("drop %p", user); } } @@ -133,8 +135,8 @@ static void bridge_thread (void * param) if(COMMS_SUCCESS == comms_send(bt->layer, &(bt->msg), bridge_send_done, bt)) { + debug4("%p snd", &(bt->msg)); flags = osThreadFlagsWait(MIST_COMM_BRIDGE_FLAG_SEND_DONE, osFlagsWaitAny, osWaitForever); - debug4("snt"); } else { From b546ab3502acc4df9d4a6923e4c427f1737e3ce7 Mon Sep 17 00:00:00 2001 From: Raido Date: Thu, 17 Dec 2020 21:20:31 +0200 Subject: [PATCH 59/80] Decrease disco stack. --- am/mist_comm_am_addrdisco.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index eba33df..0ba75af 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -179,7 +179,7 @@ void comms_am_addrdisco_init (comms_layer_t * comms, am_addrdisco_t * disco, com const osMutexAttr_t app_mutex_attr = { .attr_bits = osMutexPrioInherit }; disco->mutex = osMutexNew(&app_mutex_attr); - const osThreadAttr_t app_thread_attr = { .name = "disco", .stack_size = 2048 }; + const osThreadAttr_t app_thread_attr = { .name = "disco", .stack_size = 1536 }; disco->thread = osThreadNew(addrdisco_loop, disco, &app_thread_attr); } From efeab134fba6832f55179fe45cf0d673f5bbf633 Mon Sep 17 00:00:00 2001 From: Raido Date: Thu, 17 Dec 2020 23:16:47 +0200 Subject: [PATCH 60/80] Pass messages even if EUI not known. --- api/mist_comm_rcv.c | 1 - 1 file changed, 1 deletion(-) diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 542dd28..9977610 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -102,7 +102,6 @@ comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg) { if(eui64_is_zeros(&(source.eui))) { resolve = true; - continue; // Cannot deliver if source identity not known } } delivered = true; From 1933aebab4f5b69d1a55572291b860164d83437b Mon Sep 17 00:00:00 2001 From: Raido Date: Sun, 14 Feb 2021 22:29:08 +0200 Subject: [PATCH 61/80] Add nx_am_addr_t --- include/compat/mist_comm_basics.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 4a8ed6b..02c1b96 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -9,6 +9,8 @@ typedef uint8_t am_group_t; // This is actually PAN typedef uint8_t am_id_t; typedef uint16_t am_addr_t; +typedef uint16_t nx_am_addr_t; + #define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) #endif//MIST_COMM_BASICS From 92d0211bfcbc620c0bdb9e83740a36c058af5895 Mon Sep 17 00:00:00 2001 From: Raido Date: Tue, 30 Mar 2021 13:17:18 +0300 Subject: [PATCH 62/80] Import fragmenter-assembler. --- util/fragmenter_assembler.c | 63 +++++++++++++++++++++++++++++++++++++ util/fragmenter_assembler.h | 41 ++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 util/fragmenter_assembler.c create mode 100644 util/fragmenter_assembler.h diff --git a/util/fragmenter_assembler.c b/util/fragmenter_assembler.c new file mode 100644 index 0000000..5bbe3d7 --- /dev/null +++ b/util/fragmenter_assembler.c @@ -0,0 +1,63 @@ +/** + * Fragmentation and assembly functions. + * Maximum fragment size needs to be known for assembly, all but the last + * fragment need to be of this size, the last one can be shorter. + * Maximum number of fragments is 8, maximum data size is 255 bytes. + * + * @author Raido Pahtma + * @license MIT + */ +#include "fragmenter_assembler.h" + + +uint8_t data_fragments (uint8_t dataSize, uint8_t fragMaxSize) +{ + uint8_t frags = (uint8_t)(1 + ((((int16_t)dataSize) - 1) / fragMaxSize)); + if (frags == 0) + { + return 1; + } + return frags; +} + + +uint8_t data_fragmenter (uint8_t fragment[], uint8_t fragSize, uint8_t offset, + uint8_t data[], uint8_t dataSize) +{ + if (offset < dataSize) + { + if (dataSize - offset < fragSize) + { + fragSize = dataSize - offset; + } + memcpy(fragment, &data[offset], fragSize); + return fragSize; + } + return 0; +} + + +bool data_assembler (uint8_t fragMaxSize, uint8_t object[], uint8_t objectSize, + uint8_t fragment[], uint8_t fragSize, + uint8_t offset, uint8_t* fragMap) +{ + uint8_t frag = offset / fragMaxSize; + uint8_t frags = objectSize / fragMaxSize + (objectSize % fragMaxSize != 0 ? 1 : 0); + uint8_t i; + if ((uint16_t)offset + fragSize <= objectSize) // (uint16_t) to make sure that offset+fragSize does not wrap + { + if (offset % fragMaxSize == 0) // is properly fragmented + { + memcpy(&object[offset], fragment, fragSize); + *fragMap = *fragMap | (1 << frag); + } + } + for (i=0;i +#include +#include + +/** + * Compute the number of fragments needed to split dataSize over fragments of fragMaxSize. + * Supports sending empty messages - returns 1 for dataSize 0. + * + * @param dataSize - Number of bytes to send. + * @param fragMaxSize - Free space in one fragment. + * + * @return Number of fragments needed to send dataSize bytes of data. + */ +uint8_t data_fragments(uint8_t dataSize, uint8_t fragMaxSize); + +/** + * @return size of fragment + */ +uint8_t data_fragmenter(uint8_t fragment[], uint8_t fragSize, uint8_t offset, + uint8_t data[], uint8_t dataSize); + +/** + * @return true, if assembly complete, false if data still missing. + */ +bool data_assembler(uint8_t fragMaxSize, uint8_t object[], uint8_t objectSize, + uint8_t fragment[], uint8_t fragSize, + uint8_t offset, uint8_t* fragMap); + +#endif // FRAGMENTER_ASSEMBLER_H_ From 9498758cb6f4dc49a56b2555aff404ddd2429f6d Mon Sep 17 00:00:00 2001 From: "DESKTOP-8HJ1Q1L\\boss" Date: Tue, 27 Apr 2021 13:30:20 +0300 Subject: [PATCH 63/80] Fixed some unalignement. --- am/mist_comm_am.c | 16 ++++++++-------- include/mist_comm.h | 4 ++-- include/mist_comm_am_msg.h | 2 +- include/mist_comm_private.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 09dfce8..8f0b64a 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -196,23 +196,23 @@ static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8 } static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { - return *((am_addr_t*)msg->body.destination.local.data); + return *((__packed am_addr_t*)msg->body.destination.local.data); } static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { memset(&(msg->body.destination.local), 0, sizeof(msg->body.destination.local)); - *((am_addr_t*)msg->body.destination.local.data) = dest; - *((am_addr_t*)msg->body.destination.updated) = 0; - // *((am_addr_t*)msg->body.destination.updated) = now_s(); + *((__packed am_addr_t*)msg->body.destination.local.data) = dest; + msg->body.destination.updated = 0; + //msg->body.destination.updated) = now_s(); } static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* msg) { - return *((am_addr_t*)msg->body.source.local.data); + return *((__packed am_addr_t*)msg->body.source.local.data); } static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { memset(&(msg->body.source.local), 0, sizeof(msg->body.source.local)); - *((am_addr_t*)msg->body.source.local.data) = source; - *((am_addr_t*)msg->body.source.updated) = 0; - // *((am_addr_t*)msg->body.source.updated) = now_s(); + *((__packed am_addr_t*)msg->body.source.local.data) = source; + msg->body.source.updated = 0; + //msg->body.source.updated = now_s(); } am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg) { diff --git a/include/mist_comm.h b/include/mist_comm.h index bbdc6bf..ca8faa4 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -57,7 +57,7 @@ typedef struct comms_layer { */ typedef struct comms_local_addr { uint8_t data[COMMS_MSG_ADDRESSING_SIZE]; -} comms_local_addr_t; +} __attribute__((packed))comms_local_addr_t; /** * The comms address structure. @@ -66,7 +66,7 @@ typedef struct comms_address { ieee_eui64_t eui; comms_local_addr_t local; uint32_t updated; // Timestamp, seconds -} comms_address_t; +} __attribute__((packed))comms_address_t; /* * The comms message structure. Should only be manipulated through the APIs. diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index 6089ef3..86ab378 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -25,6 +25,6 @@ typedef struct comms_am_msg_metadata { bool event_time_valid; uint32_t event_time; -} comms_am_msg_metadata_t; +} __attribute__((packed))comms_am_msg_metadata_t; #endif//MIST_COMM_AM_H_ diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index bb53f69..147ecad 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -18,7 +18,7 @@ struct comms_msg { uint8_t footer[COMMS_MSG_FOOTER_SIZE]; uint8_t metadata[COMMS_MSG_METADATA_SIZE]; - } body; + } __attribute__((packed)) body; }; // Receiver structure ---------------------------------------------------------- From e44fdbb00332d9ed5e08f34431c1600924d72f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madis=20Uusj=C3=A4rv?= Date: Thu, 10 Jun 2021 16:59:29 +0300 Subject: [PATCH 64/80] [HIOT-455] WIP --- am/mist_comm_am.c | 18 ++++++++++++++++++ api/mist_comm_api.c | 14 ++++++++++++++ include/mist_comm.h | 3 +++ include/mist_comm_am_msg.h | 3 +++ include/mist_comm_iface.h | 5 +++++ 5 files changed, 43 insertions(+) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 09dfce8..ceaebb0 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -195,6 +195,21 @@ static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8 ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi = rssi; } +static int8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg_t* msg) { + if (true == ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid) + { + return ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority; + } + else + { + return 0xFF; + } +} +static void am_comms_set_priority(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t priority) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid = true; + ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority = priority; +} + static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { return *((am_addr_t*)msg->body.destination.local.data); } @@ -293,6 +308,9 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms->get_rssi = &am_comms_get_rssi; comms->set_rssi = &am_comms_set_rssi; + comms->get_priority = &am_comms_get_priority; + comms->set_priority = &am_comms_set_priority; + amcomms->am_get_destination = &am_comms_get_destination; amcomms->am_set_destination = &am_comms_set_destination; amcomms->am_get_source = &am_comms_get_source; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index d842441..14f332e 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -346,3 +346,17 @@ void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { cl->set_rssi(cl, msg, rssi); } } + +int8_t comms_get_priority(comms_layer_t* comms, const comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_priority(cl, msg); + } + return 0xFF; +} +void comms_set_priority(comms_layer_t* comms, comms_msg_t* msg, int8_t priority) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_priority(cl, msg, priority); + } +} diff --git a/include/mist_comm.h b/include/mist_comm.h index bbdc6bf..0cef259 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -274,6 +274,9 @@ void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); // Value in dBm int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg); void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); + +int8_t comms_get_priority(comms_layer_t* comms, const comms_msg_t* msg); +void comms_set_priority(comms_layer_t* comms, comms_msg_t* msg, int8_t priority); // ----------------------------------------------------------------------------- // Received message delivery --------------------------------------------------- diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index 6089ef3..4f4b733 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -25,6 +25,9 @@ typedef struct comms_am_msg_metadata { bool event_time_valid; uint32_t event_time; + + bool priority_valid; + uint8_t priority; } comms_am_msg_metadata_t; #endif//MIST_COMM_AM_H_ diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 3215a72..70a39d9 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -57,6 +57,8 @@ typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); +typedef int8_t comms_get_priority_f(comms_layer_iface_t*, const comms_msg_t*); +typedef void comms_set_priority_f(comms_layer_iface_t*, comms_msg_t*, int8_t); // ----------------------------------------------------------------------------- struct comms_layer_iface { @@ -114,6 +116,9 @@ struct comms_layer_iface { comms_get_rssi_f* get_rssi; comms_set_rssi_f* set_rssi; + comms_get_priority_f* get_priority; + comms_set_priority_f* set_priority; + // Receivers comms_receiver_t* receivers; // List of registered receivers From 31e01ba34aeba985c17a583876971bc1a0af3f75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madis=20Uusj=C3=A4rv?= Date: Fri, 11 Jun 2021 14:17:49 +0300 Subject: [PATCH 65/80] [HIOT-455] Bug fix: changed int8_t to uint8_t --- am/mist_comm_am.c | 4 ++-- include/mist_comm_iface.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index ceaebb0..c495bc4 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -195,7 +195,7 @@ static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8 ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi = rssi; } -static int8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg_t* msg) { if (true == ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority; @@ -205,7 +205,7 @@ static int8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg_ return 0xFF; } } -static void am_comms_set_priority(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t priority) { +static void am_comms_set_priority(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t priority) { ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid = true; ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority = priority; } diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 70a39d9..8317a02 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -57,8 +57,8 @@ typedef void comms_set_lqi_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); typedef int8_t comms_get_rssi_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_rssi_f(comms_layer_iface_t*, comms_msg_t*, int8_t); -typedef int8_t comms_get_priority_f(comms_layer_iface_t*, const comms_msg_t*); -typedef void comms_set_priority_f(comms_layer_iface_t*, comms_msg_t*, int8_t); +typedef uint8_t comms_get_priority_f(comms_layer_iface_t*, const comms_msg_t*); +typedef void comms_set_priority_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); // ----------------------------------------------------------------------------- struct comms_layer_iface { From 7e51006a837b6cba0679f7a31797483f585b3e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Madis=20Uusj=C3=A4rv?= Date: Wed, 30 Jun 2021 15:40:19 +0300 Subject: [PATCH 66/80] Fixed some unalignement --- include/mist_comm_am_msg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index 4f4b733..d71d022 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -28,6 +28,6 @@ typedef struct comms_am_msg_metadata { bool priority_valid; uint8_t priority; -} comms_am_msg_metadata_t; +}__attribute__((packed))comms_am_msg_metadata_t; #endif//MIST_COMM_AM_H_ From 40e0dd25d56c71936c5a8eda595e6cd5bd070589 Mon Sep 17 00:00:00 2001 From: Konstantin Bilozor Date: Fri, 10 Sep 2021 09:38:30 +0300 Subject: [PATCH 67/80] [HIOT-523] Fixed attribute warnings. --- am/mist_comm_am.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 6a3d1ef..2b5ca7a 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -211,21 +211,37 @@ static void am_comms_set_priority(comms_layer_iface_t* comms, comms_msg_t* msg, } static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { +#ifdef ALIGN_CM0 return *((__packed am_addr_t*)msg->body.destination.local.data); +#else + return *((am_addr_t*)msg->body.destination.local.data); +#endif } static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { memset(&(msg->body.destination.local), 0, sizeof(msg->body.destination.local)); +#ifdef ALIGN_CM0 *((__packed am_addr_t*)msg->body.destination.local.data) = dest; +#else + *((am_addr_t*)msg->body.destination.local.data) = dest; +#endif msg->body.destination.updated = 0; //msg->body.destination.updated) = now_s(); } static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* msg) { +#ifdef ALIGN_CM0 return *((__packed am_addr_t*)msg->body.source.local.data); +#else + return *((am_addr_t*)msg->body.source.local.data); +#endif } static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { memset(&(msg->body.source.local), 0, sizeof(msg->body.source.local)); +#ifdef ALIGN_CM0 *((__packed am_addr_t*)msg->body.source.local.data) = source; +#else + *((am_addr_t*)msg->body.source.local.data) = source; +#endif msg->body.source.updated = 0; //msg->body.source.updated = now_s(); } From 313b295d53600cbbcabc79823b6ff26c97307afa Mon Sep 17 00:00:00 2001 From: Raido Date: Wed, 17 Nov 2021 00:12:33 +0200 Subject: [PATCH 68/80] Fix a debug string. --- bridge/mist_comm_bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index 2a02534..335a043 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -41,7 +41,7 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, const osThreadAttr_t bridge_thread_2_attr = { .name = "bt2" }; bridge->t2.thread = osThreadNew(bridge_thread, &(bridge->t2), &bridge_thread_2_attr); - debug1("bt1 %p", bridge->t2.thread); + debug1("bt2 %p", bridge->t2.thread); bridge->t1.layer = a; bridge->t2.layer = b; From 2573f4fba16e23c05e507421df951f34996dcf51 Mon Sep 17 00:00:00 2001 From: Raido Date: Wed, 17 Nov 2021 21:13:49 +0200 Subject: [PATCH 69/80] (void) not () --- include/mist_comm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mist_comm.h b/include/mist_comm.h index 1722d33..b9904f5 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -355,7 +355,7 @@ bool comms_sleep_blocked(comms_sleep_controller_t * ctrl); * Create a mutex. * @return NULL for failure. */ -commsMutexId_t comms_mutex_create(); +commsMutexId_t comms_mutex_create(void); /** * Acquire the specified mutex. Blocks until aquired. From 8463c64b5e113d29b7f74c6a853ef5ff37313b24 Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 22 Nov 2021 13:54:44 +0200 Subject: [PATCH 70/80] Added message pool component. --- cmsis/mist_comm_pool.c | 45 +++++++++++++++++++++++++++++++++++ cmsis/mist_comm_pool_struct.h | 16 +++++++++++++ include/mist_comm_pool.h | 42 ++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 cmsis/mist_comm_pool.c create mode 100644 cmsis/mist_comm_pool_struct.h create mode 100644 include/mist_comm_pool.h diff --git a/cmsis/mist_comm_pool.c b/cmsis/mist_comm_pool.c new file mode 100644 index 0000000..919e781 --- /dev/null +++ b/cmsis/mist_comm_pool.c @@ -0,0 +1,45 @@ +/** + * Message pool for MistComm messages. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#include "mist_comm_pool.h" + + +comms_error_t comms_pool_init (comms_pool_t * p_pool, int num_messages) +{ + p_pool->pool = osMemoryPoolNew(num_messages, sizeof(comms_msg_t), NULL); + if (NULL == p_pool->pool) + { + return COMMS_ENOMEM; + } + return COMMS_SUCCESS; +} + + +comms_msg_t * comms_pool_get (comms_pool_t * p_pool, uint32_t timeout_ms) +{ + if (UINT32_MAX == timeout_ms) + { + return osMemoryPoolAlloc(p_pool->pool, osWaitForever); + } + else if (0 == timeout_ms) + { + return osMemoryPoolAlloc(p_pool->pool, 0); + } + else + { + return osMemoryPoolAlloc(p_pool->pool, timeout_ms * 1000 / osKernelGetTickFreq()); + } +} + + +comms_error_t comms_pool_put (comms_pool_t * p_pool, comms_msg_t * p_msg) +{ + if (osOK == osMemoryPoolFree(p_pool->pool, p_msg)) + { + return COMMS_SUCCESS; + } + return COMMS_FAIL; +} diff --git a/cmsis/mist_comm_pool_struct.h b/cmsis/mist_comm_pool_struct.h new file mode 100644 index 0000000..65c0ca8 --- /dev/null +++ b/cmsis/mist_comm_pool_struct.h @@ -0,0 +1,16 @@ +/** + * Message pool for MistComm messages on CMSIS OS2. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#ifndef MIST_COMM_POOL_STRUCT_H +#define MIST_COMM_POOL_STRUCT_H + +#include "cmsis_os2.h" + +typedef struct comms_pool { + osMemoryPoolId_t pool; +} comms_pool_t; + +#endif//MIST_COMM_POOL_STRUCT_H diff --git a/include/mist_comm_pool.h b/include/mist_comm_pool.h new file mode 100644 index 0000000..0b48e7b --- /dev/null +++ b/include/mist_comm_pool.h @@ -0,0 +1,42 @@ +/** + * Message pool for MistComm messages. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#ifndef MIST_COMM_POOL_H +#define MIST_COMM_POOL_H + +#include "mist_comm.h" + +#include "mist_comm_pool_struct.h" // Include a platform-specific structure for the pool definition + +/** + * Initialize a message pool. + * This will usually allocate a pool using the underlying OS heap. + * + * @param pool Pointer to a message pool that is to be initialized. + * @param num_messages Number of messages to be allocated. + * @return COMMS_SUCCESS or an error in case of failure. + */ +comms_error_t comms_pool_init (comms_pool_t * pool, int num_messages); + +/** + * Get a message from the pool. + * + * @param pool Pointer to a message pool. + * @param timeout_ms How long to wait for a message to become available, UINT32_MAX to wait forever. + * @return message pointer or NULL when a message was not available within the allowed timeout. + */ +comms_msg_t * comms_pool_get (comms_pool_t * pool, uint32_t timeout_ms); + +/** + * Return a message to the pool. + * + * @param pool Pointer to a message pool. + * @param p_msg Pointer to a message to be returned. + * @return COMMS_SUCCESS or an error, if the pool is full. + */ +comms_error_t comms_pool_put (comms_pool_t * pool, comms_msg_t * p_msg); + +#endif//MIST_COMM_POOL_H From 6601a2fc5e97c95bb33d276048bf5cdd75f40e77 Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 22 Nov 2021 23:55:52 +0200 Subject: [PATCH 71/80] Add packet groups and max lengths. --- am/mist_comm_am.c | 23 ++++++++++++++++++----- api/mist_comm_api.c | 14 ++++++++++++++ include/mist_comm.h | 5 +++++ include/mist_comm_am.h | 4 +++- include/mist_comm_iface.h | 8 ++++++++ include/mist_comm_private.h | 4 +++- serial/serial_activemessage.c | 35 ++++++++++++++++++++++++++--------- serial/serial_activemessage.h | 3 ++- serial/serial_basicmessage.c | 17 +++++++++++++---- 9 files changed, 92 insertions(+), 21 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 2b5ca7a..06abad3 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -97,14 +97,22 @@ static comms_error_t am_comms_send(comms_layer_iface_t* iface, comms_msg_t* msg, } static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { - return msg->body.type; + return 0xFF & msg->body.type; } static void am_comms_set_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg, am_id_t ptype) { - msg->body.type = ptype; + msg->body.type = 0x3F00 + ptype; } -static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* comms) { - return 114; +static uint16_t am_comms_get_packet_group(comms_layer_iface_t* comms, const comms_msg_t* msg) { + return msg->body.group; +} +static void am_comms_set_packet_group(comms_layer_iface_t* comms, comms_msg_t* msg, uint16_t group) { + msg->body.group = group; +} + +static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* iface) { + comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; + return amcomms->link_plenf(iface); } static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, const comms_msg_t* msg) { return msg->body.length; @@ -265,7 +273,8 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc } comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, - comms_send_f* sendf, comms_start_f* startf, comms_stop_f* stopf) { + comms_send_f* sendf, comms_plen_f* plenf, + comms_start_f* startf, comms_stop_f* stopf) { comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; @@ -291,6 +300,10 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms->get_packet_type = &am_comms_get_packet_type; comms->set_packet_type = &am_comms_set_packet_type; + comms->get_packet_group = &am_comms_get_packet_group; + comms->set_packet_group = &am_comms_set_packet_group; + + amcomms->link_plenf = plenf; comms->get_payload_max_length = &am_comms_get_payload_max_length; comms->get_payload_length = &am_comms_get_payload_length; comms->set_payload_length = &am_comms_set_payload_length; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 14f332e..0894438 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -177,6 +177,20 @@ void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype } } +uint16_t comms_get_packet_group(comms_layer_t* comms, const comms_msg_t* msg) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + return cl->get_packet_group(cl, msg); + } + return 0; +} +void comms_set_packet_group(comms_layer_t* comms, comms_msg_t* msg, uint16_t group) { + if((msg != NULL)&&(comms != NULL)) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + cl->set_packet_group(cl, msg, group); + } +} + uint8_t comms_get_payload_max_length(comms_layer_t* comms) { return ((comms_layer_iface_t*)comms)->get_payload_max_length((comms_layer_iface_t*)comms); } diff --git a/include/mist_comm.h b/include/mist_comm.h index b9904f5..5adbab4 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -200,6 +200,11 @@ am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg); void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype); // ----------------------------------------------------------------------------- +// Packet group (PAN ID, AM group, etc) ---------------------------------------- +uint16_t comms_get_packet_group(comms_layer_t* comms, const comms_msg_t* msg); +void comms_set_packet_group(comms_layer_t* comms, comms_msg_t* msg, uint16_t group); +// ----------------------------------------------------------------------------- + // Addressing ------------------------------------------------------------------ void comms_get_destination(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* destination); void comms_set_destination(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* destination); diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index 1ec01cc..a0d75ba 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -28,6 +28,7 @@ struct comms_layer_am { comms_am_addr_f* am_address; comms_send_f* link_sendf; + comms_plen_f* link_plenf; am_addr_t am_addr; @@ -49,7 +50,8 @@ void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t sourc // ----------------------------------------------------------------------------- // Create an ActiveMessage comms layer ----------------------------------------- -comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_send_f* sender, +comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, + comms_send_f* sendf, comms_plen_f* plenf, comms_start_f* startf, comms_stop_f* stopf); // ----------------------------------------------------------------------------- diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index 8317a02..d12f3b3 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -14,6 +14,8 @@ typedef void comms_init_message_f(comms_layer_iface_t*, comms_msg_t*); typedef comms_error_t comms_send_f(comms_layer_iface_t*, comms_msg_t*, comms_send_done_f*, void*); typedef bool comms_deliver_f(comms_layer_iface_t*, comms_msg_t*); +typedef uint8_t comms_plen_f(comms_layer_iface_t*); + typedef comms_error_t comms_register_recv_f(comms_layer_iface_t*, comms_receiver_t*, comms_receive_f*, void*, am_id_t, bool); typedef comms_error_t comms_deregister_recv_f(comms_layer_iface_t*, comms_receiver_t*); @@ -23,6 +25,9 @@ typedef comms_error_t comms_deregister_snooper_f(comms_layer_iface_t*, comms_rec typedef am_id_t comms_get_packet_type_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_packet_type_f(comms_layer_iface_t*, comms_msg_t*, am_id_t); +typedef uint16_t comms_get_packet_group_f(comms_layer_iface_t*, const comms_msg_t*); +typedef void comms_set_packet_group_f(comms_layer_iface_t*, comms_msg_t*, uint16_t); + typedef uint8_t comms_get_payload_max_length_f(comms_layer_iface_t*); typedef uint8_t comms_get_payload_length_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_payload_length_f(comms_layer_iface_t*, comms_msg_t*, uint8_t); @@ -83,6 +88,9 @@ struct comms_layer_iface { comms_get_packet_type_f* get_packet_type; comms_set_packet_type_f* set_packet_type; + comms_get_packet_group_f* get_packet_group; + comms_set_packet_group_f* set_packet_group; + comms_get_payload_max_length_f* get_payload_max_length; comms_get_payload_length_f* get_payload_length; comms_set_payload_length_f* set_payload_length; diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 147ecad..6f5d3a1 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -6,7 +6,9 @@ // Message structure ----------------------------------------------------------- struct comms_msg { struct { - am_id_t type; // AMID, port? + uint16_t type; // 0x3F00 + AMID + + uint16_t group; // PAN_ID - 0x0000 + AM Group comms_address_t source; comms_address_t destination; diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index 3e86ca2..1884514 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -39,6 +39,8 @@ typedef struct tos_serial_message static comms_error_t serial_activemessage_send (comms_layer_iface_t * iface, comms_msg_t * msg, comms_send_done_f * send_done, void * user); +static uint8_t serial_activemessage_max_length (comms_layer_iface_t * iface); + static bool serial_am_receive(uint8_t dspch, const uint8_t data[], uint8_t length, void* user); static void serial_am_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_am_timer_cb(void * argument); @@ -48,7 +50,7 @@ comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_pr sam->mutex = osMutexNew(NULL); sam->timer = osTimerNew(&serial_am_timer_cb, osTimerOnce, sam, NULL); - sam->group_id = pan_id; + sam->pan_id = pan_id; // Initialize send queueing system sam->send_busy = false; @@ -65,13 +67,15 @@ comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_pr // Set up dispatcher sam->protocol = spr; serial_protocol_add_dispatcher(sam->protocol, 0x00, - &(sam->dispatcher), - &serial_am_receive, &serial_am_senddone, - sam); + &(sam->dispatcher), + &serial_am_receive, &serial_am_senddone, + sam); // Set up the mist-comm layer // TODO start-stop handlers - comms_am_create((comms_layer_t *)sam, address, &serial_activemessage_send, NULL, NULL); + comms_am_create((comms_layer_t *)sam, address, + &serial_activemessage_send, &serial_activemessage_max_length, + NULL, NULL); // serial_activemessage_t is a valid comms_layer_t return (comms_layer_t *)sam; @@ -130,6 +134,8 @@ static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t le } comms_set_packet_type(lyr, &msg, m->amid); + // SAM group is 8-bits, PAN is 16. Add higher bits according to configured PAN + comms_set_packet_group(lyr, &msg, m->group | (sam->pan_id & 0xFF00)); comms_set_payload_length(lyr, &msg, m->payload_length); memcpy(payload, (const void *)m->payload, m->payload_length); @@ -138,12 +144,12 @@ static bool serial_am_receive(uint8_t dispatch, const uint8_t data[], uint8_t le comms_am_set_destination(lyr, &msg, ntoh16(m->destination)); comms_am_set_source(lyr, &msg, ntoh16(m->source)); - debugb1("rx {%02X}%04"PRIX16"->%04"PRIX16"[%02X]", + debugb1("rx {%02"PRIX16"}%04"PRIX16"->%04"PRIX16"[%02X]", payload, comms_get_payload_length(lyr, &msg), - (int)m->group, + comms_get_packet_group(lyr, &msg), comms_am_get_source(lyr, &msg), comms_am_get_destination(lyr, &msg), - comms_get_packet_type(lyr, &msg)); + (unsigned int)comms_get_packet_type(lyr, &msg)); comms_deliver(lyr, &msg); @@ -172,6 +178,12 @@ static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_ { tos_serial_message_t* m = (tos_serial_message_t*)buffer; uint16_t src = comms_am_get_source(lyr, msg); + uint16_t group = comms_get_packet_group(lyr, msg); + + if (0 == group) + { + group = sam->pan_id; + } if (0 == src) { @@ -180,7 +192,7 @@ static uint16_t prepare_sp_message(uint8_t buffer[], uint16_t length, comms_msg_ m->destination = hton16(comms_am_get_destination(lyr, msg)); m->source = hton16(src); - m->group = sam->group_id; // TODO variable + m->group = 0xFF & group; // Group/PAN is 16-bits, however, the TinyOS SAM protocol only supports 8-bits. m->amid = comms_get_packet_type(lyr, msg); m->payload_length = plen; memcpy(m->payload, payload, plen); @@ -329,3 +341,8 @@ static comms_error_t serial_activemessage_send (comms_layer_iface_t * iface, return result; } + +static uint8_t serial_activemessage_max_length (comms_layer_iface_t * iface) +{ + return COMMS_MSG_PAYLOAD_SIZE; +} diff --git a/serial/serial_activemessage.h b/serial/serial_activemessage.h index bc2c299..fbb4002 100644 --- a/serial/serial_activemessage.h +++ b/serial/serial_activemessage.h @@ -80,7 +80,8 @@ struct serial_activemessage sam_queue_element_t queue_memory[SERIAL_ACTIVEMESSAGE_QUEUE_LENGTH]; am_addr_t am_addr; - am_group_t group_id; + + uint16_t pan_id; // only 8-bits currently get sent on the wire! bool send_busy; uint8_t send_buffer[SERIAL_ACTIVEMESSAGE_MAX_MESSAGE_LENGTH]; diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index aa81996..07c2eed 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -24,6 +24,8 @@ static comms_error_t serial_basicmessage_send (comms_layer_iface_t * iface, comms_msg_t * msg, comms_send_done_f * send_done, void * user); +static uint8_t serial_basicmessage_max_length (comms_layer_iface_t * iface); + static bool serial_bm_receive(uint8_t dspch, const uint8_t data[], uint8_t length, void* user); static void serial_bm_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_bm_timer_cb(void * argument); @@ -50,13 +52,15 @@ comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_pro // Set up dispatcher sbm->protocol = spr; serial_protocol_add_dispatcher(sbm->protocol, dispatch, - &(sbm->dispatcher), - &serial_bm_receive, &serial_bm_senddone, - sbm); + &(sbm->dispatcher), + &serial_bm_receive, &serial_bm_senddone, + sbm); // Set up the mist-comm layer // TODO start-stop handlers - comms_am_create((comms_layer_t *)sbm, 0, &serial_basicmessage_send, NULL, NULL); + comms_am_create((comms_layer_t *)sbm, 0, + &serial_basicmessage_send, &serial_basicmessage_max_length, + NULL, NULL); // serial_basicmessage_t is a semi-valid comms_layer_t return (comms_layer_t *)sbm; @@ -249,3 +253,8 @@ static comms_error_t serial_basicmessage_send (comms_layer_iface_t * iface, return result; } + +static uint8_t serial_basicmessage_max_length (comms_layer_iface_t * iface) +{ + return COMMS_MSG_PAYLOAD_SIZE; +} From 5be1af0a6279cb2ab551bd1cfe6355779084bc8e Mon Sep 17 00:00:00 2001 From: Raido Date: Thu, 25 Nov 2021 13:22:18 +0200 Subject: [PATCH 72/80] Some additional documentation. --- am/mist_comm_am.c | 2 + include/mist_comm.h | 239 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 189 insertions(+), 52 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 06abad3..55141d0 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -26,6 +26,8 @@ static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) comms_am_msg_metadata_t* metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); memset(&(msg->body.destination), 0, sizeof(msg->body.destination)); memset(&(msg->body.source), 0, sizeof(msg->body.source)); + msg->body.type = 0; + msg->body.group = 0; msg->body.length = 0; metadata->timestamp_valid = false; metadata->event_time_valid = false; diff --git a/include/mist_comm.h b/include/mist_comm.h index 5adbab4..d19bab6 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -1,6 +1,11 @@ -#ifndef MIST_COMM_H_ -#define MIST_COMM_H_ -// Mist Communication API ------------------------------------------------------ +/** + * Mist communications API. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#ifndef MIST_COMM_H +#define MIST_COMM_H #include #include @@ -13,6 +18,17 @@ #include "platform_msg.h" +#define MIST_COMM_VERSION_MAJOR 0 +#define MIST_COMM_VERSION_MINOR 0 +#define MIST_COMM_VERSION_PATCH 0 + +/** + * Communication layer result values. Generally derived from TinyOS error_t, + * however, all bad things have a negative value and there is a positive + * ALREADY. + * + * FIXME: Can we retire COMMS_EALREADY? + */ typedef enum CommsErrors { COMMS_UNINITIALIZED = -127, COMMS_NOT_SUPPORTED = -126, @@ -24,7 +40,7 @@ typedef enum CommsErrors { COMMS_ETIMEOUT = -12, COMMS_ENOACK = -11, COMMS_ENOMEM = -10, - COMMS_EALREADY = -9, // Would prefer to use positive COMMS_ALREADY instead + COMMS_EALREADY = -9, // Use positive COMMS_ALREADY instead! COMMS_ERESERVE = -8, COMMS_ERETRY = -7, COMMS_EINVAL = -6, @@ -38,6 +54,9 @@ typedef enum CommsErrors { COMMS_ALREADY = 1 } comms_error_t; +/** + * Communication layer status values (states). + */ typedef enum CommsStatus { COMMS_STOPPING = -2, COMMS_STARTING = -1, @@ -45,6 +64,10 @@ typedef enum CommsStatus { COMMS_STARTED = 1 } comms_status_t; +/** + * Base structure for communications layers. Every interface has a type + * and an EUI-64 address. + */ typedef struct comms_layer { uint8_t type; // TODO type definitions for reflection ieee_eui64_t eui; @@ -53,14 +76,16 @@ typedef struct comms_layer { /** * The comms local address structure. This carries a link-local address which - * may take different forms. + * may take different forms, depending on the environment. */ typedef struct comms_local_addr { uint8_t data[COMMS_MSG_ADDRESSING_SIZE]; } __attribute__((packed))comms_local_addr_t; /** - * The comms address structure. + * The comms address structure, carries mappings from globally unique EUI64 + * addresses to link-local platform/environment specific addresses. + * It should be assumed that the local address may change at runtime! */ typedef struct comms_address { ieee_eui64_t eui; @@ -68,7 +93,7 @@ typedef struct comms_address { uint32_t updated; // Timestamp, seconds } __attribute__((packed))comms_address_t; -/* +/** * The comms message structure. Should only be manipulated through the APIs. */ typedef struct comms_msg comms_msg_t; @@ -86,7 +111,7 @@ typedef struct comms_msg comms_msg_t; * @param result The result of the transmission. * @param user The user pointer provided to comms_send. */ -typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_error_t result, void* user); +typedef void comms_send_done_f (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); /** * Signalled when a message is received. Functions of this type must first be @@ -96,7 +121,7 @@ typedef void comms_send_done_f(comms_layer_t* comms, comms_msg_t* msg, comms_err * @param msg The message, only valid while this call is running. * @param user The user pointer given to comms_register_recv. */ -typedef void comms_receive_f(comms_layer_t* comms, const comms_msg_t* msg, void* user); +typedef void comms_receive_f (comms_layer_t * comms, const comms_msg_t * msg, void * user); /** * Signalled when a status change is requested and completed. @@ -105,7 +130,7 @@ typedef void comms_receive_f(comms_layer_t* comms, const comms_msg_t* msg, void* * @param status The new status (may not be what was actually requested). * @param user The user pointer. */ -typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, void* user); +typedef void comms_status_change_f (comms_layer_t * comms, comms_status_t status, void * user); // ----------------------------------------------------------------------------- @@ -116,7 +141,7 @@ typedef void comms_status_change_f(comms_layer_t* comms, comms_status_t status, * @param user Argument passed to the callback. * @return COMMS_SUCCESS if the callback will be called in the future. */ -comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user); +comms_error_t comms_start (comms_layer_t * comms, comms_status_change_f * start_done, void * user); /** * Stop a comms layer. Use this or sleep controllers, not both. @@ -125,83 +150,193 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don * @param user Argument passed to the callback. * @return COMMS_SUCCESS if the callback will be called in the future. */ -comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user); +comms_error_t comms_stop (comms_layer_t * comms, comms_status_change_f * stop_done, void * user); /** * Get current status of the comms layer. + * @param comms The comms layer to query. * @return Current status. */ -comms_status_t comms_status(comms_layer_t* comms); +comms_status_t comms_status (comms_layer_t * comms); // ----------------------------------------------------------------------------- -// Initialize a message structure for use on the specified communications -// layer. Must be called before any packet functions can be used. -void comms_init_message(comms_layer_t* comms, comms_msg_t* msg); +/** + * Initialize a message structure for use on the specified communications + * layer. Must be called before any packet functions can be used. A message + * initialized with one comms layer must not be used with another layer, unless + * initialized again with that layer! + * + * @param comms The comms layer to use for initilization. + * @param msg The message to initialize. + */ +void comms_init_message (comms_layer_t * comms, comms_msg_t * msg); -// Send a message through the specified communications layer. -// The callback function specified with the send done function argument sdf will -// be called some time in the future if comms_send returns SUCCESS. The sdf -// argument is mandatory, the user argument may be NULL. -comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user); +/** + * Send a message through the specified communications layer. + * + * The message must stay allocated and not be modified while the layer is + * processing it (until send-done is called). + * + * @param comms The comms layer to use for sending the message. + * @param msg The message to send. + * @param sdf Pointer to a send-done function. + * @param user Optional user pointer, returned in send-done. + * @return COMMS_SUCCESS, if the send-done function will be called some time in the future. + */ +comms_error_t comms_send (comms_layer_t * comms, comms_msg_t * msg, comms_send_done_f * sdf, void * user); // Receiver registration ------------------------------------------ +/** + * Receiver structure for registering a receive callback. + * Must not go out of scope before it is deregistered! + */ typedef struct comms_receiver comms_receiver_t; /** - * Register to receive messages. + * Register to receive messages of a specific type. * * Must pass an unused comms_receiver_t object, guaranteeing that the * memory remains allocated and is not used elsewhere until deregister is called. - * One receiver object may not be used in multiple roles at the same time, but - * the same receive function can be registered several times with different - * conditions and/or with a different user argument. + * + * One receiver object may not be used in multiple roles at the same time + * + * The same receive function may be registered several times with different + * conditions and/or with a different user pointer. + * + * Multiple receivers may be registered for the same packet type, the message will + * be delivered to all receivers. + * + * @param comms Pointer to a comms layer. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. + * @param amid The message type to register the receiver for. */ -comms_error_t comms_register_recv(comms_layer_t* comms, - comms_receiver_t* rcvr, - comms_receive_f* func, void *user, - am_id_t amid); +comms_error_t comms_register_recv (comms_layer_t * comms, + comms_receiver_t * rcvr, + comms_receive_f * func, void * user, + am_id_t amid); /** - * Register to receive messages, require the EUI64 addresses to be resolved. + * Register to receive messages, requesting the EUI64 addresses to be resolved. + * + * Receive callbacks will still be called, even if the EUI64 of the sender is not + * known, but the comms layer will attempt to resolve the address for subsequent + * messages. * * Must pass an unused comms_receiver_t object, guaranteeing that the * memory remains allocated and is not used elsewhere until deregister is called. - * One receiver object may not be used in multiple roles at the same time, but - * the same receive function can be registered several times with different - * conditions and/or with a different user argument. + * + * One receiver object may not be used in multiple roles at the same time + * + * The same receive function may be registered several times with different + * conditions and/or with a different user pointer. + * + * Multiple receivers may be registered for the same packet type, the message will + * be delivered to all receivers. + * + * @param comms Pointer to a comms layer. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. + * @param amid The message type to register the receiver for. + * @return COMMS_SUCCESS if successfully registered. */ -comms_error_t comms_register_recv_eui(comms_layer_t* comms, - comms_receiver_t* rcvr, - comms_receive_f* func, void *user, - am_id_t amid); - +comms_error_t comms_register_recv_eui (comms_layer_t * comms, + comms_receiver_t * rcvr, + comms_receive_f * func, void * user, + am_id_t amid); -// ??? Open questions regarding receivers and their registration: -// AMID param should be some form of generic args, but this is C ... are we ok -// to only have the 8-bit AM ID or should we expand and rename? 16 bit port? -// Are any other filtering options needed for receiveres? -// ??? - -// Remove an already registered receiver. -comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr); +/** + * Remove an already registered receiver. + * + * @param comms Pointer to a comms layer. + * @param rcvr Receiver structure to deregister. + * @return COMMS_SUCCESS if receiver has been removed and can be recycled. + */ +comms_error_t comms_deregister_recv (comms_layer_t * comms, comms_receiver_t * rcvr); // Snoopers don't look at the type (amid) -comms_error_t comms_register_snooper(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void *user); -// Remove an already registered snooper. -comms_error_t comms_deregister_snooper(comms_layer_t* comms, comms_receiver_t* rcvr); +/** + * Register to snoop for messages: + * All messages, regardless of AMID. + * All destinations, if underlying device is in promiscuous mode. + * + * Must pass an unused comms_receiver_t object, guaranteeing that the + * memory remains allocated and is not used elsewhere until deregister is called. + * + * One receiver object may not be used in multiple roles at the same time + * + * The same receive function may be registered several times with different + * conditions and/or with a different user pointer. + * + * Multiple receivers may be registered for the same packet type, the message will + * be delivered to all receivers. + * + * @param comms Pointer to a comms layer. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. + */ +comms_error_t comms_register_snooper (comms_layer_t * comms, + comms_receiver_t * rcvr, + comms_receive_f * func, void * user); + +/** + * Remove an already registered snooper. + * + * @param comms Pointer to a comms layer. + * @param rcvr Receiver structure to deregister. + * @return COMMS_SUCCESS if receiver has been removed and can be recycled. + */ +comms_error_t comms_deregister_snooper (comms_layer_t * comms, comms_receiver_t * rcvr); // ----------------------------------------------------------------------------- // Packet type ----------------------------------------------------------------- -am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg); -void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype); +// TODO explain the AM ID logic + +/** + * Get the packet type (AM ID - Active Message ID) of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Packet type (AM ID). + **/ +am_id_t comms_get_packet_type (comms_layer_t * comms, const comms_msg_t * msg); + +/** + * Set the packet type (AM ID - Active Message ID) of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param ptype The type. + **/ +void comms_set_packet_type (comms_layer_t * comms, comms_msg_t * msg, am_id_t ptype); // ----------------------------------------------------------------------------- // Packet group (PAN ID, AM group, etc) ---------------------------------------- +// TODO explain the AM group/PAN-ID logic + +/** + * Get the packet group (AM group / PAN ID) of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Packet group (PAN ID). + **/ uint16_t comms_get_packet_group(comms_layer_t* comms, const comms_msg_t* msg); + +/** + * Set the packet group (AM group / PAN ID) of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param group Packet group (PAN ID). + **/ void comms_set_packet_group(comms_layer_t* comms, comms_msg_t* msg, uint16_t group); // ----------------------------------------------------------------------------- @@ -379,4 +514,4 @@ void comms_mutex_release(commsMutexId_t mutex); // ----------------------------------------------------------------------------- #include "mist_comm_private.h" -#endif//MIST_COMM_H_ +#endif//MIST_COMM_H From d29c36e257f42f8a2258765d98796b2c34582951 Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 29 Nov 2021 23:38:59 +0200 Subject: [PATCH 73/80] Add/fix some mocks. --- mock/mist_comm_mutex.c | 12 ++++++------ mock/mist_comm_pool.c | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 mock/mist_comm_pool.c diff --git a/mock/mist_comm_mutex.c b/mock/mist_comm_mutex.c index 6e3119b..2693fe3 100644 --- a/mock/mist_comm_mutex.c +++ b/mock/mist_comm_mutex.c @@ -10,21 +10,21 @@ #include "mist_comm_private.h" static volatile bool m_mutexes[8]; -static int m_mutex_count = 0; +static intptr_t m_mutex_count = 0; void comms_mutex_acquire(commsMutexId_t mutex) { - while(m_mutexes[mutex]); - m_mutexes[mutex] = true; + while(m_mutexes[(intptr_t)mutex]); + m_mutexes[(intptr_t)mutex] = true; } void comms_mutex_release(commsMutexId_t mutex) { - m_mutexes[mutex] = false; + m_mutexes[(intptr_t)mutex] = false; } -commsMutexId_t comms_mutex_create() +commsMutexId_t comms_mutex_create(void) { m_mutexes[m_mutex_count] = false; - return m_mutex_count++; + return (commsMutexId_t)m_mutex_count++; } diff --git a/mock/mist_comm_pool.c b/mock/mist_comm_pool.c new file mode 100644 index 0000000..5d133c0 --- /dev/null +++ b/mock/mist_comm_pool.c @@ -0,0 +1,27 @@ +/** + * Mock message pool for MistComm messages. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#include "mist_comm_pool.h" + +#include + +comms_error_t comms_pool_init (comms_pool_t * p_pool, int num_messages) +{ + return COMMS_SUCCESS; +} + + +comms_msg_t * comms_pool_get (comms_pool_t * p_pool, uint32_t timeout_ms) +{ + return malloc(sizeof(comms_msg_t)); +} + + +comms_error_t comms_pool_put (comms_pool_t * p_pool, comms_msg_t * p_msg) +{ + free(p_msg); + return COMMS_SUCCESS; +} From 96c31c175f5e12f03c95f6c54b23df59c7d44b3f Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 29 Nov 2021 23:39:09 +0200 Subject: [PATCH 74/80] Fix snoopers being uninitialized! --- api/mist_comm_rcv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/api/mist_comm_rcv.c b/api/mist_comm_rcv.c index 9977610..2d43d00 100644 --- a/api/mist_comm_rcv.c +++ b/api/mist_comm_rcv.c @@ -130,6 +130,7 @@ comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg) { comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms) { comms_mutex_acquire(comms->receiver_mutex); comms->receivers = NULL; + comms->snoopers = NULL; comms->register_recv = &rcv_comms_register_recv; comms->deregister_recv = &rcv_comms_deregister_recv; comms->register_snooper = &rcv_comms_register_snooper; From 9c8ff1bb5247cb49e394ca153fe7c73cf0f4f97b Mon Sep 17 00:00:00 2001 From: Lembitu Valdmets Date: Fri, 3 Dec 2021 16:25:11 +0200 Subject: [PATCH 75/80] update radio mock --- mock/mist_mock_radio_cmsis.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mock/mist_mock_radio_cmsis.c b/mock/mist_mock_radio_cmsis.c index 3ba9d5c..1bc5257 100644 --- a/mock/mist_mock_radio_cmsis.c +++ b/mock/mist_mock_radio_cmsis.c @@ -11,6 +11,8 @@ #include "cmsis_os2.h" +#define RADIO_TOS_MAX_PAYLOAD_LENGTH 114 + static comms_layer_am_t m_radio_iface; static osThreadId_t m_thread; @@ -59,12 +61,16 @@ static void mock_radio_loop (void * arg) } } +static uint8_t radio_max_length (comms_layer_iface_t * iface) +{ + return RADIO_TOS_MAX_PAYLOAD_LENGTH; +} comms_layer_t * mist_mock_cmsis_radio_init (am_addr_t address, comms_send_f * send_copy) { mf_send_copy = send_copy; - comms_am_create((comms_layer_t *)&m_radio_iface, address, radio_send, NULL, NULL); + comms_am_create((comms_layer_t *)&m_radio_iface, address, radio_send, radio_max_length, NULL, NULL); m_mutex = osMutexNew(NULL); From 333f6ce621ed8c282298742c924b67af8e4c04c5 Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 13 Dec 2021 17:54:15 +0200 Subject: [PATCH 76/80] API changes and README. --- README.md | 367 ++++++++++++++++++- am/mist_comm_am.c | 4 +- api/mist_comm_api.c | 24 +- bridge/mist_comm_bridge.c | 1 - cmsis/mist_comm_mutex.h | 6 +- include/compat/mist_comm_basics.h | 6 +- include/mist_comm.h | 577 +++++++++++++++++++++++------- include/mist_comm_am.h | 12 +- include/mist_comm_am_msg.h | 6 +- include/mist_comm_bridge.h | 6 +- include/mist_comm_iface.h | 8 +- include/mist_comm_private.h | 74 +++- include/mist_comm_ref.h | 6 +- include/mist_comm_routing.h | 8 +- include/tos/mist_comm_basics.h | 6 +- mock/mist_comm_mutex.h | 7 +- mock/mist_mock_radio_cmsis.h | 6 +- serial/serial_activemessage.c | 12 +- serial/serial_basicmessage.c | 14 +- util/fragmenter_assembler.c | 2 +- util/fragmenter_assembler.h | 2 +- 21 files changed, 940 insertions(+), 214 deletions(-) diff --git a/README.md b/README.md index 0f6c3e4..3206723 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,370 @@ # mist-comm -Mist communications and security APIs. +Mist communications APIs, abstractions for various communication interfaces. # Features -* address mapping +The Mist Communication API abstracts the specifics of different communication +implementations from the higher layers. Applications can use +a consistent globally unique EUI-64 based addressing scheme and common functions +for sending and receiving messages, regardless of the underlying communication +technology. This makes it possible to replace the underlying communication +interface without making any changes to the application code. All API calls +are done through methods that include a pointer to the API layer and for basic +communication flows, it is usually not necessary to be aware of what the actual +underlying communications technology is. + + +# Included implementations + +The mist-comm library contains an adapter for adding the mist-comm API to +radio layers. This is used by the 802.15.4 implementations in +[node-platform](https://github.com/thinnect/node-platform) +and by the `serial_activemessage` and `serial_basicmessage` implementations +bundled with the library. + +The API has been intended to be platform independent, however, in practice +a CMSIS2 (cmsis_os2.h) environment is currently required for running the API in +most cases, since no other OS wrappers have been developed. It has, however, +also not been decided to exclusively rely on CMSIS2 and it should be possible to +set up a basic communications flow without an OS using for example +[radio_basic.c](https://github.com/thinnect/node-platform/blob/master/silabs/radio_basic.c). + + +# Addresses and identifiers + +## Addressing + +Messages are ideally addressed using the endpoint IEEE EUI-64 addresses, however, +the actual address structure is a composite of a global and a local address, +since the mist-comm API is mostly used on embedded devices and over communication +interfaces where it is necessary to map interface-specific addresses and global +identities. + +## Packet type - Active Message ID (AMID) + +The Mist AMID concept derives from the TinyOS Active Message ID, which is an +8-bit value. On the cloud side this has been extended to include the +TinyOS message identifier 0x3F as a prefix, with the goal of opening up the rest +of the 16-bit space in the future, as other protocols and tools are extended. +The mist-comm API currently uses the 8-bit value, a future version may move to +the full 16-bit identifier. + +## Packet group - Active Message Group / PAN ID + +The Mist Group ID concept derives from the TinyOS Active Message Group ID, +which itself relies on the 802.15.4 PAN ID, however, exposes only 8-bits of the +original 16-bit value. The mist-comm API uses the 16-bit value, however, the +high-byte currently needs to be 0, because the serial protocol only transfers +the lower 8 bits. + + +# Setting up a communications layer + +## Initialization + +Initializing a communications layer is usually a simple as calling the init or +setup function of a specific communications layer. A pointer to the layer is +returned or NULL if something went wrong. This is usually done once on startup, +allocates some resources and probably starts a background thread. Some layers +may allow de-initialization and re-initialization, but many implementations +lack support for this and subsequent calls to the setup function will fail. + +For example: +```C +comms_layer_t * p_radio = radio_setup(node_local_address, node_eui64); +if (NULL == radio) +{ + // panic +} + +// START the radio or apply a sleep-block +``` + +The communications layer may start automatically or may require `comms_start` +to be called or a sleep-block to be applied to actually start it. `comms_status` +can be used to check the status. + + +## Creation + +The mist-comm interface structure (`comms_layer_iface_t`) carries function +pointers for packet manipulation and messaging tasks. These functions are +accessed by the respective API functions. It is possible to create +a completely custom implementation, however, an adapter component exists for +common ActiveMessage layers (used by most 802.15.4 radio and UART implementations). + +`comms_am_create` initializes a layer structure with most necessary ActiveMessage +functions, only requiring the send and max packet length functions. Also +start and stop may be added, but are not needed for always-on implementations. + +Basic receiver management functionality can be added to a layer by calling +`comms_initialize_rcvr_management`, `comms_am_create` does this internally +already! + +When creating a new communications layer, it is a good idea to call `comms_verify_api` +first and check that it returns `true`. This will allow compile-time detection +of some incompatibilities, if static communications libraries are being linked +together. + + +# Sending a message + +Before using a `comms_msg_t` structure, it must be initialized for the layer +that it is going to be used with. This will clear all the contents and may +set some fields in the message necessary for the communications layer. Messages +may not be passed from one layer to another directly. + +```C +static comms_msg_t m_msg; +comms_init_message(p_radio, &m_msg); // A message must be initialized + +comms_address_t dest; // Send message to 1122334455667788 +memset(&dest, 0, sizeof(dest)); // Clear the structure +eui64_set(&dest.eui, "\x11\x22\x33\x44\x55\x66\x77\x88") + +comms_set_destination(p_radio, &m_msg, &dest); + +custom_packet_t * pcp = (custom_packet_t*)comms_get_payload(p_radio, &m_msg, sizeof(custom_packet_t)); +if (NULL != pcp) +{ + pcp->field1 = 1; + pcp->field2 = 2; + + comms_set_packet_type(p_radio, &m_msg, CUSTOM_PROTOCOL_AMID); + comms_set_payload_length(p_radio, &m_msg, sizeof(custom_packet_t)); + + comms_set_ack_required(p_radio, &m_msg, true); // Request an ack + + comms_error_t result = comms_send(radio, &m_msg, radio_send_done, NULL); + if (COMMS_SUCCESS == result) + { + sending = true; // wait for radio_send_done to be called + } +} +``` + +If `comms_send` returns COMMS_SUCCESS, the communications layer takes possession +of the message until it is returned with the send-done event. +*The message structure must not be modified by the user between send and send-done!* + +When sending a message, some fields, like the source address or group will default +to the values configured for the communications layer and do not normally need +setting. Some layers may not even support setting these fields to those of other +devices, but they do need to be set when for example bridging / routing messages. + +```C +static void radio_send_done (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user) +{ + // Result can be checked from result + if (COMMS_SUCCESS != result) + { + // Something went wrong + } + // User carries what-ever pointer was passed as the final argument to comms_send ... NULL in this example + if (comms_ack_received(comms, msg)) + { + // Ack was received + } + + // The message can now be freed, put back in a pool or re-used (but not directly from send-done) + + // Signal your thread perhaps or clear the sending flag, for example: + osThreadFlagsSet(my_thread_id, MY_THREAD_FLAG_MESSAGE_SENT); +} +``` + +The send-done event should be treated like an interrupt - don't do too much in there +as it is usually fired from the communication layer thread and holding it up may +cause subsequent packets to be dropped. + + +# Receiving a message + +Receiving a message requires registering a receiver and a receive function. +A regular receiver will pass a message to the receive function when the type (AM ID) +of the message matches and the message destination is either the address of the +node or the broadcast address. Alternatively a snooper can be registered with +`comms_register_snooper`, which will pass all messages to the receive callback +regardless of type or destination address. Multiple receivers or snoopers may be +registered and each will get a copy of the message, if it matches the parameters. +The same receive function may be used for multiple receivers, but a receiver +structure can obly be registered once, unless de-registered first! + +```C +static comms_layer_t * mp_comms; +static comms_receiver_t m_rcvr1; +static comms_receiver_t m_rcvr2; + +void setup_function (comms_layer_t * p_comms) +{ + mp_comms = p_comms; + comms_register_recv_eui(mp_comms, &m_rcvr1, receive_message, NULL, AMID_PROTOCOL_1); + comms_register_recv(mp_comms, &m_rcvr2, receive_message, NULL, AMID_PROTOCOL_2); +} + +// Same function given to both receivers +static void receive_message (comms_layer_t * p_comms, const comms_msg_t * p_msg, void * p_user) +{ + am_id_t ptype = comms_get_packet_type(p_comms, msg); + if (AMID_PROTOCOL_1 == ptype) + { + comms_address_t source; + comms_get_source(p_comms, p_msg, &source); + if (eui64_is_zeros(&source.eui)) + { + return; // Don't know source EUI64 + } + // packet processing here + } + else if (AMID_PROTOCOL_2 == ptype) + { + // packet processing where EUI64 of source is not important + } +} + +``` + + +# Addressing + +The message sending example above uses global EUI64 addressing when sending the +message. In this case, the sender is starting with a blank `comms_address_t` +structure and knows the EUI64 for the destination. Alternatively a sender may +use a `comms_address_t` saved from a received message, which would already +contain the local address (if one is used). Sending without a local address +(when one is needed) will trigger a lookup from the address mapping table. +If the address is not in the table, then a discovery packet will be sent, +however, sending of the initial message will fail with `COMMS_NO_ADDR`. + +The message reception example above for the first message type sets up a receiver +through the `comms_register_recv_eui` function, meaning it will automatically +try to determine the EUI64 for all incoming messages, however, messages will be +delivered to the receive function even if the EUI64 is not known. It is therefore +important to always check the source address, if the source of the message is +important. The example for the second message type uses `comms_register_recv`, +which means messages of that type will not trigger an EUI64 lookup. + +Address discovery and caching needs to be set up for each communications layer +that needs it. + +```C + static am_addrdisco_t disco; + static comms_addr_cache_t cache; + comms_am_addrdisco_init(p_radio, &disco, &cache); // example for mist_comm_am +``` + + +# Message pool + +An allocated `comms_msg_t` structure is necessary for sending a message. In many +cases components can declare the message statically, but for many other components, +that rarely need to send a message, declaring a static message may be wasteful +in terms of overall memory usage. A message pool component is available for +cases where it is desirable to share the message structures among several components. +The message pool needs to be initialized, it normally allocates the message memory +using underlying OS memory allocation methods. + +```C +static comms_pool_t m_msg_pool; + +void setup_function (void) +{ + if (COMMS_SUCCESS != comms_pool_init(&m_msg_pool, 3)) // allocate 3 messages + { + // panic + } + custom_component_init(mp_comms, &m_msg_pool); +} + +// custom_component.c --------------------------------------------------------- + +static comms_pool_t * mp_pool; +static comms_layer_t * mp_comms; + +static void send_done (comms_layer_t * comms, comms_msg_t * p_msg, comms_error_t result, void * user) +{ + // signal something + comms_pool_put(mp_pool, p_msg); // Message not sent, put it back to pool +} + +void custom_component_function (void) +{ + comms_msg_t * p_msg = comms_pool_get(mp_pool, 0); // no wait + if (NULL != p_msg) + { + // format message, add payload ... + + comms_error_t result = comms_send(mp_comms, p_msg, send_done, NULL); + if (COMMS_SUCCESS != result) + { + comms_pool_put(mp_pool, p_msg); // Message not sent, put it back to pool! + } + } +} +``` + + +# Communications layer sleep management + +A communications layer may be always on (started after init) or switched either +by calling `comms_start` and `comms_stop` or through sleep controllers. +Sleep controllers control the layer using the start and stop functions so they +do not work together with direct external control. Therefore, it is recommended +to use sleep controllers if the communications layer needs to be switched +on from more than one place - for example to keep an exteremely low duty-cycle +device out of sleep for a slightly longer session. + +Sleep controllers need to be registered with a communications layer first and +then a sleep block may be applied. Starting a communications layer is not +instantaneous, so a callback is fired, if it was not running and will be started. +Allowing sleep, however, does not mean that the communications layer will +actually stop, since another component may be holding a block as well. + +```C +static comms_sleep_controller_t m_sleep_ctrl; + +// Add a sleep cotnroller +comms_register_sleep_controller(p_comms, &m_sleep_ctrl, radio_start_done, NULL); + +// Wake up a communications layer + comms_error_t rslt = comms_sleep_block(&m_sleep_ctrl); + if (rslt == COMMS_SUCCESS) + { + // radio_start_done will be called when actually started + } + else if (rslt == COMMS_ALREADY) + { + // it is already started, no callback will fire + } + +// Allow communications layer to sleep again + comms_sleep_allow(&m_sleep_ctrl); +``` + + +# Timestamps + +Received messages are timestamped as they arrive, transmitted messages are +timestamped when sent out and the timestamp can be inspected in the send-done +event. A combination of send and receive timestamping features can be used +to communicate an event timestamp (something in the past or the future) between +two devices that do not share a synchronized clock. Timestamps are relative +to the counter available from `comms_get_time_micro` and are always +represented in microseconds, though the underlying physical clock may have a +different granularity. + +**Timestamping features depend on the capabilities of the underlying +implementation and may not be supported for all communications layers!** + +## Message timestamps + +Message timestamps can be read with the combination of `comms_timestamp_valid` +and `comms_get_timestamp_micro`. It is up to the user to know if the message +was received or sent, to know if they are getting an RX or TX timestamp. + +## Event timestamps + +Event timestamps are set with the `comms_set_event_time_micro` function and +on reception, can be checked with `comms_event_time_valid` and `comms_get_event_time_micro`. +Event times must be within +- 30 minutes of the current moment. diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 55141d0..327d2f3 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -163,8 +163,8 @@ static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* msg) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } -static void am_comms_set_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg) { - ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received = true; +static void am_comms_set_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg, bool acked) { + ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received = acked; } static comms_error_t am_comms_set_timestamp(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timestamp) { diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 0894438..6a4b7e2 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -1,3 +1,10 @@ +/** + * Mist communications API. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ + #include "mist_comm.h" #include "mist_comm_iface.h" @@ -282,21 +289,21 @@ bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg) { } return false; } -void _comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg) { +void comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg, bool received) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - cl->set_ack_received(cl, msg); + cl->set_ack_received(cl, msg, received); } } -comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { +comms_error_t comms_set_timestamp_micro(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->set_timestamp(cl, msg, timestamp); } return COMMS_EINVAL; } -uint32_t comms_get_timestamp(comms_layer_t* comms, const comms_msg_t* msg) { +uint32_t comms_get_timestamp_micro(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_timestamp(cl, msg); @@ -311,20 +318,21 @@ bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg) { return false; } -comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt) { +comms_error_t comms_set_event_time_micro(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->set_event_time(cl, msg, evt); } return COMMS_EINVAL; } -uint32_t comms_get_event_time(comms_layer_t* comms, const comms_msg_t* msg) { +uint32_t comms_get_event_time_micro(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; return cl->get_event_time(cl, msg); } return 0; } + bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; @@ -340,7 +348,7 @@ uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg) { } return 0; } -void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi) { +void comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; cl->set_lqi(cl, msg, lqi); @@ -354,7 +362,7 @@ int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg) { } return -128; } -void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { +void comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; cl->set_rssi(cl, msg, rssi); diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index 335a043..c220ce8 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -4,7 +4,6 @@ * * Copyright Thinnect Inc. 2019 * @license MIT - * @author Raido Pahtma */ #include diff --git a/cmsis/mist_comm_mutex.h b/cmsis/mist_comm_mutex.h index 6b330ac..25ea493 100644 --- a/cmsis/mist_comm_mutex.h +++ b/cmsis/mist_comm_mutex.h @@ -5,11 +5,11 @@ * @license MIT * @author Raido Pahtma */ -#ifndef MIST_COMM_MUTEX_H_ -#define MIST_COMM_MUTEX_H_ +#ifndef MIST_COMM_MUTEX_H +#define MIST_COMM_MUTEX_H #include "cmsis_os2.h" typedef osMutexId_t commsMutexId_t; -#endif//MIST_COMM_MUTEX_H_ +#endif//MIST_COMM_MUTEX_H diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 02c1b96..74b802f 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -1,5 +1,5 @@ -#ifndef MIST_COMM_BASICS -#define MIST_COMM_BASICS +#ifndef MIST_COMM_BASICS_H +#define MIST_COMM_BASICS_H #include @@ -13,4 +13,4 @@ typedef uint16_t nx_am_addr_t; #define AM_BROADCAST_ADDR ((uint16_t)0xFFFF) -#endif//MIST_COMM_BASICS +#endif//MIST_COMM_BASICS_H diff --git a/include/mist_comm.h b/include/mist_comm.h index d19bab6..d231c62 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -18,16 +18,32 @@ #include "platform_msg.h" +// ----------------------------------------------------------------------------- #define MIST_COMM_VERSION_MAJOR 0 -#define MIST_COMM_VERSION_MINOR 0 +#define MIST_COMM_VERSION_MINOR 1 #define MIST_COMM_VERSION_PATCH 0 +// ----------------------------------------------------------------------------- /** - * Communication layer result values. Generally derived from TinyOS error_t, - * however, all bad things have a negative value and there is a positive - * ALREADY. + * Verify that the comms api layer seems to be correctly configured. + * + * Call this before setting up a comms layer and check that it returns true, + * panic if it does not. + * + * This should fail at compile-time for library-api version conflicts. * - * FIXME: Can we retire COMMS_EALREADY? + * @return true if API and library version matches, config appears correct. + */ +inline bool comms_verify_api (void); + +// ----------------------------------------------------------------------------- +// Result and status values ---------------------------------------------------- +// ----------------------------------------------------------------------------- + +/** + * Communication layer result values. + * Generally derived from TinyOS error_t, however, all bad things have + * a negative value and there is a positive ALREADY instead of EALREADY. */ typedef enum CommsErrors { COMMS_UNINITIALIZED = -127, @@ -40,7 +56,7 @@ typedef enum CommsErrors { COMMS_ETIMEOUT = -12, COMMS_ENOACK = -11, COMMS_ENOMEM = -10, - COMMS_EALREADY = -9, // Use positive COMMS_ALREADY instead! +// COMMS_EALREADY = -9, // Use positive COMMS_ALREADY instead! COMMS_ERESERVE = -8, COMMS_ERETRY = -7, COMMS_EINVAL = -6, @@ -64,6 +80,10 @@ typedef enum CommsStatus { COMMS_STARTED = 1 } comms_status_t; +// ----------------------------------------------------------------------------- +// Layer, address and message structures --------------------------------------- +// ----------------------------------------------------------------------------- + /** * Base structure for communications layers. Every interface has a type * and an EUI-64 address. @@ -80,25 +100,28 @@ typedef struct comms_layer { */ typedef struct comms_local_addr { uint8_t data[COMMS_MSG_ADDRESSING_SIZE]; -} __attribute__((packed))comms_local_addr_t; +} __attribute__((packed)) comms_local_addr_t; /** * The comms address structure, carries mappings from globally unique EUI64 * addresses to link-local platform/environment specific addresses. * It should be assumed that the local address may change at runtime! + * It is possible that either the eui or local address is not known (all zeros)! */ typedef struct comms_address { ieee_eui64_t eui; comms_local_addr_t local; - uint32_t updated; // Timestamp, seconds -} __attribute__((packed))comms_address_t; + uint32_t updated; // Timestamp, seconds, monotonic +} __attribute__((packed)) comms_address_t; /** * The comms message structure. Should only be manipulated through the APIs. */ typedef struct comms_msg comms_msg_t; +// ----------------------------------------------------------------------------- // Callback definitions -------------------------------------------------------- +// ----------------------------------------------------------------------------- /** * Signalled when message transmission is completed to return the message object @@ -106,10 +129,10 @@ typedef struct comms_msg comms_msg_t; * comms_send function and the passed function will be called in the future if * the comms_send returns COMMS_SUCCESS (message is accepted). * - * @param comms The layer that was used to send the message. - * @param msg The message that was sent. + * @param comms The layer that was used to send the message. + * @param msg The message that was sent. * @param result The result of the transmission. - * @param user The user pointer provided to comms_send. + * @param user The user pointer provided to comms_send. */ typedef void comms_send_done_f (comms_layer_t * comms, comms_msg_t * msg, comms_error_t result, void * user); @@ -118,28 +141,31 @@ typedef void comms_send_done_f (comms_layer_t * comms, comms_msg_t * msg, comms_ * registered with a communications layer with comms_register_recv. * * @param comms The layer where the message was received. - * @param msg The message, only valid while this call is running. - * @param user The user pointer given to comms_register_recv. + * @param msg The message, only valid while this call is running. + * @param user The user pointer given to comms_register_recv. */ typedef void comms_receive_f (comms_layer_t * comms, const comms_msg_t * msg, void * user); /** * Signalled when a status change is requested and completed. * - * @param comms The layer for which the status change took place. + * @param comms The layer for which the status change took place. * @param status The new status (may not be what was actually requested). - * @param user The user pointer. + * @param user The user pointer. */ typedef void comms_status_change_f (comms_layer_t * comms, comms_status_t status, void * user); +// ----------------------------------------------------------------------------- +// Communications control and status ------------------------------------------- // ----------------------------------------------------------------------------- /** * Start a comms layer. Use this or sleep controllers, not both. - * @param comms A comms layer to start. + * + * @param comms A comms layer to start. * @param start_done Status change callback. - * @param user Argument passed to the callback. - * @return COMMS_SUCCESS if the callback will be called in the future. + * @param user Argument passed to the callback. + * @return COMMS_SUCCESS if the callback will be called in the future. */ comms_error_t comms_start (comms_layer_t * comms, comms_status_change_f * start_done, void * user); @@ -154,11 +180,14 @@ comms_error_t comms_stop (comms_layer_t * comms, comms_status_change_f * stop_do /** * Get current status of the comms layer. + * * @param comms The comms layer to query. - * @return Current status. + * @return Current status. */ comms_status_t comms_status (comms_layer_t * comms); +// ----------------------------------------------------------------------------- +// Message sending ------------------------------------------------------------- // ----------------------------------------------------------------------------- /** @@ -168,7 +197,7 @@ comms_status_t comms_status (comms_layer_t * comms); * initialized again with that layer! * * @param comms The comms layer to use for initilization. - * @param msg The message to initialize. + * @param msg The message to initialize. */ void comms_init_message (comms_layer_t * comms, comms_msg_t * msg); @@ -179,14 +208,16 @@ void comms_init_message (comms_layer_t * comms, comms_msg_t * msg); * processing it (until send-done is called). * * @param comms The comms layer to use for sending the message. - * @param msg The message to send. - * @param sdf Pointer to a send-done function. - * @param user Optional user pointer, returned in send-done. - * @return COMMS_SUCCESS, if the send-done function will be called some time in the future. + * @param msg The message to send. + * @param sdf Pointer to a send-done function. + * @param user Optional user pointer, returned in send-done. + * @return COMMS_SUCCESS, if the send-done function will be called some time in the future. */ comms_error_t comms_send (comms_layer_t * comms, comms_msg_t * msg, comms_send_done_f * sdf, void * user); -// Receiver registration ------------------------------------------ +// ----------------------------------------------------------------------------- +// Receiver registration ------------------------------------------------------- +// ----------------------------------------------------------------------------- /** * Receiver structure for registering a receive callback. @@ -209,10 +240,10 @@ typedef struct comms_receiver comms_receiver_t; * be delivered to all receivers. * * @param comms Pointer to a comms layer. - * @param rcvr Receiver structure. - * @param func The receive function to call when a packet is received. - * @param user User pointer to be passed to the receive function on packet reception. - * @param amid The message type to register the receiver for. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. + * @param amid The message type to register the receiver for. */ comms_error_t comms_register_recv (comms_layer_t * comms, comms_receiver_t * rcvr, @@ -238,11 +269,11 @@ comms_error_t comms_register_recv (comms_layer_t * comms, * be delivered to all receivers. * * @param comms Pointer to a comms layer. - * @param rcvr Receiver structure. - * @param func The receive function to call when a packet is received. - * @param user User pointer to be passed to the receive function on packet reception. - * @param amid The message type to register the receiver for. - * @return COMMS_SUCCESS if successfully registered. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. + * @param amid The message type to register the receiver for. + * @return COMMS_SUCCESS if successfully registered. */ comms_error_t comms_register_recv_eui (comms_layer_t * comms, comms_receiver_t * rcvr, @@ -253,13 +284,11 @@ comms_error_t comms_register_recv_eui (comms_layer_t * comms, * Remove an already registered receiver. * * @param comms Pointer to a comms layer. - * @param rcvr Receiver structure to deregister. - * @return COMMS_SUCCESS if receiver has been removed and can be recycled. + * @param rcvr Receiver structure to deregister. + * @return COMMS_SUCCESS if receiver has been removed and can be recycled. */ comms_error_t comms_deregister_recv (comms_layer_t * comms, comms_receiver_t * rcvr); -// Snoopers don't look at the type (amid) - /** * Register to snoop for messages: * All messages, regardless of AMID. @@ -277,9 +306,9 @@ comms_error_t comms_deregister_recv (comms_layer_t * comms, comms_receiver_t * r * be delivered to all receivers. * * @param comms Pointer to a comms layer. - * @param rcvr Receiver structure. - * @param func The receive function to call when a packet is received. - * @param user User pointer to be passed to the receive function on packet reception. + * @param rcvr Receiver structure. + * @param func The receive function to call when a packet is received. + * @param user User pointer to be passed to the receive function on packet reception. */ comms_error_t comms_register_snooper (comms_layer_t * comms, comms_receiver_t * rcvr, @@ -289,175 +318,444 @@ comms_error_t comms_register_snooper (comms_layer_t * comms, * Remove an already registered snooper. * * @param comms Pointer to a comms layer. - * @param rcvr Receiver structure to deregister. - * @return COMMS_SUCCESS if receiver has been removed and can be recycled. + * @param rcvr Receiver structure to deregister. + * @return COMMS_SUCCESS if receiver has been removed and can be recycled. */ comms_error_t comms_deregister_snooper (comms_layer_t * comms, comms_receiver_t * rcvr); // ----------------------------------------------------------------------------- - // Packet type ----------------------------------------------------------------- -// TODO explain the AM ID logic +// ----------------------------------------------------------------------------- /** * Get the packet type (AM ID - Active Message ID) of the message. * * @param comms Pointer to a comms layer. - * @param msg Pointer to a message. - * @return Packet type (AM ID). - **/ + * @param msg Pointer to a message. + * @return Packet type (AM ID). + */ am_id_t comms_get_packet_type (comms_layer_t * comms, const comms_msg_t * msg); /** * Set the packet type (AM ID - Active Message ID) of the message. * * @param comms Pointer to a comms layer. - * @param msg Pointer to a message. + * @param msg Pointer to a message. * @param ptype The type. - **/ + */ void comms_set_packet_type (comms_layer_t * comms, comms_msg_t * msg, am_id_t ptype); -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // Packet group (PAN ID, AM group, etc) ---------------------------------------- -// TODO explain the AM group/PAN-ID logic +// ----------------------------------------------------------------------------- /** * Get the packet group (AM group / PAN ID) of the message. * * @param comms Pointer to a comms layer. - * @param msg Pointer to a message. - * @return Packet group (PAN ID). - **/ -uint16_t comms_get_packet_group(comms_layer_t* comms, const comms_msg_t* msg); + * @param msg Pointer to a message. + * @return Packet group (PAN ID). + */ +uint16_t comms_get_packet_group (comms_layer_t * comms, const comms_msg_t * msg); /** * Set the packet group (AM group / PAN ID) of the message. * * @param comms Pointer to a comms layer. - * @param msg Pointer to a message. + * @param msg Pointer to a message. * @param group Packet group (PAN ID). - **/ -void comms_set_packet_group(comms_layer_t* comms, comms_msg_t* msg, uint16_t group); -// ----------------------------------------------------------------------------- + */ +void comms_set_packet_group (comms_layer_t * comms, comms_msg_t * msg, uint16_t group); +// ----------------------------------------------------------------------------- // Addressing ------------------------------------------------------------------ -void comms_get_destination(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* destination); -void comms_set_destination(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* destination); - -void comms_get_source(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* source); -void comms_set_source(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* source); // ----------------------------------------------------------------------------- -// Message payload manipulation functions -------------------------------------- -uint8_t comms_get_payload_max_length(comms_layer_t* comms); +/** + * Get the destination of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param destination Pointer to a comms_address_t object for copying destination info. + */ +void comms_get_destination (comms_layer_t * comms, const comms_msg_t * msg, comms_address_t * destination); -uint8_t comms_get_payload_length(comms_layer_t* comms, const comms_msg_t* msg); -void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length); +/** + * Set the destination of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param destination Pointer to an object holding the destination. + */ +void comms_set_destination (comms_layer_t * comms, comms_msg_t * msg, const comms_address_t * destination); + +/** + * Get the source of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param source Pointer to a comms_address_t object for copying source info. + */ +void comms_get_source (comms_layer_t * comms, const comms_msg_t * msg, comms_address_t * source); + +/** + * Set the source of the message. Source is also set automatically on send, if not set before, + * it needs to be set explicitly when for example forwarding messages and the source is not + * the sending node itself. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param source Pointer to an object holding the source. + */ +void comms_set_source (comms_layer_t * comms, comms_msg_t * msg, const comms_address_t * source); -void* comms_get_payload(comms_layer_t* comms, const comms_msg_t* msg, uint8_t length); -// ??? Open questions regarding payload: -// Do we want support larger payloads - uint16_t length? -// ??? +// ----------------------------------------------------------------------------- +// Message payload functions --------------------------------------------------- // ----------------------------------------------------------------------------- +/** + * Get the maximum payload length supported by this communications layer. + * + * @param comms Pointer to a comms layer. + * @return Maximum supported payload length. + */ +uint8_t comms_get_payload_max_length (comms_layer_t * comms); + +/** + * Get the current payload length of this message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Payload length. + */ +uint8_t comms_get_payload_length (comms_layer_t * comms, const comms_msg_t * msg); + +/** + * Set the payload length for this message. The value must be <= comms_get_payload_max_length. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Payload length. + */ +void comms_set_payload_length (comms_layer_t * comms, comms_msg_t * msg, uint8_t length); + +/** + * Get a pointer to the payload. NULL is returned if the requested size cannot be + * accomodated by the comms layer. Actual size of the payload must be retrieved + * with comms_get_payload_length when reading the payload and set + * with comms_set_payload_length after writing the payload. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param length Expected max length of the payload. + * @return Pointer to payload or NULL + */ +void * comms_get_payload (comms_layer_t * comms, const comms_msg_t * msg, uint8_t length); + +// ----------------------------------------------------------------------------- // PacketLink & Acknowledgements ----------------------------------------------- -uint8_t comms_get_retries(comms_layer_t* comms, const comms_msg_t* msg); -comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); +// ----------------------------------------------------------------------------- + +/** + * Get the number of allowed retries for the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Number of allowed retries. + */ +uint8_t comms_get_retries (comms_layer_t * comms, const comms_msg_t * msg); +/** + * Set the number of allowed retries for the message. Setting to > 0 will cause + * an acknowledgement to be requested when sent to unicast. For broadcast the + * the message will be repeated the specified number of times. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param count Number of allowed retries. + * @return COMMS_SUCCESS when retry parameters were valid. + */ +comms_error_t comms_set_retries (comms_layer_t * comms, comms_msg_t * msg, uint8_t count); + +/** + * Get the number of retries used for the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Number of used retries, when sending the message. + */ uint8_t comms_get_retries_used(comms_layer_t* comms, const comms_msg_t* msg); + +/** + * Set the number of used retries. + * + * For communication layer implementation internal use! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Number of allowed retries. + */ comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uint8_t count); +/** + * Get the configured retry timeout. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Retry timeout (milliseconds). + */ uint32_t comms_get_timeout(comms_layer_t* comms, const comms_msg_t* msg); + +/** + * Set the retry timeout for sending this message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param timeout Retry timeout (milliseconds). + * @return COMMS_SUCCESS if the timeout value was valid. + */ comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t timeout); +/** + * Check if an ack has been requested for this message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return true if an ack was / will be requested for the message. + */ bool comms_is_ack_required(comms_layer_t* comms, const comms_msg_t* msg); -comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required); -// Check delivery for both PacketLink and simple Ack use cases -bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg); +/** + * Set if the ack is required or not. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param required Set to true to request an ack. + * @return COMMS_SUCCESS if the requested ack configuration can be supported. + */ +comms_error_t comms_set_ack_required (comms_layer_t * comms, comms_msg_t * msg, bool required); -void _comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg); -// ----------------------------------------------------------------------------- +/** + * Check if an ack was received for this message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return true if an acknowledgement was received. + */ +bool comms_ack_received (comms_layer_t * comms, const comms_msg_t * msg); + +/** + * Set the ack field in the message. + * + * For communication layer implementation internal use! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return true if an acknowledgement was received. + */ +void comms_set_ack_received (comms_layer_t * comms, comms_msg_t * msg, bool received); +// ----------------------------------------------------------------------------- // Message timestamping -------------------------------------------------------- -// Timestamps are microseconds local clock. Indicate either message reception or -// transmission time. +// ----------------------------------------------------------------------------- -// Check that the timestamp is valid with comms_timestamp_valid. -uint32_t comms_get_timestamp(comms_layer_t* comms, const comms_msg_t* msg); +/** + * Get the current communications layer time. Timestamps of messages are set + * relative to this counter. The value is in microseconds, however, depending on + * the underlying implementation, ticks may be many microseconds - for example + * the clock may actually have millisecond precision, so the returned timestamps + * will jump in 1000 microsecond steps. + * + * @param comms Pointer to a comms layer. + * @return Current timestamp (microseconds). + */ +uint32_t comms_get_time_micro (comms_layer_t * comms); -// return TRUE if message has valid timestamp -bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg); +/** + * Check if the message has a valid timestamp. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return true if the message has been timestamped on RX or TX. + */ +bool comms_timestamp_valid (comms_layer_t * comms, const comms_msg_t * msg); -// Set timestamp (low level - on receive and on send) -comms_error_t comms_set_timestamp(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp); -// ----------------------------------------------------------------------------- +/** + * Get the message timestamp: + * * RX timestamp, if message was received + * * TX timestamp, if the message was sent + * + * Always check first that the timestamp is valid with comms_timestamp_valid! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Message RX or TX timestamp. + */ +uint32_t comms_get_timestamp_micro (comms_layer_t * comms, const comms_msg_t * msg); +/** + * Set the timestamp field in the message. + * Setting the timestamp will make future calls to comms_timestamp_valid return true. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param timestamp The timestamp. + * @return COMMS_SUCCESS unless something went horribly wrong. + */ +comms_error_t comms_set_timestamp_micro (comms_layer_t * comms, comms_msg_t * msg, uint32_t timestamp); + +// ----------------------------------------------------------------------------- // TimeSync messaging ---------------------------------------------------------- -// Event time is microseconds local clock +// ----------------------------------------------------------------------------- -// Set event time -comms_error_t comms_set_event_time(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt); +/** + * Set an event time in respect to the comms_get_time_micro clock. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param timestamp The timestamp. + * @return COMMS_SUCCESS unless something went horribly wrong. + */ +comms_error_t comms_set_event_time_micro (comms_layer_t * comms, comms_msg_t * msg, uint32_t evt); + +/** + * Get the event time communicated with the message. + * + * Always check that event time is valid with comms_event_time_valid! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Event timestamp relative to comms_get_time_micro. + */ +uint32_t comms_get_event_time_micro (comms_layer_t * comms, const comms_msg_t * msg); -// Check that event time is valid with comms_event_time_valid. -uint32_t comms_get_event_time(comms_layer_t* comms, const comms_msg_t* msg); +/** + * Check if the message carries a valid event time. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return true if the message includes an event time. + */ +bool comms_event_time_valid (comms_layer_t * comms, const comms_msg_t * msg); -// return TRUE if message has valid event time -bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg); // ----------------------------------------------------------------------------- - // Message Quality ------------------------------------------------------------- -uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg); -void _comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); -// ??? standardize on 0-100 instead of 0-255, because for example CC1101 LQI goes from 0-127 and is inverse to Atmel RFX. +// ----------------------------------------------------------------------------- -// Value in dBm -int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg); -void _comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); +/** + * Get message link-quality. 0-255, 255 is best. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Message quality (0-255, 255 is best). + */ +uint8_t comms_get_lqi (comms_layer_t* comms, const comms_msg_t* msg); + +/** + * Set message link-quality. + * + * For communication layer implementation internal use! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param lqi Message quality (0-255, 255 is best). + */ +void comms_set_lqi (comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi); + +/** + * Get message RSSI - Received Signal Strength Indicator, dBm. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Message RSSI, dBm. + */ +int8_t comms_get_rssi (comms_layer_t* comms, const comms_msg_t* msg); + +/** + * Set message RSSI - Received Signal Strength Indicator, dBm. + * + * For communication layer implementation internal use! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param rssi Message RSSI, dBm. + */ +void comms_set_rssi (comms_layer_t* comms, comms_msg_t* msg, int8_t rssi); -int8_t comms_get_priority(comms_layer_t* comms, const comms_msg_t* msg); -void comms_set_priority(comms_layer_t* comms, comms_msg_t* msg, int8_t priority); // ----------------------------------------------------------------------------- +// Message Priority ------------------------------------------------------------ +// ----------------------------------------------------------------------------- + +/** + * Get message priority, 0 is default. + * + * Priority handling mostly depends on the specific of the underlying + * implementation, but is relative to 0 ... higher value, higher priority. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Message priority. + */ +int8_t comms_get_priority (comms_layer_t * comms, const comms_msg_t * msg); +/** + * Set message priority, 0 for normal (default). + * + * Priority handling mostly depends on the specific of the underlying + * implementation, but is relative to 0 ... higher value, higher priority. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param priority Message priority. + */ +void comms_set_priority (comms_layer_t * comms, comms_msg_t * msg, int8_t priority); + +// ----------------------------------------------------------------------------- // Received message delivery --------------------------------------------------- +// ----------------------------------------------------------------------------- + /** * Deliver a message to all registered receivers. * * @param comms The later to use. - * @param msg The message to deliver. - * @return true if the message was delivered to at least one receiver + * @param msg The message to deliver. + * @return true if the message was delivered to at least one receiver. */ -bool comms_deliver(comms_layer_t* comms, comms_msg_t* msg); -// ----------------------------------------------------------------------------- +bool comms_deliver (comms_layer_t * comms, comms_msg_t * msg); // ----------------------------------------------------------------------------- -// Sleep management controller -// If a sleep controller is registered for a comms layer, it will entirely take -// over start-stop management, the comms_start and comms_stop functions should -// be ignored altogether and only comms_sleep_block and comms_sleep_allow -// should be used. +// Sleep management ------------------------------------------------------------ // ----------------------------------------------------------------------------- + +/** + * Sleep management controller. + * + * If a sleep controller is registered for a comms layer, it will entirely take + * over start-stop management, the comms_start and comms_stop functions should + * be ignored altogether and only comms_sleep_block and comms_sleep_allow + * should be used. + */ typedef struct comms_sleep_controller comms_sleep_controller_t; /** * Register a sleep controller. - * @param comms Layer to register controller to. - * @param ctrl An unused controller. + * @param comms Layer to register controller to. + * @param ctrl An unused controller. * @param start_done Callback function called when a sleep block starts the comms layer. - * @param user User parameter passed with the callback. + * @param user User parameter passed with the callback. + * @return COMMS_SUCCESS if sleep controller registered. */ -comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl, - comms_status_change_f * start_done, void * user); +comms_error_t comms_register_sleep_controller (comms_layer_t * comms, comms_sleep_controller_t * ctrl, + comms_status_change_f * start_done, void * user); /** * De-register a sleep controller. + * * @param comms Layer to remove the controller from. - * @param ctrl A registered ccontroller. - * @return COMMS_SUCCESS when controller was removed. + * @param ctrl A registered ccontroller. + * @return COMMS_SUCCESS when controller was removed. */ -comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl); - -// Block may be asynchronous, wakeup may take time, or EALREADY may be returned +comms_error_t comms_deregister_sleep_controller (comms_layer_t * comms, comms_sleep_controller_t * ctrl); /** * Request a sleep block and the layer to be started. May return COMMS_ALREADY if @@ -465,27 +763,29 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle * started and therefore a state change callback will be called once ready. * * @param ctrl A registered ccontroller. - * @return COMMS_SUCCESS when callback will be called in the future, COMMS_ALREADY if block immediately successful. + * @return COMMS_SUCCESS when callback will be called in the future, + * COMMS_ALREADY when block immediately successful. */ -comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl); +comms_error_t comms_sleep_block (comms_sleep_controller_t * ctrl); /** * Release a sleep block. The block is released immediately but the layer shutdown * will only happen if other blocks are not present ... it will also take time. * No callback will be fired, it is ok to request another block immediately. * - * @param ctrl A registered ccontroller. - * @return COMMS_SUCCESS when block was released, COMMS_ALREADY if it was not event active. + * @param ctrl A registered controller. + * @return COMMS_SUCCESS when block was released, + * COMMS_ALREADY when it was not event active. */ -comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl); +comms_error_t comms_sleep_allow (comms_sleep_controller_t * ctrl); /** * Query current block status. Use comms_status to get actual status. * - * @param ctrl A registered ccontroller. - * @return true if block is active or pending. + * @param ctrl A registered controller. + * @return true if block is active or pending. */ -bool comms_sleep_blocked(comms_sleep_controller_t * ctrl); +bool comms_sleep_blocked (comms_sleep_controller_t * ctrl); // ----------------------------------------------------------------------------- // Locking, for internal use mostly -------------------------------------------- @@ -493,21 +793,24 @@ bool comms_sleep_blocked(comms_sleep_controller_t * ctrl); /** * Create a mutex. - * @return NULL for failure. + * + * @return A mutex ID or NULL for failure. */ -commsMutexId_t comms_mutex_create(void); +commsMutexId_t comms_mutex_create (void); /** * Acquire the specified mutex. Blocks until aquired. + * * @param mutex - The mutex to acquire. */ -void comms_mutex_acquire(commsMutexId_t mutex); +void comms_mutex_acquire (commsMutexId_t mutex); /** * Release the specified mutex. Returns "immediately". + * * @param mutex - The mutex to release. */ -void comms_mutex_release(commsMutexId_t mutex); +void comms_mutex_release (commsMutexId_t mutex); // ----------------------------------------------------------------------------- // Include implementation details. diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index a0d75ba..a17c685 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -1,5 +1,11 @@ -#ifndef MIST_COMM_AM_H_ -#define MIST_COMM_AM_H_ +/** + * Mist communications API for TinyOS ActiveMessage. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#ifndef MIST_COMM_AM_H +#define MIST_COMM_AM_H #include "mist_comm.h" #include "mist_comm_iface.h" @@ -55,4 +61,4 @@ comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, comms_start_f* startf, comms_stop_f* stopf); // ----------------------------------------------------------------------------- -#endif//MIST_COMM_AM_H_ +#endif//MIST_COMM_AM_H diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index d71d022..ea5abc6 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -1,5 +1,5 @@ -#ifndef MIST_COMM_AM_MSG_H_ -#define MIST_COMM_AM_MSG_H_ +#ifndef MIST_COMM_AM_MSG_H +#define MIST_COMM_AM_MSG_H #include "mist_comm_basics.h" @@ -30,4 +30,4 @@ typedef struct comms_am_msg_metadata { uint8_t priority; }__attribute__((packed))comms_am_msg_metadata_t; -#endif//MIST_COMM_AM_H_ +#endif//MIST_COMM_AM_MSG_H diff --git a/include/mist_comm_bridge.h b/include/mist_comm_bridge.h index e2f5a24..a846ed4 100644 --- a/include/mist_comm_bridge.h +++ b/include/mist_comm_bridge.h @@ -7,8 +7,8 @@ * @author Raido Pahtma */ -#ifndef MIST_COMM_BRIDGE_H_ -#define MIST_COMM_BRIDGE_H_ +#ifndef MIST_COMM_BRIDGE_H +#define MIST_COMM_BRIDGE_H #include "cmsis_os2.h" #include "mist_comm.h" @@ -52,4 +52,4 @@ comms_error_t comms_bridge_init (comms_bridge_t * bridge, */ void comms_bridge_deinit (comms_bridge_t * bridge); -#endif//MIST_COMM_BRIDGE_H_ +#endif//MIST_COMM_BRIDGE_H diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index d12f3b3..f3d4044 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -1,5 +1,5 @@ -#ifndef MIST_COMM_IFACE_H_ -#define MIST_COMM_IFACE_H_ +#ifndef MIST_COMM_IFACE_H +#define MIST_COMM_IFACE_H #include "mist_comm.h" @@ -46,7 +46,7 @@ typedef bool comms_is_ack_required_f(comms_layer_iface_t*, const comms_msg_t*); typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t*, bool); typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); -typedef void comms_set_ack_received_f(comms_layer_iface_t*, comms_msg_t*); +typedef void comms_set_ack_received_f(comms_layer_iface_t*, comms_msg_t*, bool); typedef comms_error_t comms_set_timestamp_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); typedef uint32_t comms_get_timestamp_f(comms_layer_iface_t*, const comms_msg_t*); @@ -145,4 +145,4 @@ struct comms_layer_iface { commsMutexId_t receiver_mutex; }; -#endif//MIST_COMM_IFACE_H_ +#endif//MIST_COMM_IFACE_H diff --git a/include/mist_comm_private.h b/include/mist_comm_private.h index 6f5d3a1..efbf62f 100644 --- a/include/mist_comm_private.h +++ b/include/mist_comm_private.h @@ -1,9 +1,45 @@ -#ifndef MIST_COMM_PRIVATE_H_ -#define MIST_COMM_PRIVATE_H_ +/** + * Mist communications API details. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ +#ifndef MIST_COMM_PRIVATE_H +#define MIST_COMM_PRIVATE_H #include "mist_comm.h" +// ----------------------------------------------------------------------------- +// API version checking -------------------------------------------------------- +// ----------------------------------------------------------------------------- + +/** + * Version check. Headers will check against major and minor variables that + * have the version number in the name. So if there is a version mismatch, + * it will cause linking to fail, because the variables will not be found. + */ + +#define MIST_COMM_VERSION_PASTER(x, y) x##y + +extern volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR); +extern volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR); + +inline bool comms_verify_api (void) +{ + if (MIST_COMM_VERSION_MAJOR != MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR)) + { + return false; + } + if (MIST_COMM_VERSION_MINOR != MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR)) + { + return false; + } + return true; +} + +// ----------------------------------------------------------------------------- // Message structure ----------------------------------------------------------- +// ----------------------------------------------------------------------------- struct comms_msg { struct { uint16_t type; // 0x3F00 + AMID @@ -23,36 +59,42 @@ struct comms_msg { } __attribute__((packed)) body; }; +// ----------------------------------------------------------------------------- // Receiver structure ---------------------------------------------------------- +// ----------------------------------------------------------------------------- struct comms_receiver { // Members are private, should not be accessed - am_id_t type; - comms_receive_f* callback; - void* user; - bool eui; - comms_receiver_t* next; + am_id_t type; + comms_receive_f * callback; + void * user; + bool eui; + comms_receiver_t * next; }; +// ----------------------------------------------------------------------------- // Sleep controller structure -------------------------------------------------- +// ----------------------------------------------------------------------------- struct comms_sleep_controller { - comms_layer_t* comms; + comms_layer_t * comms; bool block; bool pending; - comms_status_change_f* cb; - void* user; + comms_status_change_f * cb; + void * user; - comms_sleep_controller_t* next; + comms_sleep_controller_t * next; }; +// ----------------------------------------------------------------------------- // Deferred calls -------------------------------------------------------------- +// ----------------------------------------------------------------------------- -typedef void comms_deferred_f(void * argument); +typedef void comms_deferred_f (void * argument); -void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferred_f * cb); +void _comms_deferred_init (comms_layer_t * comms, void ** deferred, comms_deferred_f * cb); -void _comms_defer(void * deferred); +void _comms_defer (void * deferred); -void _comms_deferred_deinit(void * deferred); +void _comms_deferred_deinit (void * deferred); -#endif//MIST_COMM_PRIVATE_H_ +#endif//MIST_COMM_PRIVATE_H diff --git a/include/mist_comm_ref.h b/include/mist_comm_ref.h index 2155de6..b166bc6 100644 --- a/include/mist_comm_ref.h +++ b/include/mist_comm_ref.h @@ -1,5 +1,5 @@ -#ifndef MIST_COMM_REF_H_ -#define MIST_COMM_REF_H_ +#ifndef MIST_COMM_REF_H +#define MIST_COMM_REF_H // Add default receiver handling functionality to a layer implementation comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms); @@ -7,4 +7,4 @@ comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms); // Deliver to registered receivers. No further actions taken on the message. comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg); -#endif//MIST_COMM_REF_H_ +#endif//MIST_COMM_REF_H diff --git a/include/mist_comm_routing.h b/include/mist_comm_routing.h index 4c51b88..c1421fd 100644 --- a/include/mist_comm_routing.h +++ b/include/mist_comm_routing.h @@ -1,11 +1,11 @@ /** * Routing info callbacks for the MistComm API. * - * Copyright Thinnect Inc. 2019 - * + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ +#ifndef MIST_COMM_ROUTING_H +#define MIST_COMM_ROUTING_H #include "mist_comm_am.h" #include @@ -37,3 +37,5 @@ struct comms_layer_am_mh { comms_layer_am_t base; comms_routing_info_handler_t * routing_info_handlers; }; + +#endif//MIST_COMM_ROUTING_H diff --git a/include/tos/mist_comm_basics.h b/include/tos/mist_comm_basics.h index 02554ba..82d57e6 100644 --- a/include/tos/mist_comm_basics.h +++ b/include/tos/mist_comm_basics.h @@ -1,5 +1,5 @@ -#ifndef MIST_COMM_BASICS -#define MIST_COMM_BASICS +#ifndef MIST_COMM_BASICS_H +#define MIST_COMM_BASICS_H #include "AM.h" #include "IeeeEui64.h" @@ -12,4 +12,4 @@ //} ieee_eui64_t; // ??? this should come from some ieee_eui64.h header -#endif//MIST_COMM_BASICS +#endif//MIST_COMM_BASICS_H diff --git a/mock/mist_comm_mutex.h b/mock/mist_comm_mutex.h index f092d9c..0e39c94 100644 --- a/mock/mist_comm_mutex.h +++ b/mock/mist_comm_mutex.h @@ -3,11 +3,10 @@ * * Copyright Thinnect Inc. 2020 * @license MIT - * @author Raido Pahtma */ -#ifndef MIST_COMM_MUTEX_H_ -#define MIST_COMM_MUTEX_H_ +#ifndef MIST_COMM_MUTEX_H +#define MIST_COMM_MUTEX_H typedef int commsMutexId_t; -#endif//MIST_COMM_MUTEX_H_ +#endif//MIST_COMM_MUTEX_H diff --git a/mock/mist_mock_radio_cmsis.h b/mock/mist_mock_radio_cmsis.h index 6f0aba3..dacb09c 100644 --- a/mock/mist_mock_radio_cmsis.h +++ b/mock/mist_mock_radio_cmsis.h @@ -5,8 +5,8 @@ * Copyright Thinnect Inc. 2020 * @license MIT */ -#ifndef MIST_MOCK_RADIO_CMSIS_H_ -#define MIST_MOCK_RADIO_CMSIS_H_ +#ifndef MIST_MOCK_RADIO_CMSIS_H +#define MIST_MOCK_RADIO_CMSIS_H #include "mist_comm_am.h" @@ -18,4 +18,4 @@ */ comms_layer_t * mist_mock_cmsis_radio_init (am_addr_t address, comms_send_f * send_copy); -#endif//MIST_MOCK_RADIO_CMSIS_H_ +#endif//MIST_MOCK_RADIO_CMSIS_H diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index 1884514..d86a451 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -45,8 +45,13 @@ static bool serial_am_receive(uint8_t dspch, const uint8_t data[], uint8_t lengt static void serial_am_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_am_timer_cb(void * argument); -comms_layer_t* serial_activemessage_init (serial_activemessage_t* sam, serial_protocol_t * spr, uint16_t pan_id, uint16_t address) +comms_layer_t * serial_activemessage_init (serial_activemessage_t* sam, serial_protocol_t * spr, uint16_t pan_id, uint16_t address) { + if ( ! comms_verify_api()) + { + return NULL; + } + sam->mutex = osMutexNew(NULL); sam->timer = osTimerNew(&serial_am_timer_cb, osTimerOnce, sam, NULL); @@ -224,10 +229,7 @@ static void serial_am_senddone(uint8_t dispatch, const uint8_t data[], uint8_t l // Set flags on the message that was just sent //comms_set_timestamp(lyr, sam->sending->msg, now()); - if (acked) - { - _comms_set_ack_received(lyr, sam->sending->msg); - } + comms_set_ack_received(lyr, sam->sending->msg, acked); // Signal send done events sam->sending->send_done(lyr, sam->sending->msg, COMMS_SUCCESS, sam->sending->user); diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index 07c2eed..6d676e3 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -30,9 +30,14 @@ static bool serial_bm_receive(uint8_t dspch, const uint8_t data[], uint8_t lengt static void serial_bm_senddone(uint8_t dspch, const uint8_t data[], uint8_t length, bool acked, void* user); static void serial_bm_timer_cb(void * argument); -comms_layer_t* serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, - uint8_t dispatch, am_id_t amid) +comms_layer_t * serial_basicmessage_init (serial_basicmessage_t * sbm, serial_protocol_t * spr, + uint8_t dispatch, am_id_t amid) { + if ( ! comms_verify_api()) + { + return NULL; + } + sbm->mutex = osMutexNew(NULL); sbm->timer = osTimerNew(&serial_bm_timer_cb, osTimerOnce, sbm, NULL); @@ -135,10 +140,7 @@ static void serial_bm_senddone(uint8_t dispatch, const uint8_t data[], uint8_t l // Set flags on the message that was just sent //comms_set_timestamp(lyr, sbm->sending->msg, now()); - if (acked) - { - _comms_set_ack_received(lyr, sbm->sending->msg); - } + comms_set_ack_received(lyr, sbm->sending->msg, acked); // Signal send done events sbm->sending->send_done(lyr, sbm->sending->msg, COMMS_SUCCESS, sbm->sending->user); diff --git a/util/fragmenter_assembler.c b/util/fragmenter_assembler.c index 5bbe3d7..236cf43 100644 --- a/util/fragmenter_assembler.c +++ b/util/fragmenter_assembler.c @@ -4,7 +4,7 @@ * fragment need to be of this size, the last one can be shorter. * Maximum number of fragments is 8, maximum data size is 255 bytes. * - * @author Raido Pahtma + * Copyright Thinnect Inc. 2020 * @license MIT */ #include "fragmenter_assembler.h" diff --git a/util/fragmenter_assembler.h b/util/fragmenter_assembler.h index 09a5edf..2ba054a 100644 --- a/util/fragmenter_assembler.h +++ b/util/fragmenter_assembler.h @@ -4,7 +4,7 @@ * fragment need to be of this size, the last one can be shorter. * Maximum number of fragments is 8, maximum data size is 255 bytes. * - * @author Raido Pahtma + * Copyright Thinnect Inc. 2020 * @license MIT */ #ifndef FRAGMENTER_ASSEMBLER_H_ From 7bcfcdda7094da570e15e57c7da37148e55092be Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 13 Dec 2021 19:33:00 +0200 Subject: [PATCH 77/80] Extra docstrings. --- README.md | 34 +++++----- api/mist_comm_api.c | 3 + include/compat/mist_comm_basics.h | 6 ++ include/mist_comm.h | 2 +- include/mist_comm_am.h | 101 ++++++++++++++++++++++-------- include/mist_comm_am_msg.h | 6 ++ include/mist_comm_bridge.h | 1 - include/mist_comm_iface.h | 6 ++ include/mist_comm_ref.h | 25 ++++++-- include/mist_comm_routing.h | 60 ++++++++++++++++-- 10 files changed, 190 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 3206723..877f551 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Mist communications APIs, abstractions for various communication interfaces. -# Features +## Features The Mist Communication API abstracts the specifics of different communication implementations from the higher layers. Applications can use @@ -15,7 +15,7 @@ communication flows, it is usually not necessary to be aware of what the actual underlying communications technology is. -# Included implementations +## Included implementations The mist-comm library contains an adapter for adding the mist-comm API to radio layers. This is used by the 802.15.4 implementations in @@ -31,9 +31,9 @@ set up a basic communications flow without an OS using for example [radio_basic.c](https://github.com/thinnect/node-platform/blob/master/silabs/radio_basic.c). -# Addresses and identifiers +## Addresses and identifiers -## Addressing +### Addressing Messages are ideally addressed using the endpoint IEEE EUI-64 addresses, however, the actual address structure is a composite of a global and a local address, @@ -41,7 +41,7 @@ since the mist-comm API is mostly used on embedded devices and over communicatio interfaces where it is necessary to map interface-specific addresses and global identities. -## Packet type - Active Message ID (AMID) +### Packet type - Active Message ID (AMID) The Mist AMID concept derives from the TinyOS Active Message ID, which is an 8-bit value. On the cloud side this has been extended to include the @@ -50,7 +50,7 @@ of the 16-bit space in the future, as other protocols and tools are extended. The mist-comm API currently uses the 8-bit value, a future version may move to the full 16-bit identifier. -## Packet group - Active Message Group / PAN ID +### Packet group - Active Message Group / PAN ID The Mist Group ID concept derives from the TinyOS Active Message Group ID, which itself relies on the 802.15.4 PAN ID, however, exposes only 8-bits of the @@ -59,9 +59,9 @@ high-byte currently needs to be 0, because the serial protocol only transfers the lower 8 bits. -# Setting up a communications layer +## Setting up a communications layer -## Initialization +### Initialization Initializing a communications layer is usually a simple as calling the init or setup function of a specific communications layer. A pointer to the layer is @@ -86,7 +86,7 @@ to be called or a sleep-block to be applied to actually start it. `comms_status` can be used to check the status. -## Creation +### Creation The mist-comm interface structure (`comms_layer_iface_t`) carries function pointers for packet manipulation and messaging tasks. These functions are @@ -108,7 +108,7 @@ of some incompatibilities, if static communications libraries are being linked together. -# Sending a message +## Sending a message Before using a `comms_msg_t` structure, it must be initialized for the layer that it is going to be used with. This will clear all the contents and may @@ -179,7 +179,7 @@ as it is usually fired from the communication layer thread and holding it up may cause subsequent packets to be dropped. -# Receiving a message +## Receiving a message Receiving a message requires registering a receiver and a receive function. A regular receiver will pass a message to the receive function when the type (AM ID) @@ -226,7 +226,7 @@ static void receive_message (comms_layer_t * p_comms, const comms_msg_t * p_msg, ``` -# Addressing +## Addressing The message sending example above uses global EUI64 addressing when sending the message. In this case, the sender is starting with a blank `comms_address_t` @@ -255,7 +255,7 @@ that needs it. ``` -# Message pool +## Message pool An allocated `comms_msg_t` structure is necessary for sending a message. In many cases components can declare the message statically, but for many other components, @@ -305,7 +305,7 @@ void custom_component_function (void) ``` -# Communications layer sleep management +## Communications layer sleep management A communications layer may be always on (started after init) or switched either by calling `comms_start` and `comms_stop` or through sleep controllers. @@ -343,7 +343,7 @@ comms_register_sleep_controller(p_comms, &m_sleep_ctrl, radio_start_done, NULL); ``` -# Timestamps +## Timestamps Received messages are timestamped as they arrive, transmitted messages are timestamped when sent out and the timestamp can be inspected in the send-done @@ -357,13 +357,13 @@ different granularity. **Timestamping features depend on the capabilities of the underlying implementation and may not be supported for all communications layers!** -## Message timestamps +### Message timestamps Message timestamps can be read with the combination of `comms_timestamp_valid` and `comms_get_timestamp_micro`. It is up to the user to know if the message was received or sent, to know if they are getting an RX or TX timestamp. -## Event timestamps +### Event timestamps Event timestamps are set with the `comms_set_event_time_micro` function and on reception, can be checked with `comms_event_time_valid` and `comms_get_event_time_micro`. diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index 6a4b7e2..c4e83c7 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -11,6 +11,9 @@ #include #include +volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR); +volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR); + static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; diff --git a/include/compat/mist_comm_basics.h b/include/compat/mist_comm_basics.h index 74b802f..c8f6b55 100644 --- a/include/compat/mist_comm_basics.h +++ b/include/compat/mist_comm_basics.h @@ -1,3 +1,9 @@ +/** + * Reference basic variables definition. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ #ifndef MIST_COMM_BASICS_H #define MIST_COMM_BASICS_H diff --git a/include/mist_comm.h b/include/mist_comm.h index d231c62..142b36a 100644 --- a/include/mist_comm.h +++ b/include/mist_comm.h @@ -34,7 +34,7 @@ * * @return true if API and library version matches, config appears correct. */ -inline bool comms_verify_api (void); +inline bool comms_verify_api (void) __attribute__((always_inline)); // ----------------------------------------------------------------------------- // Result and status values ---------------------------------------------------- diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index a17c685..f40bda3 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -12,9 +12,73 @@ #include "mist_comm_addrcache.h" #include "mist_comm_am_addrdisco.h" +/** + * Structure type definition for an ActiveMessage comms layer. + */ typedef struct comms_layer_am comms_layer_am_t; -typedef am_addr_t comms_am_addr_f(comms_layer_am_t*); +/** + * ActiveMessage address of the communications layer. + * @param comms Pointer to a comms layer. + * @return ActiveMessage address. + */ +am_addr_t comms_am_address (comms_layer_t * comms); + +/** + * Get the destination of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Destination address. + */ +am_addr_t comms_am_get_destination (comms_layer_t * comms, const comms_msg_t * msg); + +/** + * Set the destination of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param dest Destination address. + */ +void comms_am_set_destination (comms_layer_t * comms, comms_msg_t * msg, am_addr_t dest); + +/** + * Get the source of the message. + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @return Source address. + */ +am_addr_t comms_am_get_source (comms_layer_t * comms, const comms_msg_t * msg); + +/** + * Set the source of the message. In most cases this is done automatically! + * + * @param comms Pointer to a comms layer. + * @param msg Pointer to a message. + * @param source Source address. + */ +void comms_am_set_source (comms_layer_t * comms, comms_msg_t * msg, am_addr_t source); + +/** + * Create an ActiveMessage comms layer. + * + * @param layer Pointer to a layer structure to initialize. + * @param address ActiveMessage address for this layer + * @param sendf Actual send function to use for sending the message. + * @param plenf Max payload length function for the underlying comms component. + * @param startf Layer start function (can be NULL, if always active). + * @param stopf Layer stop function (can be NULL, if always active). + * @return COMMS_SUCCESS if initialized correctly. + */ +comms_error_t comms_am_create (comms_layer_t * layer, am_addr_t address, + comms_send_f * sendf, comms_plen_f * plenf, + comms_start_f * startf, comms_stop_f * stopf); + + +// ----------------------------------------------------------------------------- + +typedef am_addr_t comms_am_addr_f (comms_layer_am_t*); typedef am_addr_t comms_am_get_destination_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); @@ -22,19 +86,20 @@ typedef void comms_am_set_destination_f(comms_layer_am_t*, comms_msg_t*, am_addr typedef am_addr_t comms_am_get_source_f(comms_layer_am_t*, const comms_msg_t*); typedef void comms_am_set_source_f(comms_layer_am_t*, comms_msg_t*, am_addr_t); -struct comms_layer_am { +struct comms_layer_am +{ comms_layer_iface_t base; - comms_am_get_destination_f* am_get_destination; - comms_am_set_destination_f* am_set_destination; + comms_am_get_destination_f * am_get_destination; + comms_am_set_destination_f * am_set_destination; - comms_am_get_source_f* am_get_source; - comms_am_set_source_f* am_set_source; + comms_am_get_source_f * am_get_source; + comms_am_set_source_f * am_set_source; - comms_am_addr_f* am_address; + comms_am_addr_f * am_address; - comms_send_f* link_sendf; - comms_plen_f* link_plenf; + comms_send_f * link_sendf; + comms_plen_f * link_plenf; am_addr_t am_addr; @@ -43,22 +108,4 @@ struct comms_layer_am { am_addrdisco_t * disco; }; -// ActiveMessage address -am_addr_t comms_am_address(comms_layer_t* comms); -// ----------------------------------------------------------------------------- - -// Message manipulation functions for ActiveMessage layer ---------------------- -am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg); -void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest); - -am_addr_t comms_am_get_source(comms_layer_t* comms, const comms_msg_t* msg); -void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source); -// ----------------------------------------------------------------------------- - -// Create an ActiveMessage comms layer ----------------------------------------- -comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, - comms_send_f* sendf, comms_plen_f* plenf, - comms_start_f* startf, comms_stop_f* stopf); -// ----------------------------------------------------------------------------- - #endif//MIST_COMM_AM_H diff --git a/include/mist_comm_am_msg.h b/include/mist_comm_am_msg.h index ea5abc6..4dfc0a9 100644 --- a/include/mist_comm_am_msg.h +++ b/include/mist_comm_am_msg.h @@ -1,3 +1,9 @@ +/** + * Mist communications API TinyOS ActiveMessage message structure. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ #ifndef MIST_COMM_AM_MSG_H #define MIST_COMM_AM_MSG_H diff --git a/include/mist_comm_bridge.h b/include/mist_comm_bridge.h index a846ed4..f754d1c 100644 --- a/include/mist_comm_bridge.h +++ b/include/mist_comm_bridge.h @@ -6,7 +6,6 @@ * @license MIT * @author Raido Pahtma */ - #ifndef MIST_COMM_BRIDGE_H #define MIST_COMM_BRIDGE_H diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index f3d4044..cd9b379 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -1,3 +1,9 @@ +/** + * Mist communications interface structure. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ #ifndef MIST_COMM_IFACE_H #define MIST_COMM_IFACE_H diff --git a/include/mist_comm_ref.h b/include/mist_comm_ref.h index b166bc6..3bd7346 100644 --- a/include/mist_comm_ref.h +++ b/include/mist_comm_ref.h @@ -1,10 +1,27 @@ +/** + * Mist communications reference receiver manager. + * + * Copyright Thinnect Inc. 2021 + * @license MIT + */ #ifndef MIST_COMM_REF_H #define MIST_COMM_REF_H -// Add default receiver handling functionality to a layer implementation -comms_error_t comms_initialize_rcvr_management(comms_layer_iface_t* comms); +/** + * Add default receiver handling functionality to a layer implementation. + * + * @param comms Pointer to a comms layer. + * @return COMMS_SUCCESS if no errors. + */ +comms_error_t comms_initialize_rcvr_management (comms_layer_iface_t * comms); -// Deliver to registered receivers. No further actions taken on the message. -comms_error_t comms_basic_deliver(comms_layer_t* layer, comms_msg_t* msg); +/** + * Deliver a message to registered receivers. + * + * @param comms Pointer to a comms layer. + * @param msg The message to deliver. + * @return COMMS_SUCCESS or COMMS_NO_ADDR most often. + */ +comms_error_t comms_basic_deliver (comms_layer_t * comms, comms_msg_t * msg); #endif//MIST_COMM_REF_H diff --git a/include/mist_comm_routing.h b/include/mist_comm_routing.h index c1421fd..8ccc43f 100644 --- a/include/mist_comm_routing.h +++ b/include/mist_comm_routing.h @@ -10,30 +10,82 @@ #include "mist_comm_am.h" #include +// A communications layer that extends comms_layer_am_t with routing info. typedef struct comms_layer_am_mh comms_layer_am_mh_t; + +// Structure for a routing info handler. typedef struct comms_routing_info_handler comms_routing_info_handler_t; +/** + * Initialize routing callbacks for the communication layer. + * + * @param comms Pointer to a comms layer. + * @return COMMS_SUCCESS if intialized, an error otherwise. + */ comms_error_t comms_init_routing_result_callbacks (comms_layer_am_mh_t * comms); -void comms_routing_notify_routed (comms_layer_t * comms, am_addr_t dest, uint16_t cost, comms_error_t status); +/** + * Notify routing info handlers about a routing result. + * + * @param comms Pointer to a comms layer. + * @param dest Destination that was routed. + * @param cost Route cost ... implementation specific. + * @param status COMMS_SUCCESS if routed successfully. + */ +void comms_routing_notify_routed (comms_layer_t * comms, + am_addr_t dest, uint16_t cost, comms_error_t status); -typedef void comms_am_routed_f(comms_layer_t *, am_addr_t, uint16_t, comms_error_t, void*); +/** + * Routing result callback type definition. + * + * @param comms Pointer to a comms layer. + * @param dest Destination that was routed. + * @param cost Route cost ... implementation specific. + * @param status COMMS_SUCCESS if routed successfully. + * @param user User pointer passed during registration. + */ +typedef void comms_am_routed_f (comms_layer_t * comms, + am_addr_t dest, uint16_t cost, comms_error_t result, + void * user); +/** + * Register a routing info handler. + * + * @param comms Pointer to a comms layer. + * @param rih Pointer to routing info handler. + * @param func Routing info callback function. + * @param user User pointer to pass to callback, when called. + * @return COMMS_SUCCESS if registered. + */ comms_error_t comms_routing_register_result_callback (comms_layer_am_mh_t * comms, comms_routing_info_handler_t * rih, comms_am_routed_f * func, void * user); +/** + * De-register a routing info handler. + * + * @param comms Pointer to a comms layer. + * @param rih Pointer to routing info handler. + * @return COMMS_SUCCESS if no longer registered. + */ comms_error_t comms_routing_deregister_result_callback (comms_layer_am_mh_t * comms, comms_routing_info_handler_t * rih); +/** + * Routing info handler structure. + */ struct comms_routing_info_handler { comms_am_routed_f * callback; void * user; - comms_routing_info_handler_t * next; + comms_routing_info_handler_t * next; // A list of handlers is made for their storage }; -struct comms_layer_am_mh { +/** + * Routing info capable communications layer structure. + */ +struct comms_layer_am_mh +{ comms_layer_am_t base; comms_routing_info_handler_t * routing_info_handlers; }; From a2d2186a7f84a50f8a041871dcc0d477225fb73c Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 13 Dec 2021 19:59:58 +0200 Subject: [PATCH 78/80] Bunch of BARRification. --- LICENSE | 2 +- addrcache/mist_comm_addrcache.c | 2 +- addrcache/mist_comm_addrcache.h | 2 +- am/mist_comm_am.c | 209 ++++++++++++++++++--------- am/mist_comm_am_addrdisco.c | 2 +- am/mist_comm_am_addrdisco.h | 2 +- am/mist_comm_am_addrdisco_private.h | 2 +- am/mist_comm_am_addrdisco_protocol.h | 2 +- bridge/mist_comm_bridge.c | 2 +- cmsis/mist_comm_defer.c | 9 +- cmsis/mist_comm_mutex.c | 9 +- cmsis/mist_comm_mutex.h | 3 +- control/mist_comm_controller.c | 31 ++-- include/mist_comm_bridge.h | 3 +- mock/mist_comm_mutex.c | 11 +- mock/mist_comm_mutex.h | 2 +- mock/mist_mock_radio_cmsis.c | 2 +- mock/mist_mock_radio_cmsis.h | 2 +- routing/mist_comm_routing.c | 4 +- serial/serial_activemessage.c | 3 +- serial/serial_activemessage.h | 3 +- serial/serial_basicmessage.c | 3 +- serial/serial_basicmessage.h | 3 +- test/platform_msg.h | 6 +- test/sleep/test_sleep.c | 2 +- test/startstop/test_startstop.c | 2 +- util/fragmenter_assembler.c | 2 +- util/fragmenter_assembler.h | 2 +- 28 files changed, 191 insertions(+), 136 deletions(-) diff --git a/LICENSE b/LICENSE index 4b72ce8..74a7302 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Thinnect +Copyright (c) 2021 Thinnect Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/addrcache/mist_comm_addrcache.c b/addrcache/mist_comm_addrcache.c index 850cbeb..2e760a6 100644 --- a/addrcache/mist_comm_addrcache.c +++ b/addrcache/mist_comm_addrcache.c @@ -3,7 +3,7 @@ * * Will discard older elements when it runs out of space. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #include "mist_comm_addrcache.h" diff --git a/addrcache/mist_comm_addrcache.h b/addrcache/mist_comm_addrcache.h index 42975ad..f0c550c 100644 --- a/addrcache/mist_comm_addrcache.h +++ b/addrcache/mist_comm_addrcache.h @@ -1,7 +1,7 @@ /** * EUI64<->local address cache. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_COMM_ADDRCACHE_H_ diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 327d2f3..273e09f 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -1,7 +1,7 @@ /** * TinyOS ActiveMessage transport layer implementation. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ @@ -13,17 +13,20 @@ #include #include -am_addr_t comms_am_address(comms_layer_t* comms) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; +am_addr_t comms_am_address (comms_layer_t * comms) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; return amcomms->am_address(amcomms); } -static am_addr_t am_comms_addr(comms_layer_am_t* comms) { +static am_addr_t am_comms_addr (comms_layer_am_t * comms) +{ return comms->am_addr; } -static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) { - comms_am_msg_metadata_t* metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); +static void am_comms_init_message (comms_layer_iface_t * comms, comms_msg_t * msg) +{ + comms_am_msg_metadata_t * metadata = (comms_am_msg_metadata_t*)(msg->body.metadata); memset(&(msg->body.destination), 0, sizeof(msg->body.destination)); memset(&(msg->body.source), 0, sizeof(msg->body.source)); msg->body.type = 0; @@ -40,29 +43,30 @@ static void am_comms_init_message(comms_layer_iface_t* comms, comms_msg_t* msg) metadata->rssi = -128; } -static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { - comms_layer_t* comms = (comms_layer_t*)iface; - comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; +static bool am_comms_deliver (comms_layer_iface_t * iface, comms_msg_t * msg) +{ + comms_layer_t * comms = (comms_layer_t*)iface; + comms_layer_am_t * amcomms = (comms_layer_am_t*)iface; am_addr_t dest = comms_am_get_destination(comms, msg); comms_error_t result; // Attach the eui address of the source - if(false == comms_cache_get_eui(amcomms->cache, + if (false == comms_cache_get_eui(amcomms->cache, &(msg->body.source.local), &(msg->body.source.eui))) { eui64_set_zeros(&(msg->body.destination.eui)); } // Attach the eui address of the destination - if(AM_BROADCAST_ADDR == dest) + if (AM_BROADCAST_ADDR == dest) { eui64_set_ones(&(msg->body.destination.eui)); } - else if(amcomms->am_addr == dest) + else if (amcomms->am_addr == dest) { memcpy(&(msg->body.destination.eui), &(comms->eui), sizeof(ieee_eui64_t)); } - else if(false == comms_cache_get_eui(amcomms->cache, + else if (false == comms_cache_get_eui(amcomms->cache, &(msg->body.destination.local), &(msg->body.destination.eui))) { eui64_set_zeros(&(msg->body.destination.eui)); @@ -71,7 +75,7 @@ static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { result = comms_basic_deliver(comms, msg); // Request eui source address discovery, if it was necessary for receiver - if(COMMS_NO_ADDR == result) + if (COMMS_NO_ADDR == result) { comms_am_addrdisco_discover_eui(amcomms->disco, comms_am_get_source(comms, msg)); } @@ -79,17 +83,18 @@ static bool am_comms_deliver(comms_layer_iface_t* iface, comms_msg_t* msg) { return result == COMMS_SUCCESS; } -static comms_error_t am_comms_send(comms_layer_iface_t* iface, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { - comms_layer_t* comms = (comms_layer_t*)iface; - comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; +static comms_error_t am_comms_send (comms_layer_iface_t * iface, comms_msg_t * msg, comms_send_done_f * sdf, void * user) +{ + comms_layer_t * comms = (comms_layer_t*)iface; + comms_layer_am_t * amcomms = (comms_layer_am_t*)iface; - if(0 == comms_am_get_destination(comms, msg)) // Need to see if there is something in the address cache + if (0 == comms_am_get_destination(comms, msg)) // Need to see if there is something in the address cache { - if(eui64_is_ones(&(msg->body.destination.eui))) + if (eui64_is_ones(&(msg->body.destination.eui))) { comms_am_set_destination(comms, msg, AM_BROADCAST_ADDR); } - else if(false == comms_cache_get_local(amcomms->cache, + else if (false == comms_cache_get_local(amcomms->cache, &(msg->body.destination.eui), &(msg->body.destination.local))) { return COMMS_NO_ADDR; // Nothing retrieved from cache @@ -98,114 +103,161 @@ static comms_error_t am_comms_send(comms_layer_iface_t* iface, comms_msg_t* msg, return amcomms->link_sendf(iface, msg, sdf, user); } -static am_id_t am_comms_get_packet_type(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static am_id_t am_comms_get_packet_type (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return 0xFF & msg->body.type; } -static void am_comms_set_packet_type(comms_layer_iface_t* comms, comms_msg_t* msg, am_id_t ptype) { + +static void am_comms_set_packet_type (comms_layer_iface_t * comms, comms_msg_t * msg, am_id_t ptype) +{ msg->body.type = 0x3F00 + ptype; } -static uint16_t am_comms_get_packet_group(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint16_t am_comms_get_packet_group (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return msg->body.group; } -static void am_comms_set_packet_group(comms_layer_iface_t* comms, comms_msg_t* msg, uint16_t group) { + +static void am_comms_set_packet_group (comms_layer_iface_t * comms, comms_msg_t * msg, uint16_t group) +{ msg->body.group = group; } -static uint8_t am_comms_get_payload_max_length(comms_layer_iface_t* iface) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)iface; +static uint8_t am_comms_get_payload_max_length (comms_layer_iface_t * iface) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)iface; return amcomms->link_plenf(iface); } -static uint8_t am_comms_get_payload_length(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static uint8_t am_comms_get_payload_length (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return msg->body.length; } -static void am_comms_set_payload_length(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t length) { + +static void am_comms_set_payload_length (comms_layer_iface_t * comms, comms_msg_t * msg, uint8_t length) +{ msg->body.length = length; } -static void* am_comms_get_payload(comms_layer_iface_t* comms, const comms_msg_t* msg, uint8_t length) { - if(length < sizeof(msg->body.payload)) { + +static void * am_comms_get_payload (comms_layer_iface_t * comms, const comms_msg_t * msg, uint8_t length) +{ + if (length < sizeof(msg->body.payload)) + { return (void*)(msg->body.payload); } return NULL; } -static uint8_t am_comms_get_retries(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint8_t am_comms_get_retries (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->retries; } -static comms_error_t am_comms_set_retries(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { + +static comms_error_t am_comms_set_retries (comms_layer_iface_t * comms, comms_msg_t * msg, uint8_t count) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->retries = count; return COMMS_SUCCESS; } -static uint8_t am_comms_get_retries_used(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint8_t am_comms_get_retries_used (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->sent; } -static comms_error_t am_comms_set_retries_used(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t count) { + +static comms_error_t am_comms_set_retries_used (comms_layer_iface_t * comms, comms_msg_t * msg, uint8_t count) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->sent = count; return COMMS_SUCCESS; } -static uint32_t am_comms_get_timeout(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint32_t am_comms_get_timeout (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timeout; } -static comms_error_t am_comms_set_timeout(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timeout) { + +static comms_error_t am_comms_set_timeout (comms_layer_iface_t * comms, comms_msg_t * msg, uint32_t timeout) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->timeout = timeout; return COMMS_SUCCESS; } -static bool am_comms_is_ack_required(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static bool am_comms_is_ack_required (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_required; } -static comms_error_t am_comms_set_ack_required(comms_layer_iface_t* comms, comms_msg_t* msg, bool required) { + +static comms_error_t am_comms_set_ack_required (comms_layer_iface_t * comms, comms_msg_t * msg, bool required) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_required = required; return COMMS_SUCCESS; } -static bool am_comms_ack_received(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static bool am_comms_ack_received (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received; } -static void am_comms_set_ack_received(comms_layer_iface_t* comms, comms_msg_t* msg, bool acked) { + +static void am_comms_set_ack_received (comms_layer_iface_t * comms, comms_msg_t * msg, bool acked) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->ack_received = acked; } -static comms_error_t am_comms_set_timestamp(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t timestamp) { +static comms_error_t am_comms_set_timestamp (comms_layer_iface_t * comms, comms_msg_t * msg, uint32_t timestamp) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp = timestamp; ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp_valid = true; return COMMS_SUCCESS; } -static uint32_t am_comms_get_timestamp(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static uint32_t am_comms_get_timestamp (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp; } -static bool am_comms_timestamp_valid(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static bool am_comms_timestamp_valid (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->timestamp_valid; } -static comms_error_t am_comms_set_event_time(comms_layer_iface_t* comms, comms_msg_t* msg, uint32_t evt) { +static comms_error_t am_comms_set_event_time (comms_layer_iface_t * comms, comms_msg_t * msg, uint32_t evt) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time = evt; ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid = true; return COMMS_SUCCESS; } -static uint32_t am_comms_get_event_time(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static uint32_t am_comms_get_event_time (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time; } -static bool am_comms_event_time_valid(comms_layer_iface_t* comms, const comms_msg_t* msg) { + +static bool am_comms_event_time_valid (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->event_time_valid; } -static uint8_t am_comms_get_lqi(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint8_t am_comms_get_lqi (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi; } -static void am_comms_set_lqi(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t lqi) { + +static void am_comms_set_lqi (comms_layer_iface_t * comms, comms_msg_t * msg, uint8_t lqi) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->lqi = lqi; } -static int8_t am_comms_get_rssi(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static int8_t am_comms_get_rssi (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ return ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi; } -static void am_comms_set_rssi(comms_layer_iface_t* comms, comms_msg_t* msg, int8_t rssi) { + +static void am_comms_set_rssi (comms_layer_iface_t * comms, comms_msg_t * msg, int8_t rssi) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->rssi = rssi; } -static uint8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg_t* msg) { +static uint8_t am_comms_get_priority (comms_layer_iface_t * comms, const comms_msg_t * msg) +{ if (true == ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid) { return ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority; @@ -215,71 +267,86 @@ static uint8_t am_comms_get_priority(comms_layer_iface_t* comms, const comms_msg return 0xFF; } } -static void am_comms_set_priority(comms_layer_iface_t* comms, comms_msg_t* msg, uint8_t priority) { + +static void am_comms_set_priority (comms_layer_iface_t * comms, comms_msg_t * msg, uint8_t priority) +{ ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority_valid = true; ((comms_am_msg_metadata_t*)(msg->body.metadata))->priority = priority; } -static am_addr_t am_comms_get_destination(comms_layer_am_t* comms, const comms_msg_t* msg) { +static am_addr_t am_comms_get_destination (comms_layer_am_t * comms, const comms_msg_t * msg) +{ #ifdef ALIGN_CM0 return *((__packed am_addr_t*)msg->body.destination.local.data); #else return *((am_addr_t*)msg->body.destination.local.data); #endif } -static void am_comms_set_destination(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t dest) { + +static void am_comms_set_destination (comms_layer_am_t * comms, comms_msg_t * msg, am_addr_t dest) +{ memset(&(msg->body.destination.local), 0, sizeof(msg->body.destination.local)); #ifdef ALIGN_CM0 *((__packed am_addr_t*)msg->body.destination.local.data) = dest; #else *((am_addr_t*)msg->body.destination.local.data) = dest; #endif - msg->body.destination.updated = 0; + msg->body.destination.updated = 0; // FIXME - need a second-based counter //msg->body.destination.updated) = now_s(); } -static am_addr_t am_comms_get_source(comms_layer_am_t* comms, const comms_msg_t* msg) { +static am_addr_t am_comms_get_source (comms_layer_am_t * comms, const comms_msg_t * msg) +{ #ifdef ALIGN_CM0 return *((__packed am_addr_t*)msg->body.source.local.data); #else return *((am_addr_t*)msg->body.source.local.data); #endif } -static void am_comms_set_source(comms_layer_am_t* comms, comms_msg_t* msg, am_addr_t source) { + +static void am_comms_set_source (comms_layer_am_t * comms, comms_msg_t * msg, am_addr_t source) +{ memset(&(msg->body.source.local), 0, sizeof(msg->body.source.local)); #ifdef ALIGN_CM0 *((__packed am_addr_t*)msg->body.source.local.data) = source; #else *((am_addr_t*)msg->body.source.local.data) = source; #endif - msg->body.source.updated = 0; + msg->body.source.updated = 0; // FIXME - need a second-based counter //msg->body.source.updated = now_s(); } -am_addr_t comms_am_get_destination(comms_layer_t* comms, const comms_msg_t* msg) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; +am_addr_t comms_am_get_destination (comms_layer_t * comms, const comms_msg_t * msg) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; return amcomms->am_get_destination(amcomms, msg); } -void comms_am_set_destination(comms_layer_t* comms, comms_msg_t* msg, am_addr_t dest) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + +void comms_am_set_destination (comms_layer_t * comms, comms_msg_t * msg, am_addr_t dest) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; amcomms->am_set_destination(amcomms, msg, dest); } -am_addr_t comms_am_get_source(comms_layer_t* comms, const comms_msg_t* msg) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; +am_addr_t comms_am_get_source (comms_layer_t * comms, const comms_msg_t * msg) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; return amcomms->am_get_source(amcomms, msg); } -void comms_am_set_source(comms_layer_t* comms, comms_msg_t* msg, am_addr_t source) { - comms_layer_am_t* amcomms = (comms_layer_am_t*)comms; + +void comms_am_set_source (comms_layer_t * comms, comms_msg_t * msg, am_addr_t source) +{ + comms_layer_am_t * amcomms = (comms_layer_am_t*)comms; amcomms->am_set_source(amcomms, msg, source); } -comms_error_t comms_am_create(comms_layer_t* layer, am_addr_t address, - comms_send_f* sendf, comms_plen_f* plenf, - comms_start_f* startf, comms_stop_f* stopf) { +comms_error_t comms_am_create (comms_layer_t * layer, am_addr_t address, + comms_send_f * sendf, comms_plen_f * plenf, + comms_start_f * startf, comms_stop_f * stopf) +{ - comms_layer_iface_t* comms = (comms_layer_iface_t*)layer; - comms_layer_am_t* amcomms = (comms_layer_am_t*)layer; + comms_layer_iface_t * comms = (comms_layer_iface_t*)layer; + comms_layer_am_t * amcomms = (comms_layer_am_t*)layer; comms->start = startf; comms->stop = stopf; diff --git a/am/mist_comm_am_addrdisco.c b/am/mist_comm_am_addrdisco.c index 0ba75af..3eca427 100644 --- a/am/mist_comm_am_addrdisco.c +++ b/am/mist_comm_am_addrdisco.c @@ -2,7 +2,7 @@ * EUI and link-local address discovery implementation for * the TinyOS ActiveMessage transport layer. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ diff --git a/am/mist_comm_am_addrdisco.h b/am/mist_comm_am_addrdisco.h index 2db5cbc..961037e 100644 --- a/am/mist_comm_am_addrdisco.h +++ b/am/mist_comm_am_addrdisco.h @@ -1,7 +1,7 @@ /** * EUI and link-local address discovery for the TinyOS ActiveMessage transport layer. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_COMM_AM_ADDRDISCO_H_ diff --git a/am/mist_comm_am_addrdisco_private.h b/am/mist_comm_am_addrdisco_private.h index aba9070..074982e 100644 --- a/am/mist_comm_am_addrdisco_private.h +++ b/am/mist_comm_am_addrdisco_private.h @@ -1,7 +1,7 @@ /** * Active Message address discovery object structure. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_COMM_AM_ADDRDISCO_PRIVATE_H_ diff --git a/am/mist_comm_am_addrdisco_protocol.h b/am/mist_comm_am_addrdisco_protocol.h index 623496a..949f4af 100644 --- a/am/mist_comm_am_addrdisco_protocol.h +++ b/am/mist_comm_am_addrdisco_protocol.h @@ -7,7 +7,7 @@ * discover the EUI64 address. * A broadcast message with the guid field set to all ones is forbidden. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_COMM_AM_ADDRDISCO_PROTOCOL_H_ diff --git a/bridge/mist_comm_bridge.c b/bridge/mist_comm_bridge.c index c220ce8..e961ddf 100644 --- a/bridge/mist_comm_bridge.c +++ b/bridge/mist_comm_bridge.c @@ -2,7 +2,7 @@ * MistComm bridge implementation. * Bridge messages between 2 mist-comm communication interfaces. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT */ diff --git a/cmsis/mist_comm_defer.c b/cmsis/mist_comm_defer.c index 6fcce79..d1bdd40 100644 --- a/cmsis/mist_comm_defer.c +++ b/cmsis/mist_comm_defer.c @@ -1,9 +1,8 @@ /** * MistComm deferred implementation on CMSIS with a timer. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #include "mist_comm_private.h" @@ -14,7 +13,7 @@ * Initialize a deferred. In this case deferreds are implemented through an * os timer. */ -void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferred_f * cb) +void _comms_deferred_init (comms_layer_t * comms, void ** deferred, comms_deferred_f * cb) { *deferred = osTimerNew(cb, osTimerOnce, (void*)comms, NULL); } @@ -23,7 +22,7 @@ void _comms_deferred_init(comms_layer_t * comms, void ** deferred, comms_deferre * This is a slow implementation, will take at least a millisecond to run * the deferred. */ -void _comms_defer(void * deferred) +void _comms_defer (void * deferred) { osTimerStart((osTimerId_t)deferred, 1); } @@ -31,7 +30,7 @@ void _comms_defer(void * deferred) /** * Free the resources allocated for the deferred. */ -void _comms_deferred_deinit(void * deferred) +void _comms_deferred_deinit (void * deferred) { osTimerDelete((osTimerId_t)deferred); } diff --git a/cmsis/mist_comm_mutex.c b/cmsis/mist_comm_mutex.c index 16f43f4..708fc1a 100644 --- a/cmsis/mist_comm_mutex.c +++ b/cmsis/mist_comm_mutex.c @@ -1,9 +1,8 @@ /** * MistComm locking implementation with CMSIS mutexes. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #include "mist_comm_iface.h" @@ -12,17 +11,17 @@ static const osMutexAttr_t attr = {"comms", osMutexPrioInherit, NULL, 0U}; -void comms_mutex_acquire(commsMutexId_t mutex) +void comms_mutex_acquire (commsMutexId_t mutex) { while(osOK != osMutexAcquire((osMutexId_t)(mutex), osWaitForever)); } -void comms_mutex_release(commsMutexId_t mutex) +void comms_mutex_release (commsMutexId_t mutex) { osMutexRelease((osMutexId_t)mutex); } -commsMutexId_t comms_mutex_create() +commsMutexId_t comms_mutex_create (void) { return (commsMutexId_t)osMutexNew(&attr); } diff --git a/cmsis/mist_comm_mutex.h b/cmsis/mist_comm_mutex.h index 25ea493..0087136 100644 --- a/cmsis/mist_comm_mutex.h +++ b/cmsis/mist_comm_mutex.h @@ -1,9 +1,8 @@ /** * MistComm locking with CMSIS mutexes. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #ifndef MIST_COMM_MUTEX_H #define MIST_COMM_MUTEX_H diff --git a/control/mist_comm_controller.c b/control/mist_comm_controller.c index 46c85ff..14ddfd0 100644 --- a/control/mist_comm_controller.c +++ b/control/mist_comm_controller.c @@ -1,8 +1,7 @@ /** * Sleep controller implementation. * - * Copyright Thinnect Inc. 2019 - * @author Raido Pahtma + * Copyright Thinnect Inc. 2021 * @license MIT */ @@ -14,23 +13,23 @@ #define __LOG_LEVEL__ (LOG_LEVEL_mist_comm_controller & BASE_LOG_LEVEL) #include "log.h" -static bool unsafe_update_state(comms_layer_t * comms); -static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t status); +static bool unsafe_update_state (comms_layer_t * comms); +static bool unsafe_service_callbacks (comms_layer_t * comms, comms_status_t status); -static void status_change_callback(comms_layer_t * comms, comms_status_t status, void * user) +static void status_change_callback (comms_layer_t * comms, comms_status_t status, void * user) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; bool ok; comms_mutex_acquire(cl->controller_mutex); ok = unsafe_service_callbacks(comms, status); comms_mutex_release(cl->controller_mutex); - if (!ok) + if ( ! ok) { _comms_defer(cl->sleep_controller_deferred); } } -static void deferred_callback(void * arg) +static void deferred_callback (void * arg) { comms_layer_t * comms = (comms_layer_t*)arg; comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; @@ -38,7 +37,7 @@ static void deferred_callback(void * arg) comms_mutex_acquire(cl->controller_mutex); ok = unsafe_update_state(comms); comms_mutex_release(cl->controller_mutex); - if (!ok) + if ( ! ok) { _comms_defer(cl->sleep_controller_deferred); } @@ -49,7 +48,7 @@ static void deferred_callback(void * arg) * * @return true if current state is good, false if state needs to be changed. */ -static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t status) +static bool unsafe_service_callbacks (comms_layer_t * comms, comms_status_t status) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_sleep_controller_t** indirect; @@ -83,7 +82,7 @@ static bool unsafe_service_callbacks(comms_layer_t * comms, comms_status_t statu * * @return true if current state is good, false if state needs to be changed. */ -static bool unsafe_update_state(comms_layer_t * comms) +static bool unsafe_update_state (comms_layer_t * comms) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_status_t status = comms_status(comms); @@ -114,8 +113,8 @@ static bool unsafe_update_state(comms_layer_t * comms) return true; } -comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl, - comms_status_change_f * start_done, void * user) +comms_error_t comms_register_sleep_controller (comms_layer_t * comms, comms_sleep_controller_t * ctrl, + comms_status_change_f * start_done, void * user) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_error_t err = COMMS_SUCCESS; @@ -154,7 +153,7 @@ comms_error_t comms_register_sleep_controller(comms_layer_t * comms, comms_sleep return err; } -comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sleep_controller_t * ctrl) +comms_error_t comms_deregister_sleep_controller (comms_layer_t * comms, comms_sleep_controller_t * ctrl) { comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_error_t err = COMMS_FAIL; @@ -185,7 +184,7 @@ comms_error_t comms_deregister_sleep_controller(comms_layer_t * comms, comms_sle } // Block may be asynchronous, wakeup may take time, or EALREADY may be returned -comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl) +comms_error_t comms_sleep_block (comms_sleep_controller_t * ctrl) { comms_error_t err = COMMS_EINVAL; if ((NULL != ctrl)&&(NULL != ctrl->comms)) @@ -226,7 +225,7 @@ comms_error_t comms_sleep_block(comms_sleep_controller_t * ctrl) } // Allow is synchronous, sleep is not guaranteed, but block is released immediately -comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl) +comms_error_t comms_sleep_allow (comms_sleep_controller_t * ctrl) { comms_error_t err = COMMS_EINVAL; if ((NULL != ctrl)&&(NULL != ctrl->comms)) @@ -257,7 +256,7 @@ comms_error_t comms_sleep_allow(comms_sleep_controller_t * ctrl) return err; } -bool comms_sleep_blocked(comms_sleep_controller_t * ctrl) +bool comms_sleep_blocked (comms_sleep_controller_t * ctrl) { comms_layer_iface_t * cl = (comms_layer_iface_t*)(ctrl->comms); bool blocked; diff --git a/include/mist_comm_bridge.h b/include/mist_comm_bridge.h index f754d1c..e992df8 100644 --- a/include/mist_comm_bridge.h +++ b/include/mist_comm_bridge.h @@ -2,9 +2,8 @@ * MistComm bridge. * Bridge messages between 2 mist-comm communication interfaces. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #ifndef MIST_COMM_BRIDGE_H #define MIST_COMM_BRIDGE_H diff --git a/mock/mist_comm_mutex.c b/mock/mist_comm_mutex.c index 2693fe3..6fe9e2f 100644 --- a/mock/mist_comm_mutex.c +++ b/mock/mist_comm_mutex.c @@ -1,9 +1,8 @@ /** * MistComm locking implementation with mock mutexes. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #include "mist_comm_iface.h" @@ -12,18 +11,18 @@ static volatile bool m_mutexes[8]; static intptr_t m_mutex_count = 0; -void comms_mutex_acquire(commsMutexId_t mutex) +void comms_mutex_acquire (commsMutexId_t mutex) { - while(m_mutexes[(intptr_t)mutex]); + while (m_mutexes[(intptr_t)mutex]); m_mutexes[(intptr_t)mutex] = true; } -void comms_mutex_release(commsMutexId_t mutex) +void comms_mutex_release (commsMutexId_t mutex) { m_mutexes[(intptr_t)mutex] = false; } -commsMutexId_t comms_mutex_create(void) +commsMutexId_t comms_mutex_create (void) { m_mutexes[m_mutex_count] = false; return (commsMutexId_t)m_mutex_count++; diff --git a/mock/mist_comm_mutex.h b/mock/mist_comm_mutex.h index 0e39c94..3f9f90f 100644 --- a/mock/mist_comm_mutex.h +++ b/mock/mist_comm_mutex.h @@ -1,7 +1,7 @@ /** * MistComm locking with mock mutexes. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_COMM_MUTEX_H diff --git a/mock/mist_mock_radio_cmsis.c b/mock/mist_mock_radio_cmsis.c index 1bc5257..bdb28b0 100644 --- a/mock/mist_mock_radio_cmsis.c +++ b/mock/mist_mock_radio_cmsis.c @@ -2,7 +2,7 @@ * MistComm mock radio layer. * Exports outgoing messages, giving send done events to users. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #include "mist_comm_am.h" diff --git a/mock/mist_mock_radio_cmsis.h b/mock/mist_mock_radio_cmsis.h index dacb09c..06596e7 100644 --- a/mock/mist_mock_radio_cmsis.h +++ b/mock/mist_mock_radio_cmsis.h @@ -2,7 +2,7 @@ * MistComm mock radio layer. * Exports outgoing messages, giving send done events to users. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef MIST_MOCK_RADIO_CMSIS_H diff --git a/routing/mist_comm_routing.c b/routing/mist_comm_routing.c index be0abb7..c599155 100644 --- a/routing/mist_comm_routing.c +++ b/routing/mist_comm_routing.c @@ -1,10 +1,8 @@ /** * Routing info callback handlers for the MistComm API. * - * Copyright Thinnect Inc. 2019 - * + * Copyright Thinnect Inc. 2021 * @license MIT - * @author Raido Pahtma */ #include "mist_comm_routing.h" diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index d86a451..db6cd3a 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -1,8 +1,7 @@ /** * MistComm SerialActiveMessage layer implementation. * -* Copyright Thinnect Inc. 2020 -* @author Raido Pahtma +* Copyright Thinnect Inc. 2021 * @license MIT */ #include diff --git a/serial/serial_activemessage.h b/serial/serial_activemessage.h index fbb4002..8e25921 100644 --- a/serial/serial_activemessage.h +++ b/serial/serial_activemessage.h @@ -4,8 +4,7 @@ * Many instances can be created, each needs a serial_protocol. * Instances will set up a dispatcher with dispatch ID 0x00. * -* Copyright Thinnect Inc. 2020 -* @author Raido Pahtma +* Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef SERIAL_ACTIVEMESSAGE_H_ diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index 6d676e3..af9c659 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -1,8 +1,7 @@ /** * MistComm SerialBasicMessage layer implementation. * -* Copyright Thinnect Inc. 2020 -* @author Raido Pahtma +* Copyright Thinnect Inc. 2021 * @license MIT */ #include diff --git a/serial/serial_basicmessage.h b/serial/serial_basicmessage.h index 7e5423c..ba1566e 100644 --- a/serial/serial_basicmessage.h +++ b/serial/serial_basicmessage.h @@ -3,8 +3,7 @@ * * Many instances can be created, each needs a serial_protocol. * -* Copyright Thinnect Inc. 2020 -* @author Raido Pahtma +* Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef SERIAL_BASICMESSAGE_H_ diff --git a/test/platform_msg.h b/test/platform_msg.h index c828957..68282c6 100644 --- a/test/platform_msg.h +++ b/test/platform_msg.h @@ -1,5 +1,5 @@ -#ifndef PLATFORM_MSG_H_ -#define PLATFORM_MSG_H_ +#ifndef PLATFORM_MSG_H +#define PLATFORM_MSG_H #include "mist_comm_am_msg.h" @@ -9,4 +9,4 @@ #define COMMS_MSG_FOOTER_SIZE 0 #define COMMS_MSG_METADATA_SIZE sizeof(comms_am_msg_metadata_t) -#endif//PLATFORM_MSG_H_ +#endif//PLATFORM_MSG_H diff --git a/test/sleep/test_sleep.c b/test/sleep/test_sleep.c index 1dd440d..bad8c9e 100644 --- a/test/sleep/test_sleep.c +++ b/test/sleep/test_sleep.c @@ -1,7 +1,7 @@ /** * Unit-Tests for the MistComm start-stop functionality. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT */ diff --git a/test/startstop/test_startstop.c b/test/startstop/test_startstop.c index e33797b..f28e7a3 100644 --- a/test/startstop/test_startstop.c +++ b/test/startstop/test_startstop.c @@ -1,7 +1,7 @@ /** * Unit-Tests for the MistComm start-stop functionality. * - * Copyright Thinnect Inc. 2019 + * Copyright Thinnect Inc. 2021 * @license MIT */ diff --git a/util/fragmenter_assembler.c b/util/fragmenter_assembler.c index 236cf43..3c42b56 100644 --- a/util/fragmenter_assembler.c +++ b/util/fragmenter_assembler.c @@ -4,7 +4,7 @@ * fragment need to be of this size, the last one can be shorter. * Maximum number of fragments is 8, maximum data size is 255 bytes. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #include "fragmenter_assembler.h" diff --git a/util/fragmenter_assembler.h b/util/fragmenter_assembler.h index 2ba054a..25c51e4 100644 --- a/util/fragmenter_assembler.h +++ b/util/fragmenter_assembler.h @@ -4,7 +4,7 @@ * fragment need to be of this size, the last one can be shorter. * Maximum number of fragments is 8, maximum data size is 255 bytes. * - * Copyright Thinnect Inc. 2020 + * Copyright Thinnect Inc. 2021 * @license MIT */ #ifndef FRAGMENTER_ASSEMBLER_H_ From b94117549cdc922b963acdf7cb10cd5490113682 Mon Sep 17 00:00:00 2001 From: Raido Date: Mon, 20 Dec 2021 15:52:51 +0200 Subject: [PATCH 79/80] Time ref api. --- am/mist_comm_am.c | 3 +++ api/mist_comm_api.c | 15 +++++++++++++-- include/mist_comm_am.h | 2 ++ include/mist_comm_iface.h | 4 ++++ serial/serial_activemessage.c | 1 + serial/serial_basicmessage.c | 1 + 6 files changed, 24 insertions(+), 2 deletions(-) diff --git a/am/mist_comm_am.c b/am/mist_comm_am.c index 273e09f..d730e87 100644 --- a/am/mist_comm_am.c +++ b/am/mist_comm_am.c @@ -342,6 +342,7 @@ void comms_am_set_source (comms_layer_t * comms, comms_msg_t * msg, am_addr_t so comms_error_t comms_am_create (comms_layer_t * layer, am_addr_t address, comms_send_f * sendf, comms_plen_f * plenf, + comms_get_time_micro_f * gtmf, comms_start_f * startf, comms_stop_f * stopf) { @@ -392,6 +393,8 @@ comms_error_t comms_am_create (comms_layer_t * layer, am_addr_t address, comms->ack_received = &am_comms_ack_received; comms->set_ack_received = &am_comms_set_ack_received; + comms->get_time_micro = gtmf; + comms->set_timestamp = &am_comms_set_timestamp; comms->get_timestamp = &am_comms_get_timestamp; comms->timestamp_valid = &am_comms_timestamp_valid; diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index c4e83c7..ec2c6ad 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -11,8 +11,8 @@ #include #include -volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR); -volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR); +volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR) = MIST_COMM_VERSION_MAJOR; +volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR) = MIST_COMM_VERSION_MINOR; static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; @@ -299,6 +299,17 @@ void comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg, bool receive } } +uint32_t comms_get_time_micro(comms_layer_t* comms) { + if(comms != NULL) { + comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; + if (NULL != cl->get_time_micro) + { + return cl->get_time_micro(cl); + } + } + return 0; +} + comms_error_t comms_set_timestamp_micro(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { if((msg != NULL)&&(comms != NULL)) { comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; diff --git a/include/mist_comm_am.h b/include/mist_comm_am.h index f40bda3..ada8884 100644 --- a/include/mist_comm_am.h +++ b/include/mist_comm_am.h @@ -67,12 +67,14 @@ void comms_am_set_source (comms_layer_t * comms, comms_msg_t * msg, am_addr_t so * @param address ActiveMessage address for this layer * @param sendf Actual send function to use for sending the message. * @param plenf Max payload length function for the underlying comms component. + * @param gtmf Time reference function. * @param startf Layer start function (can be NULL, if always active). * @param stopf Layer stop function (can be NULL, if always active). * @return COMMS_SUCCESS if initialized correctly. */ comms_error_t comms_am_create (comms_layer_t * layer, am_addr_t address, comms_send_f * sendf, comms_plen_f * plenf, + comms_get_time_micro_f * gtmf, comms_start_f * startf, comms_stop_f * stopf); diff --git a/include/mist_comm_iface.h b/include/mist_comm_iface.h index cd9b379..7d5ed18 100644 --- a/include/mist_comm_iface.h +++ b/include/mist_comm_iface.h @@ -54,6 +54,8 @@ typedef comms_error_t comms_set_ack_required_f(comms_layer_iface_t*, comms_msg_t typedef bool comms_ack_received_f(comms_layer_iface_t*, const comms_msg_t*); typedef void comms_set_ack_received_f(comms_layer_iface_t*, comms_msg_t*, bool); +typedef uint32_t comms_get_time_micro_f(comms_layer_iface_t*); + typedef comms_error_t comms_set_timestamp_f(comms_layer_iface_t*, comms_msg_t*, uint32_t); typedef uint32_t comms_get_timestamp_f(comms_layer_iface_t*, const comms_msg_t*); typedef bool comms_timestamp_valid_f(comms_layer_iface_t*, const comms_msg_t*); @@ -116,6 +118,8 @@ struct comms_layer_iface { comms_ack_received_f* ack_received; comms_set_ack_received_f* set_ack_received; + comms_get_time_micro_f* get_time_micro; + comms_set_timestamp_f* set_timestamp; comms_get_timestamp_f* get_timestamp; comms_timestamp_valid_f* timestamp_valid; diff --git a/serial/serial_activemessage.c b/serial/serial_activemessage.c index db6cd3a..e42cd9a 100644 --- a/serial/serial_activemessage.c +++ b/serial/serial_activemessage.c @@ -79,6 +79,7 @@ comms_layer_t * serial_activemessage_init (serial_activemessage_t* sam, serial_p // TODO start-stop handlers comms_am_create((comms_layer_t *)sam, address, &serial_activemessage_send, &serial_activemessage_max_length, + NULL, NULL, NULL); // serial_activemessage_t is a valid comms_layer_t diff --git a/serial/serial_basicmessage.c b/serial/serial_basicmessage.c index af9c659..e8a63fb 100644 --- a/serial/serial_basicmessage.c +++ b/serial/serial_basicmessage.c @@ -64,6 +64,7 @@ comms_layer_t * serial_basicmessage_init (serial_basicmessage_t * sbm, serial_pr // TODO start-stop handlers comms_am_create((comms_layer_t *)sbm, 0, &serial_basicmessage_send, &serial_basicmessage_max_length, + NULL, NULL, NULL); // serial_basicmessage_t is a semi-valid comms_layer_t From 0d290085d3c72a31db6e969d508a41890b2c92eb Mon Sep 17 00:00:00 2001 From: Raido Date: Tue, 21 Dec 2021 15:26:42 +0200 Subject: [PATCH 80/80] Reformat for BARR. --- api/mist_comm_api.c | 361 ++++++++++++++++++++++++++++---------------- 1 file changed, 229 insertions(+), 132 deletions(-) diff --git a/api/mist_comm_api.c b/api/mist_comm_api.c index ec2c6ad..fea0d33 100644 --- a/api/mist_comm_api.c +++ b/api/mist_comm_api.c @@ -14,8 +14,9 @@ volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_major_, MIST_COMM_VERSION_MAJOR) = MIST_COMM_VERSION_MAJOR; volatile uint8_t MIST_COMM_VERSION_PASTER(g_mist_comm_version_minor_, MIST_COMM_VERSION_MINOR) = MIST_COMM_VERSION_MINOR; -static void comms_status_change_callback(comms_layer_t* comms, comms_status_t status, void* user) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +static void comms_status_change_callback (comms_layer_t * comms, comms_status_t status, void * user) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_mutex_acquire(cl->start_stop_mutex); cl->status_change_user_cb(comms, status, cl->status_change_user); @@ -25,20 +26,26 @@ static void comms_status_change_callback(comms_layer_t* comms, comms_status_t st comms_mutex_release(cl->start_stop_mutex); } -comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_done, void* user) { - if((NULL != comms)&&(NULL != start_done)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - if(NULL != cl->start) { +comms_error_t comms_start (comms_layer_t * comms, comms_status_change_f* start_done, void * user) +{ + if ((NULL != comms)&&(NULL != start_done)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + if (NULL != cl->start) + { comms_mutex_acquire(cl->start_stop_mutex); - if(NULL != cl->status_change_user_cb) { + if (NULL != cl->status_change_user_cb) + { comms_mutex_release(cl->start_stop_mutex); return COMMS_EBUSY; } - else if(COMMS_STARTED == cl->status) { + else if (COMMS_STARTED == cl->status) + { comms_mutex_release(cl->start_stop_mutex); return COMMS_ALREADY; } - else { + else + { comms_status_t status = cl->status; cl->status = COMMS_STARTING; cl->status_change_user_cb = start_done; @@ -46,7 +53,8 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don comms_mutex_release(cl->start_stop_mutex); comms_error_t err = cl->start(cl, &comms_status_change_callback, NULL); - if(COMMS_SUCCESS != err) { + if (COMMS_SUCCESS != err) + { comms_mutex_acquire(cl->start_stop_mutex); cl->status = status; cl->status_change_user_cb = NULL; @@ -60,20 +68,26 @@ comms_error_t comms_start(comms_layer_t* comms, comms_status_change_f* start_don return COMMS_EINVAL; } -comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, void* user) { - if((NULL != comms)&&(NULL != stop_done)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; - if(NULL != cl->stop) { +comms_error_t comms_stop (comms_layer_t * comms, comms_status_change_f* stop_done, void * user) +{ + if ((NULL != comms)&&(NULL != stop_done)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; + if (NULL != cl->stop) + { comms_mutex_acquire(cl->start_stop_mutex); - if(NULL != cl->status_change_user_cb) { + if (NULL != cl->status_change_user_cb) + { comms_mutex_release(cl->start_stop_mutex); return COMMS_EBUSY; } - else if(COMMS_STOPPED == cl->status) { + else if (COMMS_STOPPED == cl->status) + { comms_mutex_release(cl->start_stop_mutex); return COMMS_ALREADY; } - else { + else + { comms_status_t status = cl->status; cl->status = COMMS_STOPPING; cl->status_change_user_cb = stop_done; @@ -81,7 +95,8 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, comms_mutex_release(cl->start_stop_mutex); comms_error_t err = cl->stop(cl, &comms_status_change_callback, NULL); - if(COMMS_SUCCESS != err) { + if (COMMS_SUCCESS != err) + { comms_mutex_acquire(cl->start_stop_mutex); cl->status = status; cl->status_change_user_cb = NULL; @@ -95,8 +110,9 @@ comms_error_t comms_stop(comms_layer_t* comms, comms_status_change_f* stop_done, return COMMS_EINVAL; } -comms_status_t comms_status(comms_layer_t* comms) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_status_t comms_status (comms_layer_t * comms) +{ + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; comms_status_t status; comms_mutex_acquire(cl->start_stop_mutex); status = cl->status; @@ -104,204 +120,261 @@ comms_status_t comms_status(comms_layer_t* comms) { return status; } -void comms_init_message(comms_layer_t* comms, comms_msg_t* msg) { - if((comms != NULL)&&(msg != NULL)) { +void comms_init_message (comms_layer_t * comms, comms_msg_t * msg) +{ + if ((NULL != comms)&&(NULL != msg)) + { ((comms_layer_iface_t*)comms)->init_message((comms_layer_iface_t*)comms, msg); } } -void comms_get_destination(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* destination) { +void comms_get_destination (comms_layer_t * comms, const comms_msg_t * msg, comms_address_t * destination) +{ memcpy(destination, &(msg->body.destination), sizeof(comms_address_t)); } -void comms_set_destination(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* destination) { +void comms_set_destination (comms_layer_t * comms, comms_msg_t * msg, const comms_address_t * destination) +{ memcpy(&(msg->body.destination), destination, sizeof(comms_address_t)); } -void comms_get_source(comms_layer_t* comms, const comms_msg_t* msg, comms_address_t* source) { +void comms_get_source (comms_layer_t * comms, const comms_msg_t * msg, comms_address_t * source) +{ memcpy(source, &(msg->body.source), sizeof(comms_address_t)); } -void comms_set_source(comms_layer_t* comms, comms_msg_t* msg, const comms_address_t* source) { +void comms_set_source (comms_layer_t * comms, comms_msg_t * msg, const comms_address_t * source) +{ memcpy(&(msg->body.source), source, sizeof(comms_address_t)); } -comms_error_t comms_send(comms_layer_t* comms, comms_msg_t* msg, comms_send_done_f* sdf, void* user) { - if(comms != NULL) { +comms_error_t comms_send (comms_layer_t * comms, comms_msg_t * msg, comms_send_done_f* sdf, void * user) +{ + if (NULL != comms) + { return ((comms_layer_iface_t*)comms)->sendf((comms_layer_iface_t*)comms, msg, sdf, user); } return COMMS_EINVAL; } -bool comms_deliver(comms_layer_t* comms, comms_msg_t* msg) { - comms_layer_iface_t* iface = (comms_layer_iface_t*)comms; - if((iface != NULL)&&(iface->deliverf != NULL)) { +bool comms_deliver (comms_layer_t * comms, comms_msg_t * msg) +{ + comms_layer_iface_t * iface = (comms_layer_iface_t*)comms; + if ((iface != NULL)&&(iface->deliverf != NULL)) + { return iface->deliverf(iface, msg); } return false; } -comms_error_t comms_register_recv(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { - if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { +comms_error_t comms_register_recv (comms_layer_t * comms, comms_receiver_t* rcvr, comms_receive_f* func, void * user, am_id_t amid) +{ + if ((NULL != comms)&&(rcvr != NULL)&&(func != NULL)) + { return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid, false); } return COMMS_EINVAL; } -comms_error_t comms_register_recv_eui(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user, am_id_t amid) { - if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { +comms_error_t comms_register_recv_eui (comms_layer_t * comms, comms_receiver_t* rcvr, comms_receive_f* func, void * user, am_id_t amid) +{ + if ((NULL != comms)&&(rcvr != NULL)&&(func != NULL)) + { return ((comms_layer_iface_t*)comms)->register_recv((comms_layer_iface_t*)comms, rcvr, func, user, amid, true); } return COMMS_EINVAL; } -comms_error_t comms_deregister_recv(comms_layer_t* comms, comms_receiver_t* rcvr) { - if(comms != NULL) { +comms_error_t comms_deregister_recv (comms_layer_t * comms, comms_receiver_t* rcvr) +{ + if (NULL != comms) + { return ((comms_layer_iface_t*)comms)->deregister_recv((comms_layer_iface_t*)comms, rcvr); } return COMMS_EINVAL; } -comms_error_t comms_register_snooper(comms_layer_t* comms, comms_receiver_t* rcvr, comms_receive_f* func, void* user) { - if((comms != NULL)&&(rcvr != NULL)&&(func != NULL)) { +comms_error_t comms_register_snooper (comms_layer_t * comms, comms_receiver_t* rcvr, comms_receive_f* func, void * user) +{ + if ((NULL != comms)&&(rcvr != NULL)&&(func != NULL)) + { return ((comms_layer_iface_t*)comms)->register_snooper((comms_layer_iface_t*)comms, rcvr, func, user); } return COMMS_EINVAL; } -comms_error_t comms_deregister_snooper(comms_layer_t* comms, comms_receiver_t* rcvr) { - if(comms != NULL) { +comms_error_t comms_deregister_snooper (comms_layer_t * comms, comms_receiver_t* rcvr) +{ + if (NULL != comms) + { return ((comms_layer_iface_t*)comms)->deregister_snooper((comms_layer_iface_t*)comms, rcvr); } return COMMS_EINVAL; } -am_id_t comms_get_packet_type(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +am_id_t comms_get_packet_type (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_packet_type(cl, msg); } return 0; } -void comms_set_packet_type(comms_layer_t* comms, comms_msg_t* msg, am_id_t ptype) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_packet_type (comms_layer_t * comms, comms_msg_t * msg, am_id_t ptype) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_packet_type(cl, msg, ptype); } } -uint16_t comms_get_packet_group(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint16_t comms_get_packet_group (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_packet_group(cl, msg); } return 0; } -void comms_set_packet_group(comms_layer_t* comms, comms_msg_t* msg, uint16_t group) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_packet_group (comms_layer_t * comms, comms_msg_t * msg, uint16_t group) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_packet_group(cl, msg, group); } } -uint8_t comms_get_payload_max_length(comms_layer_t* comms) { +uint8_t comms_get_payload_max_length (comms_layer_t * comms) +{ return ((comms_layer_iface_t*)comms)->get_payload_max_length((comms_layer_iface_t*)comms); } -uint8_t comms_get_payload_length(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint8_t comms_get_payload_length (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_payload_length(cl, msg); } return 0; } -void comms_set_payload_length(comms_layer_t* comms, comms_msg_t* msg, uint8_t length) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_payload_length (comms_layer_t * comms, comms_msg_t * msg, uint8_t length) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_payload_length(cl, msg, length); } } -void* comms_get_payload(comms_layer_t* comms, const comms_msg_t* msg, uint8_t length) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void * comms_get_payload (comms_layer_t * comms, const comms_msg_t * msg, uint8_t length) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_payload(cl, msg, length); } return NULL; } -uint8_t comms_get_retries(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint8_t comms_get_retries (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_retries(cl, msg); } return 0; } -comms_error_t comms_set_retries(comms_layer_t* comms, comms_msg_t* msg, uint8_t count) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_retries (comms_layer_t * comms, comms_msg_t * msg, uint8_t count) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_retries(cl, msg, count); } return COMMS_EINVAL; } -uint8_t comms_get_retries_used(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint8_t comms_get_retries_used (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_retries_used(cl, msg); } return 0; } -comms_error_t comms_set_retries_used(comms_layer_t* comms, comms_msg_t* msg, uint8_t count) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_retries_used (comms_layer_t * comms, comms_msg_t * msg, uint8_t count) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_retries_used(cl, msg, count); } return COMMS_EINVAL; } -uint32_t comms_get_timeout(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint32_t comms_get_timeout (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_timeout(cl, msg); } return 0; } -comms_error_t comms_set_timeout(comms_layer_t* comms, comms_msg_t* msg, uint32_t timeout) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_timeout (comms_layer_t * comms, comms_msg_t * msg, uint32_t timeout) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_timeout(cl, msg, timeout); } return COMMS_EINVAL; } -bool comms_is_ack_required(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +bool comms_is_ack_required (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->is_ack_required(cl, msg); } return false; } -comms_error_t comms_set_ack_required(comms_layer_t* comms, comms_msg_t* msg, bool required) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_ack_required (comms_layer_t * comms, comms_msg_t * msg, bool required) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_ack_required(cl, msg, required); } return COMMS_EINVAL; } -bool comms_ack_received(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +bool comms_ack_received (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->ack_received(cl, msg); } return false; } -void comms_set_ack_received(comms_layer_t* comms, comms_msg_t* msg, bool received) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_ack_received (comms_layer_t * comms, comms_msg_t * msg, bool received) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_ack_received(cl, msg, received); } } -uint32_t comms_get_time_micro(comms_layer_t* comms) { - if(comms != NULL) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint32_t comms_get_time_micro (comms_layer_t * comms) +{ + if (NULL != comms) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; if (NULL != cl->get_time_micro) { return cl->get_time_micro(cl); @@ -310,89 +383,113 @@ uint32_t comms_get_time_micro(comms_layer_t* comms) { return 0; } -comms_error_t comms_set_timestamp_micro(comms_layer_t* comms, comms_msg_t* msg, uint32_t timestamp) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_timestamp_micro (comms_layer_t * comms, comms_msg_t * msg, uint32_t timestamp) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_timestamp(cl, msg, timestamp); } return COMMS_EINVAL; } -uint32_t comms_get_timestamp_micro(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint32_t comms_get_timestamp_micro (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_timestamp(cl, msg); } return 0; } -bool comms_timestamp_valid(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +bool comms_timestamp_valid (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->timestamp_valid(cl, msg); } return false; } -comms_error_t comms_set_event_time_micro(comms_layer_t* comms, comms_msg_t* msg, uint32_t evt) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +comms_error_t comms_set_event_time_micro (comms_layer_t * comms, comms_msg_t * msg, uint32_t evt) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->set_event_time(cl, msg, evt); } return COMMS_EINVAL; } -uint32_t comms_get_event_time_micro(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint32_t comms_get_event_time_micro (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_event_time(cl, msg); } return 0; } -bool comms_event_time_valid(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +bool comms_event_time_valid (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->event_time_valid(cl, msg); } return false; } -uint8_t comms_get_lqi(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +uint8_t comms_get_lqi (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_lqi(cl, msg); } return 0; } -void comms_set_lqi(comms_layer_t* comms, comms_msg_t* msg, uint8_t lqi) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_lqi (comms_layer_t * comms, comms_msg_t * msg, uint8_t lqi) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_lqi(cl, msg, lqi); } } -int8_t comms_get_rssi(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +int8_t comms_get_rssi (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_rssi(cl, msg); } return -128; } -void comms_set_rssi(comms_layer_t* comms, comms_msg_t* msg, int8_t rssi) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_rssi (comms_layer_t * comms, comms_msg_t * msg, int8_t rssi) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_rssi(cl, msg, rssi); } } -int8_t comms_get_priority(comms_layer_t* comms, const comms_msg_t* msg) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +int8_t comms_get_priority (comms_layer_t * comms, const comms_msg_t * msg) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; return cl->get_priority(cl, msg); } return 0xFF; } -void comms_set_priority(comms_layer_t* comms, comms_msg_t* msg, int8_t priority) { - if((msg != NULL)&&(comms != NULL)) { - comms_layer_iface_t* cl = (comms_layer_iface_t*)comms; +void comms_set_priority (comms_layer_t * comms, comms_msg_t * msg, int8_t priority) +{ + if ((NULL != msg)&&(NULL != comms)) + { + comms_layer_iface_t * cl = (comms_layer_iface_t*)comms; cl->set_priority(cl, msg, priority); } }