Contiki-NG
ieee-mode.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**
31  * \addtogroup cc13xx-cc26xx-rf
32  * @{
33  *
34  * \defgroup cc13xx-cc26xx-rf-ieee IEEE-mode driver for CC13xx/CC26xx
35  *
36  * @{
37  *
38  * \file
39  * Implementation of the CC13xx/CC26xx IEEE-mode NETSTACK_RADIO driver.
40  * \author
41  * Edvard Pettersen <e.pettersen@ti.com>
42  */
43 /*---------------------------------------------------------------------------*/
44 #include "contiki.h"
45 #include "net/packetbuf.h"
46 #include "net/linkaddr.h"
47 #include "net/netstack.h"
48 #include "sys/energest.h"
49 #include "sys/clock.h"
50 #include "sys/rtimer.h"
51 #include "sys/ctimer.h"
52 #include "sys/cc.h"
53 /*---------------------------------------------------------------------------*/
54 /* RF driver and RF Core API */
55 #include <ti/devices/DeviceFamily.h>
56 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
57 #include DeviceFamily_constructPath(driverlib/rf_data_entry.h)
58 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
59 /*
60  * rf_ieee_cmd.h and rf_ieee_mailbox.h are included by RF settings because a
61  * discrepancy between CC13x0 and CC13x2 IEEE support. CC13x0 doesn't provide
62  * RFCore definitions of IEEE commands, and are therefore included locally
63  * from the Contiki build system. CC13x2 includes these normally from driverlib.
64  */
65 #if defined(DeviceFamily_CC13X0)
66 #include "driverlib/rf_ieee_mailbox.h"
67 #else
68 #include DeviceFamily_constructPath(driverlib/rf_ieee_mailbox.h)
69 #endif
70 
71 #include <ti/drivers/rf/RF.h>
72 /*---------------------------------------------------------------------------*/
73 /* SimpleLink Platform RF dev */
74 #include "rf/rf.h"
75 #include "rf/data-queue.h"
76 #include "rf/dot-15-4g.h"
77 #include "rf/sched.h"
78 #include "rf/settings.h"
79 #include "rf/tx-power.h"
80 #include "rf/rat.h"
81 #include "rf/radio-mode.h"
82 /*---------------------------------------------------------------------------*/
83 #include <stdint.h>
84 #include <stddef.h>
85 #include <string.h>
86 #include <stdio.h>
87 #include <stdbool.h>
88 /*---------------------------------------------------------------------------*/
89 /* Log configuration */
90 #include "sys/log.h"
91 #define LOG_MODULE "Radio"
92 #define LOG_LEVEL LOG_LEVEL_NONE
93 /*---------------------------------------------------------------------------*/
94 /* Configuration parameters */
95 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
96 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
97 #define IEEE_MODE_CCA_RSSI_THRESHOLD IEEE_MODE_CONF_CCA_RSSI_THRESHOLD
98 /*---------------------------------------------------------------------------*/
99 /* Timeout constants */
100 
101 /* How long to wait for the rx read entry to become ready */
102 #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 200)
103 
104 /* How long to wait for RX to become active after scheduled */
105 #define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10)
106 /*---------------------------------------------------------------------------*/
107 /* XXX: don't know what exactly is this */
108 #if defined(DEVICE_LINE_CC13XX)
109 #define RAT_TIMESTAMP_OFFSET USEC_TO_RAT(800)
110 #else
111 #define RAT_TIMESTAMP_OFFSET USEC_TO_RAT(-50)
112 #endif
113 /*---------------------------------------------------------------------------*/
114 #define STATUS_CORRELATION 0x3f /* bits 0-5 */
115 #define STATUS_REJECT_FRAME 0x40 /* bit 6 */
116 #define STATUS_CRC_FAIL 0x80 /* bit 7 */
117 /*---------------------------------------------------------------------------*/
118 /*
119  * The number of bytes appended at the end of an outgoing frame as a footer
120  * Currently fixed at 2 bytes for IEEE 802.15.4 compliance.
121  */
122 #define CHECKSUM_LEN 2
123 
124 /*
125  * The maximum number of bytes this driver can accept from the MAC layer for
126  * transmission or will deliver to the MAC layer after reception. Includes
127  * the MAC header and payload, but not the FCS.
128  */
129 #define MAX_PAYLOAD_LEN (127 - CHECKSUM_LEN)
130 /*---------------------------------------------------------------------------*/
131 #define FRAME_FCF_OFFSET 0
132 #define FRAME_SEQNUM_OFFSET 2
133 
134 #define FRAME_ACK_REQUEST 0x20 /* bit 5 */
135 
136 /* TX buf configuration */
137 #define TX_BUF_SIZE 180
138 /*---------------------------------------------------------------------------*/
139 /* Size of the Length representation in Data Entry, one byte in this case */
140 typedef uint8_t lensz_t;
141 
142 #define FRAME_OFFSET sizeof(lensz_t)
143 #define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */
144 /*---------------------------------------------------------------------------*/
145 /* Used for checking result of CCA_REQ command */
146 typedef enum {
147  CCA_STATE_IDLE = 0,
148  CCA_STATE_BUSY = 1,
149  CCA_STATE_INVALID = 2
150 } cca_state_t;
151 /*---------------------------------------------------------------------------*/
152 /* RF Core typedefs */
153 typedef rfc_ieeeRxOutput_t rx_output_t;
154 typedef rfc_CMD_IEEE_MOD_FILT_t cmd_mod_filt_t;
155 typedef rfc_CMD_IEEE_CCA_REQ_t cmd_cca_req_t;
156 
157 typedef struct {
158  /* RF driver */
159  RF_Handle rf_handle;
160 
161  /* Are we currently in poll mode? */
162  bool poll_mode;
163 
164  /* RAT Overflow Upkeep */
165  struct {
166  struct ctimer overflow_timer;
167  rtimer_clock_t last_overflow;
168  volatile uint32_t overflow_count;
169  } rat;
170 
171  bool (* rx_is_active)(void);
172 
173  /* Outgoing frame buffer */
174  uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
175 
176  /* RF Statistics struct */
177  rx_output_t rx_stats;
178 
179  /* Indicates RF is supposed to be on or off */
180  bool rf_is_on;
181  /* Enable/disable CCA before sending */
182  bool send_on_cca;
183 
184  /* Last RX operation stats */
185  struct {
186  int8_t rssi;
187  uint8_t corr_lqi;
188  uint32_t timestamp;
189  } last;
190 } ieee_radio_t;
191 
192 static ieee_radio_t ieee_radio;
193 
194 /* Global RF Core commands */
195 static cmd_mod_filt_t cmd_mod_filt;
196 /*---------------------------------------------------------------------------*/
197 /* Convenience macros for more succinct access of RF commands */
198 #define cmd_radio_setup rf_cmd_ieee_radio_setup
199 #define cmd_fs rf_cmd_ieee_fs
200 #define cmd_tx rf_cmd_ieee_tx
201 #define cmd_rx rf_cmd_ieee_rx
202 #define cmd_rx_ack rf_cmd_ieee_rx_ack
203 
204 /* Convenience macros for volatile access with the RF commands */
205 #define v_cmd_radio_setup CC_ACCESS_NOW(rfc_CMD_RADIO_SETUP_t, rf_cmd_ieee_radio_setup)
206 #define v_cmd_fs CC_ACCESS_NOW(rfc_CMD_FS_t, rf_cmd_ieee_fs)
207 #define v_cmd_tx CC_ACCESS_NOW(rfc_CMD_IEEE_TX_t, rf_cmd_ieee_tx)
208 #define v_cmd_rx CC_ACCESS_NOW(rfc_CMD_IEEE_RX_t, rf_cmd_ieee_rx)
209 #define v_cmd_rx_ack CC_ACCESS_NOW(rfc_CMD_IEEE_RX_ACK_t, rf_cmd_ieee_rx_ack)
210 /*---------------------------------------------------------------------------*/
211 static inline bool
212 rx_is_active(void)
213 {
214  return v_cmd_rx.status == ACTIVE;
215 }
216 /*---------------------------------------------------------------------------*/
217 /* Forward declarations of Radio driver functions */
218 static int init(void);
219 static int prepare(const void *, unsigned short);
220 static int transmit(unsigned short);
221 static int send(const void *, unsigned short);
222 static int read(void *, unsigned short);
223 static int channel_clear(void);
224 static int receiving_packet(void);
225 static int pending_packet(void);
226 static int on(void);
227 static int off(void);
228 static radio_result_t get_value(radio_param_t, radio_value_t *);
229 static radio_result_t set_value(radio_param_t, radio_value_t);
230 static radio_result_t get_object(radio_param_t, void *, size_t);
231 static radio_result_t set_object(radio_param_t, const void *, size_t);
232 /*---------------------------------------------------------------------------*/
233 static void
234 init_rf_params(void)
235 {
236  cmd_radio_setup.config.frontEndMode = RF_2_4_GHZ_FRONT_END_MODE;
237  cmd_radio_setup.config.biasMode = RF_2_4_GHZ_BIAS_MODE;
238 
239  cmd_rx.pRxQ = data_queue_init(sizeof(lensz_t));
240  cmd_rx.pOutput = &ieee_radio.rx_stats;
241 
242 #if IEEE_MODE_PROMISCOUS
243  cmd_rx.frameFiltOpt.frameFiltEn = 0;
244 #else
245  cmd_rx.frameFiltOpt.frameFiltEn = 1;
246 #endif
247 
248 #if IEEE_MODE_AUTOACK
249  cmd_rx.frameFiltOpt.autoAckEn = 1;
250 #else
251  cmd_rx.frameFiltOpt.autoAckEn = 0;
252 #endif
253 
254  cmd_rx.ccaRssiThr = IEEE_MODE_CCA_RSSI_THRESHOLD;
255 
256  cmd_tx.pNextOp = (RF_Op *)&cmd_rx_ack;
257  cmd_tx.condition.rule = COND_NEVER; /* Initially ACK turned off */
258 
259  /*
260  * ACK packet is transmitted 192 us after the end of the received packet,
261  * takes 352 us for ACK transmission, total of 546 us of expected time to
262  * recieve ACK in ideal conditions. 700 us endTime for CMD_IEEE_RX_ACK
263  * should give some margins.
264  * The ACK frame consists of 6 bytes of SHR/PDR and 5 bytes of PSDU, total
265  * of 11 bytes. 11 bytes x 32 us/byte equals 352 us of ACK transmission time.
266  */
267  cmd_rx_ack.startTrigger.triggerType = TRIG_NOW;
268  cmd_rx_ack.endTrigger.triggerType = TRIG_REL_START;
269  cmd_rx_ack.endTime = RF_convertUsToRatTicks(700);
270 
271  /* Initialize address filter command */
272  cmd_mod_filt.commandNo = CMD_IEEE_MOD_FILT;
273  memcpy(&(cmd_mod_filt.newFrameFiltOpt), &(cmd_rx.frameFiltOpt), sizeof(cmd_rx.frameFiltOpt));
274  memcpy(&(cmd_mod_filt.newFrameTypes), &(cmd_rx.frameTypes), sizeof(cmd_rx.frameTypes));
275 }
276 /*---------------------------------------------------------------------------*/
277 static rf_result_t
278 set_channel(uint8_t channel)
279 {
280  if(!dot_15_4g_chan_in_range(channel)) {
281  LOG_WARN("Supplied hannel %d is illegal, defaults to %d\n",
282  (int)channel, DOT_15_4G_DEFAULT_CHAN);
283  channel = DOT_15_4G_DEFAULT_CHAN;
284  }
285 
286  /*
287  * cmd_rx.channel is initialized to 0, causing any initial call to
288  * set_channel() to cause a synth calibration, since channel must be in
289  * range 11-26.
290  */
291  if(channel == v_cmd_rx.channel) {
292  /* We are already calibrated to this channel */
293  return true;
294  }
295 
296  if(ieee_radio.rf_is_on) {
297  /* Force RAT and RTC resync */
298  rf_restart_rat();
299  }
300 
301  v_cmd_rx.channel = channel;
302 
303  const uint32_t new_freq = dot_15_4g_freq(channel);
304  const uint16_t freq = (uint16_t)(new_freq / 1000);
305  const uint16_t frac = (uint16_t)(((new_freq - (freq * 1000)) * 0x10000) / 1000);
306 
307  LOG_DBG("Set channel to %d, frequency 0x%04X.0x%04X (%lu)\n",
308  (int)channel, freq, frac, new_freq);
309 
310  v_cmd_fs.frequency = freq;
311  v_cmd_fs.fractFreq = frac;
312 
313  return netstack_sched_fs();
314 }
315 /*---------------------------------------------------------------------------*/
316 static void
317 set_send_on_cca(bool enable)
318 {
319  ieee_radio.send_on_cca = enable;
320 }
321 /*---------------------------------------------------------------------------*/
322 static int
323 init(void)
324 {
325  RF_Params rf_params;
326  RF_TxPowerTable_Value tx_power_value;
327  RF_Stat rf_stat;
328 
329  ieee_radio.rx_is_active = rx_is_active;
330  radio_mode = (simplelink_radio_mode_t *)&ieee_radio;
331 
332  if(ieee_radio.rf_handle) {
333  LOG_WARN("Radio already initialized\n");
334  return RF_RESULT_OK;
335  }
336 
337  /* RX is off */
338  ieee_radio.rf_is_on = false;
339 
340  init_rf_params();
341 
342  /* Init RF params and specify non-default params */
343  RF_Params_init(&rf_params);
344  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
345 
346  ieee_radio.rf_handle = netstack_open(&rf_params);
347 
348  if(ieee_radio.rf_handle == NULL) {
349  LOG_ERR("Unable to open RF driver\n");
350  return RF_RESULT_ERROR;
351  }
352 
353  set_channel(DOT_15_4G_DEFAULT_CHAN);
354 
355  tx_power_value = RF_TxPowerTable_findValue(rf_tx_power_table, RF_TXPOWER_DBM);
356  if(tx_power_value.rawValue != RF_TxPowerTable_INVALID_VALUE) {
357  rf_stat = RF_setTxPower(ieee_radio.rf_handle, tx_power_value);
358  if(rf_stat == RF_StatSuccess) {
359  LOG_INFO("TX power configured to %d dBm\n", RF_TXPOWER_DBM);
360  } else {
361  LOG_WARN("Setting TX power to %d dBm failed, stat=0x%02X", RF_TXPOWER_DBM, rf_stat);
362  }
363  } else {
364  LOG_WARN("Unable to find TX power %d dBm in the TX power table\n", RF_TXPOWER_DBM);
365  }
366 
367  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
368 
369  /* Start RAT overflow upkeep */
370  rat_init();
371 
372  /* Start RF process */
373  process_start(&rf_sched_process, NULL);
374 
375  return RF_RESULT_OK;
376 }
377 /*---------------------------------------------------------------------------*/
378 static int
379 prepare(const void *payload, unsigned short payload_len)
380 {
381  if(payload_len > TX_BUF_SIZE || payload_len > MAX_PAYLOAD_LEN) {
382  return RADIO_TX_ERR;
383  }
384  memcpy(ieee_radio.tx_buf, payload, payload_len);
385  return 0;
386 }
387 /*---------------------------------------------------------------------------*/
388 static int
389 transmit(unsigned short transmit_len)
390 {
391  rf_result_t res;
392 
393  if(transmit_len > MAX_PAYLOAD_LEN) {
394  LOG_ERR("Too long\n");
395  return RADIO_TX_ERR;
396  }
397 
398  if(ieee_radio.send_on_cca && channel_clear() != 1) {
399  LOG_WARN("Channel is not clear for transmission\n");
400  return RADIO_TX_COLLISION;
401  }
402 
403  /*
404  * Are we expecting ACK? The ACK Request flag is in the first Frame
405  * Control Field byte, that is the first byte in the frame.
406  */
407  bool ack_request;
408  if(!ieee_radio.poll_mode &&
409  (ieee_radio.tx_buf[FRAME_FCF_OFFSET] & FRAME_ACK_REQUEST)) {
410  ack_request = true;
411  } else {
412  ack_request = false;
413  }
414  if(ack_request) {
415  /* Yes, turn on chaining */
416  v_cmd_tx.condition.rule = COND_STOP_ON_FALSE;
417 
418  /* Reset CMD_IEEE_RX_ACK command */
419  v_cmd_rx_ack.status = IDLE;
420  /* Sequence number is the third byte in the frame */
421  v_cmd_rx_ack.seqNo = ieee_radio.tx_buf[FRAME_SEQNUM_OFFSET];
422  } else {
423  /* No, turn off chaining */
424  v_cmd_tx.condition.rule = COND_NEVER;
425  }
426 
427  /* Configure TX command */
428  v_cmd_tx.payloadLen = (uint8_t)transmit_len;
429  v_cmd_tx.pPayload = ieee_radio.tx_buf;
430 
431  res = netstack_sched_ieee_tx(transmit_len, ack_request);
432 
433  if(res != RF_RESULT_OK) {
434  return RADIO_TX_ERR;
435  }
436 
437  if(ack_request) {
438  switch(v_cmd_rx_ack.status) {
439  /* CMD_IEEE_RX_ACK timed out, i.e. never received ACK */
440  case IEEE_DONE_TIMEOUT: return RADIO_TX_NOACK;
441  /* An ACK was received with either pending data bit set or cleared */
442  case IEEE_DONE_ACK: /* fallthrough */
443  case IEEE_DONE_ACKPEND: return RADIO_TX_OK;
444  /* Any other statuses are errors */
445  default: return RADIO_TX_ERR;
446  }
447  }
448 
449  /* No ACK expected, TX OK */
450  return RADIO_TX_OK;
451 }
452 /*---------------------------------------------------------------------------*/
453 static int
454 send(const void *payload, unsigned short payload_len)
455 {
456  prepare(payload, payload_len);
457  return transmit(payload_len);
458 }
459 /*---------------------------------------------------------------------------*/
460 static int
461 read(void *buf, unsigned short buf_len)
462 {
463  volatile data_entry_t *data_entry = data_queue_current_entry();
464 
465  const rtimer_clock_t t0 = RTIMER_NOW();
466  /* Only wait if the Radio timer is accessing the entry */
467  while((data_entry->status == DATA_ENTRY_BUSY) &&
468  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)) ;
469 
470  if(data_entry->status != DATA_ENTRY_FINISHED) {
471  /* No available data */
472  return 0;
473  }
474 
475  /*
476  * lensz bytes (1) in the data entry are the length of the received frame.
477  * Data frame is on the following format:
478  * Length (1) + Payload (N) + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
479  * Data frame DOES NOT contain the following:
480  * no PHY Header bytes
481  * no Source Index bytes
482  * Visual representation of frame format:
483  *
484  * +--------+---------+---------+--------+--------+-----------+
485  * | 1 byte | N bytes | 2 bytes | 1 byte | 1 byte | 4 bytes |
486  * +--------+---------+---------+--------+--------+-----------+
487  * | Length | Payload | FCS | RSSI | Status | Timestamp |
488  * +--------+---------+---------+--------+--------+-----------+
489  *
490  * Length bytes equal total length of entire frame excluding itself,
491  * Length = N + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
492  * Length = N + 8
493  * N = Length - 8
494  */
495  uint8_t *const frame_ptr = (uint8_t *)&data_entry->data;
496  const lensz_t frame_len = *(lensz_t *)frame_ptr;
497 
498  /* Sanity check that Frame is at least Frame Shave bytes long */
499  if(frame_len < FRAME_SHAVE) {
500  LOG_ERR("Received frame too short, len=%d\n", frame_len);
501 
502  data_queue_release_entry();
503  return 0;
504  }
505 
506  const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t);
507  const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE);
508 
509  /* Sanity check that Payload fits in buffer. */
510  if(payload_len > buf_len) {
511  LOG_ERR("MAC payload too large for buffer, len=%d buf_len=%d\n",
512  payload_len, buf_len);
513 
514  data_queue_release_entry();
515  return 0;
516  }
517 
518  memcpy(buf, payload_ptr, payload_len);
519 
520  /* RSSI stored FCS (2) bytes after payload. */
521  ieee_radio.last.rssi = (int8_t)payload_ptr[payload_len + 2];
522  /* LQI retrieved from Status byte, FCS (2) + RSSI (1) bytes after payload. */
523  ieee_radio.last.corr_lqi = (uint8_t)(payload_ptr[payload_len + 3] & STATUS_CORRELATION);
524  /* Timestamp stored FCS (2) + RSSI (1) + Status (1) bytes after payload. */
525  const uint32_t rat_ticks = *(uint32_t *)(payload_ptr + payload_len + 4);
526  /* Correct timestamp so that it refers to the end of the SFD */
527  ieee_radio.last.timestamp = rat_to_timestamp(rat_ticks, RAT_TIMESTAMP_OFFSET);
528 
529  if(!ieee_radio.poll_mode) {
530  /* Not in poll mode: packetbuf should not be accessed in interrupt context. */
531  /* In poll mode, the last packet RSSI and link quality can be obtained through */
532  /* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
533  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)ieee_radio.last.rssi);
534  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)ieee_radio.last.corr_lqi);
535  }
536 
537  data_queue_release_entry();
538  return (int)payload_len;
539 }
540 /*---------------------------------------------------------------------------*/
541 static rf_result_t
542 cca_request(cmd_cca_req_t *cmd_cca_req)
543 {
544  RF_Stat stat = RF_StatRadioInactiveError;
545  rf_result_t res;
546  bool stop_rx = false;
547 
548  /* RX is required to be running in order to do a CCA request */
549  if(!rx_is_active()) {
550  /* If RX is not pending, i.e. soon to be running, schedule the RX command */
551  if(v_cmd_rx.status != PENDING) {
552  res = netstack_sched_rx(false);
553  if(res != RF_RESULT_OK) {
554  LOG_ERR("CCA request failed to schedule RX\n");
555  return res;
556  }
557 
558  /* We only stop RX if we had to schedule it */
559  stop_rx = true;
560  }
561 
562  /* Make sure RX is running before we continue, unless we timeout and fail */
563  RTIMER_BUSYWAIT_UNTIL(rx_is_active(), TIMEOUT_ENTER_RX_WAIT);
564 
565  if(!rx_is_active()) {
566  LOG_ERR("CCA request failed to turn on RX, RX status=0x%04X\n", v_cmd_rx.status);
567  return RF_RESULT_ERROR;
568  }
569  }
570 
571  /* Perform the CCA request */
572  do {
573  memset(cmd_cca_req, 0x00, sizeof(cmd_cca_req_t));
574  cmd_cca_req->commandNo = CMD_IEEE_CCA_REQ;
575  cmd_cca_req->ccaInfo.ccaState = CCA_STATE_INVALID;
576 
577  stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)cmd_cca_req);
578 
579  if(stat != RF_StatCmdDoneSuccess) {
580  LOG_ERR("CCA request command failed, stat=0x%02X\n", stat);
581  if(stop_rx) {
582  netstack_stop_rx();
583  }
584  return RF_RESULT_ERROR;
585  }
586  } while(cmd_cca_req->ccaInfo.ccaState == CCA_STATE_INVALID);
587 
588  if(stop_rx) {
589  netstack_stop_rx();
590  }
591 
592  return RF_RESULT_OK;
593 }
594 /*---------------------------------------------------------------------------*/
595 static int
596 channel_clear(void)
597 {
598  cmd_cca_req_t cmd_cca_req;
599 
600  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
601  return 0;
602  }
603 
604  /* Channel is clear if CCA state is IDLE */
605  return cmd_cca_req.ccaInfo.ccaState == CCA_STATE_IDLE;
606 }
607 /*---------------------------------------------------------------------------*/
608 static int
609 receiving_packet(void)
610 {
611  cmd_cca_req_t cmd_cca_req;
612 
613  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
614  return 0;
615  }
616 
617  /* If we are transmitting (can only be an ACK here), we are not receiving */
618  if((cmd_cca_req.ccaInfo.ccaEnergy == CCA_STATE_BUSY) &&
619  (cmd_cca_req.ccaInfo.ccaCorr == CCA_STATE_BUSY) &&
620  (cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY)) {
621  LOG_WARN("We are TXing ACK, therefore not receiving packets\n");
622  return 0;
623  }
624 
625  /* We are receiving a packet if a CCA sync has been seen, i.e. ccaSync is busy (1) */
626  return cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY;
627 }
628 /*---------------------------------------------------------------------------*/
629 static int
630 pending_packet(void)
631 {
632  const data_entry_t *const read_entry = data_queue_current_entry();
633  volatile const data_entry_t *curr_entry = read_entry;
634 
635  int num_pending = 0;
636 
637  /* Go through RX Circular buffer and check each data entry status */
638  do {
639  const uint8_t status = curr_entry->status;
640  if((status == DATA_ENTRY_FINISHED) ||
641  (status == DATA_ENTRY_BUSY)) {
642  num_pending += 1;
643  }
644 
645  /* Stop when we have looped the circular buffer */
646  curr_entry = (data_entry_t *)curr_entry->pNextEntry;
647  } while(curr_entry != read_entry);
648 
649  if(num_pending > 0 && !ieee_radio.poll_mode) {
650  process_poll(&rf_sched_process);
651  }
652 
653  /* If we didn't find an entry at status finished or busy, no frames are pending */
654  return num_pending;
655 }
656 /*---------------------------------------------------------------------------*/
657 static int
658 on(void)
659 {
660  rf_result_t res;
661 
662  if(ieee_radio.rf_is_on) {
663  LOG_WARN("Radio is already on\n");
664  return RF_RESULT_OK;
665  }
666 
667  data_queue_reset();
668 
669  res = netstack_sched_rx(true);
670 
671  if(res != RF_RESULT_OK) {
672  return RF_RESULT_ERROR;
673  }
674 
675  ieee_radio.rf_is_on = true;
676  return RF_RESULT_OK;
677 }
678 /*---------------------------------------------------------------------------*/
679 static int
680 off(void)
681 {
682  if(!ieee_radio.rf_is_on) {
683  LOG_WARN("Radio is already off\n");
684  return RF_RESULT_OK;
685  }
686 
687  rf_yield();
688 
689  ieee_radio.rf_is_on = false;
690  return RF_RESULT_OK;
691 }
692 /*---------------------------------------------------------------------------*/
693 static radio_result_t
694 get_value(radio_param_t param, radio_value_t *value)
695 {
696  rf_result_t res;
697 
698  if(!value) {
700  }
701 
702  switch(param) {
703 
704  /* Power Mode */
706  *value = (ieee_radio.rf_is_on)
709  return RADIO_RESULT_OK;
710 
711  /* Channel */
712  case RADIO_PARAM_CHANNEL:
713  *value = (radio_value_t)v_cmd_rx.channel;
714  return RADIO_RESULT_OK;
715 
716  /* PAN ID */
717  case RADIO_PARAM_PAN_ID:
718  *value = (radio_value_t)v_cmd_rx.localPanID;
719  return RADIO_RESULT_OK;
720 
721  /* 16-bit address */
723  *value = (radio_value_t)v_cmd_rx.localShortAddr;
724  return RADIO_RESULT_OK;
725 
726  /* RX mode */
727  case RADIO_PARAM_RX_MODE:
728  *value = 0;
729  if(v_cmd_rx.frameFiltOpt.frameFiltEn) {
731  }
732  if(v_cmd_rx.frameFiltOpt.autoAckEn) {
734  }
735  if(ieee_radio.poll_mode) {
737  }
738  return RADIO_RESULT_OK;
739 
740  /* TX mode */
741  case RADIO_PARAM_TX_MODE:
742  *value = 0;
743  return RADIO_RESULT_OK;
744 
745  /* TX power */
746  case RADIO_PARAM_TXPOWER:
747  res = rf_get_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t *)&value);
748  return ((res == RF_RESULT_OK) &&
749  (*value != RF_TxPowerTable_INVALID_DBM))
752 
753  /* CCA threshold */
755  *value = v_cmd_rx.ccaRssiThr;
756  return RADIO_RESULT_OK;
757 
758  /* RSSI */
759  case RADIO_PARAM_RSSI:
760  *value = RF_getRssi(ieee_radio.rf_handle);
761  return (*value == RF_GET_RSSI_ERROR_VAL)
763  : RADIO_RESULT_OK;
764 
765  /* Channel min */
767  *value = (radio_value_t)DOT_15_4G_CHAN_MIN;
768  return RADIO_RESULT_OK;
769 
770  /* Channel max */
772  *value = (radio_value_t)DOT_15_4G_CHAN_MAX;
773  return RADIO_RESULT_OK;
774 
776  *value = (radio_value_t)tx_power_min(rf_tx_power_table);
777  return RADIO_RESULT_OK;
778 
779  /* TX power max */
781  *value = (radio_value_t)tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
782  return RADIO_RESULT_OK;
783 
784  /* Last RSSI */
786  *value = (radio_value_t)ieee_radio.last.rssi;
787  return RADIO_RESULT_OK;
788 
789  /* Last link quality */
791  *value = (radio_value_t)ieee_radio.last.corr_lqi;
792  return RADIO_RESULT_OK;
793 
794  case RADIO_CONST_MAX_PAYLOAD_LEN:
795  *value = (radio_value_t)MAX_PAYLOAD_LEN;
796  return RADIO_RESULT_OK;
797 
798  default:
800  }
801 }
802 /*---------------------------------------------------------------------------*/
803 static radio_result_t
804 set_value(radio_param_t param, radio_value_t value)
805 {
806  rf_result_t res;
807 
808  switch(param) {
809 
810  /* Power Mode */
812 
813  if(value == RADIO_POWER_MODE_ON) {
814  return (on() == RF_RESULT_OK)
817  } else if(value == RADIO_POWER_MODE_OFF) {
818  off();
819  return RADIO_RESULT_OK;
820  }
821 
823 
824  /* Channel */
825  case RADIO_PARAM_CHANNEL:
826  if(!dot_15_4g_chan_in_range(value)) {
828  }
829  set_channel((uint8_t)value);
830  return RADIO_RESULT_OK;
831 
832  /* PAN ID */
833  case RADIO_PARAM_PAN_ID:
834  v_cmd_rx.localPanID = (uint16_t)value;
835  if(!ieee_radio.rf_is_on) {
836  return RADIO_RESULT_OK;
837  }
838 
839  netstack_stop_rx();
840  res = netstack_sched_rx(false);
841  return (res == RF_RESULT_OK)
844 
845  /* 16bit address */
847  v_cmd_rx.localShortAddr = (uint16_t)value;
848  if(!ieee_radio.rf_is_on) {
849  return RADIO_RESULT_OK;
850  }
851 
852  netstack_stop_rx();
853  res = netstack_sched_rx(false);
854  return (res == RF_RESULT_OK)
857 
858  /* RX Mode */
859  case RADIO_PARAM_RX_MODE: {
860  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
864  }
865 
866  v_cmd_rx.frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
867  v_cmd_rx.frameFiltOpt.frameFiltStop = 1;
868  v_cmd_rx.frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
869  v_cmd_rx.frameFiltOpt.slottedAckEn = 0;
870  v_cmd_rx.frameFiltOpt.autoPendEn = 0;
871  v_cmd_rx.frameFiltOpt.defaultPend = 0;
872  v_cmd_rx.frameFiltOpt.bPendDataReqOnly = 0;
873  v_cmd_rx.frameFiltOpt.bPanCoord = 0;
874  v_cmd_rx.frameFiltOpt.bStrictLenFilter = 0;
875 
876  const bool old_poll_mode = ieee_radio.poll_mode;
877  ieee_radio.poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
878  if(old_poll_mode == ieee_radio.poll_mode) {
879  /* Do not turn the radio off and on, just send an update command */
880  memcpy(&cmd_mod_filt.newFrameFiltOpt, &(cmd_rx.frameFiltOpt), sizeof(cmd_rx.frameFiltOpt));
881  const RF_Stat stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)&cmd_mod_filt);
882  if(stat != RF_StatCmdDoneSuccess) {
883  LOG_ERR("Setting address filter failed, stat=0x%02X\n", stat);
884  return RADIO_RESULT_ERROR;
885  }
886  return RADIO_RESULT_OK;
887  }
888  if(!ieee_radio.rf_is_on) {
889  return RADIO_RESULT_OK;
890  }
891 
892  netstack_stop_rx();
893  res = netstack_sched_rx(false);
894  return (res == RF_RESULT_OK)
897  }
898 
899  /* TX Mode */
900  case RADIO_PARAM_TX_MODE:
901  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
903  }
904  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
905  return RADIO_RESULT_OK;
906 
907  /* TX Power */
908  case RADIO_PARAM_TXPOWER:
909  if(!tx_power_in_range((int8_t)value, rf_tx_power_table, rf_tx_power_table_size)) {
911  }
912  res = rf_set_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t)value);
913  return (res == RF_RESULT_OK)
916 
917  /* CCA Threshold */
919  v_cmd_rx.ccaRssiThr = (int8_t)value;
920  if(!ieee_radio.rf_is_on) {
921  return RADIO_RESULT_OK;
922  }
923 
924  netstack_stop_rx();
925  res = netstack_sched_rx(false);
926  return (res == RF_RESULT_OK)
929 
930  default:
932  }
933 }
934 /*---------------------------------------------------------------------------*/
935 static radio_result_t
936 get_object(radio_param_t param, void *dest, size_t size)
937 {
938  if(!dest) {
940  }
941 
942  switch(param) {
943  /* 64bit address */
944  case RADIO_PARAM_64BIT_ADDR: {
945  const size_t srcSize = sizeof(v_cmd_rx.localExtAddr);
946  if(size != srcSize) {
948  }
949 
950  const uint8_t *pSrc = (uint8_t *)&(v_cmd_rx.localExtAddr);
951  uint8_t *pDest = dest;
952  for(size_t i = 0; i < srcSize; ++i) {
953  pDest[i] = pSrc[srcSize - 1 - i];
954  }
955 
956  return RADIO_RESULT_OK;
957  }
958  /* Last packet timestamp */
960  if(size != sizeof(rtimer_clock_t)) {
962  }
963 
964  *(rtimer_clock_t *)dest = ieee_radio.last.timestamp;
965 
966  return RADIO_RESULT_OK;
967 
968  default:
970  }
971 }
972 /*---------------------------------------------------------------------------*/
973 static radio_result_t
974 set_object(radio_param_t param, const void *src, size_t size)
975 {
976  rf_result_t res;
977 
978  if(!src) {
980  }
981 
982  switch(param) {
983  /* 64-bit address */
984  case RADIO_PARAM_64BIT_ADDR: {
985  const size_t destSize = sizeof(v_cmd_rx.localExtAddr);
986  if(size != destSize) {
988  }
989 
990  const uint8_t *pSrc = (const uint8_t *)src;
991  volatile uint8_t *pDest = (uint8_t *)&(v_cmd_rx.localExtAddr);
992  for(size_t i = 0; i < destSize; ++i) {
993  pDest[i] = pSrc[destSize - 1 - i];
994  }
995 
996  if(!rx_is_active()) {
997  return RADIO_RESULT_OK;
998  }
999 
1000  netstack_stop_rx();
1001  res = netstack_sched_rx(false);
1002  return (res == RF_RESULT_OK)
1003  ? RADIO_RESULT_OK
1005  }
1006  default:
1008  }
1009 }
1010 /*---------------------------------------------------------------------------*/
1011 const struct radio_driver ieee_mode_driver = {
1012  init,
1013  prepare,
1014  transmit,
1015  send,
1016  read,
1017  channel_clear,
1020  on,
1021  off,
1022  get_value,
1023  set_value,
1024  get_object,
1025  set_object,
1026 };
1027 /*---------------------------------------------------------------------------*/
1028 /**
1029  * @}
1030  * @}
1031  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:762
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:572
Header file of TX power functionality of CC13xx/CC26xx.
The parameter is not supported.
Definition: radio.h:473
static uint8_t rf_is_on(void)
Checks whether the RFC domain is accessible and the RFC is in IEEE RX.
Definition: ieee-mode.c:267
#define FRAME_SHAVE
RSSI (1) + Timestamp (4) + Status (1)
Definition: prop-mode.c:172
Header file for the energy estimation mechanism
TX failed due to a collision.
Definition: radio.h:503
The maximum transmission power in dBm.
Definition: radio.h:318
Header file for the link-layer address representation
Received signal strength indicator in dBm.
Definition: radio.h:218
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:676
Header file of the generic radio mode API.
The short address (16 bits) for the radio, which is used by the h/w filter.
Definition: radio.h:166
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:748
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver&#39;s buffers.
Definition: radio.h:689
The structure of a Contiki-NG radio device driver.
Definition: radio.h:526
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:211
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:175
Channel used for radio communication.
Definition: radio.h:134
The value argument was incorrect.
Definition: radio.h:474
The parameter was set/read successfully.
Definition: radio.h:472
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
Definition: radio.h:664
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
Definition: radio.h:88
An error occurred when getting/setting the parameter, but the arguments were otherwise correct...
Definition: radio.h:480
Header file of the CC13xx/CC26xx RAT timer handler.
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
The RSSI value of the last received packet.
Definition: radio.h:226
Clear channel assessment threshold in dBm.
Definition: radio.h:205
Header file of the CC13xx/CC26xx RF scheduler.
Header file for the callback timer
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:623
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:611
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
int(* off)(void)
Turn the radio off.
Definition: radio.h:721
#define RF_CONF_INACTIVITY_TIMEOUT
2 ms
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
Definition: radio.h:150
The lowest radio channel number.
Definition: radio.h:303
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
Header file for the real-time timer module.
The highest radio channel number.
Definition: radio.h:308
A unicast frame was sent OK but an ACK was not received.
Definition: radio.h:508
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition: radio.h:443
Header file of the CC13xx/CC26xx RF data queue.
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:466
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:448
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:547
Header file of RF settings for CC13xx/CC26xx.
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:453
Link quality indicator of the last received packet.
Definition: radio.h:236
Long (64 bits) address for the radio, which is used by the address filter.
Definition: radio.h:255
The minimum transmission power in dBm.
Definition: radio.h:313
Radio powered on and able to receive frames.
Definition: radio.h:392
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:647
Transmission power in dBm.
Definition: radio.h:192
Header file of common CC13xx/CC26xx RF functionality.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:733
Default definitions of C compiler quirk work-arounds.
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:278
An error occurred during transmission.
Definition: radio.h:498
Header file for the logging system
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:779
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:387
TX was successful and where an ACK was requested one was received.
Definition: radio.h:490
int(* on)(void)
Turn the radio on.
Definition: radio.h:703
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99