Skip to content

Update to EFR32 15.4 driver #6701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@
#define RF_QUEUE_SIZE 8
#endif

/* 802.15.4 maximum size of a single packet including PHY byte is 128 bytes */
#define MAC_PACKET_MAX_LENGTH 128
/* Offsets of prepended data in packet buffer */
#define MAC_PACKET_OFFSET_RSSI 0
#define MAC_PACKET_OFFSET_LQI 1
/* This driver prepends RSSI and LQI */
#define MAC_PACKET_INFO_LENGTH 2

/* RFThreadSignal used to signal from interrupts to the adaptor thread */
enum RFThreadSignal {
Expand All @@ -68,12 +75,12 @@ enum RFThreadSignal {
/* Adaptor thread definitions */
static void rf_thread_loop(const void *arg);
static osThreadDef(rf_thread_loop, osPriorityRealtime, RF_THREAD_STACK_SIZE);
static osThreadId rf_thread_id;
static osThreadId rf_thread_id = 0;

/* Queue for passing messages from interrupt to adaptor thread */
static volatile void* rx_queue[8];
static volatile size_t rx_queue_head;
static volatile size_t rx_queue_tail;
static volatile uint8_t rx_queue[RF_QUEUE_SIZE][MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
static volatile size_t rx_queue_head = 0;
static volatile size_t rx_queue_tail = 0;

/* Silicon Labs headers */
extern "C" {
Expand Down Expand Up @@ -123,7 +130,7 @@ static const RAIL_CsmaConfig_t csma_config = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_
#error "Not a valid target."
#endif

#ifdef MBED_CONF_SL_RAIL_HAS_SUBGIG
#if MBED_CONF_SL_RAIL_HAS_SUBGIG
static RAIL_ChannelConfigEntryAttr_t entry_868;
static RAIL_ChannelConfigEntryAttr_t entry_915;
static const RAIL_ChannelConfigEntry_t entry[] = {
Expand Down Expand Up @@ -151,7 +158,7 @@ static const RAIL_ChannelConfigEntry_t entry[] = {
#endif

#if MBED_CONF_SL_RAIL_BAND == 868
#ifndef MBED_CONF_SL_RAIL_HAS_SUBGIG
#if !MBED_CONF_SL_RAIL_HAS_SUBGIG
#error "Sub-Gigahertz band is not supported on this target."
#endif
static const RAIL_ChannelConfig_t channels = {
Expand All @@ -161,7 +168,7 @@ static const RAIL_ChannelConfig_t channels = {
1
};
#elif MBED_CONF_SL_RAIL_BAND == 915
#ifndef MBED_CONF_SL_RAIL_HAS_SUBGIG
#if !MBED_CONF_SL_RAIL_HAS_SUBGIG
#error "Sub-Gigahertz band is not supported on this target."
#endif
static const RAIL_ChannelConfig_t channels = {
Expand All @@ -187,7 +194,7 @@ static const RAIL_TxPowerConfig_t paInit2p4 = {
};
#endif

#if defined (MBED_CONF_SL_RAIL_HAS_SUBGIG)
#if MBED_CONF_SL_RAIL_HAS_SUBGIG
// Set up the PA for sub-GHz operation
static const RAIL_TxPowerConfig_t paInitSubGhz = {
.mode = RAIL_TX_POWER_MODE_SUBGIG,
Expand All @@ -210,9 +217,9 @@ static const RAIL_StateTiming_t timings = {
static const RAIL_IEEE802154_Config_t config = {
.addresses = NULL,
.ackConfig = {
.enable = true,
.ackTimeout = 1200,
.rxTransitions = {
.enable = true,
.ackTimeout = 1200,
.rxTransitions = {
.success = RAIL_RF_STATE_RX,
.error = RAIL_RF_STATE_RX // ignored
},
Expand Down Expand Up @@ -270,16 +277,13 @@ static void rf_thread_loop(const void *arg)
if (event.value.signals & SL_RX_DONE) {
while(rx_queue_tail != rx_queue_head) {
uint8_t* packet = (uint8_t*) rx_queue[rx_queue_tail];
SL_DEBUG_PRINT("rPKT %d\n", packet[2] - 2);
SL_DEBUG_PRINT("rPKT %d\n", packet[MAC_PACKET_INFO_LENGTH] - 2);
device_driver.phy_rx_cb(
&packet[3], /* Data payload for Nanostack starts at FCS */
packet[2] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
packet[1], /* LQI in second byte */
packet[0], /* RSSI in first byte */
&packet[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
packet[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
packet[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
packet[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
rf_radio_driver_id);

free(packet);
rx_queue[rx_queue_tail] = NULL;
rx_queue_tail = (rx_queue_tail + 1) % RF_QUEUE_SIZE;
}

Expand Down Expand Up @@ -887,6 +891,12 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
if (railHandle != gRailHandle)
return;

#ifdef MBED_CONF_RTOS_PRESENT
if(rf_thread_id == 0) {
return;
}
#endif

size_t index = 0;
do {
if (events & 1ull) {
Expand Down Expand Up @@ -956,43 +966,20 @@ static void radioEventHandler(RAIL_Handle_t railHandle,

/* Only process the packet if it had a correct CRC */
if(rxPacketInfo.packetStatus == RAIL_RX_PACKET_READY_SUCCESS) {
/* Get RSSI and LQI information about this packet */
RAIL_RxPacketDetails_t rxPacketDetails;
rxPacketDetails.timeReceived.timePosition = RAIL_PACKET_TIME_DEFAULT;
rxPacketDetails.timeReceived.totalPacketBytes = 0;
RAIL_GetRxPacketDetails(gRailHandle, rxHandle, &rxPacketDetails);

/* Allocate a contiguous buffer for this packet's payload */
uint8_t* packetBuffer = (uint8_t*) malloc(rxPacketInfo.packetBytes + 2);
if(packetBuffer == NULL) {
SL_DEBUG_PRINT("Out of memory\n");
break;
}

/* First two bytes are RSSI and LQI, respecitvely */
packetBuffer[0] = (uint8_t)rxPacketDetails.rssi;
packetBuffer[1] = (uint8_t)rxPacketDetails.lqi;

/* Copy packet payload from circular FIFO into contiguous memory */
memcpy(&packetBuffer[2], rxPacketInfo.firstPortionData, rxPacketInfo.firstPortionBytes);
if (rxPacketInfo.firstPortionBytes < rxPacketInfo.packetBytes) {
memcpy(&packetBuffer[2+rxPacketInfo.firstPortionBytes],
rxPacketInfo.lastPortionData,
rxPacketInfo.packetBytes - rxPacketInfo.firstPortionBytes);
}

/* Release RAIL resources early */
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
uint8_t header[4];
RAIL_PeekRxPacket(gRailHandle, rxHandle, header, 4, 0);

/* If this is an ACK, deal with it */
if( packetBuffer[2] == 5 &&
packetBuffer[2+3] == (current_tx_sequence) &&
/* If this is an ACK, deal with it early */
if( (header[0] == 5) &&
(header[3] == current_tx_sequence) &&
waiting_for_ack) {
/* Tell the radio to not ACK an ACK */
RAIL_CancelAutoAck(gRailHandle);
waiting_for_ack = false;
/* Save the pending bit */
last_ack_pending_bit = (packetBuffer[2+1] & (1 << 4)) != 0;
last_ack_pending_bit = (header[1] & (1 << 4)) != 0;
/* Release packet */
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
/* Tell the stack we got an ACK */
#ifdef MBED_CONF_RTOS_PRESENT
osSignalSet(rf_thread_id, SL_ACK_RECV | (last_ack_pending_bit ? SL_ACK_PEND : 0));
Expand All @@ -1004,8 +991,37 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
1,
1);
#endif
free(packetBuffer);
} else {
/* Get RSSI and LQI information about this packet */
RAIL_RxPacketDetails_t rxPacketDetails;
rxPacketDetails.timeReceived.timePosition = RAIL_PACKET_TIME_DEFAULT;
rxPacketDetails.timeReceived.totalPacketBytes = 0;
RAIL_GetRxPacketDetails(gRailHandle, rxHandle, &rxPacketDetails);

#ifdef MBED_CONF_RTOS_PRESENT
/* Drop this packet if we're out of space */
if (((rx_queue_head + 1) % RF_QUEUE_SIZE) == rx_queue_tail) {
osSignalSet(rf_thread_id, SL_QUEUE_FULL);
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);
break;
}

/* Copy into queue */
uint8_t* packetBuffer = (uint8_t*)rx_queue[rx_queue_head];
#else
/* Packet going temporarily onto stack for bare-metal apps */
uint8_t packetBuffer[MAC_PACKET_MAX_LENGTH + MAC_PACKET_INFO_LENGTH];
#endif
/* First two bytes are RSSI and LQI, respecitvely */
packetBuffer[MAC_PACKET_OFFSET_RSSI] = (uint8_t)rxPacketDetails.rssi;
packetBuffer[MAC_PACKET_OFFSET_LQI] = (uint8_t)rxPacketDetails.lqi;

/* Copy packet payload from circular FIFO into contiguous memory */
RAIL_CopyRxPacket(&packetBuffer[MAC_PACKET_INFO_LENGTH], &rxPacketInfo);

/* Release RAIL resources early */
RAIL_ReleaseRxPacket(gRailHandle, rxHandle);

/* Figure out whether we want to not ACK this packet */

/*
Expand All @@ -1015,27 +1031,20 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
* [1] => b[0:2] frame type, b[3] = security enabled, b[4] = frame pending, b[5] = ACKreq, b[6] = intrapan
* [2] => b[2:3] destmode, b[4:5] version, b[6:7] srcmode
*/
if( (packetBuffer[2+1] & (1 << 5)) == 0 ) {
if( (packetBuffer[MAC_PACKET_INFO_LENGTH + 1] & (1 << 5)) == 0 ) {
/* Cancel the ACK if the sender did not request one */
RAIL_CancelAutoAck(gRailHandle);
}
#ifdef MBED_CONF_RTOS_PRESENT
if (((rx_queue_head + 1) % RF_QUEUE_SIZE) != rx_queue_tail) {
rx_queue[rx_queue_head] = (void*)packetBuffer;
rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
osSignalSet(rf_thread_id, SL_RX_DONE);
} else {
free(packetBuffer);
osSignalSet(rf_thread_id, SL_QUEUE_FULL);
}
rx_queue_head = (rx_queue_head + 1) % RF_QUEUE_SIZE;
osSignalSet(rf_thread_id, SL_RX_DONE);
#else
SL_DEBUG_PRINT("rPKT %d\n", rxPacket[2] - 2);
device_driver.phy_rx_cb(&rxPacket[3], /* Data payload for Nanostack starts at FCS */
rxPacket[2] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
rxPacket[1], /* LQI in second byte */
rxPacket[0], /* RSSI in first byte */
SL_DEBUG_PRINT("rPKT %d\n", packetBuffer[MAC_PACKET_INFO_LENGTH] - 2);
device_driver.phy_rx_cb(&packetBuffer[MAC_PACKET_INFO_LENGTH + 1], /* Data payload for Nanostack starts at FCS */
packetBuffer[MAC_PACKET_INFO_LENGTH] - 2, /* Payload length is part of frame, but need to subtract CRC bytes */
packetBuffer[MAC_PACKET_OFFSET_LQI], /* LQI in second byte */
packetBuffer[MAC_PACKET_OFFSET_RSSI], /* RSSI in first byte */
rf_radio_driver_id);
free(packetBuffer);
#endif
}
}
Expand Down Expand Up @@ -1265,4 +1274,4 @@ static void radioEventHandler(RAIL_Handle_t railHandle,
index += 1;
}
while (events != 0);
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/***************************************************************************//**
* @file rail_ble.h
* @brief The BLE specific header file for the RAIL library.
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
* @copyright Copyright 2016 Silicon Laboratories, Inc. www.silabs.com
******************************************************************************/

#ifndef __RAIL_BLE_H__
Expand All @@ -14,48 +14,65 @@
// Get the RAIL specific structures and types
#include "rail_types.h"

/**
* @addtogroup BLE
* @ingroup Protocol_Specific
* Accelerator routines for Bluetooth Low Energy (BLE).
*
* The APIs in this module help take care of configuring the radio for BLE
* operation and provide some additional helper routines necessary for
* normal BLE send/receive that aren't available directly in RAIL. To initialize
* the radio you will still have to call RAIL_Init(). However
* RAIL_ConfigChannels(), and RAIL_ConfigRadio() will be taken care of for you.
*
* To implement a standard BLE link layer you will also need to handle tight
* turnaround times and send packets at specific instants. This can all be
* managed through general RAIL functions like RAIL_ScheduleTx(),
* RAIL_ScheduleRx(), and RAIL_SetStateTiming(). See the full RAIL API for more
* useful functions.
*
* A simple example of how to setup your application to be in BLE mode is shown
* below. Note that this will put the radio on the first advertising channel
* with the advertising Access Address. In any full featured BLE application you
* will need to use the RAIL_BLE_ConfigChannelRadioParams() function to change
* the sync word and other parameters as needed based on your connection.
*
* @code{.c}
*
* // Put the radio into receive on the first BLE advertising channel
* int bleAdvertiseEnable(void)
* {
* // Call the BLE initialization function to load the right radio config
* RAIL_BLE_Init();
*
* // Configure us for the first advertising channel (Physical: 0, Logical: 37)
* // The CRC init value and Access Address come from the BLE specification.
* RAIL_BLE_ConfigChannelRadioParams(0x555555, 0x8E89BED6, 37, false);
*
* // Start receiving on this channel (Physical: 0, Logical: 37)
* RAIL_StartRx(0);
* }
* @endcode
*
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif

/// @addtogroup BLE
/// @ingroup Protocol_Specific
/// Accelerator routines for Bluetooth Low Energy (BLE).
///
/// The APIs in this module help take care of configuring the radio for BLE
/// operation and provide some additional helper routines necessary for
/// normal BLE send/receive that aren't available directly in RAIL. All normal
/// RAIL APIs should be used to setup the application; however,
/// RAIL_ConfigChannels() and RAIL_ConfigRadio() should not be called to setup
/// the PHY. Instead, the RAIL_BLE_Config* APIs should be used to setup the
/// 1Mbps, 2Mbps, or Coded PHY configuration needed by the application. These
/// APIs will configure the hardware and also configure the set of valid BLE
/// channels.
///
/// To implement a standard BLE link layer you will also need to handle tight
/// turnaround times and send packets at specific instants. This can all be
/// managed through general RAIL functions like RAIL_ScheduleTx(),
/// RAIL_ScheduleRx(), and RAIL_SetStateTiming(). See the full RAIL API for more
/// useful functions.
///
/// A simple example of how to setup your application to be in BLE mode is shown
/// below. Note that this will put the radio on the first advertising channel
/// with the advertising Access Address. In any full featured BLE application you
/// will need to use the RAIL_BLE_ConfigChannelRadioParams() function to change
/// the sync word and other parameters as needed based on your connection.
///
/// @code{.c}
///
/// // RAIL Handle set at init time
/// static RAIL_Handle_t railHandle = NULL;
///
/// // Put the radio into receive on the first BLE advertising channel
/// int bleAdvertiseEnable(void)
/// {
/// // Call the BLE initialization function to load the right radio config
/// RAIL_BLE_Init(railHandle);
///
/// // Always choose the Viterbi PHY configuration if available on your chip
/// // for performance reasons.
/// RAIL_BLE_ConfigPhy1MbpsViterbi(railHandle);
///
/// // Configure us for the first advertising channel (Physical: 0, Logical: 37)
/// // The CRC init value and Access Address come from the BLE specification.
/// RAIL_BLE_ConfigChannelRadioParams(railHandle,
/// 0x555555,
/// 0x8E89BED6,
/// 37,
/// false);
///
/// // Start receiving on physical channel 0 (logical channel 37)
/// RAIL_StartRx(railHandle, 0, NULL);
/// }
/// @endcode
///
/// @{

/**
* @enum RAIL_BLE_Coding_t
Expand Down Expand Up @@ -175,7 +192,7 @@ RAIL_Status_t RAIL_BLE_ConfigPhy2Mbps(RAIL_Handle_t railHandle);
* Switch to the BLE Coded PHY.
*
* @param[in] railHandle Handle for RAIL instance.
* @param[in] ble_coding The RAIL_BLE_Coding_t to use
* @param[in] bleCoding The RAIL_BLE_Coding_t to use
* @return Status code indicating success of the function call.
*
* You can use this function to switch back to BLE Coded PHY from the default
Expand All @@ -188,7 +205,7 @@ RAIL_Status_t RAIL_BLE_ConfigPhy2Mbps(RAIL_Handle_t railHandle);
* manual to be sure that it does before trying this.
*/
RAIL_Status_t RAIL_BLE_ConfigPhyCoded(RAIL_Handle_t railHandle,
RAIL_BLE_Coding_t ble_coding);
RAIL_BLE_Coding_t bleCoding);

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

/** @} */ // end of BLE

#ifdef __cplusplus
}
#endif

#endif // __RAIL_BLE_H__
Loading