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.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
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 "randLIB.h" 00026 #include "ns_trace.h" 00027 00028 #define TRACE_GROUP "fhss" 00029 00030 00031 bool fhss_is_broadcast_channel_cb(const fhss_api_t *api) 00032 { 00033 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00034 if (!fhss_structure) { 00035 return false; 00036 } 00037 // FHSS is unsynchronized, broadcasts allowed 00038 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00039 return true; 00040 } 00041 return fhss_is_current_channel_broadcast(fhss_structure); 00042 } 00043 00044 bool fhss_use_broadcast_queue_cb(const fhss_api_t *api, bool is_broadcast_addr, int frame_type) 00045 { 00046 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00047 if (!fhss_structure) { 00048 return false; 00049 } 00050 // Synch requests are always stored in unicast queue 00051 if (frame_type == FHSS_SYNCH_REQUEST_FRAME) { 00052 return false; 00053 } 00054 // Broadcast packets are stored in broadcast queue 00055 return is_broadcast_addr; 00056 } 00057 00058 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) 00059 { 00060 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00061 if (!fhss_structure) { 00062 return -2; 00063 } 00064 // TODO: needs some more logic to push buffer back to queue 00065 if (frame_type == FHSS_DATA_FRAME) { 00066 if (is_broadcast_addr == true) { 00067 if (fhss_is_current_channel_broadcast(fhss_structure) == false) { 00068 tr_info("Broadcast on UC channel -> Back to queue"); 00069 return -3; 00070 } 00071 } 00072 } 00073 if (frame_type == FHSS_SYNCH_FRAME) { 00074 if (!synch_info) { 00075 return -4; 00076 } 00077 fhss_beacon_build(fhss_structure, synch_info); 00078 } else if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 00079 return -1; 00080 } 00081 // If sending Beacon request on parents Unicast channel 00082 if (frame_type == FHSS_SYNCH_REQUEST_FRAME && fhss_structure->fhss_state == FHSS_SYNCHRONIZED) { 00083 fhss_change_to_parent_channel(fhss_structure); 00084 } else if (frame_type == FHSS_DATA_FRAME) { 00085 fhss_change_to_tx_channel(fhss_structure, destination_address); 00086 } 00087 return 0; 00088 } 00089 00090 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) 00091 { 00092 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00093 if (!fhss_structure) { 00094 return false; 00095 } 00096 // This condition will check that message is not sent on bad channel 00097 if (fhss_check_bad_channel(fhss_structure, handle) == false) { 00098 return false; 00099 } 00100 00101 // This condition will check that broadcast messages are sent only broadcast channels 00102 if (fhss_check_channel_type(fhss_structure, is_broadcast_addr, frame_type) == false) { 00103 return false; 00104 } 00105 00106 // This condition will check that FHSS is on TX slot and there is enough time to transmit before channel or slot change 00107 if (fhss_check_tx_allowed(fhss_structure, is_broadcast_addr, frame_length, frame_type, phy_header_length, phy_tail_length) == false) { 00108 return false; 00109 } 00110 00111 return true; 00112 } 00113 00114 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) 00115 { 00116 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00117 if (!fhss_structure) { 00118 return; 00119 } 00120 if (FHSS_SYNCH_FRAME == frame_type) { 00121 if ((fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) || fhss_structure->synch_panid != pan_id) { 00122 fhss_add_beacon_info(fhss_structure, pan_id, source_address, timestamp, synch_info); 00123 } else { 00124 if (!fhss_compare_with_synch_parent_address(fhss_structure, source_address)) { 00125 // Synch parent address needs to be updated in case parent has changed 00126 fhss_update_synch_parent_address(fhss_structure); 00127 // Calculate time since the Beacon was received 00128 uint32_t elapsed_time = api->read_timestamp(api) - timestamp; 00129 // Synchronize to given PAN 00130 fhss_beacon_received(fhss_structure, synch_info, elapsed_time); 00131 } 00132 } 00133 } else if (FHSS_SYNCH_REQUEST_FRAME == frame_type) { 00134 // If current channel is broadcast, we don't need to send another synch info on next broadcast channel. 00135 // Only send number of MAX_SYNCH_INFOS_PER_CHANNEL_LIST synch infos per one channel list cycle 00136 if ((fhss_structure->fhss_state == FHSS_SYNCHRONIZED) && (fhss_is_current_channel_broadcast(fhss_structure) == false) 00137 && (fhss_structure->synch_infos_sent_counter < MAX_SYNCH_INFOS_PER_CHANNEL_LIST)) { 00138 fhss_structure->send_synch_info_on_next_broadcast_channel = true; 00139 } 00140 } 00141 } 00142 00143 void fhss_data_tx_done_cb(const fhss_api_t *api, bool waiting_ack, bool tx_completed, uint8_t handle) 00144 { 00145 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00146 if (!fhss_structure) { 00147 return; 00148 } 00149 if (waiting_ack == false) { 00150 fhss_change_to_rx_channel(fhss_structure); 00151 } 00152 // Buffer was successfully transmitted. Remove stored failure handle if exists. 00153 if (tx_completed == true) { 00154 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00155 if (fhss_failed_tx) { 00156 fhss_failed_handle_remove(fhss_structure, handle); 00157 } 00158 } 00159 } 00160 00161 bool fhss_data_tx_fail_cb(const fhss_api_t *api, uint8_t handle, int frame_type) 00162 { 00163 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00164 if (!fhss_structure) { 00165 return false; 00166 } 00167 // Only use channel retries when device is synchronized 00168 if (fhss_structure->fhss_state == FHSS_UNSYNCHRONIZED) { 00169 return false; 00170 } 00171 // Channel retries are disabled -> return 00172 if (fhss_structure->fhss_configuration.fhss_number_of_channel_retries == 0) { 00173 return false; 00174 } 00175 // Use channel retries only for data frames 00176 if (FHSS_DATA_FRAME != frame_type) { 00177 return false; 00178 } 00179 00180 fhss_failed_tx_t *fhss_failed_tx = fhss_failed_handle_find(fhss_structure, handle); 00181 if (fhss_failed_tx) { 00182 fhss_failed_tx->retries_done++; 00183 if (fhss_failed_tx->retries_done >= fhss_structure->fhss_configuration.fhss_number_of_channel_retries) { 00184 // No more retries. Return false to stop retransmitting. 00185 fhss_failed_handle_remove(fhss_structure, handle); 00186 return false; 00187 } 00188 } else { 00189 // Create new failure handle and return true to retransmit 00190 fhss_failed_handle_add(fhss_structure, handle); 00191 } 00192 return true; 00193 } 00194 00195 void fhss_synch_state_set_cb(const fhss_api_t *api, fhss_states fhss_state, uint16_t pan_id) 00196 { 00197 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00198 if (!fhss_structure) { 00199 return; 00200 } 00201 00202 // State is already set 00203 if (fhss_structure->fhss_state == fhss_state) { 00204 return; 00205 } 00206 00207 if (fhss_state == FHSS_UNSYNCHRONIZED) { 00208 fhss_down(fhss_structure); 00209 } else { 00210 // Do not synchronize to current pan 00211 if (fhss_structure->synch_panid == pan_id) { 00212 return; 00213 } 00214 uint32_t datarate = fhss_structure->callbacks.read_datarate(api); 00215 fhss_set_datarate(fhss_structure, datarate); 00216 uint8_t mac_address[8]; 00217 fhss_structure->callbacks.read_mac_address(fhss_structure->fhss_api, mac_address); 00218 fhss_structure->uc_channel_index = fhss_get_offset(fhss_structure, mac_address); 00219 // Get Beacon info from storage 00220 fhss_beacon_info_t *beacon_info = fhss_get_beacon_info(fhss_structure, pan_id); 00221 if (beacon_info) { 00222 memcpy(fhss_structure->synch_parent, beacon_info->source_address, 8); 00223 // Calculate time since the Beacon was received 00224 uint32_t elapsed_time = api->read_timestamp(api) - beacon_info->timestamp; 00225 // Synchronize to given PAN 00226 fhss_beacon_received(fhss_structure, beacon_info->synch_info, elapsed_time); 00227 // Delete stored Beacon infos 00228 fhss_flush_beacon_info_storage(fhss_structure); 00229 fhss_structure->synch_panid = pan_id; 00230 } else if (fhss_is_synch_root(fhss_structure) == true) { 00231 // Synch root will start new network 00232 fhss_start_timer(fhss_structure, fhss_structure->synch_configuration.fhss_superframe_length, fhss_superframe_handler); 00233 } 00234 } 00235 fhss_structure->fhss_state = fhss_state; 00236 } 00237 00238 uint32_t fhss_read_timestamp_cb(const fhss_api_t *api) 00239 { 00240 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00241 if (!fhss_structure) { 00242 return 0; 00243 } 00244 return (fhss_structure->platform_functions.fhss_get_timestamp(api) * fhss_structure->platform_functions.fhss_resolution_divider); 00245 } 00246 00247 uint16_t fhss_get_retry_period_cb(const fhss_api_t *api, uint8_t *destination_address, uint16_t phy_mtu) 00248 { 00249 uint16_t retry_period = 0; 00250 uint16_t random_number = randLIB_get_16bit(); 00251 uint16_t rnd_mask; 00252 00253 /* Generate retry back-off period. FHSS is using the known synchronization parent info to delay retransmissions upstream. 00254 * 00255 */ 00256 if (phy_mtu < 128) { 00257 // Max. random when PHY MTU below 128 is 6.4ms 00258 rnd_mask = 0x7f; 00259 } else if (phy_mtu < 256) { 00260 // Max. random when PHY MTU below 256 is 12.8ms 00261 rnd_mask = 0xff; 00262 } else { 00263 // Max. random when PHY MTU above 255 is 25.6ms 00264 rnd_mask = 0x1ff; 00265 } 00266 00267 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00268 if (fhss_structure) { 00269 uint32_t datarate = fhss_structure->datarate; 00270 uint16_t max_tx_length; 00271 00272 if (datarate && phy_mtu) { 00273 if (fhss_compare_with_synch_parent_address(fhss_structure, destination_address) == 0) { 00274 // E.g. (1000000 / (250000bit/s / 8 bits)) * 255 bytes = 8160us 00275 max_tx_length = ((1000000 / (datarate / 8)) * phy_mtu); 00276 /* Retrying upstream: delay the transmission until assumed hidden node has retried downstream: 00277 * Static period: max random + max tx length 00278 * 50 comes from MAC timer resolution (50us) 00279 */ 00280 retry_period = (rnd_mask + (max_tx_length / 50)); 00281 } 00282 } 00283 } 00284 00285 // Add 1 to not to ever return zero value. 00286 retry_period += ((random_number & rnd_mask) + 1); 00287 return retry_period; 00288 } 00289 00290 int fhss_init_callbacks_cb(const fhss_api_t *api, fhss_callback_t *callbacks) 00291 { 00292 fhss_structure_t *fhss_structure = fhss_get_object_with_api(api); 00293 if (!fhss_structure || !callbacks) { 00294 return -1; 00295 } 00296 fhss_structure->callbacks = *callbacks; 00297 return 0; 00298 }
Generated on Tue Jul 12 2022 13:02:53 by
