Skip to content

Commit 640af76

Browse files
stevew817adbridge
authored andcommitted
Update to EFR32 15.4 driver
* Updates driver library to v2.3.1 (2018q1) for bugfixes and convenience functions * Provides library in correct format (2-byte wchar_t flag) for compiling with ARMCC (#6695 uncovered by #6577) * Reverts to using a statically-allocated packet buffer since malloc is not thread-safe (and the asserts have been turned on)
1 parent 7165f31 commit 640af76

File tree

14 files changed

+2211
-1376
lines changed

14 files changed

+2211
-1376
lines changed

features/nanostack/FEATURE_NANOSTACK/targets/TARGET_SL_RAIL/NanostackRfPhyEfr32.cpp

Lines changed: 76 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
#define RF_QUEUE_SIZE 8
4747
#endif
4848

49+
/* 802.15.4 maximum size of a single packet including PHY byte is 128 bytes */
50+
#define MAC_PACKET_MAX_LENGTH 128
51+
/* Offsets of prepended data in packet buffer */
52+
#define MAC_PACKET_OFFSET_RSSI 0
53+
#define MAC_PACKET_OFFSET_LQI 1
54+
/* This driver prepends RSSI and LQI */
55+
#define MAC_PACKET_INFO_LENGTH 2
4956

5057
/* RFThreadSignal used to signal from interrupts to the adaptor thread */
5158
enum RFThreadSignal {
@@ -68,12 +75,12 @@ enum RFThreadSignal {
6875
/* Adaptor thread definitions */
6976
static void rf_thread_loop(const void *arg);
7077
static osThreadDef(rf_thread_loop, osPriorityRealtime, RF_THREAD_STACK_SIZE);
71-
static osThreadId rf_thread_id;
78+
static osThreadId rf_thread_id = 0;
7279

7380
/* Queue for passing messages from interrupt to adaptor thread */
74-
static volatile void* rx_queue[8];
75-
static volatile size_t rx_queue_head;
76-
static volatile size_t rx_queue_tail;
81+
static volatile uint8_t rx_queue[RF_QUEUE_SIZE][MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
82+
static volatile size_t rx_queue_head = 0;
83+
static volatile size_t rx_queue_tail = 0;
7784

7885
/* Silicon Labs headers */
7986
extern "C" {
@@ -123,7 +130,7 @@ static const RAIL_CsmaConfig_t csma_config = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_
123130
#error "Not a valid target."
124131
#endif
125132

126-
#ifdef MBED_CONF_SL_RAIL_HAS_SUBGIG
133+
#if MBED_CONF_SL_RAIL_HAS_SUBGIG
127134
static RAIL_ChannelConfigEntryAttr_t entry_868;
128135
static RAIL_ChannelConfigEntryAttr_t entry_915;
129136
static const RAIL_ChannelConfigEntry_t entry[] = {
@@ -151,7 +158,7 @@ static const RAIL_ChannelConfigEntry_t entry[] = {
151158
#endif
152159

153160
#if MBED_CONF_SL_RAIL_BAND == 868
154-
#ifndef MBED_CONF_SL_RAIL_HAS_SUBGIG
161+
#if !MBED_CONF_SL_RAIL_HAS_SUBGIG
155162
#error "Sub-Gigahertz band is not supported on this target."
156163
#endif
157164
static const RAIL_ChannelConfig_t channels = {
@@ -161,7 +168,7 @@ static const RAIL_ChannelConfig_t channels = {
161168
1
162169
};
163170
#elif MBED_CONF_SL_RAIL_BAND == 915
164-
#ifndef MBED_CONF_SL_RAIL_HAS_SUBGIG
171+
#if !MBED_CONF_SL_RAIL_HAS_SUBGIG
165172
#error "Sub-Gigahertz band is not supported on this target."
166173
#endif
167174
static const RAIL_ChannelConfig_t channels = {
@@ -187,7 +194,7 @@ static const RAIL_TxPowerConfig_t paInit2p4 = {
187194
};
188195
#endif
189196

190-
#if defined (MBED_CONF_SL_RAIL_HAS_SUBGIG)
197+
#if MBED_CONF_SL_RAIL_HAS_SUBGIG
191198
// Set up the PA for sub-GHz operation
192199
static const RAIL_TxPowerConfig_t paInitSubGhz = {
193200
.mode = RAIL_TX_POWER_MODE_SUBGIG,
@@ -210,9 +217,9 @@ static const RAIL_StateTiming_t timings = {
210217
static const RAIL_IEEE802154_Config_t config = {
211218
.addresses = NULL,
212219
.ackConfig = {
213-
.enable = true,
214-
.ackTimeout = 1200,
215-
.rxTransitions = {
220+
.enable = true,
221+
.ackTimeout = 1200,
222+
.rxTransitions = {
216223
.success = RAIL_RF_STATE_RX,
217224
.error = RAIL_RF_STATE_RX // ignored
218225
},
@@ -270,16 +277,13 @@ static void rf_thread_loop(const void *arg)
270277
if (event.value.signals & SL_RX_DONE) {
271278
while(rx_queue_tail != rx_queue_head) {
272279
uint8_t* packet = (uint8_t*) rx_queue[rx_queue_tail];
273-
SL_DEBUG_PRINT("rPKT %d\n", packet[2] - 2);
280+
SL_DEBUG_PRINT("rPKT %d\n", packet[MAC_PACKET_INFO_LENGTH] - 2);
274281
device_driver.phy_rx_cb(
275-
&packet[3], /* Data payload for Nanostack starts at FCS */
276-
packet[2] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
277-
packet[1], /* LQI in second byte */
278-
packet[0], /* RSSI in first byte */
282+
&packet[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
283+
packet[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
284+
packet[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
285+
packet[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
279286
rf_radio_driver_id);
280-
281-
free(packet);
282-
rx_queue[rx_queue_tail] = NULL;
283287
rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE;
284288
}
285289

@@ -887,6 +891,12 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
887891
if (railHandle != gRailHandle)
888892
return;
889893

894+
#ifdef MBED_CONF_RTOS_PRESENT
895+
if(rf_thread_id == 0) {
896+
return;
897+
}
898+
#endif
899+
890900
size_t index = 0;
891901
do {
892902
if (events & 1ull) {
@@ -956,43 +966,20 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
956966

957967
/* Only process the packet if it had a correct CRC */
958968
if(rxPacketInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS) {
959-
/* Get RSSI and LQI information about this packet */
960-
RAIL_RxPacketDetails_t rxPacketDetails;
961-
rxPacketDetails.timeReceived.timePosition = RAIL_PACKET_TIME_DEFAULT;
962-
rxPacketDetails.timeReceived.totalPacketBytes = 0;
963-
RAIL_GetRxPacketDetails(gRailHandle, rxHandle, &rxPacketDetails);
964-
965-
/* Allocate a contiguous buffer for this packet's payload */
966-
uint8_t* packetBuffer = (uint8_t*) malloc(rxPacketInfo.packetBytes + 2);
967-
if(packetBuffer == NULL) {
968-
SL_DEBUG_PRINT("Out of memory\n");
969-
break;
970-
}
971-
972-
/* First two bytes are RSSI and LQI, respecitvely */
973-
packetBuffer[0] = (uint8_t)rxPacketDetails.rssi;
974-
packetBuffer[1] = (uint8_t)rxPacketDetails.lqi;
975-
976-
/* Copy packet payload from circular FIFO into contiguous memory */
977-
memcpy(&packetBuffer[2], rxPacketInfo.firstPortionData, rxPacketInfo.firstPortionBytes);
978-
if (rxPacketInfo.firstPortionBytes < rxPacketInfo.packetBytes) {
979-
memcpy(&packetBuffer[2+rxPacketInfo.firstPortionBytes],
980-
rxPacketInfo.lastPortionData,
981-
rxPacketInfo.packetBytes - rxPacketInfo.firstPortionBytes);
982-
}
983-
984-
/* Release RAIL resources early */
985-
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
969+
uint8_t header[4];
970+
RAIL_PeekRxPacket(gRailHandle, rxHandle, header, 4, 0);
986971

987-
/* If this is an ACK, deal with it */
988-
if( packetBuffer[2] == 5 &&
989-
packetBuffer[2+3] == (current_tx_sequence) &&
972+
/* If this is an ACK, deal with it early */
973+
if( (header[0] == 5) &&
974+
(header[3] == current_tx_sequence) &&
990975
waiting_for_ack) {
991976
/* Tell the radio to not ACK an ACK */
992977
RAIL_CancelAutoAck(gRailHandle);
993978
waiting_for_ack = false;
994979
/* Save the pending bit */
995-
last_ack_pending_bit = (packetBuffer[2+1] & (1 << 4)) != 0;
980+
last_ack_pending_bit = (header[1] & (1 << 4)) != 0;
981+
/* Release packet */
982+
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
996983
/* Tell the stack we got an ACK */
997984
#ifdef MBED_CONF_RTOS_PRESENT
998985
osSignalSet(rf_thread_id, SL_ACK_RECV | (last_ack_pending_bit ? SL_ACK_PEND : 0));
@@ -1004,8 +991,37 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
1004991
1,
1005992
1);
1006993
#endif
1007-
free(packetBuffer);
1008994
} else {
995+
/* Get RSSI and LQI information about this packet */
996+
RAIL_RxPacketDetails_t rxPacketDetails;
997+
rxPacketDetails.timeReceived.timePosition = RAIL_PACKET_TIME_DEFAULT;
998+
rxPacketDetails.timeReceived.totalPacketBytes = 0;
999+
RAIL_GetRxPacketDetails(gRailHandle, rxHandle, &rxPacketDetails);
1000+
1001+
#ifdef MBED_CONF_RTOS_PRESENT
1002+
/* Drop this packet if we're out of space */
1003+
if (((rx_queue_head + 1) % RF_QUEUE_SIZE) == rx_queue_tail) {
1004+
osSignalSet(rf_thread_id, SL_QUEUE_FULL);
1005+
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
1006+
break;
1007+
}
1008+
1009+
/* Copy into queue */
1010+
uint8_t* packetBuffer = (uint8_t*)rx_queue[rx_queue_head];
1011+
#else
1012+
/* Packet going temporarily onto stack for bare-metal apps */
1013+
uint8_t packetBuffer[MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
1014+
#endif
1015+
/* First two bytes are RSSI and LQI, respecitvely */
1016+
packetBuffer[MAC_PACKET_OFFSET_RSSI] = (uint8_t)rxPacketDetails.rssi;
1017+
packetBuffer[MAC_PACKET_OFFSET_LQI] = (uint8_t)rxPacketDetails.lqi;
1018+
1019+
/* Copy packet payload from circular FIFO into contiguous memory */
1020+
RAIL_CopyRxPacket(&packetBuffer[MAC_PACKET_INFO_LENGTH], &rxPacketInfo);
1021+
1022+
/* Release RAIL resources early */
1023+
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
1024+
10091025
/* Figure out whether we want to not ACK this packet */
10101026

10111027
/*
@@ -1015,27 +1031,20 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
10151031
* [1] => b[0:2] frame type, b[3] = security enabled, b[4] = frame pending, b[5] = ACKreq, b[6] = intrapan
10161032
* [2] => b[2:3] destmode, b[4:5] version, b[6:7] srcmode
10171033
*/
1018-
if( (packetBuffer[2+1] & (1 << 5)) == 0 ) {
1034+
if( (packetBuffer[MAC_PACKET_INFO_LENGTH + 1] & (1 << 5)) == 0 ) {
10191035
/* Cancel the ACK if the sender did not request one */
10201036
RAIL_CancelAutoAck(gRailHandle);
10211037
}
10221038
#ifdef MBED_CONF_RTOS_PRESENT
1023-
if (((rx_queue_head + 1) % RF_QUEUE_SIZE) != rx_queue_tail) {
1024-
rx_queue[rx_queue_head] = (void*)packetBuffer;
1025-
rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
1026-
osSignalSet(rf_thread_id, SL_RX_DONE);
1027-
} else {
1028-
free(packetBuffer);
1029-
osSignalSet(rf_thread_id, SL_QUEUE_FULL);
1030-
}
1039+
rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
1040+
osSignalSet(rf_thread_id, SL_RX_DONE);
10311041
#else
1032-
SL_DEBUG_PRINT("rPKT %d\n", rxPacket[2] - 2);
1033-
device_driver.phy_rx_cb(&rxPacket[3], /* Data payload for Nanostack starts at FCS */
1034-
rxPacket[2] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
1035-
rxPacket[1], /* LQI in second byte */
1036-
rxPacket[0], /* RSSI in first byte */
1042+
SL_DEBUG_PRINT("rPKT %d\n", packetBuffer[MAC_PACKET_INFO_LENGTH] - 2);
1043+
device_driver.phy_rx_cb(&packetBuffer[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
1044+
packetBuffer[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
1045+
packetBuffer[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
1046+
packetBuffer[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
10371047
rf_radio_driver_id);
1038-
free(packetBuffer);
10391048
#endif
10401049
}
10411050
}
@@ -1265,4 +1274,4 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
12651274
index += 1;
12661275
}
12671276
while (events != 0);
1268-
}
1277+
}

targets/TARGET_Silicon_Labs/TARGET_SL_RAIL/efr32-rf-driver/rail/ble/rail_ble.h

100644100755
Lines changed: 66 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/***************************************************************************//**
22
* @file rail_ble.h
33
* @brief The BLE specific header file for the RAIL library.
4-
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
4+
* @copyright Copyright 2016 Silicon Laboratories, Inc. www.silabs.com
55
******************************************************************************/
66

77
#ifndef __RAIL_BLE_H__
@@ -14,48 +14,65 @@
1414
// Get the RAIL specific structures and types
1515
#include "rail_types.h"
1616

17-
/**
18-
* @addtogroup BLE
19-
* @ingroup Protocol_Specific
20-
* Accelerator routines for Bluetooth Low Energy (BLE).
21-
*
22-
* The APIs in this module help take care of configuring the radio for BLE
23-
* operation and provide some additional helper routines necessary for
24-
* normal BLE send/receive that aren't available directly in RAIL. To initialize
25-
* the radio you will still have to call RAIL_Init(). However
26-
* RAIL_ConfigChannels(), and RAIL_ConfigRadio() will be taken care of for you.
27-
*
28-
* To implement a standard BLE link layer you will also need to handle tight
29-
* turnaround times and send packets at specific instants. This can all be
30-
* managed through general RAIL functions like RAIL_ScheduleTx(),
31-
* RAIL_ScheduleRx(), and RAIL_SetStateTiming(). See the full RAIL API for more
32-
* useful functions.
33-
*
34-
* A simple example of how to setup your application to be in BLE mode is shown
35-
* below. Note that this will put the radio on the first advertising channel
36-
* with the advertising Access Address. In any full featured BLE application you
37-
* will need to use the RAIL_BLE_ConfigChannelRadioParams() function to change
38-
* the sync word and other parameters as needed based on your connection.
39-
*
40-
* @code{.c}
41-
*
42-
* // Put the radio into receive on the first BLE advertising channel
43-
* int bleAdvertiseEnable(void)
44-
* {
45-
* // Call the BLE initialization function to load the right radio config
46-
* RAIL_BLE_Init();
47-
*
48-
* // Configure us for the first advertising channel (Physical: 0, Logical: 37)
49-
* // The CRC init value and Access Address come from the BLE specification.
50-
* RAIL_BLE_ConfigChannelRadioParams(0x555555, 0x8E89BED6, 37, false);
51-
*
52-
* // Start receiving on this channel (Physical: 0, Logical: 37)
53-
* RAIL_StartRx(0);
54-
* }
55-
* @endcode
56-
*
57-
* @{
58-
*/
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
/// @addtogroup BLE
22+
/// @ingroup Protocol_Specific
23+
/// Accelerator routines for Bluetooth Low Energy (BLE).
24+
///
25+
/// The APIs in this module help take care of configuring the radio for BLE
26+
/// operation and provide some additional helper routines necessary for
27+
/// normal BLE send/receive that aren't available directly in RAIL. All normal
28+
/// RAIL APIs should be used to setup the application; however,
29+
/// RAIL_ConfigChannels() and RAIL_ConfigRadio() should not be called to setup
30+
/// the PHY. Instead, the RAIL_BLE_Config* APIs should be used to setup the
31+
/// 1Mbps, 2Mbps, or Coded PHY configuration needed by the application. These
32+
/// APIs will configure the hardware and also configure the set of valid BLE
33+
/// channels.
34+
///
35+
/// To implement a standard BLE link layer you will also need to handle tight
36+
/// turnaround times and send packets at specific instants. This can all be
37+
/// managed through general RAIL functions like RAIL_ScheduleTx(),
38+
/// RAIL_ScheduleRx(), and RAIL_SetStateTiming(). See the full RAIL API for more
39+
/// useful functions.
40+
///
41+
/// A simple example of how to setup your application to be in BLE mode is shown
42+
/// below. Note that this will put the radio on the first advertising channel
43+
/// with the advertising Access Address. In any full featured BLE application you
44+
/// will need to use the RAIL_BLE_ConfigChannelRadioParams() function to change
45+
/// the sync word and other parameters as needed based on your connection.
46+
///
47+
/// @code{.c}
48+
///
49+
/// // RAIL Handle set at init time
50+
/// static RAIL_Handle_t railHandle = NULL;
51+
///
52+
/// // Put the radio into receive on the first BLE advertising channel
53+
/// int bleAdvertiseEnable(void)
54+
/// {
55+
/// // Call the BLE initialization function to load the right radio config
56+
/// RAIL_BLE_Init(railHandle);
57+
///
58+
/// // Always choose the Viterbi PHY configuration if available on your chip
59+
/// // for performance reasons.
60+
/// RAIL_BLE_ConfigPhy1MbpsViterbi(railHandle);
61+
///
62+
/// // Configure us for the first advertising channel (Physical: 0, Logical: 37)
63+
/// // The CRC init value and Access Address come from the BLE specification.
64+
/// RAIL_BLE_ConfigChannelRadioParams(railHandle,
65+
/// 0x555555,
66+
/// 0x8E89BED6,
67+
/// 37,
68+
/// false);
69+
///
70+
/// // Start receiving on physical channel 0 (logical channel 37)
71+
/// RAIL_StartRx(railHandle, 0, NULL);
72+
/// }
73+
/// @endcode
74+
///
75+
/// @{
5976

6077
/**
6178
* @enum RAIL_BLE_Coding_t
@@ -175,7 +192,7 @@ RAIL_Status_t RAIL_BLE_ConfigPhy2Mbps(RAIL_Handle_t railHandle);
175192
* Switch to the BLE Coded PHY.
176193
*
177194
* @param[in] railHandle Handle for RAIL instance.
178-
* @param[in] ble_coding The RAIL_BLE_Coding_t to use
195+
* @param[in] bleCoding The RAIL_BLE_Coding_t to use
179196
* @return Status code indicating success of the function call.
180197
*
181198
* You can use this function to switch back to BLE Coded PHY from the default
@@ -188,7 +205,7 @@ RAIL_Status_t RAIL_BLE_ConfigPhy2Mbps(RAIL_Handle_t railHandle);
188205
* manual to be sure that it does before trying this.
189206
*/
190207
RAIL_Status_t RAIL_BLE_ConfigPhyCoded(RAIL_Handle_t railHandle,
191-
RAIL_BLE_Coding_t ble_coding);
208+
RAIL_BLE_Coding_t bleCoding);
192209

193210
/**
194211
* Helper function to change BLE radio parameters.
@@ -215,4 +232,8 @@ RAIL_Status_t RAIL_BLE_ConfigChannelRadioParams(RAIL_Handle_t railHandle,
215232

216233
/** @} */ // end of BLE
217234

235+
#ifdef __cplusplus
236+
}
237+
#endif
238+
218239
#endif // __RAIL_BLE_H__

0 commit comments

Comments
 (0)