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