[EFR32] Initial radio driver

First check-in of the EFR32 radio driver for Nanostack
pull/3157/head
Steven Cooreman 2016-10-27 23:29:31 -07:00
parent c0301b15d2
commit 01446f347f
21 changed files with 4635 additions and 0 deletions

View File

@ -0,0 +1,2 @@
Unless specifically indicated otherwise in a file, files are licensed
under the Apache 2.0 license, as can be found in: apache-2.0.txt

View File

@ -0,0 +1,6 @@
# Example 802.15.4 RF driver for Silicon Labs EFR32 Wireless SoCs #
Support for:
* EFR32MG1X
This driver is used with the mbed 6LoWPAN stack.

View File

@ -0,0 +1,56 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,102 @@
/***************************************************************************//**
* @file buffer_pool_allocator.c
* @brief The source for a simple memory allocator that statically creates pools
* of fixed size buffers to allocate from.
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#include <stdlib.h>
#include "buffer_pool_allocator.h"
#include "em_int.h"
#ifdef CONFIGURATION_HEADER
#include CONFIGURATION_HEADER
#endif
// -----------------------------------------------------------------------------
// Configuration Macros
// -----------------------------------------------------------------------------
// Default to a ping-pong buffer pool with a size of 128 (127 MTU + 1 length) bytes per buffer
#ifndef BUFFER_POOL_SIZE
#define BUFFER_POOL_SIZE 2
#endif
#ifndef MAX_BUFFER_SIZE
#define MAX_BUFFER_SIZE 128
#endif
#define INVALID_BUFFER_OBJ ((void*)0xFFFFFFFF)
typedef struct {
uint8_t refCount;
uint8_t data[MAX_BUFFER_SIZE];
} BufferPoolObj_t;
static BufferPoolObj_t memoryObjs[BUFFER_POOL_SIZE];
void* memoryAllocate(uint32_t size)
{
uint32_t i = 0;
void *handle = INVALID_BUFFER_OBJ;
// We can't support sizes greater than the maximum heap buffer size
if(size > MAX_BUFFER_SIZE) {
return INVALID_BUFFER_OBJ;
}
INT_Disable();
for(i = 0; i < BUFFER_POOL_SIZE; i++)
{
if(memoryObjs[i].refCount == 0)
{
memoryObjs[i].refCount = 1;
handle = (void*)i;
break;
}
}
INT_Enable();
return handle;
}
void *memoryPtrFromHandle(void *handle)
{
void *ptr = NULL;
// Make sure we were given a valid handle
if((handle == INVALID_BUFFER_OBJ) || ((uint32_t)handle > BUFFER_POOL_SIZE))
{
return NULL;
}
INT_Disable();
if(memoryObjs[(uint32_t)handle].refCount > 0)
{
ptr = memoryObjs[(uint32_t)handle].data;
}
INT_Enable();
return ptr;
}
void memoryFree(void *handle)
{
INT_Disable();
if(memoryPtrFromHandle(handle) != NULL)
{
memoryObjs[(uint32_t)handle].refCount--;
}
INT_Enable();
}
void memoryTakeReference(void *handle)
{
INT_Disable();
if(memoryPtrFromHandle(handle) != NULL)
{
memoryObjs[(uint32_t)handle].refCount++;
}
INT_Enable();
}

View File

@ -0,0 +1,51 @@
/***************************************************************************//**
* @file buffer_pool_allocator.h
* @brief This is a simple memory allocator that uses a build time defined pool
* of constant sized buffers. It's a very simple allocator, but one that can
* be easily used in any application.
*
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef BUFFER_POOL_ALLOCATOR_H__
#define BUFFER_POOL_ALLOCATOR_H__
// Get the standard include types
#include <stdint.h>
/**
* Allocate a buffer with at least the number of bytes specified. If there is
* not enough space then this function will return NULL.
* @param size The number of bytes to allocate for this buffer
* @return Returns a handle to a buffer at least size bytes long or NULL if no
* buffer could be allocated.
*/
void* memoryAllocate(uint32_t size);
/**
* Free the buffer pointed to by handle. This will only decrement the reference
* counter for this buffer. The memory is not freed until the reference counter
* reaches zero.
* @param handle The handle to free. Must match the value returned by
* the memoryAllocate() function.
*/
void memoryFree(void *handle);
/**
* Take a memory handle and get the data pointer associated with it. This will
* return NULL if passed an invalid or unallocated handle.
* @param handle The handle to get the pointer for. Must match the value
* returned by the memoryAllocate() function.
*/
void *memoryPtrFromHandle(void *handle);
/**
* Increment the reference counter on the memory pointed to by handle. After
* doing this there will have to be an additional call to memoryFree() to
* release the memory.
* @param handle The handle to the object which needs its reference count
* increased. Must match the value returned by the memoryAllocate() function.
*/
void memoryTakeReference(void *handle);
#endif // BUFFER_POOL_ALLOCATOR_H__

View File

@ -0,0 +1,35 @@
/***************************************************************************//**
* @file rail_integration.c
* @brief Simple code to link this memory manager with a RAIL application by
* implementing the appropriate callbacks.
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#include <stdint.h>
#include "rail.h"
#include "buffer_pool_allocator.h"
/// Rely on the pool allocator's allocate function to get memory
void *RAILCb_AllocateMemory(uint32_t size)
{
return memoryAllocate(size);
}
/// Use the pool allocator's free function to return the memory to the pool
void RAILCb_FreeMemory(void *ptr)
{
memoryFree(ptr);
}
/// Get the memory pointer for this handle and offset into it as requested
void *RAILCb_BeginWriteMemory(void *handle,
uint32_t offset,
uint32_t *available)
{
return ((uint8_t*)memoryPtrFromHandle(handle)) + offset;
}
/// We don't need to track the completion of a memory write so do nothing
void RAILCb_EndWriteMemory(void *handle, uint32_t offset, uint32_t size)
{
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016 Silicon Laboratories, Inc. http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NANOSTACK_PHY_EFR32_H_
#define NANOSTACK_PHY_EFR32_H_
#include "mbed.h"
#include "NanostackRfPhy.h"
class NanostackRfPhyEfr32 : public NanostackRfPhy {
public:
NanostackRfPhyEfr32();
~NanostackRfPhyEfr32();
int8_t rf_register();
void rf_unregister();
void get_mac_address(uint8_t *mac);
void set_mac_address(uint8_t *mac);
uint32_t get_driver_version();
};
#endif /* NANOSTACK_PHY_EFR32_H_ */

View File

@ -0,0 +1,103 @@
/***************************************************************************//**
* @brief RAIL Configuration
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
//=============================================================================
//
// WARNING: Auto-Generated Radio Config - DO NOT EDIT
//
//=============================================================================
#include <stdint.h>
const uint32_t ieee802154_config_base[] = {
0x01010FF4UL, 0x00000000UL,
0x01010FF8UL, 0x0003C000UL,
0x01010FFCUL, 0x0003C00EUL,
0x00010004UL, 0x00157001UL,
0x00010008UL, 0x0000007FUL,
0x00010018UL, 0x00000000UL,
0x0001001CUL, 0x00000000UL,
0x00010028UL, 0x00000000UL,
0x0001002CUL, 0x00000000UL,
0x00010030UL, 0x00000000UL,
0x00010034UL, 0x00000000UL,
0x0001003CUL, 0x00000000UL,
0x00010040UL, 0x000007A0UL,
0x00010048UL, 0x00000000UL,
0x00010054UL, 0x00000000UL,
0x00010058UL, 0x00000000UL,
0x000100A0UL, 0x00004000UL,
0x000100A4UL, 0x00004CFFUL,
0x000100A8UL, 0x00004100UL,
0x000100ACUL, 0x00004DFFUL,
0x00012000UL, 0x00000704UL,
0x00012010UL, 0x00000000UL,
0x00012018UL, 0x00008408UL,
0x00013008UL, 0x0000AC3FUL,
0x0001302CUL, 0x01F50AAAUL,
0x00013030UL, 0x00104924UL,
0x00013034UL, 0x00000001UL,
0x0001303CUL, 0x00010AABUL,
0x00013040UL, 0x00000000UL,
0x000140A0UL, 0x0F00277AUL,
0x000140F4UL, 0x00001020UL,
0x00014134UL, 0x00000880UL,
0x00014138UL, 0x000087E6UL,
0x00014140UL, 0x0088006DUL,
0x00014144UL, 0x1153E6C0UL,
0x00016014UL, 0x00000010UL,
0x00016018UL, 0x0413F920UL,
0x0001601CUL, 0x0052C007UL,
0x00016020UL, 0x000000C8UL,
0x00016024UL, 0x00000000UL,
0x00016028UL, 0x03000000UL,
0x0001602CUL, 0x00000000UL,
0x00016030UL, 0x00FF0264UL,
0x00016034UL, 0x000008A2UL,
0x00016038UL, 0x00000001UL,
0x0001603CUL, 0x000807B0UL,
0x00016040UL, 0x000000A7UL,
0x00016044UL, 0x00000000UL,
0x00016048UL, 0x0AC00141UL,
0x0001604CUL, 0x744AC39BUL,
0x00016050UL, 0x000003F0UL,
0x00016054UL, 0x00000000UL,
0x00016058UL, 0x00000000UL,
0x0001605CUL, 0x30100101UL,
0x00016060UL, 0x7F7F7050UL,
0x00016064UL, 0x00000000UL,
0x00017014UL, 0x000270FAUL,
0x00017018UL, 0x00001800UL,
0x0001701CUL, 0x82840000UL,
0x00017028UL, 0x01800000UL,
0x00017048UL, 0x00003D3CUL,
0x0001704CUL, 0x000019BCUL,
0x00017070UL, 0x00010103UL,
0x00017074UL, 0x00000442UL,
0x00017078UL, 0x00552300UL,
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_base_min[] = {
0x01010FFCUL, 0x0003C00EUL,
0x0001303CUL, 0x00010AABUL,
0x00016034UL, 0x000008A2UL,
0x00016038UL, 0x00000001UL,
0x00017078UL, 0x00552300UL,
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_2415MHz_min[] = {
0x01010FFCUL, 0x0003C00AUL,
0x0001303CUL, 0x00003555UL,
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_2420MHz_min[] = {
0x0001303CUL, 0x00003555UL,
0x00016034UL, 0x000004A1UL,
0x00016038UL, 0x00000009UL,
0x00017078UL, 0x0049E006UL,
0xFFFFFFFFUL,
};

View File

@ -0,0 +1,18 @@
/***************************************************************************//**
* @file ieee802154_config.h
* @brief IEEE802154 Configuration
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __IEEE802154_EFR32XG1_CONFIGURATOR_OUT_H__
#define __IEEE802154_EFR32XG1_CONFIGURATOR_OUT_H__
#include <stdint.h>
extern const uint32_t ieee802154_config_base[];
extern const uint32_t ieee802154_config_base_min[];
extern const uint32_t ieee802154_config_2415MHz_min[];
extern const uint32_t ieee802154_config_2420MHz_min[];
#endif // __IEEE802154_EFR32XG1_CONFIGURATOR_OUT_H__

View File

@ -0,0 +1,155 @@
/***************************************************************************//**
* @brief RAIL Configuration
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
//=============================================================================
//
// WARNING: Auto-Generated Radio Config - DO NOT EDIT
//
//=============================================================================
#include <stdint.h>
const uint32_t ieee802154_config_863[] = {
0x01010FF4UL, 0x00000000UL,
0x01010FF8UL, 0x0003C000UL,
0x01010FFCUL, 0x0003C008UL,
0x00010004UL, 0x00157001UL,
0x00010008UL, 0x0000007FUL,
0x00010018UL, 0x00000000UL,
0x0001001CUL, 0x00000000UL,
0x00010028UL, 0x00000000UL,
0x0001002CUL, 0x00000000UL,
0x00010030UL, 0x00000000UL,
0x00010034UL, 0x00000000UL,
0x0001003CUL, 0x00000000UL,
0x00010040UL, 0x000007A0UL,
0x00010048UL, 0x00000000UL,
0x00010054UL, 0x00000000UL,
0x00010058UL, 0x00000000UL,
0x000100A0UL, 0x00004000UL,
0x000100A4UL, 0x00004CFFUL,
0x000100A8UL, 0x00004100UL,
0x000100ACUL, 0x00004DFFUL,
0x00012000UL, 0x00000704UL,
0x00012010UL, 0x00000000UL,
0x00012018UL, 0x00008408UL,
0x00013008UL, 0x0000AC3FUL,
0x0001302CUL, 0x021EB000UL,
0x00013030UL, 0x00108000UL,
0x00013034UL, 0x00000003UL,
0x0001303CUL, 0x00014000UL,
0x00013040UL, 0x00000000UL,
0x000140A0UL, 0x0F00277AUL,
0x000140F4UL, 0x00001020UL,
0x00014134UL, 0x00000880UL,
0x00014138UL, 0x000087F6UL,
0x00014140UL, 0x00880048UL,
0x00014144UL, 0x1153E6C0UL,
0x00016014UL, 0x00000010UL,
0x00016018UL, 0x04127920UL,
0x0001601CUL, 0x0051C007UL,
0x00016020UL, 0x000000C2UL,
0x00016024UL, 0x00000000UL,
0x00016028UL, 0x03000000UL,
0x0001602CUL, 0x00000000UL,
0x00016030UL, 0x00FF0BF4UL,
0x00016034UL, 0x00000C20UL,
0x00016038UL, 0x0102000AUL,
0x0001603CUL, 0x00080430UL,
0x00016040UL, 0x000000A7UL,
0x00016044UL, 0x00000000UL,
0x00016048UL, 0x04602123UL,
0x0001604CUL, 0x0000A47CUL,
0x00016050UL, 0x00000018UL,
0x00016054UL, 0x00000000UL,
0x00016058UL, 0x00000000UL,
0x0001605CUL, 0x30100101UL,
0x00016060UL, 0x7F7F7050UL,
0x00016064UL, 0x00000000UL,
0x00017014UL, 0x000270F1UL,
0x00017018UL, 0x00001700UL,
0x0001701CUL, 0x82840000UL,
0x00017028UL, 0x00000000UL,
0x00017048UL, 0x0000383EUL,
0x0001704CUL, 0x000025BCUL,
0x00017070UL, 0x00010103UL,
0x00017074UL, 0x00000442UL,
0x00017078UL, 0x006D8480UL,
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_863_min[] = {
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_915[] = {
0x01010FF4UL, 0x00000000UL,
0x01010FF8UL, 0x0003C000UL,
0x01010FFCUL, 0x0003C008UL,
0x00010004UL, 0x00157001UL,
0x00010008UL, 0x0000007FUL,
0x00010018UL, 0x00000000UL,
0x0001001CUL, 0x00000000UL,
0x00010028UL, 0x00000000UL,
0x0001002CUL, 0x00000000UL,
0x00010030UL, 0x00000000UL,
0x00010034UL, 0x00000000UL,
0x0001003CUL, 0x00000000UL,
0x00010040UL, 0x000007A0UL,
0x00010048UL, 0x00000000UL,
0x00010054UL, 0x00000000UL,
0x00010058UL, 0x00000000UL,
0x000100A0UL, 0x00004000UL,
0x000100A4UL, 0x00004CFFUL,
0x000100A8UL, 0x00004100UL,
0x000100ACUL, 0x00004DFFUL,
0x00012000UL, 0x00000704UL,
0x00012010UL, 0x00000000UL,
0x00012018UL, 0x00008408UL,
0x00013008UL, 0x0000AC3FUL,
0x0001302CUL, 0x02364000UL,
0x00013030UL, 0x00108000UL,
0x00013034UL, 0x00000003UL,
0x0001303CUL, 0x00014000UL,
0x00013040UL, 0x00000000UL,
0x000140A0UL, 0x0F00277AUL,
0x000140F4UL, 0x00001020UL,
0x00014134UL, 0x00000880UL,
0x00014138UL, 0x000087F6UL,
0x00014140UL, 0x00880048UL,
0x00014144UL, 0x1153E6C0UL,
0x00016014UL, 0x00000010UL,
0x00016018UL, 0x04127920UL,
0x0001601CUL, 0x0051C007UL,
0x00016020UL, 0x000000C2UL,
0x00016024UL, 0x00000000UL,
0x00016028UL, 0x03000000UL,
0x0001602CUL, 0x00000000UL,
0x00016030UL, 0x00FF04C8UL,
0x00016034UL, 0x000008A2UL,
0x00016038UL, 0x0100000AUL,
0x0001603CUL, 0x00080430UL,
0x00016040UL, 0x000000A7UL,
0x00016044UL, 0x00000000UL,
0x00016048UL, 0x0AC02123UL,
0x0001604CUL, 0x0000A47CUL,
0x00016050UL, 0x00000018UL,
0x00016054UL, 0x00000000UL,
0x00016058UL, 0x00000000UL,
0x0001605CUL, 0x30100101UL,
0x00016060UL, 0x7F7F7050UL,
0x00016064UL, 0x00000000UL,
0x00017014UL, 0x000270F1UL,
0x00017018UL, 0x00001700UL,
0x0001701CUL, 0x82840000UL,
0x00017028UL, 0x00000000UL,
0x00017048UL, 0x0000383EUL,
0x0001704CUL, 0x000025BCUL,
0x00017070UL, 0x00010103UL,
0x00017074UL, 0x00000442UL,
0x00017078UL, 0x006D8480UL,
0xFFFFFFFFUL,
};
const uint32_t ieee802154_config_915_min[] = {
0xFFFFFFFFUL,
};

View File

@ -0,0 +1,31 @@
/***************************************************************************//**
* @file ieee802154_gb868_efr32xg1_configurator_out.h
* @brief IEEE802154 GB868_Configuration
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __IEEE802154_GB868_EFR32XG1_CONFIGURATOR_OUT_H__
#define __IEEE802154_GB868_EFR32XG1_CONFIGURATOR_OUT_H__
#include <stdint.h>
#define IEEE802154_863_RADIO_CONFIG_BASE_FREQUENCY 868300000UL
#define IEEE802154_863_RADIO_CONFIG_XTAL_FREQUENCY 38400000UL
#define IEEE802154_863_RADIO_CONFIG_BITRATE "100kbps"
#define IEEE802154_863_RADIO_CONFIG_MODULATION_TYPE "OQPSK"
#define IEEE802154_863_RADIO_CONFIG_DEVIATION "333.3kHz"
extern const uint32_t ieee802154_config_863[];
extern const uint32_t ieee802154_config_863_min[];
#define IEEE802154_915_RADIO_CONFIG_BASE_FREQUENCY 906000000UL
#define IEEE802154_915_RADIO_CONFIG_XTAL_FREQUENCY 38400000UL
#define IEEE802154_915_RADIO_CONFIG_BITRATE "250kbps"
#define IEEE802154_915_RADIO_CONFIG_MODULATION_TYPE "OQPSK"
#define IEEE802154_915_RADIO_CONFIG_DEVIATION "333.3kHz"
extern const uint32_t ieee802154_config_915[];
extern const uint32_t ieee802154_config_915_min[];
#endif // __IEEE802154_GB868_EFR32XG1_CONFIGURATOR_OUT_H__

View File

@ -0,0 +1,374 @@
/***************************************************************************//**
* @file rail_ieee802154.h
* @brief The IEEE 802.15.4 specific header file for the RAIL library.
* @copyright Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __RAIL_IEEE802154_H__
#define __RAIL_IEEE802154_H__
/**
* @addtogroup Protocol_Specific
* @{
*/
/**
* @addtogroup IEEE802_15_4
* @brief IEEE 802.15.4 configuration routines
*
* The functions in this group configure RAIL IEEE 802.15.4 hardware
* acceleration. To configure 802.15.4 functionality, call
* RAIL_IEEE802154_Init(). Make note that this function calls many other RAIL
* functions; the application is advised to not reconfigure any of these
* functions. When using 802.15.4 functionality in the 2.4 GHz band, consider
* using RAIL_IEEE802154_2p4GHzRadioConfig() instead of RAIL_RadioConfig() and
* RAIL_ChannelConfig().
*
* @code{.c}
* RAIL_IEEE802154_Config_t config = { false, false,
* RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
* RAIL_RF_STATE_RX, 100, 192, 894, NULL };
* RAIL_IEEE802154_2p4GHzRadioConfig();
* RAIL_IEEE802154_Init(&config);
* @endcode
*
* The application can configure the node's address by using
* RAIL_IEEE802154_SetAddresses(). Inidividual members can be changed with
* RAIL_IEEE802154_SetPanId(), RAIL_IEEE802154_SetShortAddress(),
* RAIL_IEEE802154_SetLongAddress(). RAIL only supports one set of addresses at
* a time. Beacon addresses are supported by default, without additional
* configuration.
*
* @code{.c}
* uint8_t longAddress[8] = { 0x11, 0x22, 0x33, 0x44,
* 0x55, 0x66, 0x77, 0x88};
* // PanID OTA value of 0x34 0x12
* // Short Address OTA byte order of 0x78 0x56
* // Long address with OTA byte order of 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
* RAIL_IEEE802154_AddrConfig_t nodeAddress = { 0x1234, 0x5678,
* &longAddress[0] };
*
* bool status = RAIL_IEEE802154_SetAddresses(&nodeAddress);
*
* // Alternative methods:
* status = RAIL_IEEE802154_SetPanId(nodeAddress.panId);
* status = RAIL_IEEE802154_SetShortAddress(nodeAddress.shortAddr);
* status = RAIL_IEEE802154_SetLongAddress(nodeAddress.longAddr);
* @endcode
*
* Auto ack is initialized through RAIL_IEEE802154_Init(). It is not advised
* to call RAIL_AutoAckConfig() while 802.15.4 hardware acceleration is
* enabled. The default IEEE 802.15.4 ack will have a 5 byte length. The frame
* type will be an ack. The frame pending bit will be set based on the
* RAIL_IEEE802154_SetFramePending() function. The sequence number will be set to
* match the packet being acknowledged. All other frame control fields will be
* set to 0, in compliance with IEEE Std 802.15.4-2011 section 5.2.2.3.
* However, the auto ack modification function can be used to control auto
* acking. Documentation for these functions can be found in \ref Auto_Ack.
* @{
*/
/**
* @enum RAIL_IEEE802154_AddressLength_t
* @brief Different lengths that an 802.15.4 address can have
*/
typedef enum RAIL_IEEE802154_AddressLength
{
RAIL_IEEE802154_ShortAddress = 2, /**< 2 byte short address. */
RAIL_IEEE802154_LongAddress = 3, /**< 8 byte extended address. */
} RAIL_IEEE802154_AddressLength_t;
/**
* @struct RAIL_IEEE802154_Address_t
* @brief Representation of 802.15.4 address
* This structure is only used for a received address, which needs to be parsed
* to discover the type.
*/
typedef struct RAIL_IEEE802154_Address
{
/**
* Enum of the received address length
*/
RAIL_IEEE802154_AddressLength_t length;
union
{
uint16_t shortAddress; /**< Present for 2 byte addresses. */
uint8_t longAddress[8]; /**< Present for 8 byte addresses. */
};
} RAIL_IEEE802154_Address_t;
/**
* @struct RAIL_IEEE802154_AddrConfig_t
* @brief Configuration structure for IEEE 802.15.4 Address Filtering. The
* broadcast addresses are handled separately, and do not need to be specified
* here. Any address which is NULL will be ignored.
*/
typedef struct RAIL_IEEE802154_AddrConfig
{
uint16_t panId; /**< PAN ID for destination filtering. */
uint16_t shortAddr; /**< Network address for destination filtering. */
uint8_t *longAddr; /**< 64 bit address for destination filtering. In OTA byte order.*/
} RAIL_IEEE802154_AddrConfig_t;
/**
* @struct RAIL_IEEE802154_Config_t
* @brief Configuration structure for IEEE 802.15.4 in RAIL
*/
typedef struct RAIL_IEEE802154_Config {
/**
* Enable promiscuous mode during configuration. This can be overridden via
* RAIL_IEEE802154_SetPromiscuousMode() afterwards.
*/
bool promiscuousMode;
/**
* Set whether the device is a PAN Coordinator during configuration. This can
* be overridden via RAIL_IEEE802154_SetPanCoordinator() afterwards.
*/
bool isPanCoordinator;
/**
* Set which 802.15.4 frame types will be received, of Beacon, Data, Ack, and
* Command. This setting can be overridden via RAIL_IEEE802154_AcceptFrames().
*/
uint8_t framesMask;
/**
* Defines the default radio state after a transmit operation (transmit
* packet, wait for ack) or a receive operation (receive packet, transmit
* ack) finishes.
*/
RAIL_RadioState_t defaultState;
/**
* Define the idleToRx and idleToTx time
* This defines the time it takes for the radio to go into RX or TX from an
* idle radio state
*/
uint16_t idleTime;
/**
* Define the turnaround time after receiving a packet and transmitting an
* ack and vice versa
*/
uint16_t turnaroundTime;
/**
* Define the ack timeout time in microseconds
*/
uint16_t ackTimeout;
/**
* Configure the RAIL Address Filter to allow the given destination
* addresses. If addresses is NULL, defer destination address configuration.
* If a member of addresses is NULL, defer configuration of just that member.
* This can be overridden via RAIL_IEEE802154_SetAddresses(), or the
* individual members can be changed via RAIL_IEEE802154_SetPanId(),
* RAIL_IEEE802154_SetShortAddress(), and RAIL_IEEE802154_SetLongAddress().
*/
RAIL_IEEE802154_AddrConfig_t *addresses;
} RAIL_IEEE802154_Config_t;
/**
* Initialize RAIL for IEEE802.15.4 features
*
* @param[in] config IEEE802154 configuration struct
* @return \ref RAIL_STATUS_NO_ERROR if successfully configured.
*
* This function calls the following RAIL functions to configure the radio for
* IEEE802.15.4 features.
*
* Initializes the following:
* - Enables IEEE802154 hardware acceleration
* - Configures RAIL Auto Ack functionality
* - Configures RAIL Address Filter for 802.15.4 address filtering
*
* It calls the following functions:
* - RAIL_AutoAckConfig()
* - RAIL_SetRxTransitions()
* - RAIL_SetTxTransitions()
* - RAIL_SetStateTiming()
* - RAIL_AddressFilterConfig()
* - RAIL_AddressFilterEnable()
*/
RAIL_Status_t RAIL_IEEE802154_Init(RAIL_IEEE802154_Config_t *config);
/**
* Configures the radio for 2.4GHz 802.15.4 operation
*
* @return \ref RAIL_STATUS_NO_ERROR if successfully configured.
*
* This initializes the radio for 2.4GHz operation. It takes the place of
* calling \ref RAIL_RadioConfig and \ref RAIL_ChannelConfig. After this call,
* channels 11-26 will be available, giving the frequencies of those channels
* on channel page 0, as defined by IEEE 802.15.4-2011 section 8.1.2.2.
*/
RAIL_Status_t RAIL_IEEE802154_2p4GHzRadioConfig(void);
/**
* De-initializes IEEE802.15.4 hardware acceleration
*
* @return 0 if IEEE802.15.4 hardware acceleration is successfully
* deinitialized. Error code on failure
*
* Disables and resets all IEE802.15.4 hardware acceleration features. This
* function should only be called when the radio is IDLE. This calls the
* following:
* - RAIL_AutoAckDisable(), which resets the state transitions to IDLE
* - RAIL_SetStateTiming(), to reset all timings to 100 us
* - RAIL_AddressFilterDisable()
* - RAIL_AddressFilterReset()
*/
RAIL_Status_t RAIL_IEEE802154_Deinit(void);
/**
* Return whether IEEE802.15.4 hardware accelertion is currently enabled.
*
* @return True if IEEE802.15.4 hardware acceleration was enabled to start with
* and false otherwise
*/
bool RAIL_IEEE802154_IsEnabled(void);
/**
* Configure the RAIL Address Filter for 802.15.4 filtering
*
* @param[in] addresses The address information that should be used
* @return True if addresses were successfully set, false otherwise
*
* Set up the 802.15.4 address filter to accept messages to the given
* addresses. This will return true if at least one address was successfully
* stored to be used.
*/
bool RAIL_IEEE802154_SetAddresses(RAIL_IEEE802154_AddrConfig_t *addresses);
/**
* Set a PAN ID for 802.15.4 address filtering
*
* @param[in] panId The 16-bit PAN ID information.
* This will be matched against the destination PAN ID of incoming messages.
* The PAN ID is sent little endian over the air meaning panId[7:0] is first in
* the payload followed by panId[15:8].
* @return True if the PAN ID was successfully set, false otherwise
*
* Set up the 802.15.4 address filter to accept messages to the given PAN ID.
*/
bool RAIL_IEEE802154_SetPanId(uint16_t panId);
/**
* Set a short address for 802.15.4 address filtering
*
* @param[in] shortAddr 16 bit short address value. This will be matched against the
* destination short address of incoming messages. The short address is sent
* little endian over the air meaning shortAddr[7:0] is first in the payload
* followed by shortAddr[15:8].
* @return True if the short address was successfully set, false otherwise
*
* Set up the 802.15.4 address filter to accept messages to the given short
* address.
*/
bool RAIL_IEEE802154_SetShortAddress(uint16_t shortAddr);
/**
* Set a long address for 802.15.4 address filtering
*
* @param[in] longAddr Pointer to a 8 byte array containing the long address
* information. The long address must be in over the air byte order. This will
* be matched against the destination long address of incoming messages.
* @return True if the long address was successfully set, false otherwise
*
* Set up the 802.15.4 address filter to accept messages to the given long
* address.
*/
bool RAIL_IEEE802154_SetLongAddress(uint8_t *longAddr);
/**
* Set whether the current node is a PAN coordinator
*
* @param[in] isPanCoordinator True if this device is a PAN coordinator
* @return Returns zero on success and an error code on error
*
* If the device is a PAN Coordinator, then it will accept data and command
* frames with no destination address. This function will fail if 802.15.4
* hardware acceleration is not currently enabled. This setting may be changed
* at any time when 802.15.4 hardwarea acceleration is enabled.
*/
RAIL_Status_t RAIL_IEEE802154_SetPanCoordinator(bool isPanCoordinator);
/**
* Set whether to enable 802.15.4 promiscuous mode
*
* @param[in] enable True if all frames and addresses should be accepted
* @return Returns zero on success and an error code on error
*
* If promiscuous mode is enabled, then no frame or address filtering steps
* will be performed, other than checking the CRC. This function will fail if
* 802.15.4 hardware acceleration is not currently enabled. This setting may be
* changed at any time when 802.15.4 hardware acceleration is enabled.
*/
RAIL_Status_t RAIL_IEEE802154_SetPromiscuousMode(bool enable);
/// When receiving packets, accept 802.15.4 BEACON frame types
#define RAIL_IEEE802154_ACCEPT_BEACON_FRAMES (0x01)
/// When receiving packets, accept 802.15.4 DATA frame types
#define RAIL_IEEE802154_ACCEPT_DATA_FRAMES (0x02)
/// When receiving packets, accept 802.15.4 ACK frame types
/// If this is not enabled, ACK frame types will only be accepted while waiting
/// for an ack
#define RAIL_IEEE802154_ACCEPT_ACK_FRAMES (0x04)
/// When receiving packets, accept 802.15.4 COMMAND frame types
#define RAIL_IEEE802154_ACCEPT_COMMAND_FRAMES (0x08)
/// In standard operation, accept BEACON, DATA and COMMAND frames.
/// Only receive ACK frames while waiting for ack
#define RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES (RAIL_IEEE802154_ACCEPT_BEACON_FRAMES | \
RAIL_IEEE802154_ACCEPT_DATA_FRAMES | \
RAIL_IEEE802154_ACCEPT_COMMAND_FRAMES)
/**
* Set which 802.15.4 frame types to accept
*
* @param[in] framesMask Mask containing which 802.15.4 frame types to receive
* @return Returns zero on success and an error code on error
*
* This function will fail if 802.15.4 hardware acceleration is not currently
* enabled. This setting may be changed at any time when 802.15.4 hardware
* acceleration is enabled. Only Beacon, Data, Ack, and Command frames may
* be received. The RAIL_IEEE802154_ACCEPT_XXX_FRAMES defines may be combined
* to create a bitmask to pass into this function.
*
* \ref RAIL_IEEE802154_ACCEPT_ACK_FRAMES behaves slightly different than the
* other defines. If \ref RAIL_IEEE802154_ACCEPT_ACK_FRAMES is set, the radio
* will accept an ACK frame during normal packet reception. If \ref
* RAIL_IEEE802154_ACCEPT_ACK_FRAMES is not set, ACK frames will be filtered
* unless the radio is waiting for an ACK.
*/
RAIL_Status_t RAIL_IEEE802154_AcceptFrames(uint8_t framesMask);
/**
* Callback for when a Data Request is being received
*
* @param address The source address of the data request command
*
* This function is called when the command byte of an incoming frame is for a
* data request, which requests an ACK. This callback will be called before the
* packet is fully received, to allow the node to have more time to decide
* whether to set frame pending in the outgoing ACK.
*/
void RAILCb_IEEE802154_DataRequestCommand(RAIL_IEEE802154_Address_t *address);
/**
* Set the frame pending bit on the outgoing ACK
*
* @return Returns zero on success and an error code on error
*
* This function should be called after receiving
* RAILCb_IEEE802154_DataRequestCommand(), if the given source address has a
* pending frame. This will return \ref RAIL_STATUS_INVALID_STATE if it is too
* late to modify the ACK.
*/
RAIL_Status_t RAIL_IEEE802154_SetFramePending(void);
/**
* @}
* end of IEEE802.15.4
*/
/**
* @}
* end of Protocol_Specific
*/
#endif // __RAIL_IEEE802154_H__

View File

@ -0,0 +1,115 @@
/***************************************************************************//**
* @file pa.h
* @brief RADIO PA API
*******************************************************************************
* @section License
* <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
* obligation to support this Software. Silicon Labs is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Silicon Labs will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
******************************************************************************/
#ifndef __RADIO_PA_H
#define __RADIO_PA_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @addtogroup RF_Library
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup PA
* @{
******************************************************************************/
/*******************************************************************************
**************************** CONFIGURATION ********************************
******************************************************************************/
#define PA_SCALING_FACTOR 10
/**
* @struct RADIO_PASel_t
* @brief Selection of the rf power amplifier (PA) to use
*/
typedef enum RADIO_PASel
{
/** High power PA */
PA_SEL_2P4_HP,
/** Low power PA */
PA_SEL_2P4_LP,
/** SubGig PA*/
PA_SEL_SUBGIG
} RADIO_PASel_t;
typedef enum RADIO_PAVoltMode
{
/** Vpa = Vbat = 3.3V */
PA_VOLTMODE_VBAT,
/** Vpa = DCDC Vout = 1.8V */
PA_VOLTMODE_DCDC
} RADIO_PAVoltMode_t;
/**
* @struct RADIO_PAInit_t
* @brief Configuration structure for the rf power amplifier (PA)
*/
typedef struct RADIO_PAInit {
/** Power Amplifier mode */
RADIO_PASel_t paSel;
/** Power Amplifier vPA Voltage mode */
RADIO_PAVoltMode_t voltMode;
/** Desired output power in dBm * 10 */
int16_t power;
/** Output power offset in dBm * 10 */
int16_t offset;
/** Desired ramp time in us */
uint16_t rampTime;
} RADIO_PAInit_t;
/*******************************************************************************
****************************** PROTOTYPES *********************************
******************************************************************************/
bool RADIO_PA_Init(RADIO_PAInit_t * paInit);
int32_t PA_OutputPowerGet(void);
int32_t PA_OutputPowerSet(int32_t power);
int32_t PA_MaxOutputPowerSet(void);
uint32_t PA_RampTimeGet(void);
uint32_t PA_RampTimeSet(uint32_t ramptime);
void PA_CTuneSet(uint8_t txPaCtuneValue, uint8_t rxPaCtuneValue);
/** @} (end addtogroup PA) */
/** @} (end addtogroup RF_Library) */
#ifdef __cplusplus
}
#endif
#endif /* __RADIO_PA_H */

View File

@ -0,0 +1,75 @@
/***************************************************************************//**
* @file pti.h
* @brief This header file contains information for working with the packet
* trace APIs.
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __RADIO_PTI_H
#define __RADIO_PTI_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "em_gpio.h"
/******************************** TYPEDEFS *********************************/
/** Channel type enumeration. */
typedef enum RADIO_PTIMode
{
/** SPI mode. */
RADIO_PTI_MODE_SPI = 0U,
/** UART mode. */
RADIO_PTI_MODE_UART = 1U,
/** 9bit UART mode. */
RADIO_PTI_MODE_UART_ONEWIRE = 2U,
/** Turn PTI off entirely */
RADIO_PTI_MODE_DISABLED = 3U,
} RADIO_PTIMode_t;
/**
* @struct RADIO_PTIInit_t
* @brief Configuration structure for the packet trace interface (PTI)
*/
typedef struct RADIO_PTIInit {
/** Packet Trace mode (UART or SPI) */
RADIO_PTIMode_t mode;
/** Output baudrate for PTI in Hz */
uint32_t baud;
/** Data output (DOUT) location for pin/port */
uint8_t doutLoc;
/** Data output (DOUT) GPIO port */
GPIO_Port_TypeDef doutPort;
/** Data output (DOUT) GPIO pin */
uint8_t doutPin;
/** Data clock (DCLK) location for pin/port. Only used in SPI mode */
uint8_t dclkLoc;
/** Data clock (DCLK) GPIO port. Only used in SPI mode */
GPIO_Port_TypeDef dclkPort;
/** Data clock (DCLK) GPIO pin. Only used in SPI mode */
uint8_t dclkPin;
/** Data frame (DFRAME) location for pin/port. Only used for */
uint8_t dframeLoc;
/** Data frame (DFRAME) GPIO port */
GPIO_Port_TypeDef dframePort;
/** Data frame (DFRAME) GPIO pin */
uint8_t dframePin;
} RADIO_PTIInit_t;
/************************* FUNCTION PROTOTYPES *****************************/
void RADIO_PTI_Init(RADIO_PTIInit_t *pitInit);
void RADIO_PTI_Enable(void);
void RADIO_PTI_Disable(void);
#ifdef __cplusplus
}
#endif
#endif //__RADIO_PTI_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
/***************************************************************************//**
* @file rail_chip_specific.h
* @brief This file contains the type definitions for EFR32 chip specific
* aspects of RAIL.
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __RAIL_CHIP_SPECIFIC_H_
#define __RAIL_CHIP_SPECIFIC_H_
// Include standard type headers to help define structures
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
// -----------------------------------------------------------------------------
// Calibration
// -----------------------------------------------------------------------------
/**
* @addtogroup Calibration
* @{
*/
/**
* @addtogroup EFR32
* @{
* @brief EFR32 Specific Calibrations
*
* The EFR32 has two supported calibrations. There is the Image Rejection (IR)
* calibration and a temperature dependent calibration. The IR calibration is
* something that can be computed once and stored off or computed each time at
* startup. It is PHY specific and provides sensitivity improvements so we
* highly recommend using it. The IR calibration should only be run when the
* radio is IDLE. The temperature dependent calibrations are used to
* recalibrate the synth if the temperature falls below 0 or changes by a
* certain amount while sitting in receive. We will do this automatically upon
* entering the receive state so you may omit this calibration if you feel that
* your stack will turn receive on and off frequently enough. If you do not
* calibrate for temperature it's possible to miss receive packets due to drift
* in the carrier frequency.
*/
/**
* @struct RAIL_CalValues_t
* @brief Calibration value structure
*
* This structure contains the set of persistent calibration values for the
* EFR32. You can set these before hand and apply them at startup to save the
* time required to compute them. Any of these values may be set to
* RAIL_CAL_INVALID_VALUE to force the code to compute that calibration value.
*/
typedef struct RAIL_CalValues {
uint32_t imageRejection; /**< Image Rejection (IR) calibration value */
} RAIL_CalValues_t;
/** Invalid calibration value */
#define RAIL_CAL_INVALID_VALUE (0xFFFFFFFF)
/**
* A define to set all RAIL_CalValues_t values to uninitialized.
*
* This define can be used when you have no data to pass to the calibration
* routines but wish to compute and save all possible calibrations.
*/
#define RAIL_CALVALUES_UNINIT { \
RAIL_CAL_INVALID_VALUE, \
}
/** EFR32 specific temperature calibration bit */
#define RAIL_CAL_TEMP_VCO (0x00000001)
/** EFR32 specific IR calibration bit */
#define RAIL_CAL_ONETIME_IRCAL (0x00010000)
/** Mask to run temperature dependent calibrations */
#define RAIL_CAL_TEMP (RAIL_CAL_TEMP_VCO)
/** Mask to run one time calibrations */
#define RAIL_CAL_ONETIME (RAIL_CAL_ONETIME_IRCAL)
/** Mask to run optional performance calibrations */
#define RAIL_CAL_PERF ()
/** Mask for calibrations that require the radio to be off */
#define RAIL_CAL_OFFLINE (RAIL_CAL_ONETIME_IRCAL)
/** Mask to run all possible calibrations for this chip */
#define RAIL_CAL_ALL (RAIL_CAL_TEMP | RAIL_CAL_ONETIME)
/** Mask to run all pending calibrations */
#define RAIL_CAL_ALL_PENDING (0x00000000)
/**
* @}
* @}
*/
#endif

View File

@ -0,0 +1,855 @@
/***************************************************************************//**
* @file rail_types.h
* @brief This file contains the type definitions for RAIL structures, enums,
* and other types.
* @copyright Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com
******************************************************************************/
#ifndef __RAIL_TYPES_H__
#define __RAIL_TYPES_H__
// Include standard type headers to help define structures
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "rail/rail_chip_specific.h"
/**
* @addtogroup RAIL_API
* @{
*/
// -----------------------------------------------------------------------------
// Calibration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup Calibration
* @{
*/
/**
* @typedef RAIL_CalMask_t
* @brief Calibration mask type
*
* This type is a bitmask of different RAIL calibration values. The exact
* meaning of these bits depends on what your particular chip supports.
*/
typedef uint32_t RAIL_CalMask_t;
/**
* @struct RAIL_CalInit_t
* @brief Initialization structure for RAIL calibrations.
*/
typedef struct RAIL_CalInit {
RAIL_CalMask_t calEnable; /**< Mask that defines calibrations to perform in RAIL. */
const uint8_t *irCalSettings; /**< Pointer to image rejection calibration settings. */
} RAIL_CalInit_t;
/**
* @}
*/
// -----------------------------------------------------------------------------
// Radio Configuration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup General
* @{
*/
/**
* @struct RAIL_Version_t
* @brief Contains RAIL Library Version Information
*/
typedef struct RAIL_Version {
uint32_t hash; /**< Git hash */
uint8_t major; /**< Major number */
uint8_t minor; /**< Minor number */
uint8_t rev; /**< Revision number */
uint8_t build; /**< Build number */
uint8_t flags; /**< Build flags */
} RAIL_Version_t;
/**
* @struct RAIL_Init_t
* @brief Initialization structure for the RAIL library.
*/
typedef struct RAIL_Init {
uint16_t maxPacketLength; /**< The maximum number of bytes in a packet. */
const uint32_t rfXtalFreq; /**< The xtal frequency of the radio. */
RAIL_CalMask_t calEnable; /**< Mask that defines calibrations to perform in RAIL. */
} RAIL_Init_t;
/**
* @enum RAIL_PtiProtocol_t
* @brief The protocol that RAIL outputs via the Packet Trace Interface (PTI)
*/
typedef enum RAIL_PtiProtocol {
RAIL_PTI_PROTOCOL_CUSTOM = 0, /**< PTI output for a custom protocol */
RAIL_PTI_PROTOCOL_ZIGBEE = 1, /**< PTI output for the Zigbee protocol */
RAIL_PTI_PROTOCOL_THREAD = 2, /**< PTI output for the Thread protocol */
RAIL_PTI_PROTOCOL_BLE = 3, /**< PTI output for the Bluetooth Smart protocol */
RAIL_PTI_PROTOCOL_CONNECT = 4, /**< PTI output for the Connect protocol */
RAIL_PTI_PROTOCOL_MAX = 0xF /**< Maximum possible protocol value for PTI */
} RAIL_PtiProtocol_t;
/**
* @enum RAIL_RadioState_t
* @brief The current state of the radio
*/
typedef enum RAIL_RadioState {
RAIL_RF_STATE_IDLE, /**< Radio is idle */
RAIL_RF_STATE_RX, /**< Radio is in receive */
RAIL_RF_STATE_TX, /**< Radio is in transmit */
} RAIL_RadioState_t;
/**
* @enum RAIL_Status_t
* @brief The available status options
*/
typedef enum RAIL_Status {
RAIL_STATUS_NO_ERROR, /**< RAIL function reports no error */
RAIL_STATUS_INVALID_PARAMETER, /**< Call to RAIL function errored because of an invalid parameter */
RAIL_STATUS_INVALID_STATE, /**< Call to RAIL function errored because called during an invalid radio state */
RAIL_STATUS_INVALID_CALL, /**< The function is called in an invalid order */
} RAIL_Status_t;
/**
* @enum RAIL_RfSenseBand_t
* @brief Enumeration for specifying Rf Sense frequency band.
*/
typedef enum {
RAIL_RFSENSE_OFF, /**< RFSense is disabled */
RAIL_RFSENSE_2_4GHZ, /**< RFSense is in 2.4G band */
RAIL_RFSENSE_SUBGHZ, /**< RFSense is in subgig band */
RAIL_RFSENSE_ANY, /**< RfSense is in both bands */
RAIL_RFSENSE_MAX // Must be last
} RAIL_RfSenseBand_t;
/**
* @enum RAIL_RfIdleMode_t
* @brief Enumeration for the different types of idle modes we support. These
* vary how quickly and destructively we will put the radio into idle.
*/
typedef enum {
/**
* Idle the radio by turning off receive and canceling any future scheduled
* receive or transmit operations. This will not abort a receive or
* transmit that is in progress.
*/
RAIL_IDLE,
/**
* Idle the radio by turning off receive and any scheduled events. This will
* also abort any receive, transmit, or scheduled events in progress.
*/
RAIL_IDLE_ABORT,
/**
* Force the radio into a shutdown mode as quickly as possible. This will
* abort all current operations and cancel any pending scheduled operations.
* It may also corrupt receive or transmit buffers and end up clearing them.
*/
RAIL_IDLE_FORCE_SHUTDOWN
} RAIL_RfIdleMode_t;
/**
* @}
*/
// -----------------------------------------------------------------------------
// PHY Configuration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup Radio_Configuration
* @{
*/
/**
* @struct RAIL_StateTiming_t
* @brief Timing configuration structure for the RAIL State Machine
*
* This is used to configure the timings of the radio state transitions for
* common situations. All of the listed timings are in us. Timing values cannot
* exceed 13ms. Transitions to IDLE always happen as fast as possible.
*/
typedef struct RAIL_StateTiming {
uint16_t idleToRx; /**<Transition time from IDLE to RX */
uint16_t txToRx; /**<Transition time from TX to RX */
uint16_t idleToTx; /**<Transition time from IDLE to RX */
uint16_t rxToTx; /**<Transition time from RX to TX */
} RAIL_StateTiming_t;
/**
* @struct RAIL_FrameType_t
* @brief Configure if there is a frame type in your frame and the lengths of each frame.
* The number of bits set in the mask determines the number of elements in frameLen
* If your packet does not have frame types but instead are of fixed length, set the mask
* and offset to 0. RAIL will use the value at frameLen to determine the packet length.
* If each frame type has a different location for the addres, variableAddrLoc should be True.
*/
typedef struct RAIL_FrameType {
uint8_t offset; /**< Zero-based location of the frame type field in packet. */
uint8_t mask; /**< Bit mask of the frame type field. Determines number of frames expected. Must be contiguous ones. */
uint16_t *frameLen; /**< Pointer to array of frame lengths for each frame type. */
uint8_t *isValid; /**< Pointer to array that marks if each frame is valid or should be filtered. */
bool variableAddrLoc; /**< If true, address location varies per frame type. */
} RAIL_FrameType_t;
/**
* @struct RAIL_ChannelConfigEntry_t
* @brief Channel configuration entry structure. Defines a base frequency and
* channel space and the channel indexes that are valid within this range.
*
* * frequency = baseFrequency + channelSpacing * (channel - channelNumberStart);
*/
typedef struct RAIL_ChannelConfigEntry {
uint16_t channelNumberStart; /**< RAIL Channel number in which this channel set begins.*/
uint16_t channelNumberEnd; /**< The last valid RAIL channel number for this channel set. */
uint32_t channelSpacing; /**< Channel spacing in Hz of this channel set. */
uint32_t baseFrequency; /**< Base frequency in Hz of this channel set. */
} RAIL_ChannelConfigEntry_t;
/**
* @struct RAIL_ChannelConfig_t
* @brief Channel configuration structure which defines the channel meaning when
* passed into RAIL functions, eg. RAIL_TxStart(), RAIL_RxStart()
*/
typedef struct RAIL_ChannelConfig {
RAIL_ChannelConfigEntry_t *configs; /**< Pointer to an array of RAIL_ChannelConfigEntry_t entries.*/
uint32_t length; /**< Number of RAIL_ChannelConfigEntry_t entries. */
} RAIL_ChannelConfig_t;
/**
* @}
*/
// -----------------------------------------------------------------------------
// Address Filtering Configuration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup Address_Filtering
* @{
*/
/// Default address filtering match table for configurations that use only one
/// address field. The truth table for address matching is below.
///
/// | | 0000 | 0001 | 0010 | 0100 | 1000 |
/// |----------|------|------|------|------|------|
/// | __0000__ | 0 | 1 | 1 | 1 | 1 |
/// | __0001__ | 1 | 1 | 1 | 1 | 1 |
/// | __0010__ | 1 | 1 | 1 | 1 | 1 |
/// | __0100__ | 1 | 1 | 1 | 1 | 1 |
/// | __1000__ | 1 | 1 | 1 | 1 | 1 |
///
#define ADDRCONFIG_MATCH_TABLE_SINGLE_FIELD (0x1fffffe)
/// Default address filtering match table for configurations that use two
/// address fields and just want to match the same index in each. The truth
/// table for address matching is shown below.
///
/// | | 0000 | 0001 | 0010 | 0100 | 1000 |
/// |----------|------|------|------|------|------|
/// | __0000__ | 0 | 0 | 0 | 0 | 0 |
/// | __0001__ | 0 | 1 | 0 | 0 | 0 |
/// | __0010__ | 0 | 0 | 1 | 0 | 0 |
/// | __0100__ | 0 | 0 | 0 | 1 | 0 |
/// | __1000__ | 0 | 0 | 0 | 0 | 1 |
#define ADDRCONFIG_MATCH_TABLE_DOUBLE_FIELD (0x1041040)
/**
* @struct RAIL_AddrConfig_t
* @brief A structure to configure the address filtering functionality in RAIL.
*/
typedef struct RAIL_AddrConfig {
/** The number of fields to configure. You cannot have more than 2. */
uint8_t numFields;
/**
* A list of the start offsets for each field
*
* These offsets are specified relative to the previous field's end. In the
* case of the first field it's relative to either the beginning of the packet
* or the end of the frame type byte if frame type decoding is enabled.
*/
uint8_t *offsets;
/**
* A list of the address field sizes
*
* These sizes are specified in bytes and can be from 0 to 8. If you choose a
* size of 0 this field is effectively disabled.
*/
uint8_t *sizes;
/**
* The truth table to determine how the two fields combine to create a match
*
* For detailed information about how this truth table is formed see the
* detailed description of @ref Address_Filtering.
*
* For simple predefined configurations you can use the following defines.
* - ADDRCONFIG_MATCH_TABLE_SINGLE_FIELD
* - For filtering that only uses a single address field
* - ADDRCONFIG_MATCH_TABLE_DOUBLE_FIELD for two field filtering where you
* - For filtering that uses two address fields in a configurations where
* you want the following logic `((Field0, Index0) && (Field1, Index0)) ||
* ((Field0, Index1) && (Field1, Index1)) || ...`
*/
uint32_t matchTable;
} RAIL_AddrConfig_t;
/**
* @}
*/
// -----------------------------------------------------------------------------
// System Timing Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup System_Timing
* @{
*/
/**
* @enum RAIL_TimeMode_t
* @brief Enumeration for specifying timing offsets in RAIL for any APIs that
* use them.
*/
typedef enum RAIL_TimeMode {
RAIL_TIME_ABSOLUTE, /**< The time specified is an exact time in the RAIL timebase */
RAIL_TIME_DELAY, /**< The time specified is relative to now */
RAIL_TIME_DISABLED /**< The time specified is not intended to be used */
} RAIL_TimeMode_t;
/**
* @}
*/
// -----------------------------------------------------------------------------
// Pre-Tx Configuration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup Pre-Transmit
* @{
*/
/**
* @typedef RAIL_PreTxOp_t
* @brief Generic type used for all configurable pre-transmit operation
* functions.
*/
typedef uint8_t (*RAIL_PreTxOp_t)(void *params);
/**
* @struct RAIL_ScheduleTxConfig_t
* @brief This structure is used to configure the Scheduled Tx algorithm.
* When using the built-in RAIL_PreTxSchedule() algorithm as your
* pre-transmit hook within RAIL_TxStart(), an instance of this structure
* must be passed as its argument.
*/
typedef struct RAIL_ScheduleTxConfig {
uint32_t when; /**< When to transmit this packet in the RAIL timebase. */
RAIL_TimeMode_t mode; /**< Specifies whether when is an absolute time or an offset from now. */
} RAIL_ScheduleTxConfig_t;
/**
* @def RAIL_MAX_LBT_TRIES
* @brief The maximum number of LBT/CSMA retries supported
*/
#define RAIL_MAX_LBT_TRIES 15
/**
* @struct RAIL_CsmaConfig_t
* @brief This structure is used to configure the CSMA algorithm. When using
* the built-in RAIL_PreTxCsma() algorithm as your pre-transmit hook within
* RAIL_TxStart(), an instance of this structure must be passed as its
* argument.
*/
typedef struct RAIL_CsmaConfig {
uint8_t csmaMinBoExp; /**< Minimum (starting) exponent for CSMA backoff (2^exp - 1) */
uint8_t csmaMaxBoExp; /**< Maximum exponent for CSMA backoff */
/**
* Number of CCA failures before report CCA_FAIL. With a maximum value defined
* in @ref RAIL_MAX_LBT_TRIES). A value of 0 will perform no CCA assessments,
* and always transmit immediately.
*/
uint8_t csmaTries;
/**
* The CCA RSSI threshold, in dBm, above which the channel is
* considered 'busy'.
*/
int8_t ccaThreshold;
/**
* The backoff unit period, in RAIL's microsecond time base. This is
* mulitiplied by the random backoff multiplier controlled by @ref
* csmaMinBoExp and @ref csmaMaxBoExp to determine the overall backoff
* period. This value must be at least the idleToRx time (set by
* RAIL_SetStateTimings). For random backoffs, any value above 511
* microseconds will be truncated; for fixed backoffs it can go up to 65535
* microseconds.
*/
uint16_t ccaBackoff;
uint16_t ccaDuration; /**< CCA check duration, in microseconds */
/**
* An overall timeout, in RAIL's microsecond time base, for the operation. If
* transmission doesn't start before this timeout expires, the transmission
* will fail. A value of 0 means no timeout is imposed.
*/
uint32_t csmaTimeout;
} RAIL_CsmaConfig_t;
/**
* @def RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA
* @brief RAIL_CsmaConfig_t initializer configuring CSMA per 802.15.4-2003
* on 2.4 GHz OSPSK, commonly used by ZigBee.
*/
#define RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA { \
/* CSMA per 802.15.4-2003 on 2.4 GHz OSPSK, commonly used by ZigBee */ \
/* csmaMinBoExp */ 3, /* 2^3-1 for 0..7 backoffs on 1st try */ \
/* csmaMaxBoExp */ 5, /* 2^5-1 for 0..31 backoffs on 3rd+ tries */ \
/* csmaTries */ 5, /* 5 tries overall (4 re-tries) */ \
/* ccaThreshold */ -75, /* 10 dB above sensitivity */ \
/* ccaBackoff */ 320, /* 20 symbols at 16 us/symbol */ \
/* ccaDuration */ 128, /* 8 symbols at 16 us/symbol */ \
/* csmaTimeout */ 0, /* no timeout */ \
}
/**
* @def RAIL_CSMA_CONFIG_SINGLE_CCA
* @brief RAIL_CsmaConfig_t initializer configuring a single CCA prior to Tx.
* Can be used to as a basis for implementing other channel access schemes
* with custom backoff delays. User can override ccaBackoff with a fixed
* delay on each use.
*/
#define RAIL_CSMA_CONFIG_SINGLE_CCA { \
/* Perform a single CCA after 'fixed' delay */ \
/* csmaMinBoExp */ 0, /* Used for fixed backoff */ \
/* csmaMaxBoExp */ 0, /* Used for fixed backoff */ \
/* csmaTries */ 1, /* Single try */ \
/* ccaThreshold */ -75, /* Override if not desired choice */ \
/* ccaBackoff */ 0, /* No backoff (override with fixed value) */ \
/* ccaDuration */ 128, /* Override if not desired length */ \
/* csmaTimeout */ 0, /* no timeout */ \
}
/**
* @struct RAIL_LbtConfig_t
* @brief This structure is used to configure the LBT algorithm. When using
* the built-in RAIL_PreTxLbt() algorithm as your pre-transmit hook within
* RAIL_TxStart(), an instance of this structure must be passed as its
* argument.
*/
typedef struct RAIL_LbtConfig {
uint8_t lbtMinBoRand; /**< Minimum backoff random multiplier */
uint8_t lbtMaxBoRand; /**< Maximum backoff random multiplier */
/**
* Number of CCA failures before report CCA_FAIL. With a maximum value defined
* in @ref RAIL_MAX_LBT_TRIES). A value of 0 will perform no CCA assessments,
* and always transmit immediately.
*/
uint8_t lbtTries; /**< Number of LBT failures before report CCA_FAIL */
/**
* The CCA RSSI threshold, in dBm, above which the channel is
* considered 'busy'.
*/
int8_t lbtThreshold;
/**
* The backoff unit period, in RAIL's microsecond time base. This is
* mulitiplied by the random backoff multiplier controlled by @ref
* csmaMinBoExp and @ref csmaMaxBoExp to determine the overall backoff
* period. For random backoffs, this value must be in the range from
* idleToRx time (set by RAIL_SetStateTimings) to 511 microseconds; for fixed
* backoffs it can go up to 65535 microseconds.
*/
uint16_t lbtBackoff;
uint16_t lbtDuration; /**< LBT check duration, in microseconds */
/**
* An overall timeout, in RAIL's microsecond time base, for the
* operation. If transmission doesn't start before this timeout expires, the
* transmission will fail. This is important for limiting LBT due to LBT's
* unbounded requirement that if the channel is busy, the next try must wait
* for the channel to clear. A value of 0 means no timeout is imposed.
*/
uint32_t lbtTimeout;
} RAIL_LbtConfig_t;
/**
* @def RAIL_LBT_CONFIG_ETSI_EN_300_220_1_V2_4_1
* @brief RAIL_LbtConfig_t initializer configuring LBT per ETSI 300 220-1
* V2.4.1 for a typical Sub-GHz band. To be practical, user should override
* lbtTries and/or lbtTimeout so channel access failure will be reported in a
* reasonable timeframe rather than the unbounded timeframe ETSI defined.
*/
#define RAIL_LBT_CONFIG_ETSI_EN_300_220_1_V2_4_1 { \
/* LBT per ETSI 300 220-1 V2.4.1 */ \
/* LBT time = random backoff of 0-5ms in 0.5ms increments plus 5ms fixed */ \
/* lbtMinBoRand */ 0, /* */ \
/* lbtMaxBoRand */ 10, /* */ \
/* lbtTries */ RAIL_MAX_LBT_TRIES, /* the maximum supported */ \
/* lbtThreshold */ -87, /* */ \
/* lbtBackoff */ 500, /* 0.5 ms */ \
/* lbtDuration */ 5000, /* 5 ms */ \
/* lbtTimeout */ 0, /* no timeout (recommend user override) */ \
}
/**
* @}
*/
// -----------------------------------------------------------------------------
// Tx/Rx Configuration Structures
// -----------------------------------------------------------------------------
/**
* @addtogroup Transmit
* @{
*/
// Tx Config Callback Defines
/** Callback for a transmit buffer underflow event */
#define RAIL_TX_CONFIG_BUFFER_UNDERFLOW (0x01 << 1)
/** Callback for CCA/CSMA/LBT failure */
#define RAIL_TX_CONFIG_CHANNEL_BUSY (0x01 << 2)
/** Callback for when a Tx is aborted by the user */
#define RAIL_TX_CONFIG_TX_ABORTED (0x01 << 3)
/** Callback for when a Tx is blocked by something like PTA or RHO */
#define RAIL_TX_CONFIG_TX_BLOCKED (0x01 << 4)
/**
* @struct RAIL_TxData_t
* @brief This structure is used to define the data to transmit. The data is copied
* into an RAIL space buffer so after RAIL_TxLoadData returns, the pointer
* can be deallocated or reused.
*/
typedef struct RAIL_TxData {
uint8_t *dataPtr; /**< Pointer to data to transmit */
uint16_t dataLength; /**< Number of bytes to transmit */
} RAIL_TxData_t;
/**
* @struct RAIL_TxPacketInfo_t
* @brief Information about the packet that was just transmitted.
*/
typedef struct RAIL_TxPacketInfo {
/**
* Time recorded when the last bit is transmitted out of the modulator.
*/
uint32_t timeUs;
} RAIL_TxPacketInfo_t;
/**
* @struct RAIL_TxOptions_t
* @brief Tx Option structure that modifies the transmit. Only applies to one
* transmit.
*/
typedef struct RAIL_TxOptions {
/**
* Configure if radio should wait for ack after transmit. waitForAck is only
* honored if Auto Ack is enabled and if Auto Ack Tx is not paused
*/
bool waitForAck;
} RAIL_TxOptions_t;
/**
* @}
*/
/**
* @addtogroup Receive
* @{
*/
// Rx Config Callback Defines
/** Callback for preamble detection */
#define RAIL_RX_CONFIG_PREAMBLE_DETECT (0x01 << 1)
/** Callback for detection of the first sync word */
#define RAIL_RX_CONFIG_SYNC1_DETECT (0x01 << 2)
/** Callback for detection of the second sync word */
#define RAIL_RX_CONFIG_SYNC2_DETECT (0x01 << 3)
/** Callback for detection of frame errors */
#define RAIL_RX_CONFIG_FRAME_ERROR (0x01 << 4)
/** Callback for when we run out of Rx buffer space */
#define RAIL_RX_CONFIG_BUFFER_OVERFLOW (0x01 << 5)
/** Callback for when a packet is address filtered */
#define RAIL_RX_CONFIG_ADDRESS_FILTERED (0x01 << 6)
/** Callback for RF Sensed */
#define RAIL_RX_CONFIG_RF_SENSED (0x01 << 7)
/** Callback for when an Rx event times out */
#define RAIL_RX_CONFIG_TIMEOUT (0x01 << 8)
/** Callback for when the scheduled Rx window ends */
#define RAIL_RX_CONFIG_SCHEDULED_RX_END (0x01 << 9)
/** To maintain backwards compatibility with RAIL 1.1,
* RAIL_RX_CONFIG_INVALID_CRC is the same as RAIL_RX_CONFIG_FRAME_ERROR
*/
#define RAIL_RX_CONFIG_INVALID_CRC RAIL_RX_CONFIG_FRAME_ERROR
// Rx Config Ignore Error Defines
/** Ignore no errors. Drop all packets with errors */
#define RAIL_IGNORE_NO_ERRORS (0x00)
/** Ignore CRC errors. Receive packets with CRC errors */
#define RAIL_IGNORE_CRC_ERRORS (0x01 << 0)
/** Ignore all possible errors. Receive all possible packets */
#define RAIL_IGNORE_ALL_ERRORS (0xFF)
/** The value returned by RAIL for an invalid RSSI: (-128 * 4) quarter dBm */
#define RAIL_RSSI_INVALID ((int16_t)(-128 * 4))
/**
* @struct RAIL_AppendedInfo_t
* @brief Appended info structure that is returned in the RAILCb_RxPacketReceived
* callback
*
* @todo Define where the rssi latch point is. Is it configurable?
*/
typedef struct RAIL_AppendedInfo {
/**
* Timestamp of the received packet in the RAIL timebase of microseconds.
* This time is recorded at sync detect.
*/
uint32_t timeUs;
/**
* Indicates whether the CRC passed or failed for the receive packet. This
* will be set to 0 for fail and 1 for pass.
*/
bool crcStatus:1;
/**
* Indicates whether frame coding found any errors in the receive packet.
* This will be set to 0 for fail and 1 for pass.
*/
bool frameCodingStatus:1;
/**
* Indicates if the received packet is an ack. An 'ack' is defined as a
* packet received during the rx ack window when autoack is enabled.
* Set to 0 for not an ack, and 1 for is an ack.
*/
bool isAck:1;
/**
* RSSI of the received packet in integer dBm. This is latched when the sync
* word is detected for this packet.
*/
int8_t rssiLatch;
/**
* Link quality indicator of the received packet. This is not currently
* implemented.
*/
uint8_t lqi;
/**
* For radios and PHY configurations that support multiple sync words this
* number will be the ID of the sync word that was used for this packet.
*/
uint8_t syncWordId;
} RAIL_AppendedInfo_t;
/**
* @struct RAIL_RxPacketInfo_t
* @brief Rx Packet Information structure passed into RAILCb_RxPacketReceived
* after a packet has been received. Contains a pointer to the data recieved,
* as well as other packet information.
*/
typedef struct RAIL_RxPacketInfo {
RAIL_AppendedInfo_t appendedInfo; /**< A structure containing various extra information about the received packet. */
uint16_t dataLength; /**< The number of bytes in the dataPtr array. */
uint8_t dataPtr[]; /**< A variable length array holding the packet contents. */
} RAIL_RxPacketInfo_t;
/**
* @struct RAIL_ScheduleRxConfig_t
* @brief This structure is used to configure the Scheduled Rx algorithm. It
* allows you to define the start and end times of the window in either absolute
* or relative times. If start is set to \ref RAIL_TIME_DISABLED it will be
* assumed that we should start receive now. If end is set to \ref
* RAIL_TIME_DISABLED then the only way to end this scheduled receive is with an
* explicit call to RAIL_RfIdle(). If end is relative it is relative to the
* start time not the current time. All times are assumed to be specified in the
* RAIL timebase.
*/
typedef struct RAIL_ScheduleRxConfig {
/**
* The time to start receive. See startMode for more information about they
* types of start times that you can specify.
*/
uint32_t start;
/**
* The type of time value specified in the start parameter. If this is
* \ref RAIL_TIME_ABSOLUTE then it's an exact time, if it's \ref
* RAIL_TIME_DELAY then it's an offset relative to the current time. If you
* specify \ref RAIL_TIME_DISABLED for this then the start event will be
* ignored.
*/
RAIL_TimeMode_t startMode;
/**
* The time to end receive. See endMode for more information about the types
* of end times you can specify.
*/
uint32_t end;
/**
* The type of time value specified in the end parameter. If this is
* \ref RAIL_TIME_ABSOLUTE then it's an exact time, if it's \ref RAIL_TIME_DELAY then
* it's an offset relative to the start time as long as the startMode isn't
* \ref RAIL_TIME_DISABLED and if it's \ref RAIL_TIME_DISABLED we will not configure the
* end event so that this can run indefinitely.
*/
RAIL_TimeMode_t endMode;
/**
* While in scheduled Rx you are still able to control the radio state via
* state transitions. This option allows you to configure whether a transition
* to Rx goes back to scheduled Rx or to the normal Rx state. Once in the
* normal Rx state you will effectively end the scheduled Rx window and can
* continue to receive indefinitely depending on your state transitions. Set
* this to 1 to transition to normal Rx and 0 to stay in scheduled Rx.
*/
uint8_t rxTransitionEndSchedule;
/**
* If set to 0 this will allow any packets being received when the window end
* event occurs to complete. If set to anything else we will force an abort of
* any packets being received when the window end occurs.
*/
uint8_t hardWindowEnd;
} RAIL_ScheduleRxConfig_t;
/**
* @}
*/
/**
* @addtogroup Auto_Ack
* @{
*/
/**
* @struct RAIL_AutoAckConfig_t
* @brief This structure is used to configure the Auto Ack algorithm. The
* structure provides a defaultState for the radio to return to once an ack
* operation occurs (transmitting or attempting to receive an ack). Regardless
* if the ack operation was successful, the radio will return to the specified
* default state.
*
* The other parameters configure auto ack timing. The application can specify
* timing from when the radio is idle to TX/RX, the turnaround time from TX->RX
* and RX->TX, and finally the total amount of time to look for an ack. All of
* these timing parameters are in microseconds.
*/
typedef struct RAIL_AutoAckConfig {
/**
* Default state once auto ack sequence completes or errors. Can only be
* RAIL_RF_STATE_RX or RAIL_RF_STATE_IDLE.
*/
RAIL_RadioState_t defaultState;
/**
* Define the time from idleToTx and idleToRx in us. Limited to a max of
* 13ms.
*/
uint16_t idleTiming;
/**
* Define the ack turnaround time in us. Limited to a max of 13ms.
*/
uint16_t turnaroundTime;
/**
* Define the rx ack timeout duration in us. Limited to a max of 65.535ms.
*/
uint16_t ackTimeout;
} RAIL_AutoAckConfig_t;
/**
* @struct RAIL_AutoAckData_t
* @brief This structure is used to define the data to use during auto
* acknowledgement. The data is copied into an RAIL space buffer so after
* RAIL_AutoAckLoadBuffer returns, the pointer can be deallocated or reused.
*
* Size limited to \ref RAIL_AUTOACK_MAX_LENGTH.
*/
typedef struct RAIL_AutoAckData {
uint8_t *dataPtr; /**< Pointer to ack data to transmit */
uint8_t dataLength; /**< Number of ack bytes to transmit */
} RAIL_AutoAckData_t;
/// Acknowledgement packets cannot be longer than 64 bytes.
#define RAIL_AUTOACK_MAX_LENGTH 64
/**
* @}
* endofgroup AutoAck
*/
/******************************************************************************
* Version
*****************************************************************************/
/**
* @addtogroup Diagnostic
* @{
*/
/**
* @enum RAIL_StreamMode_t
* @brief Possible stream output modes.
*/
typedef enum RAIL_StreamMode {
PSEUDO_RANDOM_STREAM, /**< Pseudo random stream of bytes */
PN9_STREAM /**< PN9 byte sequence */
} RAIL_StreamMode_t;
/**
* @struct RAIL_BerConfig_t
* @brief BER test parameters.
*/
typedef struct RAIL_BerConfig
{
uint32_t bytesToTest; /**< Number of bytes to test */
} RAIL_BerConfig_t;
/**
* @struct RAIL_BerStatus_t
* @brief The status of the latest bit error rate (BER) test.
*/
typedef struct RAIL_BerStatus
{
uint32_t bitsTotal; /**< Number of bits to receive */
uint32_t bitsTested; /**< Number of bits currently tested */
uint32_t bitErrors; /**< Number of bits errors detected */
int8_t rssi; /**< Latched RSSI value at pattern detect */
} RAIL_BerStatus_t;
/**
* @}
*/
#ifndef DOXYGEN_SHOULD_SKIP_THIS
/******************************************************************************
* Debug
*****************************************************************************/
/**
* @addtogroup Debug
* @{
*/
// Debug Config Callback Defines
/** Callback for radio state change */
#define RAIL_DEBUG_CONFIG_STATE_CHANGE (0x01 << 1)
/**
* @def RAIL_DEBUG_MODE_FREQ_OVERRIDE
* @brief A bitmask to enable the frequency override debug mode where you can
* manually tune to a specified frequency. Note that this should only be used
* for testing and is not as tuned as frequencies from the calculator.
*/
#define RAIL_DEBUG_MODE_FREQ_OVERRIDE 0x00000001UL
/**
* @def RAIL_DEBUG_MODE_VALID_MASK
* @brief Any debug mode bits outside of this mask are invalid and ignored.
*/
#define RAIL_DEBUG_MODE_VALID_MASK (!(RAIL_DEBUG_MODE_FREQ_OVERRIDE))
/**
* @}
*/
#endif
/**
* @}
* end of RAIL_API
*/
#endif // __RAIL_TYPES_H__

View File

@ -0,0 +1,827 @@
/*
* Copyright (c) 2016 Silicon Laboratories, Inc. http://www.silabs.com
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NanostackRfPhyEfr32.h"
#include "ns_types.h"
#include "platform/arm_hal_interrupt.h"
#include "nanostack/platform/arm_hal_phy.h"
#include "toolchain.h"
#include <string.h>
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "SLRF"
/* Silicon Labs headers */
extern "C" {
#include "rail/rail.h"
#include "rail/pa.h"
#include "rail/pti.h"
#include "rail/ieee802154/rail_ieee802154.h"
#include "buffer-pool-memory-manager/buffer_pool_allocator.h"
}
/* RF driver data */
static phy_device_driver_s device_driver;
static int8_t rf_radio_driver_id = -1;
static uint8_t MAC_address[8];
static uint16_t PAN_address;
static uint16_t short_address;
/* Driver instance handle */
static NanostackRfPhyEfr32 *rf = NULL;
/* Channel configurations */
static const phy_rf_channel_configuration_s phy_24ghz = {2405000000U, 5000000U, 250000U, 16U, M_OQPSK};
static const phy_rf_channel_configuration_s phy_subghz = {868300000U, 2000000U, 250000U, 11U, M_OQPSK};
static const phy_device_channel_page_s phy_channel_pages[] = {
{ CHANNEL_PAGE_0, &phy_24ghz},
{ CHANNEL_PAGE_2, &phy_subghz},
{ CHANNEL_PAGE_0, NULL}
};
/* Driver structures */
typedef enum {
RADIO_UNINIT,
RADIO_INITING,
RADIO_IDLE,
RADIO_TX,
RADIO_RX,
RADIO_CALIBRATION
} siliconlabs_modem_state_t;
static const RAIL_CsmaConfig_t csma_config = RAIL_CSMA_CONFIG_802_15_4_2003_2p4_GHz_OQPSK_CSMA;
#if defined(TARGET_EFR32MG1)
#include "ieee802154_subg_efr32xg1_configurator_out.h"
#include "ieee802154_efr32xg1_configurator_out.h"
#else
#error "Not a valid target."
#endif
static const RAIL_ChannelConfigEntry_t entry[] = {
{0U, 0U, 600000U, 868300000U},
{1U, 10U, 2000000U, 906000000U},
{11U, 26U, 5000000U, 2405000000U}
};
#if MBED_CONF_SL_RAIL_BAND == 868
#ifndef DEVICE_RF_SUBGHZ
#error "Sub-Gigahertz band is not supported on this target."
#endif
static const RAIL_ChannelConfig_t channels = {
(RAIL_ChannelConfigEntry_t *) &entry[0],
1
};
#elif MBED_CONF_SL_RAIL_BAND == 915
#ifndef DEVICE_RF_SUBGHZ
#error "Sub-Gigahertz band is not supported on this target."
#endif
static const RAIL_ChannelConfig_t channels = {
(RAIL_ChannelConfigEntry_t *) &entry[1],
1
};
#elif MBED_CONF_SL_RAIL_BAND == 2400
#ifndef DEVICE_RF_2P4GHZ
#error "2.4GHz band is not supported on this target."
#endif
static const RAIL_ChannelConfig_t channels = {
(RAIL_ChannelConfigEntry_t *) &entry[2],
1
};
#else
#error "sl-rail.band is not correctly defined"
#endif
static const RAIL_IEEE802154_Config_t config = { false, false,
RAIL_IEEE802154_ACCEPT_STANDARD_FRAMES,
RAIL_RF_STATE_RX, 100, 192, 894, NULL };
static const RAIL_Init_t railInitParams = { 140, 38400000, RAIL_CAL_ALL_PENDING };
#if defined (DEVICE_RF_2P4GHZ)
// Set up the PA for 2.4 GHz operation
static const RADIO_PAInit_t paInit2p4 = {
PA_SEL_2P4_HP, /* Power Amplifier mode */
PA_VOLTMODE_DCDC, /* Power Amplifier vPA Voltage mode */
100, /* Desired output power in dBm * 10 */
0, /* Output power offset in dBm * 10 */
10 /* Desired ramp time in us */
};
#endif
#if defined (DEVICE_RF_SUBGHZ)
// Set up the PA for sub-GHz operation
static const RADIO_PAInit_t paInitSubGhz = {
PA_SEL_SUBGIG, /* Power Amplifier mode */
PA_VOLTMODE_DCDC, /* Power Amplifier vPA Voltage mode */
100, /* Desired output power in dBm * 10 */
0, /* Output power offset in dBm * 10 */
10 /* Desired ramp time in us */
};
#endif
static volatile siliconlabs_modem_state_t radio_state = RADIO_UNINIT;
static volatile int8_t channel = -1;
static volatile uint8_t current_tx_handle = 0;
static volatile uint8_t current_tx_sequence = 0;
static volatile bool waiting_for_ack = false;
static volatile bool data_pending = false, last_ack_pending_bit = false;
static volatile uint32_t last_tx = 0;
/* ARM_NWK_HAL prototypes */
static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr);
static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel);
static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr);
static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol );
/* Local function prototypes */
static bool rail_checkAndSwitchChannel(uint8_t channel);
/*============ CODE =========*/
/*
* \brief Function initialises and registers the RF driver.
*
* \param none
*
* \return rf_radio_driver_id Driver ID given by NET library
*/
static int8_t rf_device_register(void)
{
// If we already exist, bail.
if(radio_state != RADIO_UNINIT) {
return -1;
}
#if MBED_CONF_SL_RAIL_BAND == 2400
RADIO_PA_Init((RADIO_PAInit_t*)&paInit2p4);
#elif (MBED_CONF_SL_RAIL_BAND == 915) || (MBED_CONF_SL_RAIL_BAND == 868)
RADIO_PA_Init((RADIO_PAInit_t*)&paInitSubGhz);
#endif
// Set up PTI since it makes life so much easier
#if defined(DEVICE_SL_PTI)
RADIO_PTIInit_t ptiInit = {
RADIO_PTI_MODE_UART,
1600000,
6,
// TODO: Configure PTI pinout using config system.
// Not very urgent, since all boards use the same pins now.
gpioPortB,
12,
6,
gpioPortB,
11,
6,
gpioPortB,
13,
};
RADIO_PTI_Init(&ptiInit);
#endif
// Set up RAIL
RAIL_RfInit(&railInitParams);
RAIL_ChannelConfig(&channels);
#if MBED_CONF_SL_RAIL_BAND == 2400
RAIL_RadioConfig((void*) ieee802154_config_base);
channel = 11;
#elif (MBED_CONF_SL_RAIL_BAND == 915)
RAIL_RadioConfig((void*) ieee802154_config_915);
channel = 1;
#elif MBED_CONF_SL_RAIL_BAND == 868
RAIL_RadioConfig((void*) ieee802154_config_863);
channel = 0;
#endif
RAIL_IEEE802154_Init((RAIL_IEEE802154_Config_t*)&config);
/* Get real MAC address */
/* MAC is stored MSB first */
memcpy(MAC_address, (const void*)&DEVINFO->UNIQUEH, 4);
memcpy(&MAC_address[4], (const void*)&DEVINFO->UNIQUEL, 4);
/*Set pointer to MAC address*/
device_driver.PHY_MAC = MAC_address;
device_driver.driver_description = (char*)"EFR32_154";
/*Type of RF PHY*/
#if MBED_CONF_SL_RAIL_BAND == 2400
device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
#elif (MBED_CONF_SL_RAIL_BAND == 915) || (MBED_CONF_SL_RAIL_BAND == 868)
device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
#endif
device_driver.phy_channel_pages = phy_channel_pages;
/*Maximum size of payload is 127*/
device_driver.phy_MTU = 127;
/*1 byte header in PHY layer (length)*/
device_driver.phy_header_length = 1;
/*No tail in PHY layer*/
device_driver.phy_tail_length = 0;
/*Set address write function*/
device_driver.address_write = &rf_address_write;
/*Set RF extension function*/
device_driver.extension = &rf_extension;
/*Set RF state control function*/
device_driver.state_control = &rf_interface_state_control;
/*Set transmit function*/
device_driver.tx = &rf_start_cca;
/*Upper layer callbacks init to NULL, get populated by arm_net_phy_register*/
device_driver.phy_rx_cb = NULL;
device_driver.phy_tx_done_cb = NULL;
/*Virtual upper data callback init to NULL*/
device_driver.arm_net_virtual_rx_cb = NULL;
device_driver.arm_net_virtual_tx_cb = NULL;
/*Register device driver*/
rf_radio_driver_id = arm_net_phy_register(&device_driver);
// If the radio hasn't called the ready callback by now, place it in the initing state
if(radio_state == RADIO_UNINIT) {
radio_state = RADIO_INITING;
}
return rf_radio_driver_id;
}
/*
* \brief Function unregisters the RF driver.
*
* \param none
*
* \return none
*/
static void rf_device_unregister(void)
{
arm_net_phy_unregister(rf_radio_driver_id);
}
/*
* \brief Function starts the CCA process before starting data transmission and copies the data to RF TX FIFO.
*
* \param data_ptr Pointer to TX data
* \param data_length Length of the TX data
* \param tx_handle Handle to transmission
* \return 0 Success
* \return -1 Busy
*/
static int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol )
{
RAIL_TxData_t txData = {
data_ptr,
data_length + 3
};
tr_debug("Called TX, len %d, chan %d\n", data_length, channel);
switch(radio_state) {
case RADIO_UNINIT:
tr_debug("Radio uninit\n");
return -1;
case RADIO_INITING:
tr_debug("Radio initing\n");
return -1;
case RADIO_CALIBRATION:
tr_debug("Radio calibrating\n");
return -1;
case RADIO_TX:
tr_debug("Radio in TX mode\n");
return -1;
case RADIO_IDLE:
case RADIO_RX:
// If we're still waiting for an ACK, don't mess up the internal state
if(waiting_for_ack || RAIL_RfStateGet() == RAIL_RF_STATE_TX) {
if((RAIL_GetTime() - last_tx) < 30000) {
tr_debug("Still waiting on previous ACK\n");
return -1;
} else {
tr_debug("TXerr\n");
}
}
data_ptr[0] = data_length + 2;
RAIL_RfIdleExt(RAIL_IDLE_ABORT , true);
RAIL_TxDataLoad(&txData);
radio_state = RADIO_TX;
RAIL_TxOptions_t txOpt;
//Check to see whether we'll be waiting for an ACK
if(data_ptr[1] & (1 << 5)) {
txOpt.waitForAck = true;
waiting_for_ack = true;
} else {
txOpt.waitForAck = false;
}
if(RAIL_TxStartWithOptions(channel, &txOpt, &RAIL_CcaCsma, (RAIL_CsmaConfig_t*) &csma_config) == 0) {
//Save packet number and sequence
current_tx_handle = tx_handle;
current_tx_sequence = data_ptr[3];
return 0;
} else {
RAIL_RfIdle();
RAIL_RxStart(channel);
radio_state = RADIO_RX;
return -1;
}
}
//Should never get here...
return -1;
}
/*
* \brief Function gives the control of RF states to MAC.
*
* \param new_state RF state
* \param rf_channel RF channel
*
* \return 0 Success
*/
static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
{
int8_t ret_val = 0;
switch (new_state)
{
/* Reset PHY driver and set to idle */
case PHY_INTERFACE_RESET:
RAIL_RfIdle();
radio_state = RADIO_IDLE;
break;
/* Disable PHY Interface driver */
case PHY_INTERFACE_DOWN:
RAIL_RfIdle();
radio_state = RADIO_IDLE;
break;
/* Enable RX */
case PHY_INTERFACE_UP:
if(rail_checkAndSwitchChannel(rf_channel)) {
RAIL_IEEE802154_SetPromiscuousMode(false);
RAIL_RxStart(channel);
radio_state = RADIO_RX;
} else {
ret_val = -1;
}
break;
/* Enable wireless interface ED scan mode */
case PHY_INTERFACE_RX_ENERGY_STATE:
tr_debug("Energy det req\n");
// TODO: implement energy detection
break;
/* Enable RX in promiscuous mode (aka no address filtering) */
case PHY_INTERFACE_SNIFFER_STATE:
if(rail_checkAndSwitchChannel(rf_channel)) {
RAIL_IEEE802154_SetPromiscuousMode(true);
RAIL_RxStart(channel);
radio_state = RADIO_RX;
} else {
ret_val = -1;
}
break;
}
return ret_val;
}
/*
* \brief Function controls the ACK pending, channel setting and energy detection.
*
* \param extension_type Type of control
* \param data_ptr Data from NET library
*
* \return 0 Success
*/
static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
{
switch (extension_type)
{
/* Control MAC pending bit for Indirect data transmission */
case PHY_EXTENSION_CTRL_PENDING_BIT:
if(*data_ptr) {
data_pending = true;
} else {
data_pending = false;
}
break;
/* Return frame pending bit from last received ACK */
case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
if(last_ack_pending_bit) {
*data_ptr = 0xFF;
} else {
*data_ptr = 0;
}
break;
/* Set channel */
case PHY_EXTENSION_SET_CHANNEL:
channel = *data_ptr;
break;
/* Read energy on the channel */
case PHY_EXTENSION_READ_CHANNEL_ENERGY:
// TODO: implement energy detection
*data_ptr = 0;
break;
/* Read status of the link */
case PHY_EXTENSION_READ_LINK_STATUS:
// TODO: return accurate value here
tr_debug("Trying to read link status\n");
break;
/* Convert between LQI and RSSI */
case PHY_EXTENSION_CONVERT_SIGNAL_INFO:
// TODO: return accurate value here
tr_debug("Trying to read signal info\n");
break;
}
return 0;
}
/*
* \brief Function sets the addresses to RF address filters.
*
* \param address_type Type of address
* \param address_ptr Pointer to given address
*
* \return 0 Success
*/
static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
{
int8_t ret_val = 0;
switch (address_type)
{
/*Set 48-bit address*/
case PHY_MAC_48BIT:
// 15.4 does not support 48-bit addressing
ret_val = -1;
break;
/*Set 64-bit MAC address*/
case PHY_MAC_64BIT:
/* Store MAC in MSB order */
memcpy(MAC_address, address_ptr, 8);
tr_debug("MACw ");
for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
tr_debug("%02x:", MAC_address[i]);
}
tr_debug("\n");
/* Pass MAC to the RF driver in LSB order */
uint8_t MAC_reversed[8];
for(unsigned int i = 0; i < sizeof(MAC_address); i ++) {
MAC_reversed[i] = MAC_address[sizeof(MAC_address) - 1 - i];
}
RAIL_IEEE802154_SetLongAddress(MAC_reversed);
break;
/*Set 16-bit address*/
case PHY_MAC_16BIT:
short_address = address_ptr[0] << 8 | address_ptr[1];
tr_debug("Filter EUI16 %04x\n", short_address);
RAIL_IEEE802154_SetShortAddress(short_address);
break;
/*Set PAN Id*/
case PHY_MAC_PANID:
PAN_address = address_ptr[0] << 8 | address_ptr[1];
tr_debug("Filter PAN %04x\n", PAN_address);
RAIL_IEEE802154_SetPanId(PAN_address);
break;
}
return ret_val;
}
/*****************************************************************************/
/*****************************************************************************/
static void rf_if_lock(void)
{
platform_enter_critical();
}
static void rf_if_unlock(void)
{
platform_exit_critical();
}
NanostackRfPhyEfr32::NanostackRfPhyEfr32() : NanostackRfPhy()
{
// Do nothing
}
NanostackRfPhyEfr32::~NanostackRfPhyEfr32()
{
rf_unregister();
}
int8_t NanostackRfPhyEfr32::rf_register()
{
rf_if_lock();
if (rf != NULL) {
rf_if_unlock();
error("Multiple registrations of NanostackRfPhyEfr32 not supported");
return -1;
}
int8_t radio_id = rf_device_register();
if (radio_id < 0) {
rf = NULL;
} else {
rf = this;
}
rf_if_unlock();
return radio_id;
}
void NanostackRfPhyEfr32::rf_unregister()
{
rf_if_lock();
if (rf != this) {
rf_if_unlock();
return;
}
rf_device_unregister();
rf = NULL;
rf_if_unlock();
}
void NanostackRfPhyEfr32::get_mac_address(uint8_t *mac)
{
rf_if_lock();
memcpy(mac, MAC_address, sizeof(MAC_address));
rf_if_unlock();
}
void NanostackRfPhyEfr32::set_mac_address(uint8_t *mac)
{
rf_if_lock();
if (NULL != rf) {
error("NanostackRfPhyEfr32 cannot change mac address when running");
rf_if_unlock();
return;
}
memcpy(MAC_address, mac, sizeof(MAC_address));
rf_if_unlock();
}
uint32_t NanostackRfPhyEfr32::get_driver_version()
{
RAIL_Version_t railversion;
RAIL_VersionGet(&railversion, true);
return (railversion.major << 24) |
(railversion.minor << 16) |
(railversion.rev << 8) |
(railversion.build);
}
//====================== RAIL-defined callbacks =========================
/**
* Callback that lets the app know when the radio has finished init
* and is ready.
*/
void RAILCb_RfReady(void) {
radio_state = RADIO_IDLE;
}
/**
* Interrupt level callback
* Allows the user finer granularity in tx radio events.
*
* Radio Statuses:
* RAIL_TX_CONFIG_BUFFER_UNDERFLOW
* RAIL_TX_CONFIG_CHANNEL_BUSY
*
* @param[in] status A bit field that defines what event caused the callback
*/
void RAILCb_TxRadioStatus(uint8_t status) {
tr_debug("Packet TX error %d\n", status);
if(device_driver.phy_tx_done_cb != NULL) {
if(status == RAIL_TX_CONFIG_BUFFER_UNDERFLOW ||
status == RAIL_TX_CONFIG_CHANNEL_BUSY ||
status == RAIL_TX_CONFIG_TX_ABORTED ||
status == RAIL_TX_CONFIG_TX_BLOCKED) {
waiting_for_ack = false;
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
PHY_LINK_CCA_FAIL,
8,
1);
}
}
radio_state = RADIO_RX;
}
/**
* Called whenever an enabled radio status event occurs
*
* Triggers:
* RAIL_RX_CONFIG_PREAMBLE_DETECT
* RAIL_RX_CONFIG_SYNC1_DETECT
* RAIL_RX_CONFIG_SYNC2_DETECT
* RAIL_RX_CONFIG_INVALID_CRC
* RAIL_RX_CONFIG_BUFFER_OVERFLOW
* RAIL_RX_CONFIG_ADDRESS_FILTERED
*
* @param[in] status The event that triggered this callback
*/
void RAILCb_RxRadioStatus(uint8_t status) {
tr_debug("RXE %d\n", status);
}
/**
* Callback that notifies the application that a calibration is needed.
*
* This callback function is called whenever the RAIL library detects that a
* calibration is needed. It is up to the application to determine a valid
* window to call RAIL_CalStart().
*
*/
void RAILCb_CalNeeded(void) {
// TODO: Implement on-the-fly recalibration
tr_debug("!!!! Calling for calibration\n");
}
/**
* Interrupt level callback to signify when the radio changes state.
*
* @param[in] state Current state of the radio, as defined by EFR32 data sheet
*/
void RAILCb_RadioStateChanged(uint8_t state) {
return;
}
/**
* This function is called when the RAIL timer expires
*
* You must implement a stub for this in your RAIL application even if you
* don't use the timer.
*/
void RAILCb_TimerExpired(void) {
}
/**
* Interrupt level callback to signify when the packet was sent
* @param txPacketInfo Information about the packet that was transmitted.
* @note that this structure is only valid during the timeframe of the
* callback.
*/
void RAILCb_TxPacketSent(RAIL_TxPacketInfo_t *txPacketInfo) {
if(device_driver.phy_tx_done_cb != NULL) {
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
// Normally we'd switch on ACK requested here, but Nanostack does that for us.
PHY_LINK_TX_SUCCESS,
// Succeeded, so how many times we tried is really not relevant.
1,
1);
}
last_tx = RAIL_GetTime();
radio_state = RADIO_RX;
}
/**
* Receive packet callback.
*
* @param[in] rxPacketHandle Contains a handle that points to the memory that
* the packet was stored in. This handle will be the same as something
* returned by the RAILCb_AllocateMemory() API. To convert this into a receive
* packet info struct use the *** function.
*
* This function is called whenever a packet is received and returns to you the
* memory handle for where this received packet and its appended information was
* stored. After this callback is done we will release the memory handle so you
* must somehow increment a reference count or copy the data out within this
* function.
*/
void RAILCb_RxPacketReceived(void *rxPacketHandle) {
RAIL_RxPacketInfo_t* rxPacketInfo = (RAIL_RxPacketInfo_t*) memoryPtrFromHandle(rxPacketHandle);
if(rxPacketInfo->appendedInfo.crcStatus) {
/* If this is an ACK, deal with it */
if( rxPacketInfo->dataLength == 4 &&
rxPacketInfo->dataPtr[3] == (current_tx_sequence) &&
waiting_for_ack) {
/* Tell the radio to not ACK an ACK */
RAIL_AutoAckCancelAck();
waiting_for_ack = false;
/* Save the pending bit */
last_ack_pending_bit = (rxPacketInfo->dataPtr[1] & (1 << 4)) != 0;
/* Tell the stack we got an ACK */
tr_debug("rACK\n");
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
PHY_LINK_TX_DONE,
1,
1);
} else {
/* Figure out whether we want to not ACK this packet */
/*
* dataPtr[0] = length
* dataLength = length w/o length byte
* dataptr[1:2] = 0x61C9 -> 0b01100001 0b1100 1001 (version 1, dest 3, src 2, ACKreq, type = 1)
* [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( (rxPacketInfo->dataPtr[1] & (1 << 5)) == 0 ) {
/* Cancel the ACK if the sender did not request one */
RAIL_AutoAckCancelAck();
}
tr_debug("rPKT %d\n", rxPacketInfo->dataLength);
/* Feed the received packet into the stack */
device_driver.phy_rx_cb(rxPacketInfo->dataPtr + 1,
rxPacketInfo->dataLength - 1,
//TODO: take a new RAIL release that exposes LQI, or have LQI as function of RSSI
255,
rxPacketInfo->appendedInfo.rssiLatch,
rf_radio_driver_id);
}
}
}
/**
* Callback for when a Data Request is being received
*
* @param address The source address of the data request command
*
* This function is called when the command byte of an incoming frame is for a
* data request, which requests an ACK. This callback will be called before the
* packet is fully received, to allow the node to have more time to decide
* whether to set frame pending in the outgoing ACK.
*/
void RAILCb_IEEE802154_DataRequestCommand(RAIL_IEEE802154_Address_t *address) {
if(data_pending) {
RAIL_IEEE802154_SetFramePending();
}
}
/**
* Callback that notifies the application when searching for an ACK has timed
* out.
*
* @return void
*
* This callback function is called whenever the timeout for searching for an
* ack is exceeded.
*/
void RAILCb_RxAckTimeout(void) {
if(waiting_for_ack) {
waiting_for_ack = false;
device_driver.phy_tx_done_cb( rf_radio_driver_id,
current_tx_handle,
PHY_LINK_TX_FAIL,
1,
1);
}
}
/**
* Function to check the requested channel against the current channel,
* and change the radio configuration if necessary.
*
* @param channel The new channel number requested
* @return bool True if able to switch to the requested channel
*
*/
static bool rail_checkAndSwitchChannel(uint8_t newChannel) {
if(channel == newChannel) {
return true;
}
if(newChannel > 0 && newChannel < 11) {
if(MBED_CONF_SL_RAIL_BAND == 915) {
channel = newChannel;
return true;
} else {
return false;
}
} else if(newChannel >= 11 && newChannel <= 26) {
if(MBED_CONF_SL_RAIL_BAND == 2400) {
channel = newChannel;
return true;
} else {
return false;
}
} else {
return false;
}
}

View File

@ -0,0 +1,6 @@
{
"name": "sl-rail",
"config": {
"band": 2400
}
}