Imported more library files
Not compiling currently
This commit is contained in:
473
Libs/protocol/openthread/platform-abstraction/efr32/diag.c
Normal file
473
Libs/protocol/openthread/platform-abstraction/efr32/diag.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Copyright (c) 2023, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the OpenThread platform abstraction for the diagnostics.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef SL_COMPONENT_CATALOG_PRESENT
|
||||
#include "sl_component_catalog.h"
|
||||
#endif // SL_COMPONENT_CATALOG_PRESENT
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <utils/code_utils.h>
|
||||
#include <openthread/cli.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/logging.hpp"
|
||||
|
||||
#include "diag.h"
|
||||
|
||||
#include "sl_gpio.h"
|
||||
#include "sl_hal_gpio.h"
|
||||
|
||||
#include "platform-band.h"
|
||||
#include "platform-efr32.h"
|
||||
#include "rail_ieee802154.h"
|
||||
|
||||
#include "sl_status.h"
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
#ifdef SL_COMPONENT_CATALOG_PRESENT
|
||||
#include "sl_component_catalog.h"
|
||||
#endif // SL_COMPONENT_CATALOG_PRESENT
|
||||
|
||||
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
|
||||
#include "sl_rail_util_ant_div.h"
|
||||
#endif
|
||||
|
||||
#define GPIO_PIN_BITMASK 0xFFFFUL
|
||||
#define GPIO_PORT_BITMASK (0xFFFFUL << 16)
|
||||
#define GET_GPIO_PIN(x) (x & GPIO_PIN_BITMASK)
|
||||
#define GET_GPIO_PORT(x) ((x & GPIO_PORT_BITMASK) >> 16)
|
||||
|
||||
// To cache the transmit power, so that we don't override it while loading the
|
||||
// channel config or setting the channel.
|
||||
static int8_t sTxPower = OPENTHREAD_CONFIG_DEFAULT_TRANSMIT_POWER;
|
||||
|
||||
struct PlatformDiagCommand
|
||||
{
|
||||
const char *mName;
|
||||
otError (*mCommand)(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[]);
|
||||
};
|
||||
|
||||
// Diagnostics mode variables.
|
||||
static bool sDiagMode = false;
|
||||
|
||||
static otPlatDiagOutputCallback sDiagOutputCallback = NULL;
|
||||
static void *sDiagCallbackContext = NULL;
|
||||
|
||||
static void diagOutput(const char *aFormat, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, aFormat);
|
||||
|
||||
if (sDiagOutputCallback != NULL)
|
||||
{
|
||||
sDiagOutputCallback(aFormat, args, sDiagCallbackContext);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void appendErrorResult(otError aError)
|
||||
{
|
||||
if (aError != OT_ERROR_NONE)
|
||||
{
|
||||
diagOutput("failed\r\nstatus %#x\r\n", aError);
|
||||
}
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// CLI functions
|
||||
// *****************************************************************************
|
||||
static otError processAddressMatch(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
if (strcmp(aArgs[0], "enable") == 0)
|
||||
{
|
||||
error = otPlatDiagRadioAddressMatch(true);
|
||||
}
|
||||
else if (strcmp(aArgs[0], "disable") == 0)
|
||||
{
|
||||
error = otPlatDiagRadioAddressMatch(false);
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static otError processAutoAck(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_INVALID_ARGS;
|
||||
|
||||
VerifyOrExit(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
if (strcmp(aArgs[0], "enable") == 0)
|
||||
{
|
||||
error = otPlatDiagRadioAutoAck(true);
|
||||
}
|
||||
else if (strcmp(aArgs[0], "disable") == 0)
|
||||
{
|
||||
error = otPlatDiagRadioAutoAck(false);
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// Add more platform specific diagnostic's CLI features here.
|
||||
// *****************************************************************************
|
||||
const struct PlatformDiagCommand sCommands[] = {
|
||||
{"addr-match", &processAddressMatch},
|
||||
{"auto-ack", &processAutoAck},
|
||||
};
|
||||
|
||||
otError otPlatDiagProcess(otInstance *aInstance, uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_INVALID_COMMAND;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < otARRAY_LENGTH(sCommands); i++)
|
||||
{
|
||||
if (strcmp(aArgs[0], sCommands[i].mName) == 0)
|
||||
{
|
||||
error = sCommands[i].mCommand(aInstance, aArgsLength - 1, aArgsLength > 1 ? &aArgs[1] : NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
// Implement platform specific diagnostic's APIs.
|
||||
// *****************************************************************************
|
||||
|
||||
void otPlatDiagSetOutputCallback(otInstance *aInstance, otPlatDiagOutputCallback aCallback, void *aContext)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sDiagOutputCallback = aCallback;
|
||||
sDiagCallbackContext = aContext;
|
||||
}
|
||||
|
||||
void otPlatDiagModeSet(bool aMode)
|
||||
{
|
||||
sDiagMode = aMode;
|
||||
}
|
||||
|
||||
bool otPlatDiagModeGet()
|
||||
{
|
||||
return sDiagMode;
|
||||
}
|
||||
|
||||
static RAIL_Status_t startTxStream(RAIL_StreamMode_t aMode)
|
||||
{
|
||||
uint16_t txChannel;
|
||||
RAIL_Status_t status;
|
||||
|
||||
SuccessOrExit(status = RAIL_GetChannel(gRailHandle, &txChannel));
|
||||
|
||||
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
|
||||
RAIL_TxOptions_t txOptions = RAIL_TX_OPTIONS_DEFAULT;
|
||||
// Translate Tx antenna diversity mode into RAIL Tx Antenna options:
|
||||
// If enabled, use the currently-selected antenna, otherwise leave
|
||||
// both options 0 so Tx antenna tracks Rx antenna.
|
||||
if (sl_rail_util_ant_div_get_tx_antenna_mode() != SL_RAIL_UTIL_ANTENNA_MODE_DISABLED)
|
||||
{
|
||||
txOptions |= ((sl_rail_util_ant_div_get_tx_antenna_selected() == SL_RAIL_UTIL_ANTENNA_SELECT_ANTENNA1)
|
||||
? RAIL_TX_OPTION_ANTENNA0
|
||||
: RAIL_TX_OPTION_ANTENNA1);
|
||||
}
|
||||
|
||||
status = RAIL_StartTxStreamAlt(gRailHandle, txChannel, aMode, txOptions);
|
||||
#else // !SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
|
||||
status = RAIL_StartTxStream(gRailHandle, txChannel, aMode);
|
||||
#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static RAIL_Status_t stopTxStream(void)
|
||||
{
|
||||
RAIL_Status_t status;
|
||||
uint16_t currentChannel;
|
||||
RAIL_SchedulerInfo_t rxSchedulerInfo = {
|
||||
.priority = SL_802154_RADIO_PRIO_BACKGROUND_RX_VALUE,
|
||||
};
|
||||
|
||||
SuccessOrExit(status = RAIL_StopTxStream(gRailHandle));
|
||||
// Since start transmit stream turn off the radio state,
|
||||
// call the RAIL_StartRx to turn on radio
|
||||
IgnoreError(RAIL_GetChannel(gRailHandle, ¤tChannel));
|
||||
|
||||
status = RAIL_StartRx(gRailHandle, currentChannel, &rxSchedulerInfo);
|
||||
OT_ASSERT(status == RAIL_STATUS_NO_ERROR);
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
otError otPlatDiagRadioTransmitCarrier(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
RAIL_Status_t status;
|
||||
|
||||
if (aEnable)
|
||||
{
|
||||
otLogInfoPlat("Diag CARRIER-WAVE/Tone start");
|
||||
status = startTxStream(RAIL_STREAM_CARRIER_WAVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoPlat("Diag CARRIER-WAVE/Tone stop");
|
||||
status = stopTxStream();
|
||||
}
|
||||
return (status != RAIL_STATUS_NO_ERROR ? OT_ERROR_FAILED : OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
otError otPlatDiagRadioTransmitStream(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
RAIL_Status_t status;
|
||||
|
||||
if (aEnable)
|
||||
{
|
||||
otLogInfoPlat("Diag Stream PN9 start");
|
||||
status = startTxStream(RAIL_STREAM_PN9_STREAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoPlat("Diag Stream stop");
|
||||
status = stopTxStream();
|
||||
}
|
||||
return (status != RAIL_STATUS_NO_ERROR ? OT_ERROR_FAILED : OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
otError otPlatDiagRadioAddressMatch(bool aEnable)
|
||||
{
|
||||
RAIL_Status_t status;
|
||||
|
||||
otLogInfoPlat("Diag address-match %s", aEnable ? "enable" : "disable");
|
||||
|
||||
status = RAIL_IEEE802154_SetPromiscuousMode(gRailHandle, !aEnable);
|
||||
return (status != RAIL_STATUS_NO_ERROR ? OT_ERROR_FAILED : OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
otError otPlatDiagRadioAutoAck(bool aAutoAckEnabled)
|
||||
{
|
||||
otLogInfoPlat("Diag auto-ack %s", aAutoAckEnabled ? "enable" : "disable");
|
||||
|
||||
RAIL_PauseRxAutoAck(gRailHandle, !aAutoAckEnabled);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
void otPlatDiagChannelSet(uint8_t aChannel)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
RAIL_Status_t status;
|
||||
|
||||
RAIL_SchedulerInfo_t bgRxSchedulerInfo = {
|
||||
.priority = SL_802154_RADIO_PRIO_BACKGROUND_RX_VALUE,
|
||||
// sliptime/transaction time is not used for bg rx
|
||||
};
|
||||
|
||||
error = efr32RadioLoadChannelConfig(aChannel, sTxPower);
|
||||
OT_ASSERT(error == OT_ERROR_NONE);
|
||||
|
||||
status = RAIL_StartRx(gRailHandle, aChannel, &bgRxSchedulerInfo);
|
||||
OT_ASSERT(status == RAIL_STATUS_NO_ERROR);
|
||||
}
|
||||
|
||||
void otPlatDiagTxPowerSet(int8_t aTxPower)
|
||||
{
|
||||
RAIL_Status_t status;
|
||||
|
||||
// RAIL_SetTxPowerDbm() takes power in units of deci-dBm (0.1dBm)
|
||||
// Multiply by 10 because aPower is supposed be in units dBm
|
||||
status = RAIL_SetTxPowerDbm(gRailHandle, ((RAIL_TxPower_t)aTxPower) * 10);
|
||||
OT_ASSERT(status == RAIL_STATUS_NO_ERROR);
|
||||
sTxPower = aTxPower;
|
||||
}
|
||||
|
||||
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(aFrame);
|
||||
OT_UNUSED_VARIABLE(aError);
|
||||
}
|
||||
|
||||
void otPlatDiagAlarmCallback(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
}
|
||||
|
||||
static otError getGpioPortAndPin(uint32_t aGpio, uint16_t *aPort, uint16_t *aPin)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
*aPort = GET_GPIO_PORT(aGpio);
|
||||
*aPin = GET_GPIO_PIN(aGpio);
|
||||
|
||||
#if defined(SL_CATALOG_GPIO_PRESENT)
|
||||
if (*aPort > SL_HAL_GPIO_PORT_MAX || *aPin > SL_HAL_GPIO_PIN_MAX)
|
||||
#else
|
||||
if (*aPort > GPIO_PORT_MAX || *aPin > GPIO_PIN_MAX)
|
||||
#endif
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatDiagGpioSet(uint32_t aGpio, bool aValue)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t port;
|
||||
uint16_t pin;
|
||||
|
||||
SuccessOrExit(error = getGpioPortAndPin(aGpio, &port, &pin));
|
||||
|
||||
sl_gpio_t gpio;
|
||||
|
||||
gpio.port = (uint8_t)port;
|
||||
gpio.pin = (uint8_t)pin;
|
||||
|
||||
if (aValue)
|
||||
{
|
||||
VerifyOrExit(sl_gpio_set_pin(&gpio) == SL_STATUS_OK, error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(sl_gpio_clear_pin(&gpio) == SL_STATUS_OK, error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatDiagGpioGet(uint32_t aGpio, bool *aValue)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t port;
|
||||
uint16_t pin;
|
||||
|
||||
SuccessOrExit(error = getGpioPortAndPin(aGpio, &port, &pin));
|
||||
|
||||
sl_gpio_t gpio;
|
||||
|
||||
gpio.port = (uint8_t)port;
|
||||
gpio.pin = (uint8_t)pin;
|
||||
|
||||
VerifyOrExit(sl_gpio_get_pin_input(&gpio, aValue) == SL_STATUS_OK, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatDiagGpioSetMode(uint32_t aGpio, otGpioMode aMode)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t port;
|
||||
uint16_t pin;
|
||||
sl_gpio_mode_t mode;
|
||||
|
||||
SuccessOrExit(error = getGpioPortAndPin(aGpio, &port, &pin));
|
||||
|
||||
mode = (aMode == OT_GPIO_MODE_INPUT) ? SL_GPIO_MODE_INPUT : SL_GPIO_MODE_PUSH_PULL;
|
||||
|
||||
sl_gpio_t gpio;
|
||||
|
||||
gpio.port = (uint8_t)port;
|
||||
gpio.pin = (uint8_t)pin;
|
||||
|
||||
error = sl_gpio_set_pin_mode(&gpio, mode, 0 /*out*/);
|
||||
|
||||
// Convert to otError.
|
||||
VerifyOrExit(error == SL_STATUS_OK,
|
||||
error = (error == SL_STATUS_INVALID_STATE ? OT_ERROR_INVALID_STATE : OT_ERROR_INVALID_ARGS));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatDiagGpioGetMode(uint32_t aGpio, otGpioMode *aMode)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t port;
|
||||
uint16_t pin;
|
||||
sl_gpio_mode_t mode;
|
||||
|
||||
SuccessOrExit(error = getGpioPortAndPin(aGpio, &port, &pin));
|
||||
|
||||
sl_gpio_t gpio;
|
||||
sl_gpio_pin_config_t pin_config;
|
||||
|
||||
gpio.port = (uint8_t)port;
|
||||
gpio.pin = (uint8_t)pin;
|
||||
|
||||
VerifyOrExit(sl_gpio_get_pin_config(&gpio, &pin_config) == SL_STATUS_OK, error = OT_ERROR_INVALID_ARGS);
|
||||
mode = pin_config.mode;
|
||||
|
||||
*aMode = (mode == SL_GPIO_MODE_INPUT) ? OT_GPIO_MODE_INPUT : OT_GPIO_MODE_OUTPUT;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
Reference in New Issue
Block a user