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