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  * This is taken care of RF settings.
65  */
66 
67 #include <ti/drivers/rf/RF.h>
68 /*---------------------------------------------------------------------------*/
69 /* SimpleLink Platform RF dev */
70 #include "rf/rf.h"
71 #include "rf/data-queue.h"
72 #include "rf/dot-15-4g.h"
73 #include "rf/sched.h"
74 #include "rf/settings.h"
75 #include "rf/tx-power.h"
76 /*---------------------------------------------------------------------------*/
77 #include <stdint.h>
78 #include <stddef.h>
79 #include <string.h>
80 #include <stdio.h>
81 #include <stdbool.h>
82 /*---------------------------------------------------------------------------*/
83 /* Log configuration */
84 #include "sys/log.h"
85 #define LOG_MODULE "Radio"
86 #define LOG_LEVEL LOG_LEVEL_NONE
87 /*---------------------------------------------------------------------------*/
88 /* Configuration parameters */
89 #define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK
90 #define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS
91 #define IEEE_MODE_CCA_RSSI_THRESHOLD IEEE_MODE_CONF_CCA_RSSI_THRESHOLD
92 /*---------------------------------------------------------------------------*/
93 /* Timeout constants */
94 
95 /* How long to wait for the rx read entry to become ready */
96 #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250)
97 
98 /* How long to wait for RX to become active after scheduled */
99 #define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10)
100 /*---------------------------------------------------------------------------*/
101 #define RAT_RANGE (~(uint32_t)0)
102 #define RAT_ONE_QUARTER (RAT_RANGE / (uint32_t)4)
103 #define RAT_THREE_QUARTERS ((RAT_RANGE * (uint32_t)3) / (uint32_t)4)
104 
105 /* XXX: don't know what exactly is this, looks like the time to TX 3 octets */
106 #define RAT_TIMESTAMP_OFFSET -(USEC_TO_RAT(32 * 3) - 1) /* -95.75 usec */
107 /*---------------------------------------------------------------------------*/
108 #define STATUS_CORRELATION 0x3f /* bits 0-5 */
109 #define STATUS_REJECT_FRAME 0x40 /* bit 6 */
110 #define STATUS_CRC_FAIL 0x80 /* bit 7 */
111 /*---------------------------------------------------------------------------*/
112 #define FRAME_FCF_OFFSET 0
113 #define FRAME_SEQNUM_OFFSET 2
114 
115 #define FRAME_ACK_REQUEST 0x20 /* bit 5 */
116 
117 /* TX buf configuration */
118 #define TX_BUF_SIZE 180
119 /*---------------------------------------------------------------------------*/
120 /* Size of the Length representation in Data Entry, one byte in this case */
121 typedef uint8_t lensz_t;
122 
123 #define FRAME_OFFSET sizeof(lensz_t)
124 #define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */
125 /*---------------------------------------------------------------------------*/
126 /* Used for checking result of CCA_REQ command */
127 typedef enum {
128  CCA_STATE_IDLE = 0,
129  CCA_STATE_BUSY = 1,
130  CCA_STATE_INVALID = 2
131 } cca_state_t;
132 /*---------------------------------------------------------------------------*/
133 /* RF Core typedefs */
134 typedef rfc_ieeeRxOutput_t rx_output_t;
135 typedef rfc_CMD_IEEE_MOD_FILT_t cmd_mod_filt_t;
136 typedef rfc_CMD_IEEE_CCA_REQ_t cmd_cca_req_t;
137 
138 typedef struct {
139  /* Outgoing frame buffer */
140  uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4);
141 
142  /* RF Statistics struct */
143  rx_output_t rx_stats;
144 
145  /* Indicates RF is supposed to be on or off */
146  bool rf_is_on;
147  /* Enable/disable CCA before sending */
148  bool send_on_cca;
149  /* Are we currently in poll mode? */
150  bool poll_mode;
151 
152  /* Last RX operation stats */
153  struct {
154  int8_t rssi;
155  uint8_t corr_lqi;
156  uint32_t timestamp;
157  } last;
158 
159  /* RAT Overflow Upkeep */
160  struct {
161  struct ctimer overflow_timer;
162  rtimer_clock_t last_overflow;
163  volatile uint32_t overflow_count;
164  } rat;
165 
166  /* RF driver */
167  RF_Handle rf_handle;
168 } ieee_radio_t;
169 
170 static ieee_radio_t ieee_radio;
171 
172 /* Global RF Core commands */
173 static cmd_mod_filt_t cmd_mod_filt;
174 /*---------------------------------------------------------------------------*/
175 /* RF Command volatile objects */
176 #define cmd_radio_setup (*(volatile rfc_CMD_RADIO_SETUP_t *)&rf_cmd_ieee_radio_setup)
177 #define cmd_fs (*(volatile rfc_CMD_FS_t *) &rf_cmd_ieee_fs)
178 #define cmd_tx (*(volatile rfc_CMD_IEEE_TX_t *) &rf_cmd_ieee_tx)
179 #define cmd_rx (*(volatile rfc_CMD_IEEE_RX_t *) &rf_cmd_ieee_rx)
180 #define cmd_rx_ack (*(volatile rfc_CMD_IEEE_RX_ACK_t *)&rf_cmd_ieee_rx_ack)
181 /*---------------------------------------------------------------------------*/
182 static inline bool
183 rx_is_active(void)
184 {
185  return cmd_rx.status == ACTIVE;
186 }
187 /*---------------------------------------------------------------------------*/
188 /* Forward declarations of local functions */
189 static void check_rat_overflow(void);
190 static uint32_t rat_to_timestamp(const uint32_t);
191 /*---------------------------------------------------------------------------*/
192 /* Forward declarations of Radio driver functions */
193 static int init(void);
194 static int prepare(const void *, unsigned short);
195 static int transmit(unsigned short);
196 static int send(const void *, unsigned short);
197 static int read(void *, unsigned short);
198 static int channel_clear(void);
199 static int receiving_packet(void);
200 static int pending_packet(void);
201 static int on(void);
202 static int off(void);
203 static radio_result_t get_value(radio_param_t, radio_value_t *);
204 static radio_result_t set_value(radio_param_t, radio_value_t);
205 static radio_result_t get_object(radio_param_t, void *, size_t);
206 static radio_result_t set_object(radio_param_t, const void *, size_t);
207 /*---------------------------------------------------------------------------*/
208 static void
209 rat_overflow_cb(void *arg)
210 {
211  check_rat_overflow();
212  /* Check next time after half of the RAT interval */
213  const clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND;
214  ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL);
215 }
216 /*---------------------------------------------------------------------------*/
217 static void
218 init_rf_params(void)
219 {
220  cmd_radio_setup.config.frontEndMode = RF_2_4_GHZ_FRONT_END_MODE;
221  cmd_radio_setup.config.biasMode = RF_2_4_GHZ_BIAS_MODE;
222 
223  data_queue_t *rx_q = data_queue_init(sizeof(lensz_t));
224 
225  cmd_rx.pRxQ = rx_q;
226  cmd_rx.pOutput = &ieee_radio.rx_stats;
227 
228 #if IEEE_MODE_PROMISCOUS
229  cmd_rx.frameFiltOpt.frameFiltEn = 0;
230 #else
231  cmd_rx.frameFiltOpt.frameFiltEn = 1;
232 #endif
233 
234 #if IEEE_MODE_AUTOACK
235  cmd_rx.frameFiltOpt.autoAckEn = 1;
236 #else
237  cmd_rx.frameFiltOpt.autoAckEn = 0;
238 #endif
239 
240  cmd_rx.ccaRssiThr = IEEE_MODE_CCA_RSSI_THRESHOLD;
241 
242  cmd_tx.pNextOp = (RF_Op *)&cmd_rx_ack;
243  cmd_tx.condition.rule = COND_NEVER; /* Initially ACK turned off */
244 
245  /*
246  * ACK packet is transmitted 192 us after the end of the received packet,
247  * takes 352 us for ACK transmission, total of 546 us of expected time to
248  * recieve ACK in ideal conditions. 700 us endTime for CMD_IEEE_RX_ACK
249  * should give some margins.
250  * The ACK frame consists of 6 bytes of SHR/PDR and 5 bytes of PSDU, total
251  * of 11 bytes. 11 bytes x 32 us/byte equals 352 us of ACK transmission time.
252  */
253  cmd_rx_ack.startTrigger.triggerType = TRIG_NOW;
254  cmd_rx_ack.endTrigger.triggerType = TRIG_REL_START;
255  cmd_rx_ack.endTime = RF_convertUsToRatTicks(700);
256 
257  /* Initialize address filter command */
258  cmd_mod_filt.commandNo = CMD_IEEE_MOD_FILT;
259  memcpy(&(cmd_mod_filt.newFrameFiltOpt), &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt));
260  memcpy(&(cmd_mod_filt.newFrameTypes), &(rf_cmd_ieee_rx.frameTypes), sizeof(rf_cmd_ieee_rx.frameTypes));
261 }
262 /*---------------------------------------------------------------------------*/
263 static rf_result_t
264 set_channel(uint8_t channel)
265 {
266  if(!dot_15_4g_chan_in_range(channel)) {
267  LOG_WARN("Supplied hannel %d is illegal, defaults to %d\n",
268  (int)channel, DOT_15_4G_DEFAULT_CHAN);
269  channel = DOT_15_4G_DEFAULT_CHAN;
270  }
271 
272  /*
273  * cmd_rx.channel is initialized to 0, causing any initial call to
274  * set_channel() to cause a synth calibration, since channel must be in
275  * range 11-26.
276  */
277  if(channel == cmd_rx.channel) {
278  /* We are already calibrated to this channel */
279  return true;
280  }
281 
282  cmd_rx.channel = channel;
283 
284  const uint32_t new_freq = dot_15_4g_freq(channel);
285  const uint16_t freq = (uint16_t)(new_freq / 1000);
286  const uint16_t frac = (uint16_t)(((new_freq - (freq * 1000)) * 0x10000) / 1000);
287 
288  LOG_DBG("Set channel to %d, frequency 0x%04X.0x%04X (%lu)\n",
289  (int)channel, freq, frac, new_freq);
290 
291  cmd_fs.frequency = freq;
292  cmd_fs.fractFreq = frac;
293 
294  return netstack_sched_fs();
295 }
296 /*---------------------------------------------------------------------------*/
297 static void
298 set_send_on_cca(bool enable)
299 {
300  ieee_radio.send_on_cca = enable;
301 }
302 /*---------------------------------------------------------------------------*/
303 static void
304 check_rat_overflow(void)
305 {
306  const bool was_off = !rx_is_active();
307 
308  if(was_off) {
309  RF_runDirectCmd(ieee_radio.rf_handle, CMD_NOP);
310  }
311 
312  const uint32_t current_value = RF_getCurrentTime();
313 
314  static bool initial_iteration = true;
315  static uint32_t last_value;
316 
317  if(initial_iteration) {
318  /* First time checking overflow will only store the current value */
319  initial_iteration = false;
320  } else {
321  /* Overflow happens in the last quarter of the RAT range */
322  if((current_value + RAT_ONE_QUARTER) < last_value) {
323  /* Overflow detected */
324  ieee_radio.rat.last_overflow = RTIMER_NOW();
325  ieee_radio.rat.overflow_count += 1;
326  }
327  }
328 
329  last_value = current_value;
330 
331  if(was_off) {
332  RF_yield(ieee_radio.rf_handle);
333  }
334 }
335 /*---------------------------------------------------------------------------*/
336 static uint32_t
337 rat_to_timestamp(const uint32_t rat_ticks)
338 {
339  check_rat_overflow();
340 
341  uint64_t adjusted_overflow_count = ieee_radio.rat.overflow_count;
342 
343  /* If the timestamp is in the 4th quarter and the last overflow was recently,
344  * assume that the timestamp refers to the time before the overflow */
345  if(rat_ticks > RAT_THREE_QUARTERS) {
346  const rtimer_clock_t one_quarter = (RAT_ONE_QUARTER * RTIMER_SECOND) / RAT_SECOND;
347  if(RTIMER_CLOCK_LT(RTIMER_NOW(), ieee_radio.rat.last_overflow + one_quarter)) {
348  adjusted_overflow_count -= 1;
349  }
350  }
351 
352  /* Add the overflowed time to the timestamp */
353  const uint64_t rat_ticks_adjusted = (uint64_t)rat_ticks + (uint64_t)RAT_RANGE * adjusted_overflow_count;
354 
355  /* Correct timestamp so that it refers to the end of the SFD and convert to RTIMER */
356  return RAT_TO_RTIMER(rat_ticks_adjusted + RAT_TIMESTAMP_OFFSET);
357 }
358 /*---------------------------------------------------------------------------*/
359 static int
360 init(void)
361 {
362  if(ieee_radio.rf_handle) {
363  LOG_WARN("Radio already initialized\n");
364  return RF_RESULT_OK;
365  }
366 
367  /* RX is off */
368  ieee_radio.rf_is_on = false;
369 
370  init_rf_params();
371 
372  /* Init RF params and specify non-default params */
373  RF_Params rf_params;
374  RF_Params_init(&rf_params);
375  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
376 
377  ieee_radio.rf_handle = netstack_open(&rf_params);
378 
379  if(ieee_radio.rf_handle == NULL) {
380  LOG_ERR("Unable to open RF driver\n");
381  return RF_RESULT_ERROR;
382  }
383 
384  set_channel(DOT_15_4G_DEFAULT_CHAN);
385 
386  int8_t max_tx_power = tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
387  rf_set_tx_power(ieee_radio.rf_handle, rf_tx_power_table, max_tx_power);
388 
389  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
390 
391  /* Start RAT overflow upkeep */
392  check_rat_overflow();
393  clock_time_t two_quarters = (2 * RAT_ONE_QUARTER * CLOCK_SECOND) / RAT_SECOND;
394  ctimer_set(&ieee_radio.rat.overflow_timer, two_quarters, rat_overflow_cb, NULL);
395 
396  /* Start RF process */
397  process_start(&rf_sched_process, NULL);
398 
399  return RF_RESULT_OK;
400 }
401 /*---------------------------------------------------------------------------*/
402 static int
403 prepare(const void *payload, unsigned short payload_len)
404 {
405  if(payload_len > TX_BUF_SIZE || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
406  return RADIO_TX_ERR;
407  }
408  memcpy(ieee_radio.tx_buf, payload, payload_len);
409  return 0;
410 }
411 /*---------------------------------------------------------------------------*/
412 static int
413 transmit(unsigned short transmit_len)
414 {
415  rf_result_t res;
416 
417  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
418  LOG_ERR("Too long\n");
419  return RADIO_TX_ERR;
420  }
421 
422  if(ieee_radio.send_on_cca && channel_clear() != 1) {
423  LOG_WARN("Channel is not clear for transmission\n");
424  return RADIO_TX_COLLISION;
425  }
426 
427  /*
428  * Are we expecting ACK? The ACK Request flag is in the first Frame
429  * Control Field byte, that is the first byte in the frame.
430  */
431  const bool ack_request = (bool)(ieee_radio.tx_buf[FRAME_FCF_OFFSET] & FRAME_ACK_REQUEST);
432  if(ack_request) {
433  /* Yes, turn on chaining */
434  cmd_tx.condition.rule = COND_STOP_ON_FALSE;
435 
436  /* Reset CMD_IEEE_RX_ACK command */
437  cmd_rx_ack.status = IDLE;
438  /* Sequence number is the third byte in the frame */
439  cmd_rx_ack.seqNo = ieee_radio.tx_buf[FRAME_SEQNUM_OFFSET];
440  } else {
441  /* No, turn off chaining */
442  cmd_tx.condition.rule = COND_NEVER;
443  }
444 
445  /* Configure TX command */
446  cmd_tx.payloadLen = (uint8_t)transmit_len;
447  cmd_tx.pPayload = ieee_radio.tx_buf;
448 
449  res = netstack_sched_ieee_tx(ack_request);
450 
451  if(res != RF_RESULT_OK) {
452  return RADIO_TX_ERR;
453  }
454 
455  if(ack_request) {
456  switch(cmd_rx_ack.status) {
457  /* CMD_IEEE_RX_ACK timed out, i.e. never received ACK */
458  case IEEE_DONE_TIMEOUT: return RADIO_TX_NOACK;
459  /* An ACK was received with either pending data bit set or cleared */
460  case IEEE_DONE_ACK: /* fallthrough */
461  case IEEE_DONE_ACKPEND: return RADIO_TX_OK;
462  /* Any other statuses are errors */
463  default: return RADIO_TX_ERR;
464  }
465  }
466 
467  /* No ACK expected, TX OK */
468  return RADIO_TX_OK;
469 }
470 /*---------------------------------------------------------------------------*/
471 static int
472 send(const void *payload, unsigned short payload_len)
473 {
474  prepare(payload, payload_len);
475  return transmit(payload_len);
476 }
477 /*---------------------------------------------------------------------------*/
478 static int
479 read(void *buf, unsigned short buf_len)
480 {
481  volatile data_entry_t *data_entry = data_queue_current_entry();
482 
483  const rtimer_clock_t t0 = RTIMER_NOW();
484  /* Only wait if the Radio timer is accessing the entry */
485  while((data_entry->status == DATA_ENTRY_BUSY) &&
486  RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)) ;
487 
488  if(data_entry->status != DATA_ENTRY_FINISHED) {
489  /* No available data */
490  return -1;
491  }
492 
493  /*
494  * lensz bytes (1) in the data entry are the length of the received frame.
495  * Data frame is on the following format:
496  * Length (1) + Payload (N) + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
497  * Data frame DOES NOT contain the following:
498  * no PHY Header bytes
499  * no Source Index bytes
500  * Visual representation of frame format:
501  *
502  * +--------+---------+---------+--------+--------+-----------+
503  * | 1 byte | N bytes | 2 bytes | 1 byte | 1 byte | 4 bytes |
504  * +--------+---------+---------+--------+--------+-----------+
505  * | Length | Payload | FCS | RSSI | Status | Timestamp |
506  * +--------+---------+---------+--------+--------+-----------+
507  *
508  * Length bytes equal total length of entire frame excluding itself,
509  * Length = N + FCS (2) + RSSI (1) + Status (1) + Timestamp (4)
510  * Length = N + 8
511  * N = Length - 8
512  */
513  uint8_t *const frame_ptr = (uint8_t *)&data_entry->data;
514  const lensz_t frame_len = *(lensz_t *)frame_ptr;
515 
516  /* Sanity check that Frame is at least Frame Shave bytes long */
517  if(frame_len < FRAME_SHAVE) {
518  LOG_ERR("Received frame too short, len=%d\n", frame_len);
519 
520  data_queue_release_entry();
521  return 0;
522  }
523 
524  const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t);
525  const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE);
526 
527  /* Sanity check that Payload fits in buffer. */
528  if(payload_len > buf_len) {
529  LOG_ERR("MAC payload too large for buffer, len=%d buf_len=%d\n",
530  payload_len, buf_len);
531 
532  data_queue_release_entry();
533  return 0;
534  }
535 
536  memcpy(buf, payload_ptr, payload_len);
537 
538  /* RSSI stored FCS (2) bytes after payload. */
539  ieee_radio.last.rssi = (int8_t)payload_ptr[payload_len + 2];
540  /* LQI retrieved from Status byte, FCS (2) + RSSI (1) bytes after payload. */
541  ieee_radio.last.corr_lqi = (uint8_t)(payload_ptr[payload_len + 3] & STATUS_CORRELATION);
542  /* Timestamp stored FCS (2) + RSSI (1) + Status (1) bytes after payload. */
543  const uint32_t rat_ticks = *(uint32_t *)(payload_ptr + payload_len + 4);
544  ieee_radio.last.timestamp = rat_to_timestamp(rat_ticks);
545 
546  if(!ieee_radio.poll_mode) {
547  /* Not in poll mode: packetbuf should not be accessed in interrupt context. */
548  /* In poll mode, the last packet RSSI and link quality can be obtained through */
549  /* RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */
550  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)ieee_radio.last.rssi);
551  packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)ieee_radio.last.corr_lqi);
552  }
553 
554  data_queue_release_entry();
555  return (int)payload_len;
556 }
557 /*---------------------------------------------------------------------------*/
558 static rf_result_t
559 cca_request(cmd_cca_req_t *cmd_cca_req)
560 {
561  RF_Stat stat = RF_StatRadioInactiveError;
562  rf_result_t res;
563  bool stop_rx = false;
564 
565  /* RX is required to be running in order to do a CCA request */
566  if(!rx_is_active()) {
567  /* If RX is not pending, i.e. soon to be running, schedule the RX command */
568  if(cmd_rx.status != PENDING) {
569  res = netstack_sched_rx(false);
570  if(res != RF_RESULT_OK) {
571  LOG_ERR("CCA request failed to schedule RX\n");
572  return res;
573  }
574 
575  /* We only stop RX if we had to schedule it */
576  stop_rx = true;
577  }
578 
579  /* Make sure RX is running before we continue, unless we timeout and fail */
580  RTIMER_BUSYWAIT_UNTIL(!rx_is_active(), TIMEOUT_ENTER_RX_WAIT);
581 
582  if(!rx_is_active()) {
583  LOG_ERR("CCA request failed to turn on RX, RX status=0x%04X\n", cmd_rx.status);
584  return RF_RESULT_ERROR;
585  }
586  }
587 
588  /* Perform the CCA request */
589  stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)cmd_cca_req);
590 
591  if(stop_rx) {
592  netstack_stop_rx();
593  }
594 
595  if(stat != RF_StatCmdDoneSuccess) {
596  LOG_ERR("CCA request command failed, stat=0x%02X\n", stat);
597  return RF_RESULT_ERROR;
598  }
599 
600  return RF_RESULT_OK;
601 }
602 /*---------------------------------------------------------------------------*/
603 static int
604 channel_clear(void)
605 {
606  cmd_cca_req_t cmd_cca_req;
607  memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t));
608  cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ;
609 
610  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
611  return 0;
612  }
613 
614  /* Channel is clear if CCA state is IDLE */
615  return cmd_cca_req.ccaInfo.ccaState == CCA_STATE_IDLE;
616 }
617 /*---------------------------------------------------------------------------*/
618 static int
619 receiving_packet(void)
620 {
621  cmd_cca_req_t cmd_cca_req;
622  memset(&cmd_cca_req, 0x0, sizeof(cmd_cca_req_t));
623  cmd_cca_req.commandNo = CMD_IEEE_CCA_REQ;
624 
625  if(cca_request(&cmd_cca_req) != RF_RESULT_OK) {
626  return 0;
627  }
628 
629  /* If we are transmitting (can only be an ACK here), we are not receiving */
630  if((cmd_cca_req.ccaInfo.ccaEnergy == CCA_STATE_BUSY) &&
631  (cmd_cca_req.ccaInfo.ccaCorr == CCA_STATE_BUSY) &&
632  (cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY)) {
633  LOG_WARN("We are TXing ACK, therefore not receiving packets\n");
634  return 0;
635  }
636 
637  /* We are receiving a packet if a CCA sync has been seen, i.e. ccaSync is busy (1) */
638  return cmd_cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY;
639 }
640 /*---------------------------------------------------------------------------*/
641 static int
642 pending_packet(void)
643 {
644  const data_entry_t *const read_entry = data_queue_current_entry();
645  volatile const data_entry_t *curr_entry = read_entry;
646 
647  int num_pending = 0;
648 
649  /* Go through RX Circular buffer and check each data entry status */
650  do {
651  const uint8_t status = curr_entry->status;
652  if((status == DATA_ENTRY_FINISHED) ||
653  (status == DATA_ENTRY_BUSY)) {
654  num_pending += 1;
655  }
656 
657  /* Stop when we have looped the circular buffer */
658  curr_entry = (data_entry_t *)curr_entry->pNextEntry;
659  } while(curr_entry != read_entry);
660 
661  if((num_pending > 0) && !ieee_radio.poll_mode) {
662  process_poll(&rf_sched_process);
663  }
664 
665  /* If we didn't find an entry at status finished or busy, no frames are pending */
666  return num_pending;
667 }
668 /*---------------------------------------------------------------------------*/
669 static int
670 on(void)
671 {
672  rf_result_t res;
673 
674  if(ieee_radio.rf_is_on) {
675  LOG_WARN("Radio is already on\n");
676  return RF_RESULT_OK;
677  }
678 
679  data_queue_reset();
680 
681  res = netstack_sched_rx(true);
682 
683  if(res != RF_RESULT_OK) {
684  return RF_RESULT_ERROR;
685  }
686 
687  ieee_radio.rf_is_on = true;
688  return RF_RESULT_OK;
689 }
690 /*---------------------------------------------------------------------------*/
691 static int
692 off(void)
693 {
694  if(!ieee_radio.rf_is_on) {
695  LOG_WARN("Radio is already off\n");
696  return RF_RESULT_OK;
697  }
698 
699  rf_yield();
700 
701  ieee_radio.rf_is_on = false;
702  return RF_RESULT_OK;
703 }
704 /*---------------------------------------------------------------------------*/
705 static radio_result_t
706 get_value(radio_param_t param, radio_value_t *value)
707 {
708  rf_result_t res;
709 
710  if(!value) {
711  return RADIO_RESULT_INVALID_VALUE;
712  }
713 
714  switch(param) {
715 
716  /* Power Mode */
717  case RADIO_PARAM_POWER_MODE:
718  *value = (ieee_radio.rf_is_on)
719  ? RADIO_POWER_MODE_ON
720  : RADIO_POWER_MODE_OFF;
721  return RADIO_RESULT_OK;
722 
723  /* Channel */
724  case RADIO_PARAM_CHANNEL:
725  *value = (radio_value_t)cmd_rx.channel;
726  return RADIO_RESULT_OK;
727 
728  /* PAN ID */
729  case RADIO_PARAM_PAN_ID:
730  *value = (radio_value_t)cmd_rx.localPanID;
731  return RADIO_RESULT_OK;
732 
733  /* 16-bit address */
734  case RADIO_PARAM_16BIT_ADDR:
735  *value = (radio_value_t)cmd_rx.localShortAddr;
736  return RADIO_RESULT_OK;
737 
738  /* RX mode */
739  case RADIO_PARAM_RX_MODE:
740  *value = 0;
741  if(cmd_rx.frameFiltOpt.frameFiltEn) {
743  }
744  if(cmd_rx.frameFiltOpt.autoAckEn) {
745  *value |= (radio_value_t)RADIO_RX_MODE_AUTOACK;
746  }
747  if(ieee_radio.poll_mode) {
748  *value |= (radio_value_t)RADIO_RX_MODE_POLL_MODE;
749  }
750  return RADIO_RESULT_OK;
751 
752  /* TX mode */
753  case RADIO_PARAM_TX_MODE:
754  *value = 0;
755  return RADIO_RESULT_OK;
756 
757  /* TX power */
758  case RADIO_PARAM_TXPOWER:
759  res = rf_get_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t *)&value);
760  return ((res == RF_RESULT_OK) &&
761  (*value != RF_TxPowerTable_INVALID_DBM))
762  ? RADIO_RESULT_OK
763  : RADIO_RESULT_ERROR;
764 
765  /* CCA threshold */
766  case RADIO_PARAM_CCA_THRESHOLD:
767  *value = cmd_rx.ccaRssiThr;
768  return RADIO_RESULT_OK;
769 
770  /* RSSI */
771  case RADIO_PARAM_RSSI:
772  *value = RF_getRssi(ieee_radio.rf_handle);
773  return (*value == RF_GET_RSSI_ERROR_VAL)
774  ? RADIO_RESULT_ERROR
775  : RADIO_RESULT_OK;
776 
777  /* Channel min */
778  case RADIO_CONST_CHANNEL_MIN:
779  *value = (radio_value_t)DOT_15_4G_CHAN_MIN;
780  return RADIO_RESULT_OK;
781 
782  /* Channel max */
783  case RADIO_CONST_CHANNEL_MAX:
784  *value = (radio_value_t)DOT_15_4G_CHAN_MAX;
785  return RADIO_RESULT_OK;
786 
787  case RADIO_CONST_TXPOWER_MIN:
788  *value = (radio_value_t)tx_power_min(rf_tx_power_table);
789  return RADIO_RESULT_OK;
790 
791  /* TX power max */
792  case RADIO_CONST_TXPOWER_MAX:
793  *value = (radio_value_t)tx_power_max(rf_tx_power_table, rf_tx_power_table_size);
794  return RADIO_RESULT_OK;
795 
796  /* Last RSSI */
797  case RADIO_PARAM_LAST_RSSI:
798  *value = (radio_value_t)ieee_radio.last.rssi;
799  return RADIO_RESULT_OK;
800 
801  /* Last link quality */
802  case RADIO_PARAM_LAST_LINK_QUALITY:
803  *value = (radio_value_t)ieee_radio.last.corr_lqi;
804  return RADIO_RESULT_OK;
805 
806  default:
807  return RADIO_RESULT_NOT_SUPPORTED;
808  }
809 }
810 /*---------------------------------------------------------------------------*/
811 static radio_result_t
812 set_value(radio_param_t param, radio_value_t value)
813 {
814  rf_result_t res;
815 
816  switch(param) {
817 
818  /* Power Mode */
819  case RADIO_PARAM_POWER_MODE:
820 
821  if(value == RADIO_POWER_MODE_ON) {
822  return (on() == RF_RESULT_OK)
823  ? RADIO_RESULT_OK
824  : RADIO_RESULT_ERROR;
825  } else if(value == RADIO_POWER_MODE_OFF) {
826  off();
827  return RADIO_RESULT_OK;
828  }
829 
830  return RADIO_RESULT_INVALID_VALUE;
831 
832  /* Channel */
833  case RADIO_PARAM_CHANNEL:
834  if(!dot_15_4g_chan_in_range(value)) {
835  return RADIO_RESULT_INVALID_VALUE;
836  }
837  set_channel((uint8_t)value);
838  return RADIO_RESULT_OK;
839 
840  /* PAN ID */
841  case RADIO_PARAM_PAN_ID:
842  cmd_rx.localPanID = (uint16_t)value;
843  if(!ieee_radio.rf_is_on) {
844  return RADIO_RESULT_OK;
845  }
846 
847  netstack_stop_rx();
848  res = netstack_sched_rx(false);
849  return (res == RF_RESULT_OK)
850  ? RADIO_RESULT_OK
851  : RADIO_RESULT_ERROR;
852 
853  /* 16bit address */
854  case RADIO_PARAM_16BIT_ADDR:
855  cmd_rx.localShortAddr = (uint16_t)value;
856  if(!ieee_radio.rf_is_on) {
857  return RADIO_RESULT_OK;
858  }
859 
860  netstack_stop_rx();
861  res = netstack_sched_rx(false);
862  return (res == RF_RESULT_OK)
863  ? RADIO_RESULT_OK
864  : RADIO_RESULT_ERROR;
865 
866  /* RX Mode */
867  case RADIO_PARAM_RX_MODE: {
868  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
869  RADIO_RX_MODE_AUTOACK |
870  RADIO_RX_MODE_POLL_MODE)) {
871  return RADIO_RESULT_INVALID_VALUE;
872  }
873 
874  cmd_rx.frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0;
875  cmd_rx.frameFiltOpt.frameFiltStop = 1;
876  cmd_rx.frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0;
877  cmd_rx.frameFiltOpt.slottedAckEn = 0;
878  cmd_rx.frameFiltOpt.autoPendEn = 0;
879  cmd_rx.frameFiltOpt.defaultPend = 0;
880  cmd_rx.frameFiltOpt.bPendDataReqOnly = 0;
881  cmd_rx.frameFiltOpt.bPanCoord = 0;
882  cmd_rx.frameFiltOpt.bStrictLenFilter = 0;
883 
884  const bool old_poll_mode = ieee_radio.poll_mode;
885  ieee_radio.poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
886  if(old_poll_mode == ieee_radio.poll_mode) {
887  /* Do not turn the radio off and on, just send an update command */
888  memcpy(&cmd_mod_filt.newFrameFiltOpt, &(rf_cmd_ieee_rx.frameFiltOpt), sizeof(rf_cmd_ieee_rx.frameFiltOpt));
889  const RF_Stat stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)&cmd_mod_filt);
890  if(stat != RF_StatCmdDoneSuccess) {
891  LOG_ERR("Setting address filter failed, stat=0x%02X\n", stat);
892  return RADIO_RESULT_ERROR;
893  }
894  return RADIO_RESULT_OK;
895  }
896  if(!ieee_radio.rf_is_on) {
897  return RADIO_RESULT_OK;
898  }
899 
900  netstack_stop_rx();
901  res = netstack_sched_rx(false);
902  return (res == RF_RESULT_OK)
903  ? RADIO_RESULT_OK
904  : RADIO_RESULT_ERROR;
905  }
906 
907  /* TX Mode */
908  case RADIO_PARAM_TX_MODE:
909  if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
910  return RADIO_RESULT_INVALID_VALUE;
911  }
912  set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
913  return RADIO_RESULT_OK;
914 
915  /* TX Power */
916  case RADIO_PARAM_TXPOWER:
917  if(!tx_power_in_range((int8_t)value, rf_tx_power_table, rf_tx_power_table_size)) {
918  return RADIO_RESULT_INVALID_VALUE;
919  }
920  res = rf_set_tx_power(ieee_radio.rf_handle, rf_tx_power_table, (int8_t)value);
921  return (res == RF_RESULT_OK)
922  ? RADIO_RESULT_OK
923  : RADIO_RESULT_ERROR;
924 
925  /* CCA Threshold */
926  case RADIO_PARAM_CCA_THRESHOLD:
927  cmd_rx.ccaRssiThr = (int8_t)value;
928  if(!ieee_radio.rf_is_on) {
929  return RADIO_RESULT_OK;
930  }
931 
932  netstack_stop_rx();
933  res = netstack_sched_rx(false);
934  return (res == RF_RESULT_OK)
935  ? RADIO_RESULT_OK
936  : RADIO_RESULT_ERROR;
937 
938  default:
939  return RADIO_RESULT_NOT_SUPPORTED;
940  }
941 }
942 /*---------------------------------------------------------------------------*/
943 static radio_result_t
944 get_object(radio_param_t param, void *dest, size_t size)
945 {
946  if(!dest) {
947  return RADIO_RESULT_INVALID_VALUE;
948  }
949 
950  switch(param) {
951  /* 64bit address */
952  case RADIO_PARAM_64BIT_ADDR: {
953  const size_t srcSize = sizeof(cmd_rx.localExtAddr);
954  if(size != srcSize) {
955  return RADIO_RESULT_INVALID_VALUE;
956  }
957 
958  const uint8_t *pSrc = (uint8_t *)&(cmd_rx.localExtAddr);
959  uint8_t *pDest = dest;
960  for(size_t i = 0; i < srcSize; ++i) {
961  pDest[i] = pSrc[srcSize - 1 - i];
962  }
963 
964  return RADIO_RESULT_OK;
965  }
966  /* Last packet timestamp */
967  case RADIO_PARAM_LAST_PACKET_TIMESTAMP:
968  if(size != sizeof(rtimer_clock_t)) {
969  return RADIO_RESULT_INVALID_VALUE;
970  }
971 
972  *(rtimer_clock_t *)dest = ieee_radio.last.timestamp;
973 
974  return RADIO_RESULT_OK;
975 
976  default:
977  return RADIO_RESULT_NOT_SUPPORTED;
978  }
979 }
980 /*---------------------------------------------------------------------------*/
981 static radio_result_t
982 set_object(radio_param_t param, const void *src, size_t size)
983 {
984  rf_result_t res;
985 
986  if(!src) {
987  return RADIO_RESULT_INVALID_VALUE;
988  }
989 
990  switch(param) {
991  /* 64-bit address */
992  case RADIO_PARAM_64BIT_ADDR: {
993  const size_t destSize = sizeof(cmd_rx.localExtAddr);
994  if(size != destSize) {
995  return RADIO_RESULT_INVALID_VALUE;
996  }
997 
998  const uint8_t *pSrc = (const uint8_t *)src;
999  volatile uint8_t *pDest = (uint8_t *)&(cmd_rx.localExtAddr);
1000  for(size_t i = 0; i < destSize; ++i) {
1001  pDest[i] = pSrc[destSize - 1 - i];
1002  }
1003 
1004  if(!rx_is_active()) {
1005  return RADIO_RESULT_OK;
1006  }
1007 
1008  netstack_stop_rx();
1009  res = netstack_sched_rx(false);
1010  return (res == RF_RESULT_OK)
1011  ? RADIO_RESULT_OK
1012  : RADIO_RESULT_ERROR;
1013  }
1014  default:
1015  return RADIO_RESULT_NOT_SUPPORTED;
1016  }
1017 }
1018 /*---------------------------------------------------------------------------*/
1019 const struct radio_driver ieee_mode_driver = {
1020  init,
1021  prepare,
1022  transmit,
1023  send,
1024  read,
1025  channel_clear,
1028  on,
1029  off,
1030  get_value,
1031  set_value,
1032  get_object,
1033  set_object,
1034 };
1035 /*---------------------------------------------------------------------------*/
1036 /**
1037  * @}
1038  * @}
1039  */
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:307
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:269
static uint8_t rf_cmd_ieee_rx()
Set up radio in IEEE802.15.4 RX mode.
Definition: ieee-mode.c:478
Header file of TX power functionality of CC13xx/CC26xx.
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:254
#define FRAME_SHAVE
RSSI (1) + Status (1)
Definition: prop-mode.c:139
Header file for the energy estimation mechanism
Header file for the link-layer address representation
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:285
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:300
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Definition: radio.h:288
The structure of a device driver for a radio in Contiki.
Definition: radio.h:264
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
Definition: rtimer.h:202
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:168
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:282
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
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:160
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
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:275
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:272
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:294
#define RF_CONF_INACTIVITY_TIMEOUT
2 ms
Header file for the real-time timer module.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:231
Header file of the CC13xx/CC26xx RF data queue.
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
Definition: radio.h:243
Header file of RF settings for CC13xx/CC26xx.
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
Definition: radio.h:278
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:297
Default definitions of C compiler quirk work-arounds.
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:313
int(* on)(void)
Turn the radio on.
Definition: radio.h:291
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99