1 /*
2 * Copyright (c) 2017 - 2023, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 /**
36 * @file
37 * This file implements storage of PIB attributes in nRF 802.15.4 radio driver.
38 *
39 */
40
41 #include "nrf_802154_pib.h"
42
43 #include <assert.h>
44 #include <stdbool.h>
45 #include <stdint.h>
46 #include <string.h>
47
48 #include "nrf_802154_config.h"
49 #include "nrf_802154_const.h"
50 #include "nrf_802154_utils.h"
51
52 #define CSMACA_BE_MAXIMUM 8 ///< The maximum allowed CSMA-CA backoff exponent (BE) that results from the implementation
53
54 typedef struct
55 {
56 nrf_802154_coex_rx_request_mode_t rx_request_mode; ///< Coex request mode in receive operation.
57 nrf_802154_coex_tx_request_mode_t tx_request_mode; ///< Coex request mode in transmit operation.
58 } nrf_802154_pib_coex_t;
59
60 #if NRF_802154_CSMA_CA_ENABLED
61 typedef struct
62 {
63 uint8_t min_be; // The minimum value of the backoff exponent (BE) in the CSMA-CA algorithm
64 uint8_t max_be; // The maximum value of the backoff exponent (BE) in the CSMA-CA algorithm
65 uint8_t max_backoffs; // The maximum number of backoffs that the CSMA-CA algorithm will attempt before declaring a channel access failure.
66 } nrf_802154_pib_csmaca_t;
67
68 #endif // NRF_802154_CSMA_CA_ENABLED
69
70 #if NRF_802154_IFS_ENABLED
71 typedef struct
72 {
73 nrf_802154_ifs_mode_t mode; ///< Mode of Interframe Space insertion.
74 uint16_t min_sifs_period_us; ///< Minimum Short Interframe Space period in us.
75 uint16_t min_lifs_period_us; ///< Minimum Long Interframe Space period in us.
76 } nrf_802154_pib_ifs_t;
77
78 #endif // NRF_802154_IFS_ENABLED
79
80 #if NRF_802154_TEST_MODES_ENABLED
81 typedef struct
82 {
83 nrf_802154_test_mode_csmaca_backoff_t csmaca_backoff; ///< CSMA/CA control mode
84 } nrf_802154_pib_test_modes_t;
85
86 #endif // NRF_802154_TEST_MODES_ENABLED
87
88 typedef struct
89 {
90 int8_t tx_power; ///< Transmit power.
91 uint8_t pan_id[PAN_ID_SIZE]; ///< Pan Id of this node.
92 uint8_t short_addr[SHORT_ADDRESS_SIZE]; ///< Short Address of this node.
93 uint8_t extended_addr[EXTENDED_ADDRESS_SIZE]; ///< Extended Address of this node.
94 nrf_802154_cca_cfg_t cca; ///< CCA mode and thresholds.
95 bool promiscuous : 1; ///< Indicating if radio is in promiscuous mode.
96 bool auto_ack : 1; ///< Indicating if auto ACK procedure is enabled.
97 bool pan_coord : 1; ///< Indicating if radio is configured as the PAN coordinator.
98 uint8_t channel : 5; ///< Channel on which the node receives messages.
99 nrf_802154_pib_coex_t coex; ///< Coex-related fields.
100
101 #if NRF_802154_CSMA_CA_ENABLED
102 nrf_802154_pib_csmaca_t csmaca; ///< CSMA-CA related fields.
103
104 #endif
105
106 #if NRF_802154_IFS_ENABLED
107 nrf_802154_pib_ifs_t ifs; ///< IFS-related fields.
108
109 #endif
110
111 #if NRF_802154_TEST_MODES_ENABLED
112 nrf_802154_pib_test_modes_t test_modes; ///< Test modes
113
114 #endif
115
116 } nrf_802154_pib_data_t;
117
118 // Static variables.
119 static nrf_802154_pib_data_t m_data; ///< Buffer containing PIB data.
120
121 /**
122 * @brief Checks if provided Coex transmit request mode is supported.
123 *
124 * @param[in] mode Coex transmit request mode to check.
125 *
126 * @retval true When value provided by @p mode param is supported.
127 * @retval false Otherwise.
128 */
coex_tx_request_mode_is_supported(nrf_802154_coex_tx_request_mode_t mode)129 static bool coex_tx_request_mode_is_supported(nrf_802154_coex_tx_request_mode_t mode)
130 {
131 bool result = false;
132
133 switch (mode)
134 {
135 case NRF_802154_COEX_TX_REQUEST_MODE_FRAME_READY:
136 case NRF_802154_COEX_TX_REQUEST_MODE_CCA_START:
137 case NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE:
138 case NRF_802154_COEX_TX_REQUEST_MODE_ON_CCA_TOGGLE:
139 result = true;
140 break;
141
142 default:
143 break;
144 }
145
146 return result;
147 }
148
149 /**
150 * @brief Checks if provided Coex receive request mode is supported.
151 *
152 * @param[in] mode Coex receive request mode to check.
153 *
154 * @retval true When value provided by @p mode param is supported.
155 * @retval false Otherwise.
156 */
coex_rx_request_mode_is_supported(nrf_802154_coex_rx_request_mode_t mode)157 static bool coex_rx_request_mode_is_supported(nrf_802154_coex_rx_request_mode_t mode)
158 {
159 bool result = false;
160
161 switch (mode)
162 {
163 #if defined(RADIO_INTENSET_SYNC_Msk)
164 case NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION:
165 #endif
166 case NRF_802154_COEX_RX_REQUEST_MODE_PREAMBLE:
167 case NRF_802154_COEX_RX_REQUEST_MODE_DESTINED:
168 result = true;
169 break;
170
171 default:
172 break;
173 }
174
175 return result;
176 }
177
nrf_802154_pib_init(void)178 void nrf_802154_pib_init(void)
179 {
180 m_data.promiscuous = false;
181 m_data.auto_ack = true;
182 m_data.pan_coord = false;
183 m_data.channel = 11;
184
185 memset(m_data.pan_id, 0xff, sizeof(m_data.pan_id));
186 m_data.short_addr[0] = 0xfe;
187 m_data.short_addr[1] = 0xff;
188 memset(m_data.extended_addr, 0, sizeof(m_data.extended_addr));
189
190 m_data.cca.mode = NRF_802154_CCA_MODE_DEFAULT;
191 m_data.cca.ed_threshold = NRF_802154_CCA_ED_THRESHOLD_DEFAULT;
192 m_data.cca.corr_threshold = NRF_802154_CCA_CORR_THRESHOLD_DEFAULT;
193 m_data.cca.corr_limit = NRF_802154_CCA_CORR_LIMIT_DEFAULT;
194
195 m_data.coex.rx_request_mode = NRF_802154_COEX_RX_REQUEST_MODE_DESTINED;
196 m_data.coex.tx_request_mode = NRF_802154_COEX_TX_REQUEST_MODE_ON_CCA_TOGGLE;
197
198 #if NRF_802154_CSMA_CA_ENABLED
199 m_data.csmaca.min_be = NRF_802154_CSMA_CA_MIN_BE_DEFAULT;
200 m_data.csmaca.max_be = NRF_802154_CSMA_CA_MAX_BE_DEFAULT;
201 m_data.csmaca.max_backoffs = NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS_DEFAULT;
202 #endif // NRF_802154_CSMA_CA_ENABLED
203
204 #if NRF_802154_IFS_ENABLED
205 m_data.ifs.min_sifs_period_us = MIN_SIFS_PERIOD_US;
206 m_data.ifs.min_lifs_period_us = MIN_LIFS_PERIOD_US;
207 m_data.ifs.mode = NRF_802154_IFS_MODE_DISABLED;
208 #endif // NRF_802154_IFS_ENABLED
209
210 #if NRF_802154_TEST_MODES_ENABLED
211 m_data.test_modes.csmaca_backoff = NRF_802154_TEST_MODE_CSMACA_BACKOFF_RANDOM;
212 #endif
213
214 }
215
nrf_802154_pib_promiscuous_get(void)216 bool nrf_802154_pib_promiscuous_get(void)
217 {
218 return m_data.promiscuous;
219 }
220
nrf_802154_pib_promiscuous_set(bool enabled)221 void nrf_802154_pib_promiscuous_set(bool enabled)
222 {
223 m_data.promiscuous = enabled;
224 }
225
nrf_802154_pib_auto_ack_get(void)226 bool nrf_802154_pib_auto_ack_get(void)
227 {
228 return m_data.auto_ack;
229 }
230
nrf_802154_pib_auto_ack_set(bool enabled)231 void nrf_802154_pib_auto_ack_set(bool enabled)
232 {
233 m_data.auto_ack = enabled;
234 }
235
nrf_802154_pib_pan_coord_get(void)236 bool nrf_802154_pib_pan_coord_get(void)
237 {
238 return m_data.pan_coord;
239 }
240
nrf_802154_pib_pan_coord_set(bool enabled)241 void nrf_802154_pib_pan_coord_set(bool enabled)
242 {
243 m_data.pan_coord = enabled;
244 }
245
nrf_802154_pib_channel_get(void)246 uint8_t nrf_802154_pib_channel_get(void)
247 {
248 return m_data.channel;
249 }
250
nrf_802154_pib_channel_set(uint8_t channel)251 void nrf_802154_pib_channel_set(uint8_t channel)
252 {
253 m_data.channel = channel;
254 }
255
nrf_802154_pib_tx_power_get(void)256 int8_t nrf_802154_pib_tx_power_get(void)
257 {
258 return m_data.tx_power;
259 }
260
nrf_802154_pib_tx_power_set(int8_t dbm)261 void nrf_802154_pib_tx_power_set(int8_t dbm)
262 {
263 m_data.tx_power = dbm;
264 }
265
nrf_802154_pib_pan_id_get(void)266 const uint8_t * nrf_802154_pib_pan_id_get(void)
267 {
268 return m_data.pan_id;
269 }
270
nrf_802154_pib_pan_id_set(const uint8_t * p_pan_id)271 void nrf_802154_pib_pan_id_set(const uint8_t * p_pan_id)
272 {
273 memcpy(m_data.pan_id, p_pan_id, PAN_ID_SIZE);
274 }
275
nrf_802154_pib_extended_address_get(void)276 const uint8_t * nrf_802154_pib_extended_address_get(void)
277 {
278 return m_data.extended_addr;
279 }
280
nrf_802154_pib_extended_address_set(const uint8_t * p_extended_address)281 void nrf_802154_pib_extended_address_set(const uint8_t * p_extended_address)
282 {
283 memcpy(m_data.extended_addr, p_extended_address, EXTENDED_ADDRESS_SIZE);
284 }
285
nrf_802154_pib_short_address_get(void)286 const uint8_t * nrf_802154_pib_short_address_get(void)
287 {
288 return m_data.short_addr;
289 }
290
nrf_802154_pib_short_address_set(const uint8_t * p_short_address)291 void nrf_802154_pib_short_address_set(const uint8_t * p_short_address)
292 {
293 memcpy(m_data.short_addr, p_short_address, SHORT_ADDRESS_SIZE);
294 }
295
nrf_802154_pib_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg)296 void nrf_802154_pib_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg)
297 {
298 switch (p_cca_cfg->mode)
299 {
300 case NRF_RADIO_CCA_MODE_ED:
301 m_data.cca.mode = p_cca_cfg->mode;
302 m_data.cca.ed_threshold = p_cca_cfg->ed_threshold;
303 break;
304
305 case NRF_RADIO_CCA_MODE_CARRIER:
306 m_data.cca.mode = p_cca_cfg->mode;
307 m_data.cca.corr_threshold = p_cca_cfg->corr_threshold;
308 m_data.cca.corr_limit = p_cca_cfg->corr_limit;
309 break;
310
311 case NRF_RADIO_CCA_MODE_CARRIER_AND_ED:
312 case NRF_RADIO_CCA_MODE_CARRIER_OR_ED:
313 memcpy(&m_data.cca, p_cca_cfg, sizeof(m_data.cca));
314 break;
315
316 default:
317 assert(false);
318 }
319 }
320
nrf_802154_pib_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg)321 void nrf_802154_pib_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg)
322 {
323 memcpy(p_cca_cfg, &m_data.cca, sizeof(m_data.cca));
324 }
325
nrf_802154_pib_coex_rx_request_mode_set(nrf_802154_coex_rx_request_mode_t mode)326 bool nrf_802154_pib_coex_rx_request_mode_set(nrf_802154_coex_rx_request_mode_t mode)
327 {
328 bool result = coex_rx_request_mode_is_supported(mode);
329
330 if (result)
331 {
332 m_data.coex.rx_request_mode = mode;
333 }
334
335 return result;
336 }
337
nrf_802154_pib_coex_rx_request_mode_get(void)338 nrf_802154_coex_rx_request_mode_t nrf_802154_pib_coex_rx_request_mode_get(void)
339 {
340 return m_data.coex.rx_request_mode;
341 }
342
nrf_802154_pib_coex_tx_request_mode_set(nrf_802154_coex_tx_request_mode_t mode)343 bool nrf_802154_pib_coex_tx_request_mode_set(nrf_802154_coex_tx_request_mode_t mode)
344 {
345 bool result = coex_tx_request_mode_is_supported(mode);
346
347 if (result)
348 {
349 m_data.coex.tx_request_mode = mode;
350 }
351
352 return result;
353 }
354
nrf_802154_pib_coex_tx_request_mode_get(void)355 nrf_802154_coex_tx_request_mode_t nrf_802154_pib_coex_tx_request_mode_get(void)
356 {
357 return m_data.coex.tx_request_mode;
358 }
359
360 #if NRF_802154_CSMA_CA_ENABLED
nrf_802154_pib_csmaca_min_be_set(uint8_t min_be)361 bool nrf_802154_pib_csmaca_min_be_set(uint8_t min_be)
362 {
363 bool result = (min_be <= CSMACA_BE_MAXIMUM);
364
365 if (result)
366 {
367 m_data.csmaca.min_be = min_be;
368 }
369
370 return result;
371 }
372
nrf_802154_pib_csmaca_min_be_get(void)373 uint8_t nrf_802154_pib_csmaca_min_be_get(void)
374 {
375 return m_data.csmaca.min_be;
376 }
377
nrf_802154_pib_csmaca_max_be_set(uint8_t max_be)378 bool nrf_802154_pib_csmaca_max_be_set(uint8_t max_be)
379 {
380 bool result = (max_be <= CSMACA_BE_MAXIMUM);
381
382 if (result)
383 {
384 m_data.csmaca.max_be = max_be;
385 }
386
387 return result;
388 }
389
nrf_802154_pib_csmaca_max_be_get(void)390 uint8_t nrf_802154_pib_csmaca_max_be_get(void)
391 {
392 return m_data.csmaca.max_be;
393 }
394
nrf_802154_pib_csmaca_max_backoffs_set(uint8_t max_backoffs)395 void nrf_802154_pib_csmaca_max_backoffs_set(uint8_t max_backoffs)
396 {
397 m_data.csmaca.max_backoffs = max_backoffs;
398 }
399
nrf_802154_pib_csmaca_max_backoffs_get(void)400 uint8_t nrf_802154_pib_csmaca_max_backoffs_get(void)
401 {
402 return m_data.csmaca.max_backoffs;
403 }
404
405 #endif // NRF_802154_CSMA_CA_ENABLED
406
407 #if NRF_802154_IFS_ENABLED
nrf_802154_pib_ifs_mode_get(void)408 nrf_802154_ifs_mode_t nrf_802154_pib_ifs_mode_get(void)
409 {
410 return m_data.ifs.mode;
411 }
412
nrf_802154_pib_ifs_mode_set(nrf_802154_ifs_mode_t mode)413 bool nrf_802154_pib_ifs_mode_set(nrf_802154_ifs_mode_t mode)
414 {
415 switch (mode)
416 {
417 case NRF_802154_IFS_MODE_DISABLED:
418 case NRF_802154_IFS_MODE_MATCHING_ADDRESSES:
419 case NRF_802154_IFS_MODE_ALWAYS:
420 m_data.ifs.mode = mode;
421 return true;
422
423 default:
424 return false;
425 }
426 }
427
nrf_802154_pib_ifs_min_sifs_period_get(void)428 uint16_t nrf_802154_pib_ifs_min_sifs_period_get(void)
429 {
430 return m_data.ifs.min_sifs_period_us;
431 }
432
nrf_802154_pib_ifs_min_sifs_period_set(uint16_t period)433 void nrf_802154_pib_ifs_min_sifs_period_set(uint16_t period)
434 {
435 assert(period >= TURNAROUND_TIME);
436
437 m_data.ifs.min_sifs_period_us = period;
438 }
439
nrf_802154_pib_ifs_min_lifs_period_get(void)440 uint16_t nrf_802154_pib_ifs_min_lifs_period_get(void)
441 {
442 return m_data.ifs.min_lifs_period_us;
443 }
444
nrf_802154_pib_ifs_min_lifs_period_set(uint16_t period)445 void nrf_802154_pib_ifs_min_lifs_period_set(uint16_t period)
446 {
447 m_data.ifs.min_lifs_period_us = period;
448 }
449
450 #endif // NRF_802154_IFS_ENABLED
451
452 #if NRF_802154_TEST_MODES_ENABLED
nrf_802154_pib_test_mode_csmaca_backoff_get(void)453 nrf_802154_test_mode_csmaca_backoff_t nrf_802154_pib_test_mode_csmaca_backoff_get(void)
454 {
455 return m_data.test_modes.csmaca_backoff;
456 }
457
nrf_802154_pib_test_mode_csmaca_backoff_set(nrf_802154_test_mode_csmaca_backoff_t value)458 void nrf_802154_pib_test_mode_csmaca_backoff_set(nrf_802154_test_mode_csmaca_backoff_t value)
459 {
460 m_data.test_modes.csmaca_backoff = value;
461 }
462
463 #endif // NRF_802154_TEST_MODES_ENABLED
464