[radio] use stack reset in RCP (#6645)

This commit makes RCP use a stack reset instead of doing a hard reset
when a reset command is received.
This commit is contained in:
jinran-google
2021-09-17 18:36:26 -07:00
committed by GitHub
parent 8841bdd38d
commit ee58635945
17 changed files with 427 additions and 35 deletions
+24
View File
@@ -240,6 +240,30 @@ jobs:
run: |
script/check-posix-pty check
rcp-stack-reset:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Bootstrap
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: |
sudo apt-get --no-install-recommends install -y expect ninja-build lcov socat
sudo python3 -m pip install git+https://github.com/openthread/pyspinel
- name: Build
run: |
script/cmake-build simulation -DOT_CSL_RECEIVER=ON -DOT_FULL_LOGS=ON -DOT_LOG_OUTPUT=PLATFORM_DEFINED
- name: Run
run: |
python3 tests/scripts/misc/test_rcp_reset.py build/simulation/examples/apps/ncp/ot-rcp
- name: Generate Coverage
run: |
./script/test generate_coverage gcc
- uses: actions/upload-artifact@v2
with:
name: cov-rcp-stack-reset
path: tmp/coverage.info
upload-coverage:
needs:
- expects-linux
+17 -3
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (166)
#define OPENTHREAD_API_VERSION (167)
/**
* @addtogroup api-instance
@@ -244,17 +244,31 @@ void otRemoveStateChangeCallback(otInstance *aInstance, otStateChangedCallback a
* The reset process ensures that all the OpenThread state/info (stored in volatile memory) is erased. Note that the
* `otPlatformReset` does not erase any persistent state/info saved in non-volatile memory.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
void otInstanceReset(otInstance *aInstance);
/**
* This method deletes all the settings stored on non-volatile memory, and then triggers platform reset.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
void otInstanceFactoryReset(otInstance *aInstance);
/**
* This method resets the internal states of the OpenThread radio stack.
*
* Callbacks and configurations are preserved.
*
* This API is only available under radio builds (`OPENTHREAD_RADIO = 1`).
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
void otInstanceResetRadioStack(otInstance *aInstance);
/**
* This function erases all the OpenThread persistent info (network settings) stored on non-volatile memory.
* Erase is successful only if the device is in `disabled` state/role.
+9
View File
@@ -129,6 +129,15 @@ otError otInstanceErasePersistentInfo(otInstance *aInstance)
}
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO
void otInstanceResetRadioStack(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
instance.ResetRadioStack();
}
#endif
const char *otGetVersionString(void)
{
/**
+8
View File
@@ -173,6 +173,14 @@ void Instance::Reset(void)
otPlatReset(this);
}
#if OPENTHREAD_RADIO
void Instance::ResetRadioStack(void)
{
mRadio.Init();
mLinkRaw.Init();
}
#endif
void Instance::AfterInit(void)
{
mIsInitialized = true;
+8
View File
@@ -194,6 +194,14 @@ public:
*/
void Reset(void);
#if OPENTHREAD_RADIO
/**
* This method resets the internal states of the radio.
*
*/
void ResetRadioStack(void);
#endif
/**
* This method returns the active log level.
*
+15 -5
View File
@@ -51,17 +51,27 @@ namespace Mac {
LinkRaw::LinkRaw(Instance &aInstance)
: InstanceLocator(aInstance)
, mReceiveChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mPanId(kPanIdBroadcast)
, mReceiveDoneCallback(nullptr)
, mTransmitDoneCallback(nullptr)
, mEnergyScanDoneCallback(nullptr)
#if OPENTHREAD_RADIO
, mSubMac(aInstance)
#elif OPENTHREAD_CONFIG_LINK_RAW_ENABLE
, mSubMac(aInstance.Get<SubMac>())
#endif
{
Init();
}
void LinkRaw::Init(void)
{
mEnergyScanDoneCallback = nullptr;
mTransmitDoneCallback = nullptr;
mReceiveDoneCallback = nullptr;
mReceiveChannel = OPENTHREAD_CONFIG_DEFAULT_CHANNEL;
mPanId = kPanIdBroadcast;
mReceiveDoneCallback = nullptr;
#if OPENTHREAD_RADIO
mSubMac.Init();
#endif
}
Error LinkRaw::SetReceiveDone(otLinkRawReceiveDone aCallback)
+6
View File
@@ -65,6 +65,12 @@ public:
*/
explicit LinkRaw(Instance &aInstance);
/**
* This method initializes the states of the raw link-layer.
*
*/
void Init(void);
/**
* This method returns true if the raw link-layer is enabled.
*
+30 -14
View File
@@ -52,32 +52,48 @@ namespace Mac {
SubMac::SubMac(Instance &aInstance)
: InstanceLocator(aInstance)
, mRadioCaps(Get<Radio>().GetCaps())
, mState(kStateDisabled)
, mCsmaBackoffs(0)
, mTransmitRetries(0)
, mShortAddress(kShortAddrInvalid)
, mRxOnWhenBackoff(true)
, mEnergyScanMaxRssi(kInvalidRssiValue)
, mEnergyScanEndTime(0)
, mTransmitFrame(Get<Radio>().GetTransmitBuffer())
, mCallbacks(aInstance)
, mPcapCallback(nullptr)
, mPcapCallbackContext(nullptr)
, mFrameCounter(0)
, mKeyId(0)
, mTimer(aInstance, SubMac::HandleTimer)
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
, mCslPeriod(0)
, mCslChannel(0)
, mIsCslChannelSpecified(false)
, mCslLastSync(0)
, mCslParentAccuracy(kCslWorstCrystalPpm)
, mCslParentUncert(kCslWorstUncertainty)
, mCslState(kCslIdle)
, mCslTimer(aInstance, SubMac::HandleCslTimer)
#endif
{
Init();
}
void SubMac::Init(void)
{
mState = kStateDisabled;
mCsmaBackoffs = 0;
mTransmitRetries = 0;
mShortAddress = kShortAddrInvalid;
mExtAddress.Clear();
mRxOnWhenBackoff = true;
mEnergyScanMaxRssi = kInvalidRssiValue;
mEnergyScanEndTime = Time{0};
mPrevKey.Clear();
mCurrKey.Clear();
mNextKey.Clear();
mFrameCounter = 0;
mKeyId = 0;
mTimer.Stop();
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
mCslPeriod = 0;
mCslChannel = 0;
mIsCslChannelSpecified = false;
mCslSampleTime = TimeMicro{0};
mCslLastSync = TimeMicro{0};
mCslState = kCslIdle;
mCslTimer.Stop();
#endif
}
otRadioCaps SubMac::GetCaps(void) const
+11
View File
@@ -81,6 +81,10 @@ namespace Mac {
#error "OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE is required for OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE."
#endif
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
class LinkRaw;
#endif
/**
* This class implements the IEEE 802.15.4 MAC (sub-MAC).
*
@@ -101,6 +105,7 @@ namespace Mac {
class SubMac : public InstanceLocator, private NonCopyable
{
friend class Radio::Callbacks;
friend class LinkRaw;
public:
static constexpr int8_t kInvalidRssiValue = 127; ///< Invalid Received Signal Strength Indicator (RSSI) value.
@@ -591,6 +596,12 @@ private:
};
#endif
/**
* This method initializes the states of the sub-MAC layer.
*
*/
void Init(void);
bool RadioSupportsCsmaBackoff(void) const
{
return ((mRadioCaps & (OT_RADIO_CAPS_CSMA_BACKOFF | OT_RADIO_CAPS_TRANSMIT_RETRIES)) != 0);
+37
View File
@@ -33,6 +33,43 @@
namespace ot {
#if OPENTHREAD_RADIO
void Radio::Init(void)
{
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
Error error = OT_ERROR_NONE;
OT_UNUSED_VARIABLE(error);
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
error = EnableCsl(0, Mac::kShortAddrInvalid, nullptr);
OT_ASSERT(error == OT_ERROR_NONE);
#endif
EnableSrcMatch(false);
ClearSrcMatchShortEntries();
ClearSrcMatchExtEntries();
if (IsEnabled())
{
error = Sleep();
OT_ASSERT(error == OT_ERROR_NONE);
error = Disable();
OT_ASSERT(error == OT_ERROR_NONE);
}
SetPanId(Mac::kPanIdBroadcast);
SetExtendedAddress(Mac::ExtAddress{});
SetShortAddress(Mac::kShortAddrInvalid);
SetMacKey(0, 0, Mac::KeyMaterial{}, Mac::KeyMaterial{}, Mac::KeyMaterial{});
SetMacFrameCounter(0);
SetPromiscuous(false);
#endif // OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
}
#endif // OPENTHREAD_RADIO
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
void Radio::SetExtendedAddress(const Mac::ExtAddress &aExtAddress)
+8
View File
@@ -244,6 +244,14 @@ public:
*/
int8_t GetReceiveSensitivity(void);
#if OPENTHREAD_RADIO
/**
* This method initializes the states of the Thread radio.
*
*/
void Init(void);
#endif
/**
* This method sets the PAN ID for address filtering.
*
+10 -2
View File
@@ -851,6 +851,12 @@ enum
SPINEL_MD_FLAG_RESERVED = 0xFFC2, //!< Flags reserved for future use.
};
enum
{
SPINEL_RESET_PLATFORM = 1,
SPINEL_RESET_STACK = 2,
};
enum
{
/**
@@ -870,14 +876,16 @@ enum
/**
* Reset NCP command (Host -> NCP)
*
* Encoding: Empty
* Encoding: Empty or `C`
*
* Causes the NCP to perform a software reset. Due to the nature of
* this command, the TID is ignored. The host should instead wait
* for a `CMD_PROP_VALUE_IS` command from the NCP indicating
* `PROP_LAST_STATUS` has been set to `STATUS_RESET_SOFTWARE`.
*
* The command payload for this command SHOULD be empty.
* The optional command payload specifies the reset type, can be
* `SPINEL_RESET_PLATFORM` or `SPINEL_RESET_STACK`. Defaults to stack
* reset if unspecified.
*
* If an error occurs, the value of `PROP_LAST_STATUS` will be emitted
* instead with the value set to the generated status code for the error.
+36 -11
View File
@@ -1214,22 +1214,47 @@ otError NcpBase::CommandHandler_RESET(uint8_t aHeader)
{
OT_UNUSED_VARIABLE(aHeader);
otError error = OT_ERROR_NONE;
otError error = OT_ERROR_NONE;
uint8_t reset_type = SPINEL_RESET_STACK;
// Signal a platform reset. If implemented, this function
// shouldn't return.
otInstanceReset(mInstance);
if (mDecoder.GetRemainingLengthInStruct() > 0)
{
error = mDecoder.ReadUint8(reset_type);
OT_ASSERT(error == OT_ERROR_NONE);
}
#if OPENTHREAD_RADIO
if (reset_type == SPINEL_RESET_STACK)
{
otInstanceResetRadioStack(mInstance);
mIsRawStreamEnabled = false;
mCurTransmitTID = 0;
mCurScanChannel = kInvalidScanChannel;
mSrcMatchEnabled = false;
ResetCounters();
error = WriteLastStatusFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_STATUS_RESET_POWER_ON);
OT_ASSERT(error == OT_ERROR_NONE);
}
else
#endif
{
// Signal a platform reset. If implemented, this function
// shouldn't return.
otInstanceReset(mInstance);
#if OPENTHREAD_MTD || OPENTHREAD_FTD
// We only get to this point if the
// platform doesn't support resetting.
// In such a case we fake it.
IgnoreError(otThreadSetEnabled(mInstance, false));
IgnoreError(otIp6SetEnabled(mInstance, false));
// We only get to this point if the
// platform doesn't support resetting.
// In such a case we fake it.
IgnoreError(otThreadSetEnabled(mInstance, false));
IgnoreError(otIp6SetEnabled(mInstance, false));
#endif
sNcpInstance = nullptr;
sNcpInstance = nullptr;
}
return error;
}
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2021, 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.
#
source "tests/scripts/expect/_common.exp"
source "tests/scripts/expect/_multinode.exp"
# The expect on macOS doesn't support `try` or `file tempfile`.
skip_on_macos
file tempfile socat_out
set socat_pid [exec socat -d -d pty,raw,echo=0 pty,raw,echo=0 >/dev/null 2>$socat_out &]
while {true} {
if {[exec head -n2 $socat_out | wc -l] == 2} {
set radio_pty [exec head -n1 $socat_out | grep -o {/dev/.\+}]
set host_pty [exec head -n2 $socat_out | tail -n1 | grep -o {/dev/.\+}]
break
}
sleep 1
}
puts "Radio PTY: $radio_pty"
puts "Host PTY: $host_pty"
set rcp_pid [exec $::env(OT_SIMULATION_APPS)/ncp/ot-rcp 1 < $radio_pty > $radio_pty &]
puts "RCP PID: $rcp_pid"
try {
spawn_node 1 "rcp" "spinel+hdlc_uart://$host_pty"
spawn_node 2
setup_two_nodes "rn" false
switch_node 2
set addr [get_ipaddr mleid]
switch_node 1
send "ping $addr\n"
expect "16 bytes from $addr: icmp_seq=1"
expect_line "Done"
send "reset\n"
wait_for "state" "disabled"
expect_line "Done"
send "ifconfig up\n"
expect_line "Done"
send "thread start\n"
expect_line "Done"
wait_for "state" "leader"
wait_for "ping $addr" "16 bytes from $addr: icmp_seq=\\d+"
expect_line "Done"
} finally {
exec kill $rcp_pid
exec kill $socat_pid
}
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/expect -f
#
# Copyright (c) 2021, 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.
#
source "tests/scripts/expect/posix-rcp-stack-reset.exp"
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env python3
#
# Copyright (c) 2021, 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.
#
import argparse
from spinel.const import SPINEL
from spinel.codec import WpanApi
from spinel.stream import StreamOpen
def main():
parser = argparse.ArgumentParser()
parser.add_argument('rcp', type=str, help='path to rcp executable')
args = parser.parse_args()
stream = StreamOpen('p', f'{args.rcp} 1', False, 115200, False)
wpan_api = WpanApi(stream, 1)
assert wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) == 1
ext_addr = b'\x00\x11\x22\x33\x44\x55\x66\x77'
assert wpan_api.prop_set_value(SPINEL.PROP_PHY_CHAN, 17) == 17
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_15_4_SADDR, 0x1234, 'H') == 0x1234
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_15_4_LADDR, ext_addr, '8s') == ext_addr
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED, 1) == 1
while wpan_api.prop_insert_value(SPINEL.PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES, ext_addr, '8s') == ext_addr:
ext_addr = (int.from_bytes(ext_addr, 'little') + 1).to_bytes(8, 'little')
short_addr = 0x2345
while wpan_api.prop_insert_value(SPINEL.PROP_MAC_SRC_MATCH_SHORT_ADDRESSES, short_addr, 'H') == short_addr:
short_addr += 1
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_FILTER_MODE, SPINEL.MAC_FILTER_MODE_PROMISCUOUS) in {
SPINEL.MAC_FILTER_MODE_PROMISCUOUS,
SPINEL.MAC_FILTER_MODE_MONITOR,
}
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_RAW_STREAM_ENABLED, 1) == 1
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SCAN_MASK, 11) == [11]
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SCAN_STATE, SPINEL.SCAN_STATE_ENERGY) == SPINEL.SCAN_STATE_ENERGY
wpan_api.cmd_send(SPINEL.CMD_RESET)
assert wpan_api.prop_get_value(SPINEL.PROP_PHY_ENABLED) == 0
assert wpan_api.prop_set_value(SPINEL.PROP_PHY_ENABLED, 1) == 1
assert wpan_api.prop_get_value(SPINEL.PROP_PHY_CHAN) == 11
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_15_4_SADDR) == 0xfffe
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_15_4_LADDR) == b'\x00' * 8
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED) == 0
assert wpan_api.prop_set_value(SPINEL.PROP_MAC_SRC_MATCH_ENABLED, 1) == 1
assert wpan_api.prop_insert_value(SPINEL.PROP_MAC_SRC_MATCH_EXTENDED_ADDRESSES, ext_addr, '8s') == ext_addr
assert wpan_api.prop_insert_value(SPINEL.PROP_MAC_SRC_MATCH_SHORT_ADDRESSES, short_addr, 'H') == short_addr
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_FILTER_MODE) == SPINEL.MAC_FILTER_MDOE_NORMAL
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_RAW_STREAM_ENABLED) == 0
assert wpan_api.prop_get_value(SPINEL.PROP_MAC_SCAN_STATE) == SPINEL.SCAN_STATE_IDLE
if __name__ == '__main__':
main()
+7
View File
@@ -550,4 +550,11 @@ bool otPlatCryptoHasKey(otCryptoKeyRef aKeyRef)
#endif // OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE
otError otPlatRadioSetCcaEnergyDetectThreshold(otInstance *aInstance, int8_t aThreshold)
{
OT_UNUSED_VARIABLE(aInstance);
OT_UNUSED_VARIABLE(aThreshold);
return OT_ERROR_NONE;
}
} // extern "C"