Files
GClarkson 9d06f983af Imported more library files
Not compiling currently
2025-04-12 23:37:19 +01:00

524 lines
15 KiB
C

/*
* 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 vendor additions to radio communication.
*
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include "radio_extension.h"
#ifdef SL_COMPONENT_CATALOG_PRESENT
#include "sl_component_catalog.h"
#endif // SL_COMPONENT_CATALOG_PRESENT
#ifndef SL_CATALOG_OT_SIMULATION_PRESENT
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
#include "coexistence-802154.h"
#include "coexistence.h"
#endif // SL_CATALOG_RAIL_UTIL_COEX_PRESENT
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
#include "sl_rail_util_ant_div.h"
#endif // SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
#ifdef SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT_PRESENT
#include "sl_rail_util_ieee802154_phy_select.h"
#endif // SL_CATALOG_RAIL_UTIL_IEEE802154_PHY_SELECT
#ifdef SL_CATALOG_OPENTHREAD_TEST_CLI_PRESENT
#include "rail_ieee802154.h"
#endif // SL_CATALOG_OPENTHREAD_TEST_CLI_PRESENT
#else // SL_CATALOG_OT_SIMULATION_PRESENT
#include "rail_util_simulation.h"
#endif // SL_CATALOG_OT_SIMULATION_PRESENT
#include "common/code_utils.hpp"
#ifdef SL_CATALOG_OPENTHREAD_ANT_DIV_PRESENT
otError otPlatRadioExtensionGetTxAntennaMode(uint8_t *aMode)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
VerifyOrExit(aMode != NULL, error = OT_ERROR_INVALID_ARGS);
*aMode = (uint8_t)sl_rail_util_ant_div_get_tx_antenna_mode();
#else
OT_UNUSED_VARIABLE(aMode);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetTxAntennaMode(uint8_t aMode)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
sl_status_t status = sl_rail_util_ant_div_set_tx_antenna_mode(aMode);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aMode);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetRxAntennaMode(uint8_t *aMode)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
VerifyOrExit(aMode != NULL, error = OT_ERROR_INVALID_ARGS);
*aMode = (uint8_t)sl_rail_util_ant_div_get_rx_antenna_mode();
#else
OT_UNUSED_VARIABLE(aMode);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetRxAntennaMode(uint8_t aMode)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
sl_status_t status = sl_rail_util_ant_div_set_rx_antenna_mode(aMode);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aMode);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetActivePhy(uint8_t *aActivePhy)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_ANT_DIV_PRESENT
VerifyOrExit(aActivePhy != NULL, error = OT_ERROR_INVALID_ARGS);
*aActivePhy = (uint8_t)sl_rail_util_ieee802154_get_active_radio_config();
#else
OT_UNUSED_VARIABLE(aActivePhy);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
#endif // SL_CATALOG_OPENTHREAD_ANT_DIV_PRESENT
#ifdef SL_CATALOG_OPENTHREAD_COEX_PRESENT
otError otPlatRadioExtensionGetDpState(uint8_t *aDpPulse)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aDpPulse != NULL, error = OT_ERROR_INVALID_ARGS);
*aDpPulse = (uint8_t)sl_rail_util_coex_get_directional_priority_pulse_width();
#else
OT_UNUSED_VARIABLE(aDpPulse);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetDpState(uint8_t aDpPulse)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_directional_priority_pulse_width(aDpPulse);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aDpPulse);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetGpioInputOverride(uint8_t aGpioIndex, bool *aEnabled)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit((COEX_GpioIndex_t)aGpioIndex < COEX_GPIO_INDEX_COUNT, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aEnabled != NULL, error = OT_ERROR_INVALID_ARGS);
*aEnabled = sl_rail_util_coex_get_gpio_input_override(aGpioIndex);
#else
OT_UNUSED_VARIABLE(aGpioIndex);
OT_UNUSED_VARIABLE(aEnabled);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetGpioInputOverride(uint8_t aGpioIndex, bool aEnabled)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status;
VerifyOrExit((COEX_GpioIndex_t)aGpioIndex < COEX_GPIO_INDEX_COUNT, error = OT_ERROR_INVALID_ARGS);
status = sl_rail_util_coex_set_gpio_input_override((COEX_GpioIndex_t)aGpioIndex, aEnabled);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aGpioIndex);
OT_UNUSED_VARIABLE(aEnabled);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetActiveRadio(uint8_t *aActivePhy)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aActivePhy != NULL, error = OT_ERROR_INVALID_ARGS);
*aActivePhy = (uint8_t)sl_rail_util_ieee802154_get_active_radio_config();
#else
OT_UNUSED_VARIABLE(aActivePhy);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetPhySelectTimeout(uint8_t *aTimeout)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aTimeout != NULL, error = OT_ERROR_INVALID_ARGS);
*aTimeout = sl_rail_util_coex_get_phy_select_timeout();
#else
OT_UNUSED_VARIABLE(aTimeout);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetPhySelectTimeout(uint8_t aTimeout)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_phy_select_timeout(aTimeout);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aTimeout);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetCoexOptions(uint32_t *aPtaOptions)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aPtaOptions != NULL, error = OT_ERROR_INVALID_ARGS);
*aPtaOptions = (uint32_t)sl_rail_util_coex_get_options();
#else
OT_UNUSED_VARIABLE(aPtaOptions);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetCoexOptions(uint32_t aPtaOptions)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_options(aPtaOptions);
VerifyOrExit(status != SL_STATUS_INVALID_PARAMETER, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aPtaOptions);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetCoexConstantOptions(uint32_t *aPtaOptions)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aPtaOptions != NULL, error = OT_ERROR_INVALID_ARGS);
*aPtaOptions = (uint32_t)sl_rail_util_coex_get_constant_options();
#else
OT_UNUSED_VARIABLE(aPtaOptions);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionIsCoexEnabled(bool *aPtaState)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
VerifyOrExit(aPtaState != NULL, error = OT_ERROR_INVALID_ARGS);
*aPtaState = sl_rail_util_coex_is_enabled();
#else
OT_UNUSED_VARIABLE(aPtaState);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetCoexEnable(bool aPtaState)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_enable(aPtaState);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aPtaState);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionGetRequestPwmArgs(uint8_t *aPwmReq, uint8_t *aPwmDutyCycle, uint8_t *aPwmPeriodHalfMs)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
const sl_rail_util_coex_pwm_args_t *p;
VerifyOrExit(aPwmReq != NULL, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aPwmDutyCycle != NULL, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aPwmPeriodHalfMs != NULL, error = OT_ERROR_INVALID_ARGS);
p = sl_rail_util_coex_get_request_pwm_args();
VerifyOrExit(p != NULL, error = OT_ERROR_FAILED);
*aPwmReq = p->req;
*aPwmDutyCycle = p->dutyCycle;
*aPwmPeriodHalfMs = p->periodHalfMs;
#else
OT_UNUSED_VARIABLE(aPwmReq);
OT_UNUSED_VARIABLE(aPwmDutyCycle);
OT_UNUSED_VARIABLE(aPwmPeriodHalfMs);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetRequestPwmArgs(uint8_t aPwmReq, uint8_t aPwmDutyCycle, uint8_t aPwmPeriodHalfMs)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_request_pwm(aPwmReq, NULL, aPwmDutyCycle, aPwmPeriodHalfMs);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aPwmReq);
OT_UNUSED_VARIABLE(aPwmDutyCycle);
OT_UNUSED_VARIABLE(aPwmPeriodHalfMs);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
#if defined(SL_CATALOG_RAIL_UTIL_COEX_PRESENT) && SL_OPENTHREAD_COEX_COUNTER_ENABLE
extern uint32_t efr32RadioCoexCounters[SL_RAIL_UTIL_COEX_EVENT_COUNT];
extern void efr32RadioClearCoexCounters(void);
#endif
otError otPlatRadioExtensionClearCoexCounters(void)
{
otError error = OT_ERROR_NONE;
#if defined(SL_CATALOG_RAIL_UTIL_COEX_PRESENT) && SL_OPENTHREAD_COEX_COUNTER_ENABLE
efr32RadioClearCoexCounters();
#else
error = OT_ERROR_NOT_IMPLEMENTED;
#endif
return error;
}
otError otPlatRadioExtensionGetCoexCounters(uint8_t aNumEntries, uint32_t aCoexCounters[])
{
otError error = OT_ERROR_NONE;
#if defined(SL_CATALOG_RAIL_UTIL_COEX_PRESENT) && SL_OPENTHREAD_COEX_COUNTER_ENABLE
VerifyOrExit(aNumEntries == OT_PLAT_RADIO_EXTENSION_COEX_EVENT_COUNT, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(aCoexCounters != NULL, error = OT_ERROR_INVALID_ARGS);
_Static_assert((uint8_t)OT_PLAT_RADIO_EXTENSION_COEX_EVENT_COUNT == (uint8_t)SL_RAIL_UTIL_COEX_EVENT_COUNT,
"Coex counter mismatch. OT_PLAT_RADIO_EXTENSION_COEX_EVENT_COUNT != SL_RAIL_UTIL_COEX_EVENT_COUNT");
#define COPY_COEX_COUNTER(counter) \
aCoexCounters[OT_PLAT_RADIO_EXTENSION_COEX_EVENT_##counter] = \
efr32RadioCoexCounters[SL_RAIL_UTIL_COEX_EVENT_##counter]
COPY_COEX_COUNTER(LO_PRI_REQUESTED);
COPY_COEX_COUNTER(HI_PRI_REQUESTED);
COPY_COEX_COUNTER(LO_PRI_DENIED);
COPY_COEX_COUNTER(HI_PRI_DENIED);
COPY_COEX_COUNTER(LO_PRI_TX_ABORTED);
COPY_COEX_COUNTER(HI_PRI_TX_ABORTED);
#else
OT_UNUSED_VARIABLE(aNumEntries);
OT_UNUSED_VARIABLE(aCoexCounters);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionSetRadioHoldoff(bool aEnabled)
{
otError error = OT_ERROR_NONE;
#ifdef SL_CATALOG_RAIL_UTIL_COEX_PRESENT
sl_status_t status = sl_rail_util_coex_set_radio_holdoff(aEnabled);
VerifyOrExit(status == SL_STATUS_OK, error = OT_ERROR_FAILED);
#else
OT_UNUSED_VARIABLE(aEnabled);
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
#endif // SL_CATALOG_OPENTHREAD_COEX_PRESENT
#ifdef SL_CATALOG_OPENTHREAD_TEST_CLI_PRESENT
extern RAIL_IEEE802154_PtiRadioConfig_t efr32GetPtiRadioConfig(void);
extern RAIL_Status_t efr32RadioSetCcaMode(uint8_t aMode);
otError otPlatRadioExtensionGetPtiRadioConfig(uint16_t *radioConfig)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(radioConfig != NULL, error = OT_ERROR_INVALID_ARGS);
*radioConfig = (uint16_t)efr32GetPtiRadioConfig();
exit:
return error;
}
otError otPlatRadioExtensionSetCcaMode(uint8_t aMode)
{
otError error = OT_ERROR_NONE;
RAIL_Status_t status = efr32RadioSetCcaMode(aMode);
VerifyOrExit(status != RAIL_STATUS_INVALID_PARAMETER, error = OT_ERROR_INVALID_ARGS);
VerifyOrExit(status == RAIL_STATUS_NO_ERROR, error = OT_ERROR_FAILED);
exit:
return error;
}
#endif // SL_CATALOG_OPENTHREAD_TEST_CLI_PRESENT
#ifdef SL_CATALOG_OPENTHREAD_EFR32_EXT_PRESENT
extern otError efr32GetRadioCounters(efr32RadioCounters *aRadioCounters);
extern otError efr32ClearRadioCounters(void);
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
extern efr32RadioCounters railDebugCounters;
#endif
otError otPlatRadioExtensionGetRadioCounters(efr32RadioCounters *aRadioCounters)
{
otError error = OT_ERROR_NONE;
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
VerifyOrExit(aRadioCounters != NULL, error = OT_ERROR_INVALID_ARGS);
*aRadioCounters = railDebugCounters;
#else
ExitNow(error = OT_ERROR_NOT_IMPLEMENTED);
#endif
exit:
return error;
}
otError otPlatRadioExtensionClearRadioCounters(void)
{
otError error = OT_ERROR_NONE;
#if RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
efr32ClearRadioCounters();
#else
error = OT_ERROR_NOT_IMPLEMENTED;
#endif
return error;
}
#endif // SL_CATALOG_OPENTHREAD_EFR32_EXT_PRESENT