RCP firmware
When using Silicon Labs hardware, developers have 2 options to build the RCP firmware
- Either from the OpenThread repository
-
Directly within Simplicity Studio
This first method will not be covered in this guide
Modify RCP firmware
In order to be woken-up on a specifc 802.15.4 packet some modificationare necessary in RCP firmware.
-
Modify
ncp_base_radio.cpp
located ingecko_sdk_x.x\util\third_party\openthread\src\ncp
as following:extern "C" void magic_packet_test(otRadioFrame *aFrame); void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError) { uint8_t header = SPINEL_HEADER_FLAG; OT_ASSERT(aFrame->mIid < kSpinelHeaderMaxNumIID); header |= SPINEL_HEADER_IID(aFrame->mIid); magic_packet_test(aFrame); // Append frame header SuccessOrExit(mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_STREAM_RAW)); SuccessOrExit(PackRadioFrame(aFrame, aError)); SuccessOrExit(mEncoder.EndFrame()); exit: return; }
The
LinkRawReceiveDone
function is called on receipt of a IEEE 802.15.4 frame. -
Create a magic_packet.c file in the RCP project directory and add the following content to it:
#include <stdio.h> #include <openthread/ncp.h> #include "openthread-system.h" #include "em_gpio.h" #include "gpiointerrupt.h" #define ENTER_MAGIC_PKT_MODE_GPIO_PORT gpioPortD #define ENTER_MAGIC_PKT_MODE_GPIO_PIN 14 #define MAGIC_PKT_FOUND_GPIO_PORT gpioPortD #define MAGIC_PKT_FOUND_GPIO_PIN 8 uint8_t volatile magic_pkt_mode = 0; static otInstance* sInstance = NULL; /* Use falling edge of a GPIO to enter magic packet detection mode */ void ENTER_MAGIC_PKT_MODE_GPIO_callback(void) { uint8_t v = GPIO_PinInGet(ENTER_MAGIC_PKT_MODE_GPIO_PORT, ENTER_MAGIC_PKT_MODE_GPIO_PIN); /* Check if falling edge */ if (v == 0) magic_pkt_mode = 1; } /* Raise a GPIO when magic packet is detected */ void magic_packet_test(otRadioFrame *aFrame) { uint16_t panId = *(uint16_t *)((aFrame->mPsdu) + 3); uint16_t dst = *(uint16_t *)((aFrame->mPsdu) + 5); uint16_t src = *(uint16_t *)((aFrame->mPsdu) + 7); /* Any other tests can be added there */ if ((magic_pkt_mode == 1) && (panId == otLinkGetPanId(sInstance)) && (dst == 0xFFFF) && (src == 0xFFFF)) { GPIO_PinOutSet(MAGIC_PKT_FOUND_GPIO_PORT, MAGIC_PKT_FOUND_GPIO_PIN); magic_pkt_mode = 0; } } void magic_packet_init(otInstance *aInstance) { sInstance = aInstance; //GPIOINT_Init() and CMU_ClockEnable(cmuClock_GPIO) have already been called // Configure Button as input and enable interrupt GPIO_PinModeSet(ENTER_MAGIC_PKT_MODE_GPIO_PORT, ENTER_MAGIC_PKT_MODE_GPIO_PIN, gpioModeInputPull, 1); GPIO_ExtIntConfig(ENTER_MAGIC_PKT_MODE_GPIO_PORT, ENTER_MAGIC_PKT_MODE_GPIO_PIN, ENTER_MAGIC_PKT_MODE_GPIO_PIN, false, true, true); // Register callback functions and enable interrupts GPIOINT_CallbackRegister(ENTER_MAGIC_PKT_MODE_GPIO_PIN, ENTER_MAGIC_PKT_MODE_GPIO_callback); GPIO_IntEnable(1<<ENTER_MAGIC_PKT_MODE_GPIO_PIN); // Configure LED as a push pull output for LED drive GPIO_PinModeSet(MAGIC_PKT_FOUND_GPIO_PORT, MAGIC_PKT_FOUND_GPIO_PIN, gpioModePushPull, 0); }
We discriminate the magic packet here based on panId, SrcId and DstId of 802.15.4 received packet. We also use A GPIO to start searching for the magic packet. This code has been tested on BRD4166a only. You will have to modify
MAGIC_PKT_FOUND_GPIO
andENTER_MAGIC_PKT_MODE_GPIO
to have it work on another platform. -
Call
magic_packet_init()
function from app_init():void app_init(void) { OT_SETUP_RESET_JUMP(argv); magic_packet_init(sInstance); }
Build and Flash the RCP
After compilation, flash the firmware into EFR32. Don't forget to add a bootloader. If you want to use printf for debugging, enable the Tiny printf
component and the IOStream RTT
component, and use a RTT console to display log.