Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
fhss_mac_interface.c
00001 /* 00002 * Copyright (c) 2016-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "nsconfig.h" 00018 #include <string.h> 00019 #include "ns_types.h" 00020 #include "fhss_api.h " 00021 #include "fhss_config.h " 00022 #include "Service_Libs/fhss/fhss.h" 00023 #include "Service_Libs/fhss/fhss_channel.h" 00024 #include "Service_Libs/fhss/fhss_beacon.h" 00025 #include "platform/arm_hal_interrupt.h" 00026 #include "randLIB.h" 00027 #include "ns_trace.h" 00028 00029 #define TRACE_GROUP "fhss" 00030 00031 00032 bool fhss_is_broadcast_channel_cb(const fhss_api_t *api) 00033 { 00034 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00035 if (!fhss_structure) { 00036 return false; 00037 } 00038 // FHSS is unsynchronized, broadcasts allowed 00039 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00040 return true; 00041 } 00042 return fhss_is_current_channel_broadcast(fhss_structure); 00043 } 00044 00045 bool fhss_use_broadcast_queue_cb(const fhss_api_t *api, bool is_broadcast_addr, int frame_type) 00046 { 00047 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00048 if (!fhss_structure) { 00049 return false; 00050 } 00051 // Synch requests are always stored in unicast queue 00052 if (frame_type == FHSS_SYNCH_REQUEST_FRAME) { 00053 return false; 00054 } 00055 // Broadcast packets are stored in broadcast queue 00056 return is_broadcast_addr; 00057 } 00058 00059 int fhss_tx_handle_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t *destination_address, int frame_type, uint8_t *synch_info, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) 00060 { 00061 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00062 if (!fhss_structure) { 00063 return -2; 00064 } 00065 // TODO: needs some more logic to push buffer back to queue 00066 if (frame_type == FHSS_DATA_FRAME) { 00067 if (is_broadcast_addr == true) { 00068 if (fhss_is_current_channel_broadcast(fhss_structure) == false) { 00069 tr_info("Broadcast on UC channel -> Back to queue"); 00070 return -3; 00071 } 00072 } 00073 } 00074 if (frame_type == FHSS_SYNCH_FRAME) { 00075 if (!synch_info) { 00076 return -4; 00077 } 00078 fhss_beacon_build(fhss_structure, synch_info); 00079 } else if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 00080 return -1; 00081 } 00082 // If sending Beacon request on parents Unicast channel 00083 if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { 00084 fhss_change_to_parent_channel(fhss_structure); 00085 } else if (frame_type == FHSS_DATA_FRAME) { 00086 fhss_change_to_tx_channel(fhss_structure, destination_address); 00087 } 00088 return 0; 00089 } 00090 00091 bool fhss_check_tx_conditions_cb(const fhss_api_t *api, bool is_broadcast_addr, uint8_t handle, int frame_type, uint16_t frame_length, uint8_t phy_header_length, uint8_t phy_tail_length) 00092 { 00093 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00094 if (!fhss_structure) { 00095 return false; 00096 } 00097 // This condition will check that message is not sent on bad channel 00098 if (fhss_check_bad_channel(fhss_structure, handle) == false) { 00099 return false; 00100 } 00101 00102 // This condition will check that broadcast messages are sent only broadcast channels 00103 if (fhss_check_channel_type(fhss_structure, is_broadcast_addr, frame_type) == false) { 00104 return false; 00105 } 00106 00107 // This condition will check that FHSS is on TX slot and there is enough time to transmit before channel or slot change 00108 if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 00109 return false; 00110 } 00111 00112 return true; 00113 } 00114 00115 void fhss_receive_frame_cb(const fhss_api_t *api, uint16_t pan_id, uint8_t *source_address, uint32_t timestamp, uint8_t *synch_info, int frame_type) 00116 { 00117 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00118 if (!fhss_structure) { 00119 return; 00120 } 00121 if (FHSS_SYNCH_FRAME == frame_type) { 00122 if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->synch_panid != pan_id) { 00123 fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info); 00124 } else { 00125 if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) { 00126 // Synch parent address needs to be updated in case parent has changed 00127 fhss_update_synch_parent_address(fhss_structure); 00128 platform_enter_critical(); 00129 // Calculate time since the Beacon was received 00130 uint32_t elapsed_time = api->read_timestamp(api) - timestamp; 00131 // Synchronize to given PAN 00132 fhss_beacon_received(fhss_structure, synch_info, elapsed_time); 00133 platform_exit_critical(); 00134 } 00135 } 00136 } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) { 00137 // If current channel is broadcast, we don't need to send another synch info on next broadcast channel. 00138 // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle 00139 if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false) 00140 && (fhss_structure->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) { 00141 fhss_structure->send_synch_info_on_next_broadcast_channel = true; 00142 } 00143 } 00144 } 00145 00146 void fhss_data_tx_done_cb(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle) 00147 { 00148 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00149 if (!fhss_structure) { 00150 return; 00151 } 00152 if (waiting_ack == false) { 00153 fhss_change_to_rx_channel(fhss_structure); 00154 } 00155 // Buffer was successfully transmitted. Remove stored failure handle if exists. 00156 if (tx_completed == true) { 00157 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00158 if (fhss_failed_tx) { 00159 fhss_failed_handle_remove(fhss_structure, handle); 00160 } 00161 } 00162 } 00163 00164 bool fhss_data_tx_fail_cb(const fhss_api_t *api, uint8_t handle, int frame_type) 00165 { 00166 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00167 if (!fhss_structure) { 00168 return false; 00169 } 00170 // Only use channel retries when device is synchronized 00171 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00172 return false; 00173 } 00174 // Channel retries are disabled -> return 00175 if (fhss_structure->fhss_configuration.fhss_number_of_channel_retries == 0) { 00176 return false; 00177 } 00178 // Use channel retries only for data frames 00179 if (FHSS_DATA_FRAME != frame_type) { 00180 return false; 00181 } 00182 00183 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00184 if (fhss_failed_tx) { 00185 fhss_failed_tx->retries_done++; 00186 if (fhss_failed_tx->retries_done >= fhss_structure->fhss_configuration.fhss_number_of_channel_retries) { 00187 // No more retries. Return false to stop retransmitting. 00188 fhss_failed_handle_remove(fhss_structure, handle); 00189 return false; 00190 } 00191 } else { 00192 // Create new failure handle and return true to retransmit 00193 fhss_failed_handle_add(fhss_structure, handle); 00194 } 00195 return true; 00196 } 00197 00198 void fhss_synch_state_set_cb(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) 00199 { 00200 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00201 if (!fhss_structure) { 00202 return; 00203 } 00204 00205 // State is already set 00206 if (fhss_structure->fhss_state == fhss_state) { 00207 tr_debug("Synch same state %u", fhss_state); 00208 return; 00209 } 00210 00211 if (fhss_state == FHSS_UNSYNCHRONIZED) { 00212 tr_debug("FHSS down"); 00213 fhss_down(fhss_structure); 00214 } else { 00215 // Do not synchronize to current pan 00216 if (fhss_structure->synch_panid == pan_id) { 00217 tr_debug("Synch same panid %u", pan_id); 00218 return; 00219 } 00220 uint32_t datarate = fhss_structure->callbacks.read_datarate(api); 00221 fhss_set_datarate(fhss_structure, datarate); 00222 uint8_t mac_address[8]; 00223 fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); 00224 fhss_structure->uc_channel_index = fhss_get_offset(fhss_structure, mac_address); 00225 // Get Beacon info from storage 00226 fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); 00227 if (beacon_info) { 00228 memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8); 00229 platform_enter_critical(); 00230 // Calculate time since the Beacon was received 00231 uint32_t elapsed_time = api->read_timestamp(api) - beacon_info->timestamp; 00232 // Synchronize to given PAN 00233 fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time); 00234 platform_exit_critical(); 00235 // Delete stored Beacon infos 00236 fhss_flush_beacon_info_storage(fhss_structure); 00237 fhss_structure->synch_panid = pan_id; 00238 } else if (fhss_is_synch_root(fhss_structure) == true) { 00239 // Synch root will start new network 00240 fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler); 00241 } else { 00242 tr_error("Synch info not find"); 00243 } 00244 } 00245 fhss_structure->fhss_state = fhss_state; 00246 } 00247 00248 uint32_t fhss_read_timestamp_cb(const fhss_api_t *api) 00249 { 00250 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00251 if (!fhss_structure) { 00252 return 0; 00253 } 00254 return (fhss_structure->platform_functions.fhss_get_timestamp(api) * fhss_structure->platform_functions.fhss_resolution_divider); 00255 } 00256 00257 uint16_t fhss_get_retry_period_cb(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu) 00258 { 00259 uint16_t retry_period = 0; 00260 uint16_t random_number = randLIB_get_16bit(); 00261 uint16_t rnd_mask; 00262 00263 /* Generate retry back-off period. FHSS is using the known synchronization parent info to delay retransmissions upstream. 00264 * 00265 */ 00266 if (phy_mtu < 128) { 00267 // Max. random when PHY MTU below 128 is 6.4ms 00268 rnd_mask = 0x7f; 00269 } else if (phy_mtu < 256) { 00270 // Max. random when PHY MTU below 256 is 12.8ms 00271 rnd_mask = 0xff; 00272 } else { 00273 // Max. random when PHY MTU above 255 is 25.6ms 00274 rnd_mask = 0x1ff; 00275 } 00276 00277 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00278 if (fhss_structure) { 00279 uint32_t datarate = fhss_structure->datarate; 00280 uint16_t max_tx_length; 00281 00282 if (datarate && phy_mtu) { 00283 if (fhss_compare_with_synch_parent_address(fhss_structure, destination_address) == 0) { 00284 // E.g. (1000000 / (250000bit/s / 8 bits)) * 255 bytes = 8160us 00285 max_tx_length = ((1000000 / (datarate / 8)) * phy_mtu); 00286 /* Retrying upstream: delay the transmission until assumed hidden node has retried downstream: 00287 * Static period: max random + max tx length 00288 * 50 comes from MAC timer resolution (50us) 00289 */ 00290 retry_period = (rnd_mask + (max_tx_length / 50)); 00291 } 00292 } 00293 } 00294 00295 // Add 1 to not to ever return zero value. 00296 retry_period += ((random_number & rnd_mask) + 1); 00297 return retry_period; 00298 } 00299 00300 int fhss_init_callbacks_cb(const fhss_api_t *api, fhss_callback_t *callbacks) 00301 { 00302 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00303 if (!fhss_structure || !callbacks) { 00304 return -1; 00305 } 00306 fhss_structure->callbacks = *callbacks; 00307 return 0; 00308 }
Generated on Tue Jul 12 2022 18:18:35 by
