Skip to content

Commit 36dfb29

Browse files
author
Jarkko Paso
authored
MAC: Implemented automatic CCA threshold (#2353)
* MAC: Implemented automatic CCA threshold * WS bootstrap: Enable auto CCA threshold. Removed test API.
1 parent 0396b97 commit 36dfb29

24 files changed

+646
-8
lines changed

nanostack/mlme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ typedef enum {
264264
macAutoRequestKeyIndex = 0x7b, /*<The index of the key used for automatic data*/
265265
macDefaultKeySource = 0x7c, /*<Default key source*/
266266
//NON standard extension
267+
macCCAThresholdStart = 0xf4, /*< Start automatic CCA threshold */
267268
macDevicePendingAckTrig = 0xf5, /*< Trig Pending ACK for Accepted Data packet for temporary neighbour */
268269
mac802_15_4Mode = 0xf6, /*<IEEE 802.15.4 mode*/
269270
macDeviceDescriptionPanIDUpdate = 0xf7, /*<Thread pending link update case this will update device descrioton list pan-id to new one*/

nanostack/platform/arm_hal_phy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ typedef enum {
8080
PHY_EXTENSION_FILTERING_SUPPORT, /**< Return filtering modes that can be supported by the PHY driver. See phy_link_filters_e */
8181
PHY_EXTENSION_SET_TX_POWER, /**< Set TX output power which is given as percentage of maximum. 0 is the lowest possible TX power and 100 is the highest possible TX power */
8282
PHY_EXTENSION_SET_CCA_THRESHOLD, /**< Set CCA threshold which is given as percentage of maximum threshold. 0 is the lowest(strictest) possible threshold and 100 is the highest possible threshold */
83+
PHY_EXTENSION_SET_CHANNEL_CCA_THRESHOLD, /**< Set CCA threshold which is given as dBm. This value is set in PHY_LINK_CCA_PREPARE callback and PHY driver should update the CCA threshold configuration */
8384
PHY_EXTENSION_SET_802_15_4_MODE /**< Set IEEE 802.15.4 mode as defined by phy_802_15_4_mode_t*/
8485
} phy_extension_type_e;
8586

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2099,6 +2099,12 @@ int ws_bootstrap_set_rf_config(protocol_interface_info_entry_t *cur, phy_rf_chan
20992099
set_request.value_pointer = &multi_csma_params;
21002100
set_request.value_size = sizeof(mlme_multi_csma_ca_param_t);
21012101
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
2102+
// Start automatic CCA threshold
2103+
uint8_t start_cca_thr[4] = {cur->ws_info->hopping_schdule.number_of_channels, CCA_DEFAULT_DBM, CCA_HIGH_LIMIT, CCA_LOW_LIMIT};
2104+
set_request.attr = macCCAThresholdStart;
2105+
set_request.value_pointer = &start_cca_thr;
2106+
set_request.value_size = sizeof(start_cca_thr);
2107+
cur->mac_api->mlme_req(cur->mac_api, MLME_SET, &set_request);
21022108
return 0;
21032109
}
21042110

source/6LoWPAN/ws/ws_common_defines.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ typedef struct ws_bs_ie {
319319
#warning "MAX frame retries set too low"
320320
#endif
321321

322+
/*
323+
* Automatic CCA threshold: default threshold and range in dBm.
324+
*/
325+
#define CCA_DEFAULT_DBM -85
326+
#define CCA_HIGH_LIMIT -60
327+
#define CCA_LOW_LIMIT -100
328+
329+
322330
/*
323331
* Config new version consistent filter period in 100ms periods
324332
*/

source/6LoWPAN/ws/ws_test_api.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
#include <net_ws_test.h>
2424
#include "fhss_config.h"
2525
#include "ws_management_api.h"
26+
#include "mac_api.h"
2627
#include "NWK_INTERFACE/Include/protocol.h"
28+
#include "6LoWPAN/MAC/mac_helper.h"
2729
#include "6LoWPAN/ws/ws_config.h"
2830
#include "6LoWPAN/ws/ws_common.h"
2931
#include "6LoWPAN/ws/ws_bbr_api_internal.h"
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2020, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#include "string.h"
18+
#include "nsconfig.h"
19+
#include "ns_types.h"
20+
#include "ns_trace.h"
21+
#include "nsdynmemLIB.h"
22+
#include "MAC/IEEE802_15_4/mac_defines.h"
23+
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
24+
25+
#define TRACE_GROUP "mcth"
26+
27+
int8_t mac_cca_thr_init(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit)
28+
{
29+
// No changes
30+
if (rf_ptr->cca_threshold &&
31+
(number_of_channels == rf_ptr->cca_threshold->number_of_channels) &&
32+
(default_dbm == rf_ptr->cca_threshold->default_dbm) &&
33+
(high_limit == rf_ptr->cca_threshold->high_limit) &&
34+
(low_limit == rf_ptr->cca_threshold->low_limit)) {
35+
return -1;
36+
}
37+
// Validate given dBm range. Default must be in between high and low limit.
38+
if ((default_dbm > high_limit) || (default_dbm < low_limit)) {
39+
return -1;
40+
}
41+
mac_cca_thr_deinit(rf_ptr);
42+
rf_ptr->cca_threshold = ns_dyn_mem_alloc(sizeof(mac_cca_threshold_s));
43+
if (!rf_ptr->cca_threshold) {
44+
return -1;
45+
}
46+
rf_ptr->cca_threshold->ch_thresholds = ns_dyn_mem_alloc(number_of_channels);
47+
if (!rf_ptr->cca_threshold->ch_thresholds) {
48+
ns_dyn_mem_free(rf_ptr->cca_threshold);
49+
rf_ptr->cca_threshold = 0;
50+
return -1;
51+
}
52+
memset(rf_ptr->cca_threshold->ch_thresholds, default_dbm, number_of_channels);
53+
rf_ptr->cca_threshold->high_limit = high_limit;
54+
rf_ptr->cca_threshold->low_limit = low_limit;
55+
rf_ptr->cca_threshold->default_dbm = default_dbm;
56+
rf_ptr->cca_threshold->number_of_channels = number_of_channels;
57+
tr_info("Initialized CCA threshold: %u, %i, %i, %i", number_of_channels, default_dbm, high_limit, low_limit);
58+
return 0;
59+
}
60+
61+
int8_t mac_cca_thr_deinit(protocol_interface_rf_mac_setup_s *rf_ptr)
62+
{
63+
if (!rf_ptr->cca_threshold) {
64+
return -1;
65+
}
66+
ns_dyn_mem_free(rf_ptr->cca_threshold->ch_thresholds);
67+
ns_dyn_mem_free(rf_ptr->cca_threshold);
68+
rf_ptr->cca_threshold = 0;
69+
return 0;
70+
}
71+
72+
int8_t mac_cca_thr_get_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel)
73+
{
74+
if (!rf_ptr->cca_threshold) {
75+
return CCA_FAILED_DBM;
76+
}
77+
return rf_ptr->cca_threshold->ch_thresholds[channel];
78+
}
79+
80+
static int8_t mac_cca_thr_set_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
81+
{
82+
if (rf_ptr->cca_threshold->ch_thresholds[channel] != dbm) {
83+
rf_ptr->cca_threshold->ch_thresholds[channel] = dbm;
84+
return 0;
85+
}
86+
return -1;
87+
}
88+
89+
static int8_t mac_cca_thr_update_channel_threshold(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
90+
{
91+
// Already on low limit
92+
if (rf_ptr->cca_threshold->ch_thresholds[channel] == rf_ptr->cca_threshold->low_limit) {
93+
return -1;
94+
}
95+
// Already using lower threshold
96+
if (rf_ptr->cca_threshold->ch_thresholds[channel] <= (dbm - CCA_THRESHOLD_STEP)) {
97+
return -1;
98+
}
99+
// Do not set below configured low limit
100+
if ((dbm - CCA_THRESHOLD_STEP) < rf_ptr->cca_threshold->low_limit) {
101+
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->low_limit);
102+
}
103+
return mac_cca_thr_set_dbm(rf_ptr, channel, dbm - CCA_THRESHOLD_STEP);
104+
}
105+
106+
static int8_t mac_cca_thr_channel_failed(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel)
107+
{
108+
// Already on high limit
109+
if (rf_ptr->cca_threshold->ch_thresholds[channel] == rf_ptr->cca_threshold->high_limit) {
110+
return -1;
111+
}
112+
// Do not set above configured high limit
113+
if ((rf_ptr->cca_threshold->ch_thresholds[channel] + CCA_THRESHOLD_STEP) > rf_ptr->cca_threshold->high_limit) {
114+
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->high_limit);
115+
}
116+
return mac_cca_thr_set_dbm(rf_ptr, channel, rf_ptr->cca_threshold->ch_thresholds[channel] + CCA_THRESHOLD_STEP);
117+
}
118+
119+
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm)
120+
{
121+
if (dbm == CCA_FAILED_DBM) {
122+
if (mac_cca_thr_channel_failed(rf_ptr, channel)) {
123+
return -1;
124+
}
125+
} else {
126+
if (mac_cca_thr_update_channel_threshold(rf_ptr, channel, dbm)) {
127+
return -1;
128+
}
129+
}
130+
tr_debug("Channel %u CCA threshold to %i", channel, rf_ptr->cca_threshold->ch_thresholds[channel]);
131+
return 0;
132+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2020, Arm Limited and affiliates.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#ifndef MAC_CCA_THRESHOLD_H_
19+
#define MAC_CCA_THRESHOLD_H_
20+
21+
#define CCA_THRESHOLD_STEP 1
22+
#define CCA_FAILED_DBM 0x7F
23+
24+
typedef struct mac_cca_threshold {
25+
int8_t *ch_thresholds;
26+
int8_t high_limit;
27+
int8_t low_limit;
28+
int8_t default_dbm;
29+
uint8_t number_of_channels;
30+
} mac_cca_threshold_s;
31+
32+
/**
33+
* @brief Initialize automatic CCA threshold.
34+
* @param rf_ptr Pointer to MAC instance.
35+
* @param number_of_channels Number of MAC channels.
36+
* @param default_dbm Default threshold.
37+
* @param high_limit Highest allowed CCA threshold.
38+
* @param low_limit Lowest allowed CCA threshold.
39+
* @return 0 Success, negative Failed.
40+
*/
41+
int8_t mac_cca_thr_init(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t number_of_channels, int8_t default_dbm, int8_t high_limit, int8_t low_limit);
42+
43+
/**
44+
* @brief Deinitialize automatic CCA threshold.
45+
* @param rf_ptr Pointer to MAC instance.
46+
* @return 0 Success, negative Not found.
47+
*/
48+
int8_t mac_cca_thr_deinit(protocol_interface_rf_mac_setup_s *rf_ptr);
49+
50+
/**
51+
* @brief Read CCA threshold of specific channel.
52+
* @param channel Channel.
53+
* @return CCA threshold (dBm), CCA_FAILED_DBM Feature not enabled.
54+
*/
55+
int8_t mac_cca_thr_get_dbm(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel);
56+
57+
/**
58+
* @brief Update CCA threshold of specific channel.
59+
* @param channel Channel.
60+
* @param dbm CCA threshold (dBm).
61+
* @return 0 Updated, negative Already using this value.
62+
*/
63+
int8_t mac_cca_threshold_update(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int8_t dbm);
64+
65+
#endif /* MAC_CCA_THRESHOLD_H_ */

source/MAC/IEEE802_15_4/mac_data_buffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ typedef struct mac_pre_build_frame {
9191
uint8_t csma_periods_left;
9292
uint8_t fhss_retry_count;
9393
uint8_t fhss_cca_retry_count;
94+
uint16_t initial_tx_channel;
9495
uint32_t tx_time;
9596
bool upper_layer_request: 1;
9697
bool mac_allocated_payload_ptr: 1;

source/MAC/IEEE802_15_4/mac_defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ typedef struct protocol_interface_rf_mac_setup {
276276
struct arm_device_driver_list *tun_extension_rf_driver;
277277
/* End of API Control */
278278
struct mlme_scan_conf_s *mac_mlme_scan_resp;
279+
struct mac_cca_threshold *cca_threshold;
279280
//beacon_join_priority_tx_cb *beacon_join_priority_tx_cb_ptr;
280281
struct mac_statistics_s *mac_statistics;
281282
/* FHSS API*/

source/MAC/IEEE802_15_4/mac_mcps_sap.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
4646
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
4747
#include "MAC/IEEE802_15_4/mac_indirect_data.h"
48+
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
4849
#include "MAC/rf_driver_storage.h"
4950

5051
#include "sw_mac.h"
@@ -1196,6 +1197,9 @@ static void mac_mcps_sap_data_tasklet(arm_event_s *event)
11961197
case MAC_MLME_SCAN_CONFIRM_HANDLER:
11971198
mac_mlme_scan_confirmation_handle((protocol_interface_rf_mac_setup_s *) event->data_ptr);
11981199
break;
1200+
case MAC_CCA_THR_UPDATE:
1201+
mac_cca_threshold_update((protocol_interface_rf_mac_setup_s *) event->data_ptr, event->event_data >> 8, (int8_t) event->event_data);
1202+
break;
11991203
case MAC_SAP_TRIG_TX:
12001204
mac_clear_active_event((protocol_interface_rf_mac_setup_s *) event->data_ptr, MAC_SAP_TRIG_TX);
12011205
mac_mcps_trig_buffer_from_queue((protocol_interface_rf_mac_setup_s *) event->data_ptr);
@@ -1221,6 +1225,7 @@ mac_pre_build_frame_t *mcps_sap_prebuild_frame_buffer_get(uint16_t payload_size)
12211225
return NULL;
12221226
}
12231227
memset(buffer, 0, sizeof(mac_pre_build_frame_t));
1228+
buffer->initial_tx_channel = 0xffff;
12241229
buffer->aux_header.frameCounter = 0xffffffff;
12251230
if (payload_size) {
12261231
//Mac interlnal payload allocate
@@ -2255,6 +2260,25 @@ void mcps_sap_trig_tx(void *mac_ptr)
22552260
}
22562261
}
22572262

2263+
void mac_cca_threshold_event_send(protocol_interface_rf_mac_setup_s *rf_ptr, uint8_t channel, int16_t dbm)
2264+
{
2265+
// Return if feature is not initialized
2266+
if (!rf_ptr->cca_threshold) {
2267+
return;
2268+
}
2269+
uint16_t data = channel << 8 | (uint8_t) dbm;
2270+
arm_event_s event = {
2271+
.receiver = mac_tasklet_event_handler,
2272+
.sender = 0,
2273+
.event_id = 0,
2274+
.event_data = data,
2275+
.data_ptr = rf_ptr,
2276+
.event_type = MAC_CCA_THR_UPDATE,
2277+
.priority = ARM_LIB_LOW_PRIORITY_EVENT,
2278+
};
2279+
2280+
eventOS_event_send(&event);
2281+
}
22582282

22592283
void mac_generic_event_trig(uint8_t event_type, void *mac_ptr, bool low_latency)
22602284
{

source/MAC/IEEE802_15_4/mac_mcps_sap.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ typedef enum {
5656
#define MAC_MLME_SCAN_CONFIRM_HANDLER 6
5757
#define MAC_SAP_TRIG_TX 7
5858
#define MCPS_SAP_DATA_ACK_CNF_EVENT 8
59+
#define MAC_CCA_THR_UPDATE 9
5960

6061
// Default number of CSMA-CA periods
6162
#define MAC_DEFAULT_NUMBER_OF_CSMA_PERIODS 1
@@ -142,4 +143,6 @@ uint32_t mac_mcps_sap_get_phy_timestamp(struct protocol_interface_rf_mac_setup *
142143

143144
void mcps_pending_packet_counter_update_check(struct protocol_interface_rf_mac_setup *rf_mac_setup, mac_pre_build_frame_t *buffer);
144145

146+
void mac_cca_threshold_event_send(struct protocol_interface_rf_mac_setup *rf_mac_setup, uint8_t channel, int16_t dbm);
147+
145148
#endif /* MAC_IEEE802_15_4_MAC_MCPS_SAP_H_ */

source/MAC/IEEE802_15_4/mac_mlme.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "MAC/IEEE802_15_4/mac_timer.h"
4949
#include "MAC/IEEE802_15_4/mac_pd_sap.h"
5050
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
51+
#include "MAC/IEEE802_15_4/mac_cca_threshold.h"
5152
#include "MAC/virtual_rf/virtual_rf_defines.h"
5253
#include "MAC/rf_driver_storage.h"
5354

@@ -806,6 +807,10 @@ int8_t mac_mlme_set_req(protocol_interface_rf_mac_setup_s *rf_mac_setup, const m
806807
memcpy(rf_mac_setup->coord_long_address, set_req->value_pointer, 8);
807808
}
808809
return 0;
810+
case macCCAThresholdStart:
811+
pu8 = (uint8_t *) set_req->value_pointer;
812+
mac_cca_thr_init(rf_mac_setup, *pu8, *((int8_t *)pu8 + 1), *((int8_t *)pu8 + 2), *((int8_t *)pu8 + 3));
813+
return 0;
809814
case mac802_15_4Mode:
810815
pu8 = (uint8_t *) set_req->value_pointer;
811816
if (rf_mac_setup->current_mac_mode == *pu8) {
@@ -1097,6 +1102,7 @@ void mac_mlme_data_base_deallocate(struct protocol_interface_rf_mac_setup *rf_ma
10971102
ns_dyn_mem_free(rf_mac->mac_beacon_payload);
10981103

10991104
mac_sec_mib_deinit(rf_mac);
1105+
mac_cca_thr_deinit(rf_mac);
11001106
ns_dyn_mem_free(rf_mac);
11011107
}
11021108
}

0 commit comments

Comments
 (0)