Contiki-NG
efr32-radio.c
1/*
2 * Copyright (c) 2018-2019, RISE SICS
3 * Copyright (C) 2022 Yago Fontoura do Rosario <yago.rosario@hotmail.com.br>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "contiki.h"
33#include "dev/radio.h"
34#include "net/packetbuf.h"
35#include "net/netstack.h"
36#include "em_core.h"
37#include "em_system.h"
38
39#include "efr32-radio-buffer.h"
40
41#include "pa_conversions_efr32.h"
42#include "sl_rail_util_dma.h"
43#include "sl_rail_util_pti.h"
44#include "sl_rail_util_rf_path.h"
45#include "sl_rail_util_rssi.h"
46#include "rail.h"
47#include <ieee802154/rail_ieee802154.h>
48
49/* Log configuration */
50#include "sys/log.h"
51#define LOG_MODULE "EFR32"
52#define LOG_LEVEL LOG_LEVEL_NONE
53
54enum {
55 IEEE802154_ACK_REQUEST = 1 << 5,
56};
57
58typedef enum {
59 TX_IDLE,
60 TX_SENDING,
61 TX_SENT,
62 TX_NO_ACK,
63 TX_CHANNEL_BUSY,
64 TX_ERROR
65} tx_status_t;
66
67#define CHANNEL_MIN 11
68#define CHANNEL_MAX 26
69#define PTI_ENABLED false
70
71extern const RAIL_ChannelConfig_t *const RAIL_IEEE802154_Phy2p4GHz;
72
73static void rail_events_cb(RAIL_Handle_t rail_handle, RAIL_Events_t events);
74static RAILSched_Config_t rail_sched_config;
75static RAIL_Config_t rail_config = {
76 .eventsCallback = &rail_events_cb,
77 .scheduler = &rail_sched_config,
78};
79static union {
80 RAIL_FIFO_ALIGNMENT_TYPE align[RAIL_FIFO_SIZE / RAIL_FIFO_ALIGNMENT];
81 uint8_t fifo[RAIL_FIFO_SIZE];
82} sRailRxFifo;
83static RAIL_Handle_t sRailHandle = NULL;
84static RAIL_Time_t last_rx_time = 0;
85static int16_t last_rssi;
86static int16_t last_lqi;
87/* The process for receiving packets */
88PROCESS(efr32_radio_process, "efr32 radio driver");
89static uint8_t send_on_cca = 1;
90static uint8_t poll_mode = 0;
91static RAIL_DataConfig_t data_config = {
92 .txSource = TX_PACKET_DATA,
93 .rxSource = RX_PACKET_DATA,
94 .txMethod = PACKET_MODE,
95 .rxMethod = PACKET_MODE,
96};
97static RAIL_IEEE802154_Config_t rail_ieee802154_config = {
98 .addresses = NULL,
99 .ackConfig = {
100 .enable = 1,
101 .ackTimeout = 672,
102 .rxTransitions = {
103 .success = RAIL_RF_STATE_RX,
104 .error = RAIL_RF_STATE_IDLE
105 },
106 .txTransitions = {
107 .success = RAIL_RF_STATE_RX,
108 .error = RAIL_RF_STATE_IDLE
109 }
110 },
111 .timings = {
112 .idleToRx = 100,
113 .idleToTx = 100,
114 .rxToTx = 192,
115 .txToRx = 192 - 10,
116 .rxSearchTimeout = 0,
117 .txToRxSearchTimeout = 0,
118 },
119 .framesMask = RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES
120 | RAIL_IEEE802154_ACCEPT_ACK_FRAMES,
121 .promiscuousMode = 0,
122 .isPanCoordinator = 0,
123 .defaultFramePendingInOutgoingAcks = 0,
124};
125static union {
126 RAIL_FIFO_ALIGNMENT_TYPE align[RAIL_FIFO_SIZE / RAIL_FIFO_ALIGNMENT];
127 uint8_t fifo[RAIL_FIFO_SIZE];
128} sRailTxFifo;
129static uint16_t panid = 0xabcd;
130static int channel = IEEE802154_DEFAULT_CHANNEL;
131static int cca_threshold = -85;
132static RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_DEFAULT;
133volatile tx_status_t tx_status;
134volatile bool is_receiving = false;
135/*---------------------------------------------------------------------------*/
136RAIL_Status_t
137RAILCb_SetupRxFifo(RAIL_Handle_t railHandle)
138{
139 uint16_t rxFifoSize = RAIL_FIFO_SIZE;
140 RAIL_Status_t status = RAIL_SetRxFifo(railHandle, sRailRxFifo.fifo, &rxFifoSize);
141 if(rxFifoSize != RAIL_FIFO_SIZE) {
142 /* We set up an incorrect FIFO size */
143 return RAIL_STATUS_INVALID_PARAMETER;
144 }
145 if(status == RAIL_STATUS_INVALID_STATE) {
146 /* Allow failures due to multiprotocol */
147 return RAIL_STATUS_NO_ERROR;
148 }
149 return status;
150}
151/*---------------------------------------------------------------------------*/
152static uint8_t
153configure_radio_interrupts(void)
154{
155 RAIL_Status_t rail_status;
156
157 rail_status = RAIL_ConfigEvents(sRailHandle, RAIL_EVENTS_ALL,
158 RAIL_EVENT_RX_SYNC1_DETECT |
159 RAIL_EVENT_RX_SYNC2_DETECT |
160 RAIL_EVENT_RX_ACK_TIMEOUT |
161 RAIL_EVENT_RX_FRAME_ERROR |
162 RAIL_EVENT_RX_PACKET_RECEIVED |
163 RAIL_EVENT_RX_FIFO_OVERFLOW |
164 RAIL_EVENT_RX_ADDRESS_FILTERED |
165 RAIL_EVENT_RX_PACKET_ABORTED |
166 RAIL_EVENT_TX_PACKET_SENT |
167 RAIL_EVENT_TX_CHANNEL_BUSY |
168 RAIL_EVENT_TX_ABORTED |
169 RAIL_EVENT_TX_BLOCKED |
170 RAIL_EVENT_TX_UNDERFLOW |
171 RAIL_EVENT_CAL_NEEDED);
172
173 if(rail_status != RAIL_STATUS_NO_ERROR) {
174 LOG_ERR("RAIL_ConfigEvents failed, return value: %d", rail_status);
175 return 0;
176 }
177
178 return 1;
179}
180/*---------------------------------------------------------------------------*/
181static void
182handle_receive(void)
183{
184 RAIL_RxPacketHandle_t rx_packet_handle;
185 RAIL_RxPacketDetails_t packet_details;
186 RAIL_RxPacketInfo_t packet_info;
187 RAIL_Status_t rail_status;
188 uint16_t length = 0;
189 rx_buffer_t *rx_buf;
190
191 rx_packet_handle = RAIL_GetRxPacketInfo(sRailHandle, RAIL_RX_PACKET_HANDLE_OLDEST_COMPLETE, &packet_info);
192
193 if(rx_packet_handle == RAIL_RX_PACKET_HANDLE_INVALID) {
194 return;
195 }
196
197 packet_details.isAck = false;
198 packet_details.timeReceived.timePosition = RAIL_PACKET_TIME_AT_SYNC_END;
199 packet_details.timeReceived.totalPacketBytes = 0;
200
201 rail_status = RAIL_GetRxPacketDetails(sRailHandle, rx_packet_handle, &packet_details);
202 if(rail_status != RAIL_STATUS_NO_ERROR) {
203 LOG_ERR("Failed to get packet details\n");
204 return;
205 }
206
207 length = packet_info.packetBytes - 1;
208 LOG_INFO("EFR32 Radio: rcv:%d\n", length);
209
210 /* skip length byte */
211 packet_info.firstPortionData++;
212 packet_info.firstPortionBytes--;
213 packet_info.packetBytes--;
214
215 rx_buf = get_empty_rx_buf();
216 if(rx_buf != NULL) {
217 rx_buf->len = length;
218
219 /* read packet into buffer */
220 memcpy(rx_buf->buf, packet_info.firstPortionData,
221 packet_info.firstPortionBytes);
222 if(packet_info.lastPortionData != NULL) {
223 memcpy(rx_buf->buf + packet_info.firstPortionBytes,
224 packet_info.lastPortionData,
225 packet_info.packetBytes - packet_info.firstPortionBytes);
226 }
227 rx_buf->rssi = packet_details.rssi;
228 rx_buf->lqi = packet_details.lqi;
229 rx_buf->timestamp = packet_details.timeReceived.packetTime;
230 } else {
231 LOG_INFO("EFR32 Radio: Could not allocate rx_buf\n");
232 }
233
234 /* after the copy of the packet, the RX packet can be release for RAIL */
235 rail_status = RAIL_ReleaseRxPacket(sRailHandle, rx_packet_handle);
236 if(rail_status != RAIL_STATUS_NO_ERROR) {
237 LOG_WARN("RAIL_ReleaseRxPacket() result:%d", rail_status);
238 }
239}
240/*---------------------------------------------------------------------------*/
241static void
242rail_events_cb(RAIL_Handle_t rail_handle, RAIL_Events_t events)
243{
244 if(events & (RAIL_EVENT_TX_ABORTED | RAIL_EVENT_TX_BLOCKED | RAIL_EVENT_TX_UNDERFLOW)) {
245 tx_status = TX_ERROR;
246 }
247
248 if(events & RAIL_EVENT_RX_ACK_TIMEOUT) {
249 tx_status = TX_NO_ACK;
250 }
251
252 if(events & (RAIL_EVENT_RX_FIFO_OVERFLOW
253 | RAIL_EVENT_RX_ADDRESS_FILTERED
254 | RAIL_EVENT_RX_PACKET_ABORTED
255 | RAIL_EVENT_RX_FRAME_ERROR
256 | RAIL_EVENT_RX_PACKET_RECEIVED)) {
257 is_receiving = false;
258 if(events & RAIL_EVENT_RX_PACKET_RECEIVED) {
259 RAIL_HoldRxPacket(rail_handle);
260 if(!poll_mode) {
261 LOG_INFO("EFR32 Radio: Receive event - poll.\n");
262 process_poll(&efr32_radio_process);
263 }
264 }
265 }
266
267 if(events & RAIL_EVENT_TX_PACKET_SENT) {
268 LOG_INFO("EFR32 Radio: packet sent\n");
269 tx_status = TX_SENT;
270 }
271
272 if(events & RAIL_EVENT_TX_CHANNEL_BUSY) {
273 tx_status = TX_CHANNEL_BUSY;
274 }
275
276 if(events & (RAIL_EVENT_RX_SYNC1_DETECT | RAIL_EVENT_RX_SYNC2_DETECT)) {
277 is_receiving = true;
278 }
279
280 if(events & RAIL_EVENT_CAL_NEEDED) {
281 (void)RAIL_Calibrate(rail_handle, NULL, RAIL_CAL_ALL_PENDING);
282 }
283}
284/*---------------------------------------------------------------------------*/
285static int
286init(void)
287{
288 RAIL_Status_t status;
289 uint8_t *ext_addr;
290 uint16_t short_addr;
291 uint16_t allocated_tx_fifo_size;
292 uint64_t system_number;
293
294 NVIC_SetPriority(FRC_PRI_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
295 NVIC_SetPriority(FRC_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
296 NVIC_SetPriority(MODEM_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
297 NVIC_SetPriority(RAC_SEQ_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
298 NVIC_SetPriority(RAC_RSM_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
299 NVIC_SetPriority(BUFC_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
300 NVIC_SetPriority(AGC_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
301 NVIC_SetPriority(PROTIMER_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
302 NVIC_SetPriority(SYNTH_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
303 NVIC_SetPriority(RFSENSE_IRQn, CORE_INTERRUPT_HIGHEST_PRIORITY);
304
305 sl_rail_util_dma_init();
306 sl_rail_util_pa_init();
307 sl_rail_util_pti_init();
308 sl_rail_util_rf_path_init();
309 sl_rail_util_rssi_init();
310
311 /* initializes the RAIL core */
312 sRailHandle = RAIL_Init(&rail_config,
313 NULL);
314
315 if(sRailHandle == NULL) {
316 LOG_ERR("RAIL_Init failed, return value: NULL");
317 return 0;
318 }
319
320 status = RAIL_InitPowerManager();
321 if(status != RAIL_STATUS_NO_ERROR) {
322 LOG_ERR("RAIL_InitPowerManager failed, return value: %d", status);
323 return 0;
324 }
325
326 status = RAIL_ConfigData(sRailHandle, &data_config);
327
328 if(status != RAIL_STATUS_NO_ERROR) {
329 LOG_ERR("RAIL_ConfigData failed, return value: %d", status);
330 return 0;
331 }
332
333 /* configures the channels */
334 (void)RAIL_ConfigChannels(sRailHandle,
335 RAIL_IEEE802154_Phy2p4GHz,
336 &sl_rail_util_pa_on_channel_config_change);
337
338 status = RAIL_IEEE802154_Init(sRailHandle, &rail_ieee802154_config);
339 if(status != RAIL_STATUS_NO_ERROR) {
340 LOG_ERR("RAIL_IEEE802154_Init failed, return value: %d", status);
341 return 0;
342 }
343
344 status = RAIL_IEEE802154_Config2p4GHzRadio(sRailHandle);
345 if(status != RAIL_STATUS_NO_ERROR) {
346 (void)RAIL_IEEE802154_Deinit(sRailHandle);
347 LOG_ERR("RAIL_IEEE802154_Config2p4GHzRadio failed, return value: %d", status);
348 return 0;
349 }
350
351 status = RAIL_IEEE802154_ConfigEOptions(sRailHandle,
352 (RAIL_IEEE802154_E_OPTION_GB868
353 | RAIL_IEEE802154_E_OPTION_ENH_ACK
354 | RAIL_IEEE802154_E_OPTION_IMPLICIT_BROADCAST),
355 (RAIL_IEEE802154_E_OPTION_GB868
356 | RAIL_IEEE802154_E_OPTION_ENH_ACK
357 | RAIL_IEEE802154_E_OPTION_IMPLICIT_BROADCAST));
358
359 if(status != RAIL_STATUS_NO_ERROR) {
360 LOG_ERR("RAIL_IEEE802154_ConfigEOptions failed, return value: %d", status);
361 return 0;
362 }
363
364 status = RAIL_ConfigCal(sRailHandle,
365 0U
366 | (0
367 ? RAIL_CAL_TEMP : 0U)
368 | (0
369 ? RAIL_CAL_ONETIME : 0U));
370
371 if(status != RAIL_STATUS_NO_ERROR) {
372 LOG_ERR("RAIL_ConfigCal failed, return value: %d", status);
373 return 0;
374 }
375
376 if(!configure_radio_interrupts()) {
377 return 0;
378 }
379
380 system_number = SYSTEM_GetUnique();
381
382 ext_addr = (uint8_t *)&system_number;
383 short_addr = ext_addr[7];
384 short_addr |= ext_addr[6] << 8;
385
386 NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID);
387 NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr);
388 NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, &system_number, sizeof(system_number));
389
390 allocated_tx_fifo_size = RAIL_SetTxFifo(sRailHandle, sRailTxFifo.fifo,
391 0u, RAIL_FIFO_SIZE);
392
393 if(allocated_tx_fifo_size != RAIL_FIFO_SIZE) {
394 LOG_ERR("RAIL_SetTxFifo() failed to allocate a large enough fifo"
395 " (%d bytes instead of %d bytes)\n",
396 allocated_tx_fifo_size, RAIL_FIFO_SIZE);
397 return 0;
398 }
399
400 if(PTI_ENABLED) {
401 status = RAIL_SetPtiProtocol(sRailHandle, RAIL_PTI_PROTOCOL_802154);
402 if(status != RAIL_STATUS_NO_ERROR) {
403 LOG_ERR("RAIL_SetPtiProtocol() status: %d failed", status);
404 return 0;
405 }
406 status = RAIL_EnablePti(sRailHandle, PTI_ENABLED);
407 if(status != RAIL_STATUS_NO_ERROR) {
408 LOG_ERR("RAIL_EnablePti() status: %d failed", status);
409 return 0;
410 }
411 }
412
413 process_start(&efr32_radio_process, NULL);
414
415 return 0;
416}
417/*---------------------------------------------------------------------------*/
418static radio_result_t
419get_value(radio_param_t param, radio_value_t *value)
420{
421 if(!value) {
423 }
424
425 switch(param) {
427 *value = panid;
428 return RADIO_RESULT_OK;
430 *value = channel;
431 return RADIO_RESULT_OK;
432 case RADIO_CONST_MAX_PAYLOAD_LEN:
433 *value = RAIL_FIFO_SIZE;
434 return RADIO_RESULT_OK;
436 *value = 0;
437 if(!rail_ieee802154_config.promiscuousMode) {
439 }
440 if(rail_ieee802154_config.ackConfig.enable) {
441 *value |= RADIO_RX_MODE_AUTOACK;
442 }
443 if(poll_mode) {
444 *value |= RADIO_RX_MODE_POLL_MODE;
445 }
446 return RADIO_RESULT_OK;
448 *value = 0;
449 if(send_on_cca) {
451 }
452 return RADIO_RESULT_OK;
454 *value = last_rssi;
455 return RADIO_RESULT_OK;
457 *value = last_lqi;
458 return RADIO_RESULT_OK;
459 case RADIO_PARAM_RSSI:
460 {
461 int16_t rssi_value = RAIL_GetRssi(sRailHandle, true);
462 if(rssi_value != RAIL_RSSI_INVALID) {
463 /* RAIL_RxGetRSSI() returns value in quarter dBm (dBm * 4) */
464 *value = rssi_value / 4;
465 return RADIO_RESULT_OK;
466 }
467 return RADIO_RESULT_ERROR;
468 }
469 }
471}
472/*---------------------------------------------------------------------------*/
473static radio_result_t
474set_value(radio_param_t param, radio_value_t value)
475{
476 switch(param) {
478 if(value < CHANNEL_MIN ||
479 value > CHANNEL_MAX) {
481 }
482 channel = value;
483 /* start receiving on that channel */
484 const RAIL_Status_t status = RAIL_StartRx(sRailHandle, channel, NULL);
485 if(status != RAIL_STATUS_NO_ERROR) {
486 LOG_ERR("Could not start RX on channel %d\n", channel);
487 return RADIO_RESULT_ERROR;
488 }
489 return RADIO_RESULT_OK;
491 panid = value & 0xffff;
492 RAIL_IEEE802154_SetPanId(sRailHandle, panid, 0);
493 return RADIO_RESULT_OK;
495 (void)RAIL_IEEE802154_SetShortAddress(sRailHandle, value & 0xFFFF, 0);
496 return RADIO_RESULT_OK;
498 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
502 }
503
504 rail_ieee802154_config.ackConfig.enable = (value & RADIO_RX_MODE_AUTOACK) != 0;
505 rail_ieee802154_config.promiscuousMode = (value & RADIO_RX_MODE_ADDRESS_FILTER) == 0;
506 poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
507
508 if(!rail_ieee802154_config.ackConfig.enable) {
509 RAIL_StateTransitions_t transitions = {
510 .error = RAIL_RF_STATE_RX,
511 .success = RAIL_RF_STATE_RX,
512 };
513 RAIL_SetTxTransitions(sRailHandle, &transitions);
514 RAIL_SetRxTransitions(sRailHandle, &transitions);
515 }
516 (void)RAIL_ConfigAutoAck(sRailHandle, &rail_ieee802154_config.ackConfig);
517 (void)RAIL_IEEE802154_SetPromiscuousMode(sRailHandle, rail_ieee802154_config.promiscuousMode);
518 (void)configure_radio_interrupts();
519
520 return RADIO_RESULT_OK;
522 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
524 }
525
526 send_on_cca = (value & RADIO_TX_MODE_SEND_ON_CCA) != 0;
527 return RADIO_RESULT_OK;
528 }
530}
531/*---------------------------------------------------------------------------*/
532static radio_result_t
533get_object(radio_param_t param, void *dest, size_t size)
534{
536 if(size != sizeof(rtimer_clock_t) || !dest) {
538 }
539 *(rtimer_clock_t *)dest = last_rx_time;
540 return RADIO_RESULT_OK;
541 }
542
544}
545/*---------------------------------------------------------------------------*/
546static radio_result_t
547set_object(radio_param_t param, const void *src, size_t size)
548{
549 if(param == RADIO_PARAM_64BIT_ADDR) {
550 if(size != 8 || src == NULL) {
552 }
553 (void)RAIL_IEEE802154_SetLongAddress(sRailHandle, src, 0);
554 return RADIO_RESULT_OK;
555 }
557}
558/*---------------------------------------------------------------------------*/
559static int
560channel_clear(void)
561{
562 if(RAIL_GetRssi(sRailHandle, true) / 4 > cca_threshold) {
563 return 0;
564 }
565 return 1;
566}
567/*---------------------------------------------------------------------------*/
568static int
569prepare(const void *payload, unsigned short payload_len)
570{
571 uint8_t plen = (uint8_t)payload_len + 2;
572 uint8_t *data = (uint8_t *)payload;
573 int written = 0;
574 /* write the length byte */
575 written += RAIL_WriteTxFifo(sRailHandle, &plen, 1, true);
576 /* write the payload */
577 written += RAIL_WriteTxFifo(sRailHandle, payload, payload_len, false);
578
579 LOG_INFO("EFR32 Radio - wrote %d bytes to TX fifo\n", written);
580
581 if(!(poll_mode) && (data[0] & IEEE802154_ACK_REQUEST)) {
582 txOptions = RAIL_TX_OPTION_WAIT_FOR_ACK;
583 } else {
584 txOptions = RAIL_TX_OPTIONS_DEFAULT;
585 }
586
587 return RADIO_TX_OK;
588}
589/*---------------------------------------------------------------------------*/
590static int
591transmit(unsigned short transmit_len)
592{
593 uint8_t ret = RADIO_TX_OK;
594 RAIL_CsmaConfig_t csmaConfig =
595 RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
596 RAIL_Status_t status;
597
598 LOG_INFO("EFR32 Radio: Sending packet %d bytes\n", transmit_len);
599
600 tx_status = TX_SENDING;
601
602 if(send_on_cca) {
603 status = RAIL_StartCcaCsmaTx(sRailHandle,
604 channel,
605 txOptions,
606 &csmaConfig,
607 NULL);
608 } else {
609 status = RAIL_StartTx(sRailHandle,
610 channel,
611 txOptions,
612 NULL);
613 }
614
615 if(status != RAIL_STATUS_NO_ERROR) {
616 LOG_ERR("RAIL_Start***Tx status: %d failed", status);
617 tx_status = TX_IDLE;
618 return RADIO_TX_ERR;
619 }
620
621 if(poll_mode) {
622 /* Wait until TX operation finishes or timeout */
623 const uint16_t frame_length = transmit_len + RADIO_PHY_HEADER_LEN + RADIO_PHY_OVERHEAD;
624 RTIMER_BUSYWAIT_UNTIL((tx_status != TX_SENDING),
625 US_TO_RTIMERTICKS(RADIO_BYTE_AIR_TIME * frame_length + 300));
626 } else {
627 /* Wait for the transmission. */
628 while(tx_status == TX_SENDING);
629 }
630
631 if(tx_status == TX_SENT) {
632 LOG_INFO("EFR32: OK - packet sent.\n");
633 } else {
634 LOG_INFO("EFR32: TX error %d\n", tx_status);
635 }
636
637 /* always IDLE after transmission */
638 tx_status = TX_IDLE;
639
640 return ret;
641}
642/*---------------------------------------------------------------------------*/
643static int
644send(const void *payload, unsigned short payload_len)
645{
646 int ret;
647 ret = prepare(payload, payload_len);
648 if(ret) {
649 return ret;
650 }
651 return transmit(payload_len);
652}
653/*---------------------------------------------------------------------------*/
654static int
655on(void)
656{
657 return 1;
658}
659/*---------------------------------------------------------------------------*/
660static int
661off(void)
662{
663 return 1;
664}
665/*---------------------------------------------------------------------------*/
666static int
667receiving_packet(void)
668{
669 return is_receiving;
670}
671/*---------------------------------------------------------------------------*/
672static int
673read(void *buf, unsigned short bufsize)
674{
675 rx_buffer_t *rx_buf;
676 int len;
677
678 handle_receive();
679
680 rx_buf = get_full_rx_buf();
681 if(!rx_buf) {
682 return 0;
683 }
684 LOG_INFO("EFR32 Radio Read: %d\n", rx_buf->len);
685 len = rx_buf->len;
686 /* Convert from rail time domain to rtimer domain */
687 last_rx_time = RTIMER_NOW() - US_TO_RTIMERTICKS(RAIL_GetTime() - rx_buf->timestamp);
688 memcpy(buf, rx_buf->buf, len);
689 last_rssi = rx_buf->rssi;
690 last_lqi = rx_buf->lqi;
691 if(!poll_mode) {
692 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rx_buf->rssi);
693 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rx_buf->lqi);
694 }
695 free_rx_buf(rx_buf);
696 return len;
697}
698/*---------------------------------------------------------------------------*/
699static int
700pending_packet(void)
701{
702 handle_receive();
703
704 return has_packet();
705}
706/*---------------------------------------------------------------------------*/
707PROCESS_THREAD(efr32_radio_process, ev, data)
708{
709 int len;
710
712
713 while(1) {
714 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
715
716 if(pending_packet()) {
718 len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
719
720 if(len > 0) {
722 NETSTACK_MAC.input();
723 /* poll again to check if there is more to read out */
724 process_poll(&efr32_radio_process);
725 }
726 }
727 }
728 PROCESS_END();
729}
730/*---------------------------------------------------------------------------*/
731const struct radio_driver efr32_radio_driver = {
732 init,
733 prepare,
734 transmit,
735 send,
736 read,
740 on,
741 off,
742 get_value,
743 set_value,
746};
747/*---------------------------------------------------------------------------*/
GPIO HAL header file for the gecko.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
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_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_64BIT_ADDR
Long (64 bits) address for the radio, which is used by the address filter.
Definition: radio.h:263
@ 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_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_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
#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 logging system.
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
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