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