From 37425ca8115c9c1658fe092f7e19de1ab487eb8b Mon Sep 17 00:00:00 2001 From: Jarkko Paso Date: Wed, 17 Jan 2018 13:39:39 +0200 Subject: [PATCH] FHSS: Separated common FHSS functions to own module --- source/Service_Libs/fhss/fhss.c | 324 +---------------- source/Service_Libs/fhss/fhss.h | 119 +----- source/Service_Libs/fhss/fhss_beacon.c | 2 +- .../Service_Libs/fhss/fhss_beacon_tasklet.c | 1 + source/Service_Libs/fhss/fhss_channel.c | 1 + source/Service_Libs/fhss/fhss_common.c | 344 ++++++++++++++++++ source/Service_Libs/fhss/fhss_common.h | 128 +++++++ .../fhss/fhss_configuration_interface.c | 1 + source/Service_Libs/fhss/fhss_mac_interface.c | 1 + source/Service_Libs/fhss/fhss_statistics.c | 1 + sources.mk | 1 + 11 files changed, 486 insertions(+), 437 deletions(-) create mode 100644 source/Service_Libs/fhss/fhss_common.c create mode 100644 source/Service_Libs/fhss/fhss_common.h diff --git a/source/Service_Libs/fhss/fhss.c b/source/Service_Libs/fhss/fhss.c index d6fc0f1204ed..eb05b1ddcae2 100644 --- a/source/Service_Libs/fhss/fhss.c +++ b/source/Service_Libs/fhss/fhss.c @@ -18,6 +18,7 @@ #include "ns_types.h" #include "fhss_api.h" #include "fhss_config.h" +#include "fhss_common.h" #include "fhss.h" #include "fhss_channel.h" #include "channel_list.h" @@ -32,116 +33,9 @@ #define TRACE_GROUP "fhss" -// TODO: create linked list -// FHSS object pointer -fhss_structure_t *fhss_struct = 0; - +static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure); static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint16_t tx_length, uint8_t phy_header_length, uint8_t phy_tail_length); -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j); -static void fhss_update_channel(fhss_structure_t *fhss_structure); -static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation); -static int fhss_reset(fhss_structure_t *fhss_structure); -static void fhss_failed_list_free(fhss_structure_t *fhss_structure); - - -int8_t fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics) -{ - if (!fhss_api || !fhss_configuration || !fhss_timer || fhss_struct) { - tr_err("Invalid FHSS enable configuration"); - return -1; - } - int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); - if (channel_count <= 0) { - // There must be at least one configured channel in channel list - return -2; - } - fhss_struct = ns_dyn_mem_alloc(sizeof(fhss_structure_t)); - if (!fhss_struct) { - return -3; - } - memset(fhss_struct, 0, sizeof(fhss_structure_t)); - fhss_struct->fhss_api = fhss_api; - fhss_struct->fhss_configuration = *fhss_configuration; - fhss_struct->platform_functions = *fhss_timer; - fhss_struct->fhss_stats_ptr = fhss_statistics; - fhss_struct->number_of_channels = channel_count; - - // set a invalid id to tasklet_id, so we know that one is not started yet - fhss_struct->beacon_tasklet_id = -1; - - if (!fhss_struct->platform_functions.fhss_resolution_divider) { - fhss_struct->platform_functions.fhss_resolution_divider = 1; - } - // Default synch interval is 240 seconds - if (!fhss_struct->fhss_configuration.fhss_max_synch_interval) { - fhss_struct->fhss_configuration.fhss_max_synch_interval = 240; - } - ns_list_init(&fhss_struct->fhss_failed_tx_list); - fhss_struct->own_hop = 0xff; - fhss_reset(fhss_struct); - fhss_reset_synch_monitor(&fhss_struct->synch_monitor, true); - fhss_struct->active_fhss_events = 0; - fhss_struct->fhss_beacon_info_store = NULL; - fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); - - if (fhss_beacon_create_tasklet(fhss_struct) < 0) { - // XXX: should we free the fhss_structure here? - return -5; - } - - return 0; -} - -int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate) -{ - if (!fhss_structure) { - return -1; - } - // If datarate is not set, use default 250kbit/s. Datarate is used as divider later. - if (!datarate) { - datarate = 250000; - } - fhss_structure->datarate = datarate; - return 0; -} - -int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration) -{ - if (!fhss_structure) { - return -1; - } - if (!fhss_synch_configuration) { - return -2; - } - // None of the configurations can be set zero - if( fhss_synch_configuration->fhss_number_of_bc_channels == 0 || fhss_synch_configuration->fhss_number_of_tx_slots == 0 - || fhss_synch_configuration->fhss_number_of_superframes == 0 || fhss_synch_configuration->fhss_superframe_length == 0) { - return -3; - } - // Number of channels must be divisible with the number of broadcast channels. - // Number of superframes must be divisible with the number of TX slots - if (((fhss_structure->number_of_channels % fhss_synch_configuration->fhss_number_of_bc_channels) != 0) || - ((fhss_synch_configuration->fhss_number_of_superframes % fhss_synch_configuration->fhss_number_of_tx_slots) != 0) || - (fhss_synch_configuration->fhss_number_of_superframes <= fhss_synch_configuration->fhss_number_of_tx_slots)) { - return -4; - } - fhss_structure->synch_configuration = *fhss_synch_configuration; - fhss_structure->own_hop = 0; - return 0; -} - -fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api) -{ - if (!fhss_api || !fhss_struct) { - return NULL; - } - if (fhss_struct->fhss_api == fhss_api) { - return fhss_struct; - } - return NULL; -} bool fhss_is_synch_root(fhss_structure_t *fhss_structure) { @@ -151,35 +45,6 @@ bool fhss_is_synch_root(fhss_structure_t *fhss_structure) return true; } -void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) -{ - fhss_structure->active_fhss_events |= (1 << event_type); -} - -void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) -{ - fhss_structure->active_fhss_events &= ~(1 << event_type); -} - -bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) -{ - if (fhss_structure->active_fhss_events & (1 << event_type)) { - return true; - } - return false; -} - -static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) -{ - if (timer_id <0 || !fhss_struct) { - return NULL; - } - if (fhss_struct->fhss_event_timer == timer_id) { - return fhss_struct; - } - return NULL; -} - static bool fhss_is_bc_sending_superframe(fhss_structure_t *fhss_structure) { if (fhss_structure->current_superframe >= fhss_structure->broadcast_start_superframe) { @@ -288,95 +153,18 @@ bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc, uint16_ return true; } -static int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor, bool reset_compensation) +int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor) { if (synch_monitor) { synch_monitor->avg_synch_fix = 0; // Initialize to -1 instead of 0 to drop the first beacon after network scan (from synch monitoring) synch_monitor->avg_synch_fix_counter = -1; - if (reset_compensation == true) { - synch_monitor->drift_compensation = 0; - } synch_monitor->channel_counter = 0; return 0; } return -1; } -static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure) -{ - if (fhss_structure->fhss_scramble_table) { - ns_dyn_mem_free(fhss_structure->fhss_scramble_table); - fhss_structure->fhss_scramble_table = NULL; - } -} - -static int fhss_reset(fhss_structure_t *fhss_structure) -{ - if (fhss_structure) { - fhss_structure->platform_functions.fhss_timer_stop(fhss_superframe_handler, fhss_structure->fhss_api); - fhss_destroy_scramble_table(fhss_structure); - fhss_struct->synch_panid = 0xffff; - fhss_beacon_periodic_stop(fhss_structure); - fhss_struct->current_superframe = 0; - fhss_struct->current_channel_index = 0; - fhss_struct->channel_list_counter = 0; - if (fhss_is_synch_root(fhss_structure) == false) { - fhss_struct->own_hop = 0xff; - } - fhss_struct->tx_allowed = false; - fhss_struct->synch_interval = (uint32_t) (fhss_struct->fhss_configuration.fhss_max_synch_interval/BEACON_INTERVAL_INIT_DIVIDER) * 1000; - fhss_struct->rx_channel = 0; - fhss_struct->beacons_received_timer = 0; - memset(fhss_struct->synch_parent, 0xff, 8); - fhss_struct->send_synch_info_on_next_broadcast_channel = false; - memset(&fhss_struct->synch_configuration, 0, sizeof(fhss_synch_configuration_t)); - fhss_struct->synch_infos_sent_counter = 0; - fhss_struct->broadcast_start_superframe = 0; - fhss_failed_list_free(fhss_structure); - fhss_struct->fhss_state = FHSS_UNSYNCHRONIZED; - return 0; - } - return -1; -} - -int fhss_down(fhss_structure_t *fhss_structure) -{ - if (fhss_structure) { - fhss_reset(fhss_structure); - fhss_reset_synch_monitor(&fhss_struct->synch_monitor, false); - fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->synch_monitor.drift_compensation); - fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->synch_monitor.avg_synch_fix); - fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->synch_interval / 1000); - return 0; - } - return -1; -} - - -int8_t fhss_disable(fhss_structure_t *fhss_structure) -{ - if (!fhss_structure) { - return -1; - } - fhss_destroy_scramble_table(fhss_structure); - ns_dyn_mem_free(fhss_structure); - fhss_structure = 0; - fhss_struct = 0; - return 0; -} - -void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)) -{ - if (callback){ - // Don't allow starting with zero slots - if (time < fhss_structure->platform_functions.fhss_resolution_divider) { - time = fhss_structure->platform_functions.fhss_resolution_divider; - } - fhss_structure->platform_functions.fhss_timer_start(time / fhss_structure->platform_functions.fhss_resolution_divider, callback, fhss_structure->fhss_api); - } -} - uint32_t fhss_get_remaining_time_to_next_superframe(const fhss_structure_t *fhss_structure) { const uint32_t slots = fhss_structure->platform_functions.fhss_get_remaining_slots(fhss_superframe_handler, fhss_structure->fhss_api); @@ -467,26 +255,6 @@ void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay) } } -int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) -{ - if (!fhss_structure) { - return -1; - } - fhss_structure->fhss_timeout = time; - fhss_structure->fhss_timer = 0; - return 0; -} - -int fhss_timeout_stop(fhss_structure_t *fhss_structure) -{ - if (!fhss_structure) { - return -1; - } - fhss_structure->fhss_timeout = 0; - fhss_structure->fhss_timer = 0; - return 0; -} - int fhss_update_txrx_slots(fhss_structure_t *fhss_structure) { uint8_t cur_superframe = fhss_structure->current_superframe; @@ -781,81 +549,6 @@ static bool fhss_check_remaining_tx_time(fhss_structure_t *fhss_structure, uint1 return retval; } -int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure) -{ - uint8_t parent_address[8]; - - if (!fhss_get_parent_address(fhss_structure, parent_address)) { - memcpy(fhss_structure->synch_parent, parent_address, 8); - return 0; - } - return -1; -} - -void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type) -{ - if (fhss_read_active_event(fhss_structure, event_type) == true) { - return; - } - arm_event_s event; - event.receiver = fhss_structure->beacon_tasklet_id; - event.sender = 0; - event.event_type = event_type; - event.event_id = 0; - event.data_ptr = fhss_structure; - event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; - event.event_data = 0; - if (eventOS_event_send(&event) != 0) { - tr_error("Event trigger failed: eventOS_event_send() failed"); - } else { - fhss_set_active_event(fhss_structure, event_type); - } -} - -int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr) -{ - int ret_val = -1; - if (!fhss_structure || !p_addr) { - return -1; - } - - ret_val = fhss_structure->callbacks.read_coord_mac_address(fhss_structure->fhss_api, p_addr); - - if (ret_val) { - // Use default synchronization parent when RPL parent not found - memcpy(p_addr, fhss_structure->synch_parent, 8); - ret_val = 0; - } - return ret_val; -} - -int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr) -{ - int ret_val = -1; - if (!fhss_structure || !source_addr) { - return ret_val; - } - uint8_t parent_address[8]; - - if (fhss_is_synch_root(fhss_structure) == false) { - if (!fhss_get_parent_address(fhss_structure, parent_address)) { - ret_val = memcmp(source_addr, parent_address, 8); - } - } - return ret_val; -} - -static void fhss_update_channel(fhss_structure_t *fhss_structure) -{ - // If channel is broadcast channel (true), send event - if (fhss_change_to_next_channel(fhss_structure) == true) { - // Only if device is border router - if (fhss_structure->own_hop == 0) { - fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL); - } - } -} - static bool fhss_is_there_common_divisor(uint16_t i, uint8_t j) { if (i < j) { @@ -890,15 +583,6 @@ int fhss_generate_scramble_table(fhss_structure_t *fhss_structure) return 0; } -static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) -{ - (void) slots; - fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); - if (fhss_structure) { - fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); - } -} - fhss_beacon_info_t *fhss_get_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id) { fhss_beacon_info_t *beacon_info; @@ -1056,7 +740,7 @@ int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle) return 0; } -static void fhss_failed_list_free(fhss_structure_t *fhss_structure) +void fhss_failed_list_free(fhss_structure_t *fhss_structure) { for (uint16_t i = 0; i<256; i++) { fhss_failed_handle_remove(fhss_structure, i); diff --git a/source/Service_Libs/fhss/fhss.h b/source/Service_Libs/fhss/fhss.h index 2c47e9f004c5..fb3a5baa53f8 100644 --- a/source/Service_Libs/fhss/fhss.h +++ b/source/Service_Libs/fhss/fhss.h @@ -16,9 +16,8 @@ */ #ifndef FHSS_H_ #define FHSS_H_ -#include "ns_list.h" -#define MAX_SCRAMBLE_TABLE_INDEXES 20 +#define MAX_SCRAMBLE_TABLE_INDEXES 20 // Lifetime is given as seconds #define BEACON_INFO_LIFETIME 600 // Limits the number of synchronization info messages sent on broadcast channels @@ -26,136 +25,27 @@ // FHSS randomly selects the starting superframe for broadcast channel. This defines how many superframes are used for randomization. #define NUMBER_OF_BC_START_SUPERFRAMES 3 -#define FHSS_TASKLET_INIT_EVENT 0 -#define FHSS_TIMER_EVENT 1 -#define FHSS_COMPARE_SYNCH_PARENT 2 -#define FHSS_BROADCAST_CHANNEL 3 -#define FHSS_UPDATE_SYNCH_INFO_STORAGE 4 - struct fhss_callback; -typedef struct fhss_beacon_info -{ - uint16_t pan_id; - uint8_t source_address[8]; - uint32_t timestamp; - uint8_t synch_info[FHSS_SYNCH_INFO_LENGTH]; - struct fhss_beacon_info *next; -}fhss_beacon_info_t; - -typedef struct fhss_failed_tx -{ - uint8_t handle; - uint8_t bad_channel; - uint8_t retries_done; - ns_list_link_t link; -}fhss_failed_tx_t; - -typedef NS_LIST_HEAD(fhss_failed_tx_t, link) fhss_failed_tx_list_t; - -typedef struct -{ - int32_t avg_synch_fix; - int avg_synch_fix_counter; - int drift_compensation; - int channel_counter; -} fhss_synch_monitor_s; - -typedef struct -{ - fhss_api_t *fhss_api; - uint32_t datarate; - fhss_states fhss_state; - fhss_timer_t platform_functions; - fhss_configuration_t fhss_configuration; - fhss_synch_configuration_t synch_configuration; - - uint8_t fhss_resolution_divider; - /** Unicast channel index, [0..(number_of_channels-number_of_beacon_channels-1)] */ - uint8_t uc_channel_index; - /** Current superframe number, [0..(fhss_number_of_superframes-1)] */ - uint8_t current_superframe; - /** Current channel index, [0..(number_of channels-1)] */ - uint8_t current_channel_index; - /** Current broadcast index, [0..(number_of_bc_channels-1)] */ - uint8_t broadcast_index; - /** Number of channels (unicast and broadcast) */ - uint16_t number_of_channels; - /** Channel list counter is increased every time channel list is gone through*/ - uint16_t channel_list_counter; - /** This is used to store current RX channel*/ - uint8_t rx_channel; - /** Own hop count*/ - uint8_t own_hop; - /** Holds the information: transmission is allowed or not on this superframe*/ - bool tx_allowed; - /** The tasklet_id of periodic beacon sender, -1 if none is started. */ - int8_t beacon_tasklet_id; - /** When synchronization is lost, this counter is used to detect the situation and stop network*/ - uint8_t beacons_received_timer; - /** Holds the current synchronization parent MAC address*/ - uint8_t synch_parent[8]; - // Synch info needs to be sent on next broadcast channel - bool send_synch_info_on_next_broadcast_channel; - // Used for randomizing broadcast sending. Device is not allowed to start broadcasting before the given superframe. - uint8_t broadcast_start_superframe; - /*Indexes in this table will be used to extend the repeated channel sequence*/ - uint8_t *fhss_scramble_table; - /** Used to monitor and fix synchronization drift*/ - fhss_synch_monitor_s synch_monitor; - /** Used to drop multiple synch info messages on same broadcast channel*/ - bool beacon_received_on_this_bc_channel; - /** Timer used for events other than synchronization.*/ - int8_t fhss_event_timer; - /* Counts the number of sent synch Beacons (Beacon on broadcast channel). Used to limit Beacon traffic when several nodes are scanning network*/ - uint8_t synch_infos_sent_counter; - uint32_t synch_interval; - /* This timer/timeout is used to trigger periodically Beacon requests. Resolution is superframe length. Note that FHSS must be synchronized to use this*/ - uint32_t fhss_timeout; - uint32_t fhss_timer; - uint16_t synch_panid; - /* Bit mask for FHSS events pushed to event queue. Prevents pushing same event to queue multiple times*/ - uint8_t active_fhss_events; - - struct fhss_callback callbacks; - fhss_beacon_info_t *fhss_beacon_info_store; - fhss_failed_tx_list_t fhss_failed_tx_list; - fhss_statistics_t *fhss_stats_ptr; -} fhss_structure_t; - -int8_t fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics); -int8_t fhss_disable(fhss_structure_t *fhss_structure); -int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate); bool fhss_is_synch_root(fhss_structure_t *fhss_structure); -int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration); bool fhss_check_bad_channel(fhss_structure_t *fhss_structure, uint8_t handle); bool fhss_check_channel_type(fhss_structure_t *fhss_structure, bool is_bc, int frame_type); bool fhss_check_tx_allowed(fhss_structure_t *fhss_structure, bool is_bc, uint16_t frame_length, int frame_type, uint8_t phy_header_length, uint8_t phy_tail_length); -fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api); fhss_beacon_info_t *fhss_get_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id); int fhss_flush_beacon_info_storage(fhss_structure_t *fhss_structure); int fhss_add_beacon_info(fhss_structure_t *fhss_structure, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info); void fhss_update_beacon_info_lifetimes(fhss_structure_t *fhss_structure, uint32_t timestamp); -void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type); -int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time); -int fhss_timeout_stop(fhss_structure_t *fhss_structure); -int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr); uint32_t fhss_get_tx_time(fhss_structure_t *fhss_structure, uint16_t bytes_to_send, uint8_t phy_header_length, uint8_t phy_tail_length); -int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr); -int fhss_down(fhss_structure_t *fhss_structure); -int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure); void fhss_superframe_handler(const fhss_api_t *fhss_api, uint16_t delay); fhss_failed_tx_t *fhss_failed_handle_find(fhss_structure_t *fhss_structure, uint8_t handle); int fhss_failed_handle_add(fhss_structure_t *fhss_structure, uint8_t handle); int fhss_failed_handle_remove(fhss_structure_t *fhss_structure, uint8_t handle); -void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); -void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); -bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); int fhss_generate_scramble_table(fhss_structure_t *fhss_structure); +void fhss_failed_list_free(fhss_structure_t *fhss_structure); +int fhss_reset_synch_monitor(fhss_synch_monitor_s *synch_monitor); #define MAX_FHSS_TIMER_DIVIDER 100 #define SYNCH_MONITOR_AVG_SAMPLES 5 -// TX/RX slot management interface /** * Update slots * @@ -166,9 +56,6 @@ int fhss_generate_scramble_table(fhss_structure_t *fhss_structure); */ int fhss_update_txrx_slots(fhss_structure_t *fhss_structure); -void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); - - /** * Calculate time in microseconds to start of next superframe. * diff --git a/source/Service_Libs/fhss/fhss_beacon.c b/source/Service_Libs/fhss/fhss_beacon.c index fccec57b266d..76b57250b93a 100644 --- a/source/Service_Libs/fhss/fhss_beacon.c +++ b/source/Service_Libs/fhss/fhss_beacon.c @@ -19,9 +19,9 @@ #include "nsconfig.h" #include "fhss_api.h" #include "fhss_config.h" +#include "fhss_common.h" #include "fhss.h" #include "fhss_beacon.h" - #include "common_functions.h" #include // memcpy #include "ns_trace.h" diff --git a/source/Service_Libs/fhss/fhss_beacon_tasklet.c b/source/Service_Libs/fhss/fhss_beacon_tasklet.c index 2ba416cf909e..690b2923880f 100644 --- a/source/Service_Libs/fhss/fhss_beacon_tasklet.c +++ b/source/Service_Libs/fhss/fhss_beacon_tasklet.c @@ -23,6 +23,7 @@ #include "ns_trace.h" #include "fhss_api.h" #include "fhss_config.h" +#include "fhss_common.h" #include "fhss.h" #include "fhss_beacon.h" #include "fhss_statistics.h" diff --git a/source/Service_Libs/fhss/fhss_channel.c b/source/Service_Libs/fhss/fhss_channel.c index a176bb83f3db..a9c4b1417122 100644 --- a/source/Service_Libs/fhss/fhss_channel.c +++ b/source/Service_Libs/fhss/fhss_channel.c @@ -18,6 +18,7 @@ #include "ns_types.h" #include "fhss_api.h" #include "fhss_config.h" +#include "fhss_common.h" #include "fhss.h" #include "fhss_channel.h" #include "fhss_beacon.h" diff --git a/source/Service_Libs/fhss/fhss_common.c b/source/Service_Libs/fhss/fhss_common.c new file mode 100644 index 000000000000..d35c2ebbb8af --- /dev/null +++ b/source/Service_Libs/fhss/fhss_common.c @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2015-2017, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "nsconfig.h" +#include "ns_types.h" +#include "ns_trace.h" +#include "fhss_api.h" +#include "fhss_config.h" +#include "fhss_common.h" +#include "fhss.h" +#include "fhss_beacon.h" +#include "fhss_statistics.h" +#include "fhss_channel.h" +#include "channel_list.h" +#include "nsdynmemLIB.h" +#include "eventOS_event.h" +#include "eventOS_callback_timer.h" +#include + +#define TRACE_GROUP "fhssc" + +fhss_structure_t *fhss_struct = 0; + +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots); +static int fhss_reset(fhss_structure_t *fhss_structure); +static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id); +static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); +static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); + +int8_t fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics) +{ + if (!fhss_api || !fhss_configuration || !fhss_timer || fhss_struct) { + tr_err("Invalid FHSS enable configuration"); + return -1; + } + int channel_count = channel_list_count_channels(fhss_configuration->channel_mask); + if (channel_count <= 0) { + // There must be at least one configured channel in channel list + return -2; + } + fhss_struct = ns_dyn_mem_alloc(sizeof(fhss_structure_t)); + if (!fhss_struct) { + return -3; + } + memset(fhss_struct, 0, sizeof(fhss_structure_t)); + fhss_struct->fhss_api = fhss_api; + fhss_struct->fhss_configuration = *fhss_configuration; + fhss_struct->platform_functions = *fhss_timer; + fhss_struct->fhss_stats_ptr = fhss_statistics; + fhss_struct->number_of_channels = channel_count; + + // set a invalid id to tasklet_id, so we know that one is not started yet + fhss_struct->beacon_tasklet_id = -1; + + if (!fhss_struct->platform_functions.fhss_resolution_divider) { + fhss_struct->platform_functions.fhss_resolution_divider = 1; + } + // Default synch interval is 240 seconds + if (!fhss_struct->fhss_configuration.fhss_max_synch_interval) { + fhss_struct->fhss_configuration.fhss_max_synch_interval = 240; + } + ns_list_init(&fhss_struct->fhss_failed_tx_list); + fhss_struct->own_hop = 0xff; + fhss_reset(fhss_struct); + tr_debug("Synch compensation: %i", fhss_struct->synch_monitor.drift_compensation); + fhss_struct->active_fhss_events = 0; + fhss_struct->fhss_beacon_info_store = NULL; + fhss_struct->fhss_event_timer = eventOS_callback_timer_register(fhss_event_timer_cb); + + if (fhss_beacon_create_tasklet(fhss_struct) < 0) { + // XXX: should we free the fhss_structure here? + return -5; + } + + return 0; +} + +static void fhss_event_timer_cb(int8_t timer_id, uint16_t slots) +{ + (void) slots; + fhss_structure_t *fhss_structure = fhss_get_object_with_timer_id(timer_id); + if (fhss_structure) { + fhss_structure->callbacks.tx_poll(fhss_structure->fhss_api); + } +} + +static void fhss_destroy_scramble_table(fhss_structure_t *fhss_structure) +{ + if (fhss_structure->fhss_scramble_table) { + ns_dyn_mem_free(fhss_structure->fhss_scramble_table); + fhss_structure->fhss_scramble_table = NULL; + } +} + +static int fhss_reset(fhss_structure_t *fhss_structure) +{ + if (fhss_structure) { + fhss_destroy_scramble_table(fhss_structure); + fhss_structure->platform_functions.fhss_timer_stop(fhss_superframe_handler, fhss_structure->fhss_api); + fhss_struct->synch_panid = 0xffff; + fhss_beacon_periodic_stop(fhss_structure); + fhss_struct->current_superframe = 0; + fhss_struct->current_channel_index = 0; + fhss_struct->channel_list_counter = 0; + if (fhss_is_synch_root(fhss_structure) == false) { + fhss_struct->own_hop = 0xff; + } + fhss_struct->tx_allowed = false; + fhss_struct->synch_interval = (uint32_t) (fhss_struct->fhss_configuration.fhss_max_synch_interval/BEACON_INTERVAL_INIT_DIVIDER) * 1000; + fhss_struct->rx_channel = 0; + fhss_struct->beacons_received_timer = 0; + memset(fhss_struct->synch_parent, 0xff, 8); + fhss_struct->send_synch_info_on_next_broadcast_channel = false; + memset(&fhss_struct->synch_configuration, 0, sizeof(fhss_synch_configuration_t)); + fhss_struct->synch_infos_sent_counter = 0; + fhss_struct->broadcast_start_superframe = 0; + fhss_failed_list_free(fhss_structure); + fhss_struct->fhss_state = FHSS_UNSYNCHRONIZED; + return 0; + } + return -1; +} + +int fhss_down(fhss_structure_t *fhss_structure) +{ + if (fhss_structure) { + fhss_reset(fhss_structure); + fhss_reset_synch_monitor(&fhss_struct->synch_monitor); + fhss_stats_update(fhss_structure, STATS_FHSS_DRIFT_COMP, fhss_structure->synch_monitor.drift_compensation); + fhss_stats_update(fhss_structure, STATS_FHSS_AVG_SYNCH_FIX, fhss_structure->synch_monitor.avg_synch_fix); + fhss_stats_update(fhss_structure, STATS_FHSS_SYNCH_INTERVAL, fhss_structure->synch_interval / 1000); + return 0; + } + return -1; +} + +static fhss_structure_t *fhss_get_object_with_timer_id(const int8_t timer_id) +{ + if (timer_id <0 || !fhss_struct) { + return NULL; + } + if (fhss_struct->fhss_event_timer == timer_id) { + return fhss_struct; + } + return NULL; +} + +int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate) +{ + if (!fhss_structure) { + return -1; + } + // If datarate is not set, use default 250kbit/s. Datarate is used as divider later. + if (!datarate) { + datarate = 250000; + } + fhss_structure->datarate = datarate; + return 0; +} + +int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration) +{ + if (!fhss_structure) { + return -1; + } + if (!fhss_synch_configuration) { + return -2; + } + // None of the configurations can be set zero + if( fhss_synch_configuration->fhss_number_of_bc_channels == 0 || fhss_synch_configuration->fhss_number_of_tx_slots == 0 + || fhss_synch_configuration->fhss_number_of_superframes == 0 || fhss_synch_configuration->fhss_superframe_length == 0) { + return -3; + } + // Number of channels must be divisible with the number of broadcast channels. + // Number of superframes must be divisible with the number of TX slots + if (((fhss_structure->number_of_channels % fhss_synch_configuration->fhss_number_of_bc_channels) != 0) || + ((fhss_synch_configuration->fhss_number_of_superframes % fhss_synch_configuration->fhss_number_of_tx_slots) != 0) || + (fhss_synch_configuration->fhss_number_of_superframes <= fhss_synch_configuration->fhss_number_of_tx_slots)) { + return -4; + } + fhss_structure->synch_configuration = *fhss_synch_configuration; + fhss_structure->own_hop = 0; + return 0; +} + +fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api) +{ + if (!fhss_api || !fhss_struct) { + return NULL; + } + if (fhss_struct->fhss_api == fhss_api) { + return fhss_struct; + } + return NULL; +} + +static void fhss_set_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) +{ + fhss_structure->active_fhss_events |= (1 << event_type); +} + +void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) +{ + fhss_structure->active_fhss_events &= ~(1 << event_type); +} + +static bool fhss_read_active_event(fhss_structure_t *fhss_structure, uint8_t event_type) +{ + if (fhss_structure->active_fhss_events & (1 << event_type)) { + return true; + } + return false; +} + +int8_t fhss_disable(fhss_structure_t *fhss_structure) +{ + if (!fhss_structure) { + return -1; + } + fhss_destroy_scramble_table(fhss_structure); + ns_dyn_mem_free(fhss_structure); + fhss_structure = 0; + fhss_struct = 0; + return 0; +} + +void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)) +{ + if (callback){ + // Don't allow starting with zero slots + if (time < fhss_structure->platform_functions.fhss_resolution_divider) { + time = fhss_structure->platform_functions.fhss_resolution_divider; + } + fhss_structure->platform_functions.fhss_timer_start(time / fhss_structure->platform_functions.fhss_resolution_divider, callback, fhss_structure->fhss_api); + } +} + +int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time) +{ + if (!fhss_structure) { + return -1; + } + fhss_structure->fhss_timeout = time; + fhss_structure->fhss_timer = 0; + return 0; +} + +int fhss_timeout_stop(fhss_structure_t *fhss_structure) +{ + if (!fhss_structure) { + return -1; + } + fhss_structure->fhss_timeout = 0; + fhss_structure->fhss_timer = 0; + return 0; +} + +int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure) +{ + uint8_t parent_address[8]; + + if (!fhss_get_parent_address(fhss_structure, parent_address)) { + memcpy(fhss_structure->synch_parent, parent_address, 8); + return 0; + } + return -1; +} + +void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type) +{ + if (fhss_read_active_event(fhss_structure, event_type) == true) { + return; + } + arm_event_s event; + event.receiver = fhss_structure->beacon_tasklet_id; + event.sender = 0; + event.event_type = event_type; + event.event_id = 0; + event.data_ptr = fhss_structure; + event.priority = ARM_LIB_HIGH_PRIORITY_EVENT; + event.event_data = 0; + if (eventOS_event_send(&event) != 0) { + tr_error("Event trigger failed: eventOS_event_send() failed"); + } else { + fhss_set_active_event(fhss_structure, event_type); + } +} + +int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr) +{ + int ret_val = -1; + if (!fhss_structure || !p_addr) { + return -1; + } + + ret_val = fhss_structure->callbacks.read_coord_mac_address(fhss_structure->fhss_api, p_addr); + + if (ret_val) { + // Use default synchronization parent when RPL parent not found + memcpy(p_addr, fhss_structure->synch_parent, 8); + ret_val = 0; + } + return ret_val; +} + +int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr) +{ + int ret_val = -1; + if (!fhss_structure || !source_addr) { + return ret_val; + } + uint8_t parent_address[8]; + + if (fhss_is_synch_root(fhss_structure) == false) { + if (!fhss_get_parent_address(fhss_structure, parent_address)) { + ret_val = memcmp(source_addr, parent_address, 8); + } + } + return ret_val; +} + +void fhss_update_channel(fhss_structure_t *fhss_structure) +{ + // If channel is broadcast channel (true), send event + if (fhss_change_to_next_channel(fhss_structure) == true) { + // Only if device is border router + if (fhss_structure->own_hop == 0) { + fhss_trig_event(fhss_structure, FHSS_BROADCAST_CHANNEL); + } + } +} diff --git a/source/Service_Libs/fhss/fhss_common.h b/source/Service_Libs/fhss/fhss_common.h new file mode 100644 index 000000000000..c9c5080b0170 --- /dev/null +++ b/source/Service_Libs/fhss/fhss_common.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015-2017, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ns_list.h" +#define FHSS_TASKLET_INIT_EVENT 0 +#define FHSS_TIMER_EVENT 1 +#define FHSS_COMPARE_SYNCH_PARENT 2 +#define FHSS_BROADCAST_CHANNEL 3 +#define FHSS_UPDATE_SYNCH_INFO_STORAGE 4 + +typedef struct fhss_beacon_info +{ + uint16_t pan_id; + uint8_t source_address[8]; + uint32_t timestamp; + uint8_t synch_info[FHSS_SYNCH_INFO_LENGTH]; + struct fhss_beacon_info *next; +}fhss_beacon_info_t; + +typedef struct fhss_failed_tx +{ + uint8_t handle; + uint8_t bad_channel; + uint8_t retries_done; + ns_list_link_t link; +}fhss_failed_tx_t; + +typedef NS_LIST_HEAD(fhss_failed_tx_t, link) fhss_failed_tx_list_t; + +typedef struct +{ + int32_t avg_synch_fix; + int avg_synch_fix_counter; + int drift_compensation; + int channel_counter; +} fhss_synch_monitor_s; + +typedef struct fhss_structure_t +{ + fhss_api_t *fhss_api; + uint32_t datarate; + fhss_states fhss_state; + fhss_timer_t platform_functions; + fhss_configuration_t fhss_configuration; + fhss_synch_configuration_t synch_configuration; + + uint8_t fhss_resolution_divider; + /** Unicast channel index, [0..(number_of_channels-number_of_beacon_channels-1)] */ + uint8_t uc_channel_index; + /** Current superframe number, [0..(fhss_number_of_superframes-1)] */ + uint8_t current_superframe; + /** Current channel index, [0..(number_of channels-1)] */ + uint8_t current_channel_index; + /** Current broadcast index, [0..(number_of_bc_channels-1)] */ + uint8_t broadcast_index; + /** Number of channels (unicast and broadcast) */ + uint16_t number_of_channels; + /** Channel list counter is increased every time channel list is gone through*/ + uint16_t channel_list_counter; + /** This is used to store current RX channel*/ + uint8_t rx_channel; + /** Own hop count*/ + uint8_t own_hop; + /** Holds the information: transmission is allowed or not on this superframe*/ + bool tx_allowed; + /** The tasklet_id of periodic beacon sender, -1 if none is started. */ + int8_t beacon_tasklet_id; + /** When synchronization is lost, this counter is used to detect the situation and stop network*/ + uint8_t beacons_received_timer; + /** Holds the current synchronization parent MAC address*/ + uint8_t synch_parent[8]; + // Synch info needs to be sent on next broadcast channel + bool send_synch_info_on_next_broadcast_channel; + // Used for randomizing broadcast sending. Device is not allowed to start broadcasting before the given superframe. + uint8_t broadcast_start_superframe; + /*Indexes in this table will be used to extend the repeated channel sequence*/ + uint8_t *fhss_scramble_table; + /** Used to monitor and fix synchronization drift*/ + fhss_synch_monitor_s synch_monitor; + /** Used to drop multiple synch info messages on same broadcast channel*/ + bool beacon_received_on_this_bc_channel; + /** Timer used for events other than synchronization.*/ + int8_t fhss_event_timer; + /* Counts the number of sent synch Beacons (Beacon on broadcast channel). Used to limit Beacon traffic when several nodes are scanning network*/ + uint8_t synch_infos_sent_counter; + uint32_t synch_interval; + /* This timer/timeout is used to trigger periodically Beacon requests. Resolution is superframe length. Note that FHSS must be synchronized to use this*/ + uint32_t fhss_timeout; + uint32_t fhss_timer; + uint16_t synch_panid; + /* Bit mask for FHSS events pushed to event queue. Prevents pushing same event to queue multiple times*/ + uint8_t active_fhss_events; + struct fhss_callback callbacks; + fhss_beacon_info_t *fhss_beacon_info_store; + fhss_failed_tx_list_t fhss_failed_tx_list; + fhss_statistics_t *fhss_stats_ptr; +} fhss_structure_t; + +int8_t fhss_enable(fhss_api_t *fhss_api, const fhss_configuration_t *fhss_configuration, const fhss_timer_t *fhss_timer, fhss_statistics_t *fhss_statistics); +int fhss_down(fhss_structure_t *fhss_structure); +int8_t fhss_set_datarate(fhss_structure_t *fhss_structure, uint32_t datarate); +int8_t fhss_set_synch_configuration(fhss_structure_t *fhss_structure, const fhss_synch_configuration_t *fhss_synch_configuration); +fhss_structure_t *fhss_get_object_with_api(const fhss_api_t *fhss_api); +void fhss_clear_active_event(fhss_structure_t *fhss_structure, uint8_t event_type); +int8_t fhss_disable(fhss_structure_t *fhss_structure); +void fhss_start_timer(fhss_structure_t *fhss_structure, uint32_t time, void (*callback)(const fhss_api_t *fhss_api, uint16_t)); +int fhss_timeout_start(fhss_structure_t *fhss_structure, uint32_t time); +int fhss_timeout_stop(fhss_structure_t *fhss_structure); +int fhss_update_synch_parent_address(fhss_structure_t *fhss_structure); +void fhss_trig_event(fhss_structure_t *fhss_structure, uint8_t event_type); +int fhss_get_parent_address(fhss_structure_t *fhss_structure, uint8_t *p_addr); +int fhss_compare_with_synch_parent_address(fhss_structure_t *fhss_structure, const uint8_t *source_addr); + + +void fhss_update_channel(fhss_structure_t *fhss_structure); diff --git a/source/Service_Libs/fhss/fhss_configuration_interface.c b/source/Service_Libs/fhss/fhss_configuration_interface.c index 501c18cd19c8..34e417c93d93 100644 --- a/source/Service_Libs/fhss/fhss_configuration_interface.c +++ b/source/Service_Libs/fhss/fhss_configuration_interface.c @@ -21,6 +21,7 @@ #include "fhss_config.h" #include "net_fhss.h" #include "nsdynmemLIB.h" +#include "Service_Libs/fhss/fhss_common.h" #include "Service_Libs/fhss/fhss.h" #include "Service_Libs/fhss/fhss_mac_interface.h" #include "ns_trace.h" diff --git a/source/Service_Libs/fhss/fhss_mac_interface.c b/source/Service_Libs/fhss/fhss_mac_interface.c index abae349dc5e9..54b3cad54654 100644 --- a/source/Service_Libs/fhss/fhss_mac_interface.c +++ b/source/Service_Libs/fhss/fhss_mac_interface.c @@ -19,6 +19,7 @@ #include "ns_types.h" #include "fhss_api.h" #include "fhss_config.h" +#include "Service_Libs/fhss/fhss_common.h" #include "Service_Libs/fhss/fhss.h" #include "Service_Libs/fhss/fhss_channel.h" #include "Service_Libs/fhss/fhss_beacon.h" diff --git a/source/Service_Libs/fhss/fhss_statistics.c b/source/Service_Libs/fhss/fhss_statistics.c index 872298237617..fb2e035515d6 100644 --- a/source/Service_Libs/fhss/fhss_statistics.c +++ b/source/Service_Libs/fhss/fhss_statistics.c @@ -18,6 +18,7 @@ #include "ns_types.h" #include "fhss_api.h" #include "fhss_config.h" +#include "fhss_common.h" #include "fhss.h" #include "fhss_statistics.h" diff --git a/sources.mk b/sources.mk index 57dc26cff370..142153f24c55 100644 --- a/sources.mk +++ b/sources.mk @@ -91,6 +91,7 @@ SRCS += \ source/Service_Libs/fhss/fhss_configuration_interface.c \ source/Service_Libs/fhss/fhss_statistics.c \ source/Service_Libs/fhss/fhss.c \ + source/Service_Libs/fhss/fhss_common.c \ source/Service_Libs/fhss/channel_list.c \ source/Service_Libs/fnv_hash/fnv_hash.c \ source/Service_Libs/mle_service/mle_service.c \