mirror of
https://github.com/espressif/openthread.git
synced 2026-10-27 17:54:53 +00:00
[nrf528xx] change directory structure for nrf528xx family (#4206)
Merged nrf528xx sub-directories to simplify maintenance and porting of new nrf528xx family platforms in the future. Crucial changes: - Moved all source files to common 'src' directory - Merged all *.c files and treated platform specific fragments of code with conditional compilation - Created simple automake file [examples/platforms/nrf528xx/Makefile.am] that includes conditional-include blocks
This commit is contained in:
committed by
Jonathan Hui
parent
51217542ba
commit
2dedd82ef3
+2
-2
@@ -820,6 +820,7 @@ AM_COND_IF([OPENTHREAD_EXAMPLES_POSIX], CPPFLAGS="${CPPFLAGS} -DOPENTHREAD_EXAMP
|
||||
AC_MSG_CHECKING([whether to enable examples])
|
||||
AC_MSG_RESULT(${with_examples})
|
||||
|
||||
AM_CONDITIONAL([OPENTHREAD_EXAMPLES_NRF528XX], [test OPENTHREAD_EXAMPLES_NRF52811 || test OPENTHREAD_EXAMPLES_NRF52840])
|
||||
#
|
||||
# Tools
|
||||
#
|
||||
@@ -979,8 +980,7 @@ examples/platforms/efr32mg21/sleepy-demo/sleepy-demo-ftd/Makefile
|
||||
examples/platforms/efr32mg21/sleepy-demo/sleepy-demo-mtd/Makefile
|
||||
examples/platforms/gp712/Makefile
|
||||
examples/platforms/kw41z/Makefile
|
||||
examples/platforms/nrf52811/Makefile
|
||||
examples/platforms/nrf52840/Makefile
|
||||
examples/platforms/nrf528xx/Makefile
|
||||
examples/platforms/qpg6095/Makefile
|
||||
examples/platforms/samr21/Makefile
|
||||
examples/platforms/posix/Makefile
|
||||
|
||||
@@ -68,7 +68,7 @@ NRF52811_MBEDTLS_CPPFLAGS += -DNRF52811_XXAA
|
||||
|
||||
NRF52811_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-nrf52811-config.h\"'
|
||||
NRF52811_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-nrf52811-config-check.h\"'
|
||||
NRF52811_CONFIG_FILE_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/nrf52811/
|
||||
NRF52811_CONFIG_FILE_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/nrf528xx/nrf52811
|
||||
|
||||
COMMONCFLAGS := \
|
||||
-fdata-sections \
|
||||
|
||||
@@ -72,7 +72,7 @@ NRF52840_MBEDTLS_CPPFLAGS += -DNRF52840_XXAA
|
||||
|
||||
NRF52840_CONFIG_FILE_CPPFLAGS = -DOPENTHREAD_PROJECT_CORE_CONFIG_FILE='\"openthread-core-nrf52840-config.h\"'
|
||||
NRF52840_CONFIG_FILE_CPPFLAGS += -DOPENTHREAD_CORE_CONFIG_PLATFORM_CHECK_FILE='\"openthread-core-nrf52840-config-check.h\"'
|
||||
NRF52840_CONFIG_FILE_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/nrf52840/
|
||||
NRF52840_CONFIG_FILE_CPPFLAGS += -I$(AbsTopSourceDir)/examples/platforms/nrf528xx/nrf52840
|
||||
|
||||
COMMONCFLAGS := \
|
||||
-fdata-sections \
|
||||
@@ -85,7 +85,7 @@ COMMONCFLAGS := \
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/common-switches.mk
|
||||
|
||||
ifeq ($(BOOTLOADER),1)
|
||||
configure_OPTIONS += --with-custom-linker-file=$(AbsTopSourceDir)/examples/platforms/nrf52840/nrf52840_bootloader.ld
|
||||
configure_OPTIONS += --with-custom-linker-file=$(AbsTopSourceDir)/examples/platforms/nrf528xx/nrf52840/nrf52840_bootloader.ld
|
||||
COMMONCFLAGS += -DAPP_USBD_NRF_DFU_TRIGGER_ENABLED=1
|
||||
endif
|
||||
|
||||
|
||||
@@ -39,8 +39,7 @@ DIST_SUBDIRS = \
|
||||
efr32mg21 \
|
||||
gp712 \
|
||||
kw41z \
|
||||
nrf52811 \
|
||||
nrf52840 \
|
||||
nrf528xx \
|
||||
posix \
|
||||
qpg6095 \
|
||||
samr21 \
|
||||
@@ -85,12 +84,8 @@ if OPENTHREAD_EXAMPLES_KW41Z
|
||||
SUBDIRS += kw41z
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52811
|
||||
SUBDIRS += nrf52811
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52840
|
||||
SUBDIRS += nrf52840
|
||||
if OPENTHREAD_EXAMPLES_NRF528XX
|
||||
SUBDIRS += nrf528xx
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_POSIX
|
||||
@@ -120,8 +115,7 @@ PRETTY_SUBDIRS = \
|
||||
efr32mg21 \
|
||||
gp712 \
|
||||
kw41z \
|
||||
nrf52811 \
|
||||
nrf52840 \
|
||||
nrf528xx \
|
||||
posix \
|
||||
qpg6095 \
|
||||
samr21 \
|
||||
|
||||
@@ -74,11 +74,11 @@ include $(top_srcdir)/examples/platforms/kw41z/Makefile.platform.am
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52811
|
||||
include $(top_srcdir)/examples/platforms/nrf52811/Makefile.platform.am
|
||||
include $(top_srcdir)/examples/platforms/nrf528xx/nrf52811/Makefile.platform.am
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52840
|
||||
include $(top_srcdir)/examples/platforms/nrf52840/Makefile.platform.am
|
||||
include $(top_srcdir)/examples/platforms/nrf528xx/nrf52840/Makefile.platform.am
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_QPG6095
|
||||
|
||||
@@ -1,690 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 alarm.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/platform/time.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
#include "platform-config.h"
|
||||
#include "platform-nrf5.h"
|
||||
#include "cmsis/core_cmFunc.h"
|
||||
|
||||
#include <drivers/clock/nrf_drv_clock.h>
|
||||
#include <drivers/radio/nrf_802154_utils.h>
|
||||
#include <drivers/radio/platform/lp_timer/nrf_802154_lp_timer.h>
|
||||
|
||||
#include <hal/nrf_rtc.h>
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
// clang-format off
|
||||
#define RTC_FREQUENCY NRF_802154_RTC_FREQUENCY
|
||||
|
||||
#define US_PER_MS 1000ULL
|
||||
#define US_PER_S NRF_802154_US_PER_S
|
||||
#define US_PER_OVERFLOW (512UL * NRF_802154_US_PER_S) ///< Time that has passed between overflow events. On full RTC speed, it occurs every 512 s.
|
||||
|
||||
#define MS_PER_S 1000UL
|
||||
|
||||
#define MIN_RTC_COMPARE_EVENT_TICKS 2 ///< Minimum number of RTC ticks delay that guarantees that RTC compare event will fire.
|
||||
#define MIN_RTC_COMPARE_EVENT_DT (MIN_RTC_COMPARE_EVENT_TICKS * NRF_802154_US_PER_TICK) ///< Minimum time delta from now before RTC compare event is guaranteed to fire.
|
||||
#define EPOCH_32BIT_US (1ULL << 32)
|
||||
#define EPOCH_FROM_TIME(time) ((time) & ((uint64_t)UINT32_MAX << 32))
|
||||
|
||||
#define XTAL_ACCURACY 40 // The crystal used on nRF52840PDK has ±20ppm accuracy.
|
||||
// clang-format on
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kMsTimer,
|
||||
kUsTimer,
|
||||
k802154Timer,
|
||||
k802154Sync,
|
||||
kNumTimers
|
||||
} AlarmIndex;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile bool mFireAlarm; ///< Information for processing function, that alarm should fire.
|
||||
uint64_t mTargetTime; ///< Alarm fire time (in millisecond for MsTimer, in microsecond for UsTimer)
|
||||
} AlarmData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t mChannelNumber;
|
||||
uint32_t mCompareEventMask;
|
||||
nrf_rtc_event_t mCompareEvent;
|
||||
nrf_rtc_int_t mCompareInt;
|
||||
} AlarmChannelData;
|
||||
|
||||
static volatile uint32_t sOverflowCounter; ///< Counter of RTC overflowCounter, incremented by 2 on each OVERFLOW event.
|
||||
static volatile uint8_t sMutex; ///< Mutex for write access to @ref sOverflowCounter.
|
||||
static volatile uint64_t sTimeOffset = 0; ///< Time overflowCounter to keep track of current time (in millisecond).
|
||||
static volatile bool sEventPending; ///< Timer fired and upper layer should be notified.
|
||||
static AlarmData sTimerData[kNumTimers]; ///< Data of the timers.
|
||||
|
||||
static const AlarmChannelData sChannelData[kNumTimers] = //
|
||||
{ //
|
||||
[kMsTimer] =
|
||||
{
|
||||
.mChannelNumber = 0,
|
||||
.mCompareEventMask = RTC_EVTEN_COMPARE0_Msk,
|
||||
.mCompareEvent = NRF_RTC_EVENT_COMPARE_0,
|
||||
.mCompareInt = NRF_RTC_INT_COMPARE0_MASK,
|
||||
},
|
||||
[kUsTimer] =
|
||||
{
|
||||
.mChannelNumber = 1,
|
||||
.mCompareEventMask = RTC_EVTEN_COMPARE1_Msk,
|
||||
.mCompareEvent = NRF_RTC_EVENT_COMPARE_1,
|
||||
.mCompareInt = NRF_RTC_INT_COMPARE1_MASK,
|
||||
},
|
||||
[k802154Timer] =
|
||||
{
|
||||
.mChannelNumber = 2,
|
||||
.mCompareEventMask = RTC_EVTEN_COMPARE2_Msk,
|
||||
.mCompareEvent = NRF_RTC_EVENT_COMPARE_2,
|
||||
.mCompareInt = NRF_RTC_INT_COMPARE2_MASK,
|
||||
},
|
||||
[k802154Sync] = {
|
||||
.mChannelNumber = 3,
|
||||
.mCompareEventMask = RTC_EVTEN_COMPARE3_Msk,
|
||||
.mCompareEvent = NRF_RTC_EVENT_COMPARE_3,
|
||||
.mCompareInt = NRF_RTC_INT_COMPARE3_MASK,
|
||||
}};
|
||||
|
||||
static inline bool MutexGet(void)
|
||||
{
|
||||
do
|
||||
{
|
||||
volatile uint8_t mutexValue = __LDREXB(&sMutex);
|
||||
|
||||
if (mutexValue)
|
||||
{
|
||||
__CLREX();
|
||||
return false;
|
||||
}
|
||||
} while (__STREXB(1, &sMutex));
|
||||
|
||||
// Disable OVERFLOW interrupt to prevent lock-up in interrupt context while mutex is locked from lower priority
|
||||
// context and OVERFLOW event flag is stil up.
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK);
|
||||
|
||||
__DMB();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void MutexRelease(void)
|
||||
{
|
||||
// Re-enable OVERFLOW interrupt.
|
||||
nrf_rtc_int_enable(RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK);
|
||||
|
||||
__DMB();
|
||||
sMutex = 0;
|
||||
}
|
||||
|
||||
static inline uint64_t TimeToTicks(uint64_t aTime, AlarmIndex aIndex)
|
||||
{
|
||||
if (aIndex == kMsTimer)
|
||||
{
|
||||
aTime *= US_PER_MS;
|
||||
}
|
||||
|
||||
return NRF_802154_US_TO_RTC_TICKS(aTime);
|
||||
}
|
||||
|
||||
static inline uint64_t TicksToTime(uint64_t aTicks, AlarmIndex aIndex)
|
||||
{
|
||||
uint64_t result = NRF_802154_RTC_TICKS_TO_US(aTicks);
|
||||
|
||||
if (aIndex == kMsTimer)
|
||||
{
|
||||
result /= US_PER_MS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool AlarmShallStrike(uint64_t aNow, AlarmIndex aIndex)
|
||||
{
|
||||
return aNow >= sTimerData[aIndex].mTargetTime;
|
||||
}
|
||||
|
||||
static uint32_t GetOverflowCounter(void)
|
||||
{
|
||||
uint32_t overflowCounter;
|
||||
|
||||
// Get mutual access for writing to sOverflowCounter variable.
|
||||
if (MutexGet())
|
||||
{
|
||||
bool increasing = false;
|
||||
|
||||
// Check if interrupt was handled already.
|
||||
if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW))
|
||||
{
|
||||
sOverflowCounter++;
|
||||
increasing = true;
|
||||
|
||||
__DMB();
|
||||
|
||||
// Mark that interrupt was handled.
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW);
|
||||
|
||||
// Result should be incremented. sOverflowCounter will be incremented after mutex is released.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either overflow handling is not needed OR we acquired the mutex just after it was released.
|
||||
// Overflow is handled after mutex is released, but it cannot be assured that sOverflowCounter
|
||||
// was incremented for the second time, so we increment the result here.
|
||||
}
|
||||
|
||||
overflowCounter = (sOverflowCounter + 1) / 2;
|
||||
|
||||
MutexRelease();
|
||||
|
||||
if (increasing)
|
||||
{
|
||||
// It's virtually impossible that overflow event is pending again before next instruction is performed. It
|
||||
// is an error condition.
|
||||
assert(sOverflowCounter & 0x01);
|
||||
|
||||
// Increment the counter for the second time, to allow instructions from other context get correct value of
|
||||
// the counter.
|
||||
sOverflowCounter++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to acquire mutex.
|
||||
if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW) || (sOverflowCounter & 0x01))
|
||||
{
|
||||
// Lower priority context is currently incrementing sOverflowCounter variable.
|
||||
overflowCounter = (sOverflowCounter + 2) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lower priority context has already incremented sOverflowCounter variable or incrementing is not needed
|
||||
// now.
|
||||
overflowCounter = sOverflowCounter / 2;
|
||||
}
|
||||
}
|
||||
|
||||
return overflowCounter;
|
||||
}
|
||||
|
||||
static uint32_t GetRtcCounter(void)
|
||||
{
|
||||
return nrf_rtc_counter_get(RTC_INSTANCE);
|
||||
}
|
||||
|
||||
static void GetOffsetAndCounter(uint32_t *aOffset, uint32_t *aCounter)
|
||||
{
|
||||
uint32_t offset1 = GetOverflowCounter();
|
||||
|
||||
__DMB();
|
||||
|
||||
uint32_t rtcValue1 = GetRtcCounter();
|
||||
|
||||
__DMB();
|
||||
|
||||
uint32_t offset2 = GetOverflowCounter();
|
||||
|
||||
*aOffset = offset2;
|
||||
*aCounter = (offset1 == offset2) ? rtcValue1 : GetRtcCounter();
|
||||
}
|
||||
|
||||
static uint64_t GetTime(uint32_t aOffset, uint32_t aCounter, AlarmIndex aIndex)
|
||||
{
|
||||
uint64_t result = (uint64_t)aOffset * US_PER_OVERFLOW + TicksToTime(aCounter, kUsTimer);
|
||||
|
||||
if (aIndex == kMsTimer)
|
||||
{
|
||||
result /= US_PER_MS;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint64_t GetCurrentTime(AlarmIndex aIndex)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t rtc_counter;
|
||||
|
||||
GetOffsetAndCounter(&offset, &rtc_counter);
|
||||
|
||||
return GetTime(offset, rtc_counter, aIndex);
|
||||
}
|
||||
|
||||
static void HandleCompareMatch(AlarmIndex aIndex, bool aSkipCheck)
|
||||
{
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[aIndex].mCompareEvent);
|
||||
|
||||
uint64_t now = GetCurrentTime(aIndex);
|
||||
|
||||
// In case the target time was larger than single overflow,
|
||||
// we should only strike the timer on final compare event.
|
||||
if (aSkipCheck || AlarmShallStrike(now, aIndex))
|
||||
{
|
||||
nrf_rtc_event_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareEventMask);
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareInt);
|
||||
|
||||
switch (aIndex)
|
||||
{
|
||||
case k802154Timer:
|
||||
nrf_802154_lp_timer_fired();
|
||||
break;
|
||||
|
||||
case k802154Sync:
|
||||
nrf_802154_lp_timer_synchronized();
|
||||
break;
|
||||
|
||||
case kMsTimer:
|
||||
case kUsTimer:
|
||||
sTimerData[aIndex].mFireAlarm = true;
|
||||
sEventPending = true;
|
||||
otSysEventSignalPending();
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t ConvertT0AndDtTo64BitTime(uint32_t aT0, uint32_t aDt, const uint64_t *aNow)
|
||||
{
|
||||
uint64_t now;
|
||||
now = *aNow;
|
||||
|
||||
if (((uint32_t)now < aT0) && ((aT0 - (uint32_t)now) > (UINT32_MAX / 2)))
|
||||
{
|
||||
now -= EPOCH_32BIT_US;
|
||||
}
|
||||
else if (((uint32_t)now > aT0) && (((uint32_t)now) - aT0 > (UINT32_MAX / 2)))
|
||||
{
|
||||
now += EPOCH_32BIT_US;
|
||||
}
|
||||
|
||||
return (EPOCH_FROM_TIME(now)) + aT0 + aDt;
|
||||
}
|
||||
|
||||
static uint64_t RoundUpTimeToTimerTicksMultiply(uint64_t aTime, AlarmIndex aIndex)
|
||||
{
|
||||
uint64_t ticks = TimeToTicks(aTime, aIndex);
|
||||
uint64_t result = TicksToTime(ticks, aIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void TimerStartAt(uint32_t aT0, uint32_t aDt, AlarmIndex aIndex, const uint64_t *aNow)
|
||||
{
|
||||
uint64_t targetCounter;
|
||||
uint64_t targetTime;
|
||||
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareInt);
|
||||
nrf_rtc_event_enable(RTC_INSTANCE, sChannelData[aIndex].mCompareEventMask);
|
||||
|
||||
targetTime = ConvertT0AndDtTo64BitTime(aT0, aDt, aNow);
|
||||
targetCounter = TimeToTicks(targetTime, aIndex) & RTC_CC_COMPARE_Msk;
|
||||
|
||||
sTimerData[aIndex].mTargetTime = RoundUpTimeToTimerTicksMultiply(targetTime, aIndex);
|
||||
|
||||
nrf_rtc_cc_set(RTC_INSTANCE, sChannelData[aIndex].mChannelNumber, targetCounter);
|
||||
}
|
||||
|
||||
static void AlarmStartAt(uint32_t aT0, uint32_t aDt, AlarmIndex aIndex)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t rtc_value;
|
||||
uint64_t now;
|
||||
uint64_t now_rtc_protected;
|
||||
|
||||
GetOffsetAndCounter(&offset, &rtc_value);
|
||||
now = GetTime(offset, rtc_value, aIndex);
|
||||
|
||||
TimerStartAt(aT0, aDt, aIndex, &now);
|
||||
|
||||
if (rtc_value != GetRtcCounter())
|
||||
{
|
||||
GetOffsetAndCounter(&offset, &rtc_value);
|
||||
}
|
||||
|
||||
now_rtc_protected = GetTime(offset, rtc_value + MIN_RTC_COMPARE_EVENT_TICKS, aIndex);
|
||||
|
||||
if (AlarmShallStrike(now_rtc_protected, aIndex))
|
||||
{
|
||||
HandleCompareMatch(aIndex, true);
|
||||
|
||||
/**
|
||||
* Normally ISR sets event flag automatically.
|
||||
* Here we are calling HandleCompareMatch explicitly and no ISR will be fired.
|
||||
* To prevent possible permanent sleep on next WFE we have to set event flag.
|
||||
*/
|
||||
__SEV();
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_rtc_int_enable(RTC_INSTANCE, sChannelData[aIndex].mCompareInt);
|
||||
}
|
||||
}
|
||||
|
||||
static void TimerSyncStartAt(uint32_t aT0, uint32_t aDt, const uint64_t *aNow)
|
||||
{
|
||||
TimerStartAt(aT0, aDt, k802154Sync, aNow);
|
||||
|
||||
nrf_rtc_int_enable(RTC_INSTANCE, sChannelData[k802154Sync].mCompareInt);
|
||||
}
|
||||
|
||||
static void AlarmStop(AlarmIndex aIndex)
|
||||
{
|
||||
nrf_rtc_event_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareEventMask);
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[aIndex].mCompareInt);
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[aIndex].mCompareEvent);
|
||||
|
||||
sTimerData[aIndex].mFireAlarm = false;
|
||||
}
|
||||
|
||||
void nrf5AlarmInit(void)
|
||||
{
|
||||
memset(sTimerData, 0, sizeof(sTimerData));
|
||||
sOverflowCounter = 0;
|
||||
sMutex = 0;
|
||||
sTimeOffset = 0;
|
||||
|
||||
// Setup low frequency clock.
|
||||
nrf_drv_clock_lfclk_request(NULL);
|
||||
|
||||
while (!nrf_drv_clock_lfclk_is_running())
|
||||
{
|
||||
}
|
||||
|
||||
// Setup RTC timer.
|
||||
NVIC_SetPriority(RTC_IRQN, RTC_IRQ_PRIORITY);
|
||||
NVIC_ClearPendingIRQ(RTC_IRQN);
|
||||
NVIC_EnableIRQ(RTC_IRQN);
|
||||
|
||||
nrf_rtc_prescaler_set(RTC_INSTANCE, 0);
|
||||
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW);
|
||||
nrf_rtc_event_enable(RTC_INSTANCE, RTC_EVTEN_OVRFLW_Msk);
|
||||
nrf_rtc_int_enable(RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK);
|
||||
|
||||
for (uint32_t i = 0; i < kNumTimers; i++)
|
||||
{
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[i].mCompareEvent);
|
||||
nrf_rtc_event_disable(RTC_INSTANCE, sChannelData[i].mCompareEventMask);
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[i].mCompareInt);
|
||||
}
|
||||
|
||||
nrf_rtc_task_trigger(RTC_INSTANCE, NRF_RTC_TASK_START);
|
||||
}
|
||||
|
||||
void nrf5AlarmDeinit(void)
|
||||
{
|
||||
nrf_rtc_task_trigger(RTC_INSTANCE, NRF_RTC_TASK_STOP);
|
||||
|
||||
for (uint32_t i = 0; i < kNumTimers; i++)
|
||||
{
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[i].mCompareEvent);
|
||||
nrf_rtc_event_disable(RTC_INSTANCE, sChannelData[i].mCompareEventMask);
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[i].mCompareInt);
|
||||
}
|
||||
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK);
|
||||
nrf_rtc_event_disable(RTC_INSTANCE, RTC_EVTEN_OVRFLW_Msk);
|
||||
nrf_rtc_event_clear(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW);
|
||||
|
||||
nrf_802154_lp_timer_sync_stop();
|
||||
|
||||
NVIC_DisableIRQ(RTC_IRQN);
|
||||
NVIC_ClearPendingIRQ(RTC_IRQN);
|
||||
NVIC_SetPriority(RTC_IRQN, 0);
|
||||
|
||||
nrf_drv_clock_lfclk_release();
|
||||
}
|
||||
|
||||
void nrf5AlarmProcess(otInstance *aInstance)
|
||||
{
|
||||
do
|
||||
{
|
||||
sEventPending = false;
|
||||
|
||||
if (sTimerData[kMsTimer].mFireAlarm)
|
||||
{
|
||||
sTimerData[kMsTimer].mFireAlarm = false;
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagAlarmFired(aInstance);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatAlarmMilliFired(aInstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (sTimerData[kUsTimer].mFireAlarm)
|
||||
{
|
||||
sTimerData[kUsTimer].mFireAlarm = false;
|
||||
|
||||
otPlatAlarmMicroFired(aInstance);
|
||||
}
|
||||
} while (sEventPending);
|
||||
}
|
||||
|
||||
inline uint64_t nrf5AlarmGetCurrentTime(void)
|
||||
{
|
||||
return GetCurrentTime(kUsTimer);
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMilliGetNow(void)
|
||||
{
|
||||
return (uint32_t)(nrf5AlarmGetCurrentTime() / US_PER_MS);
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
AlarmStartAt(aT0, aDt, kMsTimer);
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
AlarmStop(kMsTimer);
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMicroGetNow(void)
|
||||
{
|
||||
return (uint32_t)nrf5AlarmGetCurrentTime();
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
AlarmStartAt(aT0, aDt, kUsTimer);
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
AlarmStop(kUsTimer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Radio driver timer abstraction API
|
||||
*/
|
||||
|
||||
void nrf_802154_lp_timer_init(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_deinit(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_critical_section_enter(void)
|
||||
{
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, sChannelData[k802154Timer].mCompareInt);
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_critical_section_exit(void)
|
||||
{
|
||||
nrf_rtc_int_enable(RTC_INSTANCE, sChannelData[k802154Timer].mCompareInt);
|
||||
}
|
||||
|
||||
uint32_t nrf_802154_lp_timer_time_get(void)
|
||||
{
|
||||
return (uint32_t)nrf5AlarmGetCurrentTime();
|
||||
}
|
||||
|
||||
uint32_t nrf_802154_lp_timer_granularity_get(void)
|
||||
{
|
||||
return NRF_802154_US_PER_TICK;
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_start(uint32_t t0, uint32_t dt)
|
||||
{
|
||||
AlarmStartAt(t0, dt, k802154Timer);
|
||||
}
|
||||
|
||||
bool nrf_802154_lp_timer_is_running(void)
|
||||
{
|
||||
return nrf_rtc_int_is_enabled(RTC_INSTANCE, sChannelData[k802154Timer].mCompareInt);
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_stop(void)
|
||||
{
|
||||
AlarmStop(k802154Timer);
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_sync_start_now(void)
|
||||
{
|
||||
uint32_t counter;
|
||||
uint32_t offset;
|
||||
uint64_t now;
|
||||
|
||||
do
|
||||
{
|
||||
GetOffsetAndCounter(&offset, &counter);
|
||||
now = GetTime(offset, counter, k802154Sync);
|
||||
TimerSyncStartAt((uint32_t)now, MIN_RTC_COMPARE_EVENT_DT, &now);
|
||||
} while (GetRtcCounter() != counter);
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_sync_start_at(uint32_t t0, uint32_t dt)
|
||||
{
|
||||
uint64_t now = GetCurrentTime(k802154Sync);
|
||||
|
||||
TimerSyncStartAt(t0, dt, &now);
|
||||
}
|
||||
|
||||
void nrf_802154_lp_timer_sync_stop(void)
|
||||
{
|
||||
AlarmStop(k802154Sync);
|
||||
}
|
||||
|
||||
uint32_t nrf_802154_lp_timer_sync_event_get(void)
|
||||
{
|
||||
return (uint32_t)nrf_rtc_event_address_get(RTC_INSTANCE, sChannelData[k802154Sync].mCompareEvent);
|
||||
}
|
||||
|
||||
uint32_t nrf_802154_lp_timer_sync_time_get(void)
|
||||
{
|
||||
return (uint32_t)sTimerData[k802154Sync].mTargetTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* RTC IRQ handler
|
||||
*/
|
||||
|
||||
void RTC_IRQ_HANDLER(void)
|
||||
{
|
||||
// Handle overflow.
|
||||
if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW))
|
||||
{
|
||||
// Disable OVERFLOW interrupt to prevent lock-up in interrupt context while mutex is locked from lower priority
|
||||
// context and OVERFLOW event flag is stil up. OVERFLOW interrupt will be re-enabled when mutex is released -
|
||||
// either from this handler, or from lower priority context, that locked the mutex.
|
||||
nrf_rtc_int_disable(RTC_INSTANCE, NRF_RTC_INT_OVERFLOW_MASK);
|
||||
|
||||
// Handle OVERFLOW event by reading current value of overflow counter.
|
||||
(void)GetOverflowCounter();
|
||||
}
|
||||
|
||||
// Handle compare match.
|
||||
for (uint32_t i = 0; i < kNumTimers; i++)
|
||||
{
|
||||
if (nrf_rtc_int_is_enabled(RTC_INSTANCE, sChannelData[i].mCompareInt) &&
|
||||
nrf_rtc_event_pending(RTC_INSTANCE, sChannelData[i].mCompareEvent))
|
||||
{
|
||||
HandleCompareMatch((AlarmIndex)i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
uint64_t otPlatTimeGet(void)
|
||||
{
|
||||
return nrf5AlarmGetCurrentTime();
|
||||
}
|
||||
|
||||
uint16_t otPlatTimeGetXtalAccuracy(void)
|
||||
{
|
||||
return XTAL_ACCURACY;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
@@ -1,493 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
#include <hal/nrf_gpio.h>
|
||||
|
||||
#include <openthread/cli.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
|
||||
#include <common/logging.hpp>
|
||||
#include <drivers/radio/nrf_802154.h>
|
||||
#include <utils/code_utils.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kDiagTransmitModeIdle,
|
||||
kDiagTransmitModePackets,
|
||||
kDiagTransmitModeCarrier
|
||||
} DiagTrasmitMode;
|
||||
|
||||
struct PlatformDiagCommand
|
||||
{
|
||||
const char *mName;
|
||||
void (*mCommand)(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen);
|
||||
};
|
||||
|
||||
struct PlatformDiagMessage
|
||||
{
|
||||
const char mMessageDescriptor[11];
|
||||
uint8_t mChannel;
|
||||
int16_t mID;
|
||||
uint32_t mCnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Diagnostics mode variables.
|
||||
*
|
||||
*/
|
||||
static bool sDiagMode = false;
|
||||
static bool sListen = false;
|
||||
static DiagTrasmitMode sTransmitMode = kDiagTransmitModeIdle;
|
||||
static uint8_t sChannel = 20;
|
||||
static int8_t sTxPower = 0;
|
||||
static uint32_t sTxPeriod = 1;
|
||||
static int32_t sTxCount = 0;
|
||||
static int32_t sTxRequestedCount = 1;
|
||||
static int16_t sID = -1;
|
||||
static struct PlatformDiagMessage sDiagMessage = {.mMessageDescriptor = "DiagMessage",
|
||||
.mChannel = 0,
|
||||
.mID = 0,
|
||||
.mCnt = 0};
|
||||
|
||||
static otError parseLong(char *argv, long *aValue)
|
||||
{
|
||||
char *endptr;
|
||||
*aValue = strtol(argv, &endptr, 0);
|
||||
return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_PARSE;
|
||||
}
|
||||
|
||||
static void appendErrorResult(otError aError, char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
if (aError != OT_ERROR_NONE)
|
||||
{
|
||||
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
|
||||
}
|
||||
}
|
||||
|
||||
static bool startCarrierTransmision(void)
|
||||
{
|
||||
nrf_802154_channel_set(sChannel);
|
||||
nrf_802154_tx_power_set(sTxPower);
|
||||
|
||||
return nrf_802154_continuous_carrier();
|
||||
}
|
||||
|
||||
static void processListen(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
snprintf(aOutput, aOutputMaxLen, "listen: %s\r\n", sListen == true ? "yes" : "no");
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
error = parseLong(argv[0], &value);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
sListen = (bool)(value);
|
||||
snprintf(aOutput, aOutputMaxLen, "set listen to %s\r\nstatus 0x%02x\r\n", sListen == true ? "yes" : "no",
|
||||
error);
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
static void processID(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
snprintf(aOutput, aOutputMaxLen, "ID: %" PRId16 "\r\n", sID);
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
error = parseLong(argv[0], &value);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
otEXPECT_ACTION(value >= 0, error = OT_ERROR_INVALID_ARGS);
|
||||
sID = (int16_t)(value);
|
||||
snprintf(aOutput, aOutputMaxLen, "set ID to %" PRId16 "\r\nstatus 0x%02x\r\n", sID, error);
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
static void processTransmit(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
snprintf(aOutput, aOutputMaxLen,
|
||||
"transmit will send %" PRId32 " diagnostic messages with %" PRIu32 " ms interval\r\nstatus 0x%02x\r\n",
|
||||
sTxRequestedCount, sTxPeriod, error);
|
||||
}
|
||||
else if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(sTransmitMode != kDiagTransmitModeIdle, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
otPlatAlarmMilliStop(aInstance);
|
||||
snprintf(aOutput, aOutputMaxLen, "diagnostic message transmission is stopped\r\nstatus 0x%02x\r\n", error);
|
||||
sTransmitMode = kDiagTransmitModeIdle;
|
||||
otPlatRadioReceive(aInstance, sChannel);
|
||||
}
|
||||
else if (strcmp(argv[0], "start") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(sTransmitMode == kDiagTransmitModeIdle, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
otPlatAlarmMilliStop(aInstance);
|
||||
sTransmitMode = kDiagTransmitModePackets;
|
||||
sTxCount = sTxRequestedCount;
|
||||
uint32_t now = otPlatAlarmMilliGetNow();
|
||||
otPlatAlarmMilliStartAt(aInstance, now, sTxPeriod);
|
||||
snprintf(aOutput, aOutputMaxLen,
|
||||
"sending %" PRId32 " diagnostic messages with %" PRIu32 " ms interval\r\nstatus 0x%02x\r\n",
|
||||
sTxRequestedCount, sTxPeriod, error);
|
||||
}
|
||||
else if (strcmp(argv[0], "carrier") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(sTransmitMode == kDiagTransmitModeIdle, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
otEXPECT_ACTION(startCarrierTransmision(), error = OT_ERROR_FAILED);
|
||||
|
||||
sTransmitMode = kDiagTransmitModeCarrier;
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "sending carrier on channel %d with tx power %d\r\nstatus 0x%02x\r\n",
|
||||
sChannel, sTxPower, error);
|
||||
}
|
||||
else if (strcmp(argv[0], "interval") == 0)
|
||||
{
|
||||
long value;
|
||||
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
error = parseLong(argv[1], &value);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
otEXPECT_ACTION(value > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
sTxPeriod = (uint32_t)(value);
|
||||
snprintf(aOutput, aOutputMaxLen, "set diagnostic messages interval to %" PRIu32 " ms\r\nstatus 0x%02x\r\n",
|
||||
sTxPeriod, error);
|
||||
}
|
||||
else if (strcmp(argv[0], "count") == 0)
|
||||
{
|
||||
long value;
|
||||
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
error = parseLong(argv[1], &value);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
otEXPECT_ACTION((value > 0) || (value == -1), error = OT_ERROR_INVALID_ARGS);
|
||||
sTxRequestedCount = (uint32_t)(value);
|
||||
snprintf(aOutput, aOutputMaxLen, "set diagnostic messages count to %" PRId32 "\r\nstatus 0x%02x\r\n",
|
||||
sTxRequestedCount, error);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
static void processGpio(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
long pinnum;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
error = parseLong(argv[0], &pinnum);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
value = nrf_gpio_pin_read(pinnum);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "gpio %d = %d\r\n", (uint8_t)pinnum, (uint8_t)value);
|
||||
}
|
||||
else if (strcmp(argv[0], "set") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
error = parseLong(argv[1], &pinnum);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
nrf_gpio_pin_set(pinnum);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "gpio %d = 1\r\n", (uint8_t)pinnum);
|
||||
}
|
||||
else if (strcmp(argv[0], "clr") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
error = parseLong(argv[1], &pinnum);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
nrf_gpio_pin_clear(pinnum);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "gpio %d = 0\r\n", (uint8_t)pinnum);
|
||||
}
|
||||
else if (strcmp(argv[0], "out") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
error = parseLong(argv[1], &pinnum);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
nrf_gpio_cfg_output(pinnum);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "gpio %d: out\r\n", (uint8_t)pinnum);
|
||||
}
|
||||
else if (strcmp(argv[0], "in") == 0)
|
||||
{
|
||||
otEXPECT_ACTION(argc == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
error = parseLong(argv[1], &pinnum);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
nrf_gpio_cfg_input(pinnum, NRF_GPIO_PIN_NOPULL);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "gpio %d: in no pull\r\n", (uint8_t)pinnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
static void processTemp(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
int32_t temperature;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
otEXPECT_ACTION(argc == 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
temperature = nrf5TempGet();
|
||||
|
||||
// Measurement resolution is 0.25 degrees Celsius
|
||||
// Convert the temperature measurement to a decimal value, in degrees Celsius
|
||||
snprintf(aOutput, aOutputMaxLen, "%" PRId32 ".%02" PRId32 "\r\n", temperature / 4, 25 * (temperature % 4));
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
static void processCcaThreshold(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
nrf_802154_cca_cfg_t ccaConfig;
|
||||
|
||||
otEXPECT_ACTION(otPlatDiagModeGet(), error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
if (argc == 0)
|
||||
{
|
||||
nrf_802154_cca_cfg_get(&ccaConfig);
|
||||
|
||||
snprintf(aOutput, aOutputMaxLen, "cca threshold: %u\r\n", ccaConfig.ed_threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
error = parseLong(argv[0], &value);
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
otEXPECT_ACTION(value >= 0 && value <= 0xFF, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memset(&ccaConfig, 0, sizeof(ccaConfig));
|
||||
ccaConfig.mode = NRF_RADIO_CCA_MODE_ED;
|
||||
ccaConfig.ed_threshold = (uint8_t)value;
|
||||
|
||||
nrf_802154_cca_cfg_set(&ccaConfig);
|
||||
snprintf(aOutput, aOutputMaxLen, "set cca threshold to %u\r\nstatus 0x%02x\r\n", ccaConfig.ed_threshold, error);
|
||||
}
|
||||
|
||||
exit:
|
||||
appendErrorResult(error, aOutput, aOutputMaxLen);
|
||||
}
|
||||
|
||||
const struct PlatformDiagCommand sCommands[] = {
|
||||
{"ccathreshold", &processCcaThreshold},
|
||||
{"gpio", &processGpio},
|
||||
{"id", &processID},
|
||||
{"listen", &processListen},
|
||||
{"temp", &processTemp},
|
||||
{"transmit", &processTransmit},
|
||||
};
|
||||
|
||||
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < otARRAY_LENGTH(sCommands); i++)
|
||||
{
|
||||
if (strcmp(argv[0], sCommands[i].mName) == 0)
|
||||
{
|
||||
sCommands[i].mCommand(aInstance, argc - 1, argc > 1 ? &argv[1] : NULL, aOutput, aOutputMaxLen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == otARRAY_LENGTH(sCommands))
|
||||
{
|
||||
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void otPlatDiagModeSet(bool aMode)
|
||||
{
|
||||
sDiagMode = aMode;
|
||||
|
||||
if (!sDiagMode)
|
||||
{
|
||||
otPlatRadioReceive(NULL, sChannel);
|
||||
otPlatRadioSleep(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reinit
|
||||
sTransmitMode = kDiagTransmitModeIdle;
|
||||
}
|
||||
}
|
||||
|
||||
bool otPlatDiagModeGet()
|
||||
{
|
||||
return sDiagMode;
|
||||
}
|
||||
|
||||
void otPlatDiagChannelSet(uint8_t aChannel)
|
||||
{
|
||||
sChannel = aChannel;
|
||||
}
|
||||
|
||||
void otPlatDiagTxPowerSet(int8_t aTxPower)
|
||||
{
|
||||
sTxPower = aTxPower;
|
||||
}
|
||||
|
||||
void otPlatDiagRadioReceived(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
if (sListen && (aError == OT_ERROR_NONE))
|
||||
{
|
||||
if (aFrame->mLength == sizeof(struct PlatformDiagMessage))
|
||||
{
|
||||
struct PlatformDiagMessage *message = (struct PlatformDiagMessage *)aFrame->mPsdu;
|
||||
|
||||
if (strncmp(message->mMessageDescriptor, "DiagMessage", 11) == 0)
|
||||
{
|
||||
otPlatLog(OT_LOG_LEVEL_DEBG, OT_LOG_REGION_PLATFORM,
|
||||
"{\"Frame\":{"
|
||||
"\"LocalChannel\":%u ,"
|
||||
"\"RemoteChannel\":%u,"
|
||||
"\"CNT\":%" PRIu32 ","
|
||||
"\"LocalID\":%" PRId16 ","
|
||||
"\"RemoteID\":%" PRId16 ","
|
||||
"\"RSSI\":%d"
|
||||
"}}\r\n",
|
||||
aFrame->mChannel, message->mChannel, message->mCnt, sID, message->mID,
|
||||
aFrame->mInfo.mRxInfo.mRssi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void otPlatDiagAlarmCallback(otInstance *aInstance)
|
||||
{
|
||||
if (sTransmitMode == kDiagTransmitModePackets)
|
||||
{
|
||||
if ((sTxCount > 0) || (sTxCount == -1))
|
||||
{
|
||||
otRadioFrame *sTxPacket = otPlatRadioGetTransmitBuffer(aInstance);
|
||||
|
||||
sTxPacket->mLength = sizeof(struct PlatformDiagMessage);
|
||||
sTxPacket->mChannel = sChannel;
|
||||
|
||||
sDiagMessage.mChannel = sTxPacket->mChannel;
|
||||
sDiagMessage.mID = sID;
|
||||
|
||||
memcpy(sTxPacket->mPsdu, &sDiagMessage, sizeof(struct PlatformDiagMessage));
|
||||
otPlatRadioTransmit(aInstance, sTxPacket);
|
||||
|
||||
sDiagMessage.mCnt++;
|
||||
|
||||
if (sTxCount != -1)
|
||||
{
|
||||
sTxCount--;
|
||||
}
|
||||
|
||||
uint32_t now = otPlatAlarmMilliGetNow();
|
||||
otPlatAlarmMilliStartAt(aInstance, now, sTxPeriod);
|
||||
}
|
||||
else
|
||||
{
|
||||
sTransmitMode = kDiagTransmitModeIdle;
|
||||
otPlatAlarmMilliStop(aInstance);
|
||||
otPlatLog(OT_LOG_LEVEL_DEBG, OT_LOG_REGION_PLATFORM, "Transmit done");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 an entropy source based on TRNG.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread/platform/entropy.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
#include <hal/nrf_rng.h>
|
||||
|
||||
static uint8_t sBuffer[RNG_BUFFER_SIZE];
|
||||
static volatile uint32_t sReadPosition;
|
||||
static volatile uint32_t sWritePosition;
|
||||
static volatile bool sEntropyGetEntered;
|
||||
|
||||
static inline uint32_t bufferCount(void)
|
||||
{
|
||||
uint32_t writePos = sWritePosition;
|
||||
return writePos - sReadPosition;
|
||||
}
|
||||
|
||||
static inline bool bufferIsEmpty(void)
|
||||
{
|
||||
return (bufferCount() == 0);
|
||||
}
|
||||
|
||||
static inline bool bufferIsUint32Ready(void)
|
||||
{
|
||||
return (bufferCount() >= 4);
|
||||
}
|
||||
|
||||
static inline bool bufferIsFull(void)
|
||||
{
|
||||
return (bufferCount() >= RNG_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
static inline void bufferPut(uint8_t val)
|
||||
{
|
||||
if (!bufferIsFull())
|
||||
{
|
||||
sBuffer[(sWritePosition++) % RNG_BUFFER_SIZE] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t bufferGet()
|
||||
{
|
||||
uint8_t retVal = 0;
|
||||
|
||||
if (!bufferIsEmpty())
|
||||
{
|
||||
retVal = sBuffer[sReadPosition++ % RNG_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static inline uint32_t bufferGetUint32()
|
||||
{
|
||||
uint32_t retVal = 0;
|
||||
|
||||
if (bufferIsUint32Ready())
|
||||
{
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
retVal <<= 8;
|
||||
retVal |= bufferGet();
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void generatorStart(void)
|
||||
{
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
nrf_rng_int_enable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_START);
|
||||
}
|
||||
|
||||
static void generatorStop(void)
|
||||
{
|
||||
nrf_rng_int_disable(NRF_RNG_INT_VALRDY_MASK);
|
||||
nrf_rng_task_trigger(NRF_RNG_TASK_STOP);
|
||||
}
|
||||
|
||||
void RNG_IRQHandler(void)
|
||||
{
|
||||
if (nrf_rng_event_get(NRF_RNG_EVENT_VALRDY) && nrf_rng_int_get(NRF_RNG_INT_VALRDY_MASK))
|
||||
{
|
||||
nrf_rng_event_clear(NRF_RNG_EVENT_VALRDY);
|
||||
|
||||
bufferPut(nrf_rng_random_value_get());
|
||||
|
||||
if (bufferIsFull())
|
||||
{
|
||||
generatorStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nrf5RandomInit(void)
|
||||
{
|
||||
uint32_t seed = 0;
|
||||
|
||||
memset(sBuffer, 0, sizeof(sBuffer));
|
||||
sReadPosition = 0;
|
||||
sWritePosition = 0;
|
||||
|
||||
NVIC_SetPriority(RNG_IRQn, RNG_IRQ_PRIORITY);
|
||||
NVIC_ClearPendingIRQ(RNG_IRQn);
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
|
||||
nrf_rng_error_correction_enable();
|
||||
nrf_rng_shorts_disable(NRF_RNG_SHORT_VALRDY_STOP_MASK);
|
||||
generatorStart();
|
||||
|
||||
// Wait for the first randomized 4 bytes, to randomize software generator seed.
|
||||
while (!bufferIsUint32Ready())
|
||||
;
|
||||
|
||||
seed = bufferGetUint32();
|
||||
|
||||
srand(seed);
|
||||
}
|
||||
|
||||
void nrf5RandomDeinit(void)
|
||||
{
|
||||
generatorStop();
|
||||
|
||||
NVIC_DisableIRQ(RNG_IRQn);
|
||||
NVIC_ClearPendingIRQ(RNG_IRQn);
|
||||
NVIC_SetPriority(RNG_IRQn, 0);
|
||||
}
|
||||
|
||||
otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t copyLength;
|
||||
uint16_t index = 0;
|
||||
|
||||
assert(!sEntropyGetEntered);
|
||||
sEntropyGetEntered = true;
|
||||
|
||||
otEXPECT_ACTION(aOutput && aOutputLength, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
do
|
||||
{
|
||||
copyLength = (uint8_t)bufferCount();
|
||||
|
||||
if (copyLength > aOutputLength - index)
|
||||
{
|
||||
copyLength = aOutputLength - index;
|
||||
}
|
||||
|
||||
if (copyLength > 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < copyLength; i++)
|
||||
{
|
||||
aOutput[i + index] = bufferGet();
|
||||
}
|
||||
|
||||
generatorStart();
|
||||
|
||||
index += copyLength;
|
||||
}
|
||||
} while (index < aOutputLength);
|
||||
|
||||
exit:
|
||||
sEntropyGetEntered = false;
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 FEM helper functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform-fem.h"
|
||||
|
||||
#define ENABLE_FEM 1
|
||||
#include <nrf_802154.h>
|
||||
|
||||
void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig)
|
||||
{
|
||||
nrf_802154_fem_control_cfg_t cfg;
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
|
||||
cfg.pa_cfg.enable = aConfig->mPaCfg.mEnable;
|
||||
cfg.pa_cfg.active_high = aConfig->mPaCfg.mActiveHigh;
|
||||
cfg.pa_cfg.gpio_pin = aConfig->mPaCfg.mGpioPin;
|
||||
cfg.lna_cfg.enable = aConfig->mLnaCfg.mEnable;
|
||||
cfg.lna_cfg.active_high = aConfig->mLnaCfg.mActiveHigh;
|
||||
cfg.lna_cfg.gpio_pin = aConfig->mLnaCfg.mGpioPin;
|
||||
cfg.ppi_ch_id_clr = aConfig->mPpiChIdClr;
|
||||
cfg.ppi_ch_id_set = aConfig->mPpiChIdSet;
|
||||
cfg.pa_gpiote_ch_id = aConfig->mGpiotePaChId;
|
||||
cfg.lna_gpiote_ch_id = aConfig->mGpioteLnaChId;
|
||||
|
||||
nrf_802154_fem_control_cfg_set(&cfg);
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
#include <utils/flash.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
#define FLASH_PAGE_ADDR_MASK 0xFFFFF000
|
||||
#define FLASH_PAGE_SIZE 4096
|
||||
|
||||
static uint32_t sFlashDataStart;
|
||||
static uint32_t sFlashDataEnd;
|
||||
|
||||
static inline uint32_t mapAddress(uint32_t aAddress)
|
||||
{
|
||||
return aAddress + sFlashDataStart;
|
||||
}
|
||||
|
||||
otError utilsFlashInit(void)
|
||||
{
|
||||
#if defined(__CC_ARM)
|
||||
// Temporary solution for Keil compiler.
|
||||
uint32_t const bootloaderAddr = NRF_UICR->NRFFW[0];
|
||||
uint32_t const pageSize = NRF_FICR->CODEPAGESIZE;
|
||||
uint32_t const codeSize = NRF_FICR->CODESIZE;
|
||||
|
||||
if (bootloaderAddr != 0xFFFFFFFF)
|
||||
{
|
||||
sFlashDataEnd = bootloaderAddr;
|
||||
}
|
||||
else
|
||||
{
|
||||
sFlashDataEnd = pageSize * codeSize;
|
||||
}
|
||||
|
||||
sFlashDataStart = sFlashDataEnd - (pageSize * SETTINGS_CONFIG_PAGE_NUM);
|
||||
|
||||
#elif defined(__GNUC__) || defined(__ICCARM__)
|
||||
extern uint32_t __start_ot_flash_data;
|
||||
extern uint32_t __stop_ot_flash_data;
|
||||
|
||||
sFlashDataStart = (uint32_t)&__start_ot_flash_data;
|
||||
sFlashDataEnd = (uint32_t)&__stop_ot_flash_data;
|
||||
|
||||
#endif
|
||||
|
||||
// Just ensure that the start and end addresses are page-aligned.
|
||||
assert((sFlashDataStart % FLASH_PAGE_SIZE) == 0);
|
||||
assert((sFlashDataEnd % FLASH_PAGE_SIZE) == 0);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashGetSize(void)
|
||||
{
|
||||
return sFlashDataEnd - sFlashDataStart;
|
||||
}
|
||||
|
||||
otError utilsFlashErasePage(uint32_t aAddress)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otEXPECT_ACTION(aAddress < utilsFlashGetSize(), error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
error = nrf5FlashPageErase(mapAddress(aAddress & FLASH_PAGE_ADDR_MASK));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError utilsFlashStatusWait(uint32_t aTimeout)
|
||||
{
|
||||
otError error = OT_ERROR_BUSY;
|
||||
|
||||
if (aTimeout == 0)
|
||||
{
|
||||
if (!nrf5FlashIsBusy())
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t startTime = otPlatAlarmMilliGetNow();
|
||||
|
||||
do
|
||||
{
|
||||
if (!nrf5FlashIsBusy())
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
break;
|
||||
}
|
||||
} while (otPlatAlarmMilliGetNow() - startTime < aTimeout);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashWrite(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
otEXPECT(aData);
|
||||
otEXPECT(aAddress < utilsFlashGetSize());
|
||||
otEXPECT(aSize);
|
||||
|
||||
result = nrf5FlashWrite(mapAddress(aAddress), aData, aSize);
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t utilsFlashRead(uint32_t aAddress, uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
otEXPECT(aData);
|
||||
otEXPECT(aAddress < utilsFlashGetSize());
|
||||
|
||||
memcpy(aData, (uint8_t *)mapAddress(aAddress), aSize);
|
||||
result = aSize;
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread-core-config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
#include <utils/flash.h>
|
||||
|
||||
#include "hal/nrf_nvmc.h"
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
otError nrf5FlashPageErase(uint32_t aAddress)
|
||||
{
|
||||
nrf_nvmc_page_erase(aAddress);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool nrf5FlashIsBusy(void)
|
||||
{
|
||||
return NRF_NVMC->READY != NVMC_READY_READY_Ready;
|
||||
}
|
||||
|
||||
uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
nrf_nvmc_write_bytes(aAddress, aData, aSize);
|
||||
return aSize;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 logging.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/logging.h>
|
||||
|
||||
#include <utils/logging_rtt.h>
|
||||
|
||||
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
|
||||
(OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
|
||||
void nrf5LogInit(void)
|
||||
{
|
||||
utilsLogRttInit();
|
||||
}
|
||||
|
||||
void nrf5LogDeinit(void)
|
||||
{
|
||||
utilsLogRttDeinit();
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, aFormat);
|
||||
|
||||
utilsLogRttOutput(aLogLevel, aLogRegion, aFormat, ap);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
#include <openthread/platform/misc.h>
|
||||
|
||||
#include <nrf.h>
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
static uint32_t sResetReason;
|
||||
|
||||
bool gPlatformPseudoResetWasRequested;
|
||||
|
||||
void nrf5MiscInit(void)
|
||||
{
|
||||
sResetReason = NRF_POWER->RESETREAS;
|
||||
NRF_POWER->RESETREAS = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void nrf5MiscDeinit(void)
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
void otPlatReset(otInstance *aInstance)
|
||||
{
|
||||
(void)aInstance;
|
||||
#if OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
gPlatformPseudoResetWasRequested = true;
|
||||
sResetReason = POWER_RESETREAS_SREQ_Msk;
|
||||
#else // if OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
NVIC_SystemReset();
|
||||
#endif // else OPENTHREAD_PLATFORM_USE_PSEUDO_RESET
|
||||
}
|
||||
|
||||
otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
|
||||
{
|
||||
(void)aInstance;
|
||||
otPlatResetReason reason;
|
||||
|
||||
if (sResetReason & POWER_RESETREAS_RESETPIN_Msk)
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_EXTERNAL;
|
||||
}
|
||||
else if (sResetReason & POWER_RESETREAS_DOG_Msk)
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_WATCHDOG;
|
||||
}
|
||||
else if (sResetReason & POWER_RESETREAS_SREQ_Msk)
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_SOFTWARE;
|
||||
}
|
||||
else if (sResetReason & POWER_RESETREAS_LOCKUP_Msk)
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_FAULT;
|
||||
}
|
||||
else if ((sResetReason & POWER_RESETREAS_OFF_Msk) || (sResetReason & POWER_RESETREAS_DIF_Msk))
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_OTHER;
|
||||
}
|
||||
else
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_POWER_ON;
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
void otPlatWakeHost(void)
|
||||
{
|
||||
// TODO: implement an operation to wake the host from sleep state.
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 includes the platform-specific initializers.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_NRF5_H_
|
||||
#define PLATFORM_NRF5_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/instance.h>
|
||||
|
||||
#include "platform-config.h"
|
||||
|
||||
/**
|
||||
* Initialization of UART driver.
|
||||
*
|
||||
*/
|
||||
void nrf5UartInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of UART driver.
|
||||
*
|
||||
*/
|
||||
void nrf5UartDeinit(void);
|
||||
|
||||
/**
|
||||
* This function performs UART driver processing.
|
||||
*
|
||||
*/
|
||||
void nrf5UartProcess(void);
|
||||
|
||||
/**
|
||||
* Initialization of Alarm driver.
|
||||
*
|
||||
*/
|
||||
void nrf5AlarmInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of Alarm driver.
|
||||
*
|
||||
*/
|
||||
void nrf5AlarmDeinit(void);
|
||||
|
||||
/**
|
||||
* Function for processing Alarm.
|
||||
*
|
||||
*/
|
||||
void nrf5AlarmProcess(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Function for geting current time in mircosecond.
|
||||
*
|
||||
*/
|
||||
uint64_t nrf5AlarmGetCurrentTime(void);
|
||||
|
||||
/**
|
||||
* Initialization of Random Number Generator.
|
||||
*
|
||||
*/
|
||||
void nrf5RandomInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of Random Number Generator.
|
||||
*
|
||||
*/
|
||||
void nrf5RandomDeinit(void);
|
||||
|
||||
/**
|
||||
* Initialization of Logger driver.
|
||||
*
|
||||
*/
|
||||
void nrf5LogInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of Logger driver.
|
||||
*
|
||||
*/
|
||||
void nrf5LogDeinit(void);
|
||||
|
||||
/**
|
||||
* Initialization of SPI Slave driver.
|
||||
*
|
||||
*/
|
||||
void nrf5SpiSlaveInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of SPI Slave driver.
|
||||
*
|
||||
*/
|
||||
void nrf5SpiSlaveDeinit(void);
|
||||
|
||||
/**
|
||||
* Function for processing SPI Slave driver.
|
||||
*/
|
||||
void nrf5SpiSlaveProcess(void);
|
||||
|
||||
/**
|
||||
* Initialization of Misc module.
|
||||
*
|
||||
*/
|
||||
void nrf5MiscInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of Misc module.
|
||||
*
|
||||
*/
|
||||
void nrf5MiscDeinit(void);
|
||||
|
||||
/**
|
||||
* Initialization of Radio driver.
|
||||
*
|
||||
*/
|
||||
void nrf5RadioInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of Radio driver.
|
||||
*
|
||||
*/
|
||||
void nrf5RadioDeinit(void);
|
||||
|
||||
/**
|
||||
* Function for processing Radio.
|
||||
*
|
||||
*/
|
||||
void nrf5RadioProcess(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Function for erasing page in flash.
|
||||
*
|
||||
*/
|
||||
otError nrf5FlashPageErase(uint32_t aAddress);
|
||||
|
||||
/**
|
||||
* Function for checking state of flash driver.
|
||||
*
|
||||
*/
|
||||
bool nrf5FlashIsBusy(void);
|
||||
|
||||
/**
|
||||
* Function for writing data into flash.
|
||||
*
|
||||
*/
|
||||
uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize);
|
||||
|
||||
/**
|
||||
* Initialization of temperature controller.
|
||||
*
|
||||
*/
|
||||
void nrf5TempInit(void);
|
||||
|
||||
/**
|
||||
* Deinitialization of temperature controller.
|
||||
*
|
||||
*/
|
||||
void nrf5TempDeinit(void);
|
||||
|
||||
/**
|
||||
* Function for processing temperature controller.
|
||||
*
|
||||
*/
|
||||
void nrf5TempProcess(void);
|
||||
|
||||
/**
|
||||
* Function for measuring internal temperature.
|
||||
*
|
||||
* @return Temperature value measured.
|
||||
*
|
||||
*/
|
||||
int32_t nrf5TempGet(void);
|
||||
|
||||
#endif // PLATFORM_NRF5_H_
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 includes the platform-specific initializers.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <openthread/platform/logging.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
#include "platform-fem.h"
|
||||
#include "platform-nrf5.h"
|
||||
#include <drivers/clock/nrf_drv_clock.h>
|
||||
#include <nrf.h>
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
extern bool gPlatformPseudoResetWasRequested;
|
||||
|
||||
void __cxa_pure_virtual(void)
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void otSysInit(int argc, char *argv[])
|
||||
{
|
||||
if (gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
otSysDeinit();
|
||||
}
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
#if DCDC_ENABLE
|
||||
NRF_POWER->DCDCEN = 1;
|
||||
#endif
|
||||
|
||||
nrf_drv_clock_init();
|
||||
|
||||
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
|
||||
(OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
|
||||
nrf5LogInit();
|
||||
#endif
|
||||
nrf5AlarmInit();
|
||||
nrf5RandomInit();
|
||||
if (!gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
#if (UART_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5UartInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5SpiSlaveInit();
|
||||
#endif
|
||||
nrf5MiscInit();
|
||||
nrf5RadioInit();
|
||||
nrf5TempInit();
|
||||
|
||||
#if PLATFORM_FEM_ENABLE_DEFAULT_CONFIG
|
||||
PlatformFemSetConfigParams(&PLATFORM_FEM_DEFAULT_CONFIG);
|
||||
#endif
|
||||
|
||||
gPlatformPseudoResetWasRequested = false;
|
||||
}
|
||||
|
||||
void otSysDeinit(void)
|
||||
{
|
||||
nrf5TempDeinit();
|
||||
nrf5RadioDeinit();
|
||||
nrf5MiscDeinit();
|
||||
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5SpiSlaveDeinit();
|
||||
#endif
|
||||
if (!gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
#if (UART_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5UartDeinit();
|
||||
#endif
|
||||
}
|
||||
nrf5RandomDeinit();
|
||||
nrf5AlarmDeinit();
|
||||
#if (OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED) || \
|
||||
(OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_NCP_SPINEL)
|
||||
nrf5LogDeinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool otSysPseudoResetWasRequested(void)
|
||||
{
|
||||
return gPlatformPseudoResetWasRequested;
|
||||
}
|
||||
|
||||
void otSysProcessDrivers(otInstance *aInstance)
|
||||
{
|
||||
nrf5RadioProcess(aInstance);
|
||||
#if (UART_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5UartProcess();
|
||||
#endif
|
||||
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5SpiSlaveProcess();
|
||||
#endif
|
||||
nrf5TempProcess();
|
||||
nrf5AlarmProcess(aInstance);
|
||||
}
|
||||
|
||||
__WEAK void otSysEventSignalPending(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <hal/nrf_temp.h>
|
||||
#include <utils/code_utils.h>
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
#include <drivers/radio/platform/temperature/nrf_802154_temperature.h>
|
||||
|
||||
#define US_PER_S 1000000ULL
|
||||
|
||||
static uint64_t sLastReadTimestamp;
|
||||
static int32_t sTemperature;
|
||||
|
||||
__STATIC_INLINE void dataReadyEventClear(void)
|
||||
{
|
||||
NRF_TEMP->EVENTS_DATARDY = 0;
|
||||
volatile uint32_t dummy = NRF_TEMP->EVENTS_DATARDY;
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
void nrf5TempInit(void)
|
||||
{
|
||||
nrf_temp_init();
|
||||
|
||||
NRF_TEMP->TASKS_START = 1;
|
||||
}
|
||||
|
||||
void nrf5TempDeinit(void)
|
||||
{
|
||||
NRF_TEMP->TASKS_STOP = 1;
|
||||
}
|
||||
|
||||
void nrf5TempProcess(void)
|
||||
{
|
||||
int32_t prevTemperature = sTemperature;
|
||||
uint64_t now;
|
||||
|
||||
if (NRF_TEMP->EVENTS_DATARDY)
|
||||
{
|
||||
dataReadyEventClear();
|
||||
|
||||
sTemperature = nrf_temp_read();
|
||||
}
|
||||
|
||||
now = nrf5AlarmGetCurrentTime();
|
||||
|
||||
if (now - sLastReadTimestamp > (TEMP_MEASUREMENT_INTERVAL * US_PER_S))
|
||||
{
|
||||
NRF_TEMP->TASKS_START = 1;
|
||||
sLastReadTimestamp = now;
|
||||
}
|
||||
|
||||
if (prevTemperature != sTemperature)
|
||||
{
|
||||
nrf_802154_temperature_changed();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t nrf5TempGet(void)
|
||||
{
|
||||
// Provide temperature value in [0.25 C] unit.
|
||||
return sTemperature;
|
||||
}
|
||||
|
||||
void nrf_802154_temperature_init(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
void nrf_802154_temperature_deinit(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
int8_t nrf_802154_temperature_get(void)
|
||||
{
|
||||
// Provide temperature value in [C].
|
||||
return (int8_t)(sTemperature / 4);
|
||||
}
|
||||
@@ -1,338 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 UART communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
#include <openthread/platform/toolchain.h>
|
||||
#include <openthread/platform/uart.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
#include "platform-nrf5.h"
|
||||
#include <drivers/clock/nrf_drv_clock.h>
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include <hal/nrf_uart.h>
|
||||
|
||||
#if (UART_AS_SERIAL_TRANSPORT == 1)
|
||||
|
||||
bool sUartEnabled = false;
|
||||
|
||||
/**
|
||||
* UART TX buffer variables.
|
||||
*/
|
||||
static const uint8_t *sTransmitBuffer = NULL;
|
||||
static uint16_t sTransmitLength = 0;
|
||||
static bool sTransmitDone = 0;
|
||||
|
||||
/**
|
||||
* UART RX ring buffer variables.
|
||||
*/
|
||||
static uint8_t sReceiveBuffer[UART_RX_BUFFER_SIZE];
|
||||
static uint16_t sReceiveHead = 0;
|
||||
static uint16_t sReceiveTail = 0;
|
||||
|
||||
/**
|
||||
* Function for checking if RX buffer is full.
|
||||
*
|
||||
* @retval true RX buffer is full.
|
||||
* @retval false RX buffer is not full.
|
||||
*/
|
||||
static __INLINE bool isRxBufferFull()
|
||||
{
|
||||
uint16_t next = (sReceiveHead + 1) % UART_RX_BUFFER_SIZE;
|
||||
return (next == sReceiveTail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for checking if RX buffer is empty.
|
||||
*
|
||||
* @retval true RX buffer is empty.
|
||||
* @retval false RX buffer is not empty.
|
||||
*/
|
||||
static __INLINE bool isRxBufferEmpty()
|
||||
{
|
||||
return (sReceiveHead == sReceiveTail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for notifying application about new bytes received.
|
||||
*/
|
||||
static void processReceive(void)
|
||||
{
|
||||
// Set head position to not be changed during read procedure.
|
||||
uint16_t head = sReceiveHead;
|
||||
|
||||
otEXPECT(isRxBufferEmpty() == false);
|
||||
|
||||
// In case head roll back to the beginning of the buffer, notify about left
|
||||
// bytes from the end of the buffer.
|
||||
if (head < sReceiveTail)
|
||||
{
|
||||
otPlatUartReceived(&sReceiveBuffer[sReceiveTail], (UART_RX_BUFFER_SIZE - sReceiveTail));
|
||||
sReceiveTail = 0;
|
||||
}
|
||||
|
||||
// Notify about received bytes.
|
||||
if (head > sReceiveTail)
|
||||
{
|
||||
otPlatUartReceived(&sReceiveBuffer[sReceiveTail], (head - sReceiveTail));
|
||||
sReceiveTail = head;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError otPlatUartFlush(void)
|
||||
{
|
||||
return OT_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for notifying application about transmission being done.
|
||||
*/
|
||||
static void processTransmit(void)
|
||||
{
|
||||
otEXPECT(sTransmitBuffer != NULL);
|
||||
|
||||
if (sTransmitDone)
|
||||
{
|
||||
// Clear Transmition transaction and notify application.
|
||||
sTransmitBuffer = NULL;
|
||||
sTransmitLength = 0;
|
||||
sTransmitDone = false;
|
||||
otPlatUartSendDone();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void nrf5UartProcess(void)
|
||||
{
|
||||
processReceive();
|
||||
processTransmit();
|
||||
}
|
||||
|
||||
void nrf5UartInit(void)
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
void nrf5UartDeinit(void)
|
||||
{
|
||||
if (sUartEnabled)
|
||||
{
|
||||
otPlatUartDisable();
|
||||
}
|
||||
}
|
||||
|
||||
otError otPlatUartEnable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(sUartEnabled == false, error = OT_ERROR_ALREADY);
|
||||
|
||||
// Set up TX and RX pins.
|
||||
nrf_gpio_pin_set(UART_PIN_TX);
|
||||
nrf_gpio_cfg_output(UART_PIN_TX);
|
||||
nrf_gpio_cfg_input(UART_PIN_RX, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_uart_txrx_pins_set(UART_INSTANCE, UART_PIN_TX, UART_PIN_RX);
|
||||
|
||||
#if (UART_HWFC_ENABLED == 1)
|
||||
// Set up CTS and RTS pins.
|
||||
nrf_gpio_cfg_input(UART_PIN_CTS, NRF_GPIO_PIN_NOPULL);
|
||||
nrf_gpio_pin_set(UART_PIN_RTS);
|
||||
nrf_gpio_cfg_output(UART_PIN_RTS);
|
||||
nrf_uart_hwfc_pins_set(UART_INSTANCE, UART_PIN_RTS, UART_PIN_CTS);
|
||||
|
||||
nrf_uart_configure(UART_INSTANCE, UART_PARITY, NRF_UART_HWFC_ENABLED);
|
||||
#else
|
||||
nrf_uart_configure(UART_INSTANCE, UART_PARITY, NRF_UART_HWFC_DISABLED);
|
||||
#endif
|
||||
|
||||
// Configure baudrate.
|
||||
nrf_uart_baudrate_set(UART_INSTANCE, UART_BAUDRATE);
|
||||
|
||||
// Clear UART specific events.
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR);
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
|
||||
|
||||
// Enable interrupts for TX.
|
||||
nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
|
||||
|
||||
// Enable interrupts for RX.
|
||||
nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);
|
||||
|
||||
// Configure NVIC to handle UART interrupts.
|
||||
NVIC_SetPriority(UART_IRQN, UART_IRQ_PRIORITY);
|
||||
NVIC_ClearPendingIRQ(UART_IRQN);
|
||||
NVIC_EnableIRQ(UART_IRQN);
|
||||
|
||||
// Start HFCLK
|
||||
nrf_drv_clock_hfclk_request(NULL);
|
||||
|
||||
while (!nrf_drv_clock_hfclk_is_running())
|
||||
{
|
||||
}
|
||||
|
||||
// Enable UART instance, and start RX on it.
|
||||
nrf_uart_enable(UART_INSTANCE);
|
||||
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);
|
||||
|
||||
sUartEnabled = true;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartDisable(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(sUartEnabled == true, error = OT_ERROR_ALREADY);
|
||||
|
||||
// Disable NVIC interrupt.
|
||||
NVIC_DisableIRQ(UART_IRQN);
|
||||
NVIC_ClearPendingIRQ(UART_IRQN);
|
||||
NVIC_SetPriority(UART_IRQN, 0);
|
||||
|
||||
// Disable interrupts for TX.
|
||||
nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);
|
||||
|
||||
// Disable interrupts for RX.
|
||||
nrf_uart_int_disable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);
|
||||
|
||||
// Disable UART instance.
|
||||
nrf_uart_disable(UART_INSTANCE);
|
||||
|
||||
// Release HF clock.
|
||||
nrf_drv_clock_hfclk_release();
|
||||
|
||||
sUartEnabled = false;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY);
|
||||
|
||||
// Set up transmit buffer and its size without counting first triggered byte.
|
||||
sTransmitBuffer = aBuf;
|
||||
sTransmitLength = aBufLength - 1;
|
||||
|
||||
// Initiate Transmission process.
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
|
||||
nrf_uart_txd_set(UART_INSTANCE, *sTransmitBuffer++);
|
||||
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTTX);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupt handler of UART0 peripherial.
|
||||
*/
|
||||
void UARTE0_UART0_IRQHandler(void)
|
||||
{
|
||||
// Check if any error has been detected.
|
||||
if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_ERROR))
|
||||
{
|
||||
// Clear error event and ignore erronous byte in RXD register.
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR);
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
|
||||
}
|
||||
else if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY))
|
||||
{
|
||||
// Clear RXDRDY event.
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);
|
||||
|
||||
// Read byte from the UART buffer.
|
||||
uint8_t byte = nrf_uart_rxd_get(UART_INSTANCE);
|
||||
|
||||
if (!isRxBufferFull())
|
||||
{
|
||||
sReceiveBuffer[sReceiveHead] = byte;
|
||||
sReceiveHead = (sReceiveHead + 1) % UART_RX_BUFFER_SIZE;
|
||||
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY))
|
||||
{
|
||||
// Clear TXDRDY event.
|
||||
nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
|
||||
|
||||
// Send any more bytes if available or call application about TX done.
|
||||
if (sTransmitLength)
|
||||
{
|
||||
nrf_uart_txd_set(UART_INSTANCE, *sTransmitBuffer++);
|
||||
sTransmitLength--;
|
||||
}
|
||||
else
|
||||
{
|
||||
sTransmitDone = true;
|
||||
nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STOPTX);
|
||||
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UART_AS_SERIAL_TRANSPORT == 1
|
||||
|
||||
/**
|
||||
* The UART driver weak functions definition.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_WEAK void otPlatUartSendDone(void)
|
||||
{
|
||||
}
|
||||
|
||||
OT_TOOL_WEAK void otPlatUartReceived(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aBuf);
|
||||
OT_UNUSED_VARIABLE(aBufLength);
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
## Diagnostic module
|
||||
|
||||
nRF52840 port extends [OpenThread Diagnostics Module][DIAG].
|
||||
|
||||
New commands allow for more accurate low level radio testing.
|
||||
|
||||
### New commands
|
||||
* [diag ccathreshold](#diag-ccathreshold)
|
||||
* [diag gpio](#diag-gpio)
|
||||
* [diag id](#diag-id)
|
||||
* [diag listen](#diag-listen)
|
||||
* [diag temp](#diag-temp)
|
||||
* [diag transmit](#diag-transmit)
|
||||
|
||||
### Diagnostic radio packet
|
||||
[diag listen](#diag-listen) and [diag transmit](#diag-transmit) use radio frame payload specified below.
|
||||
|
||||
```c
|
||||
struct PlatformDiagMessage
|
||||
{
|
||||
const char mMessageDescriptor[11];
|
||||
uint8_t mChannel;
|
||||
int16_t mID;
|
||||
uint32_t mCnt;
|
||||
};
|
||||
```
|
||||
|
||||
`mMessageDescriptor` is a constant string `"DiagMessage"`.<br />
|
||||
`mChannel` contains the channel number on which the packet was transmitted.<br />
|
||||
`mID` contains the board ID set with the [diag id](#diag-id) command.<br />
|
||||
`mCnt` is a counter incremented every time the board transmits diagnostic radio packet.
|
||||
|
||||
If the [listen mode](#diag-listen) is enabled and OpenThread was built with the`DEFAULT_LOGGING` flag, JSON string is printed every time a diagnostic radio packet is received.
|
||||
|
||||
```JSON
|
||||
{"Frame":{
|
||||
"LocalChannel":"<listening board channel>",
|
||||
"RemoteChannel":"<mChannel>",
|
||||
"CNT":"<mCnt>",
|
||||
"LocalID":"<listening board ID>",
|
||||
"RemoteID":"<mID>",
|
||||
"RSSI":"<packet RSSI>"
|
||||
}}
|
||||
```
|
||||
|
||||
### diag ccathreshold
|
||||
Get the current CCA threshold.
|
||||
|
||||
### diag ccathreshold \<threshold\>
|
||||
Set the CCA threshold.
|
||||
|
||||
Value range: 0 to 255.
|
||||
|
||||
Default: `45`.
|
||||
|
||||
### diag gpio
|
||||
Manage GPIO pins.
|
||||
|
||||
### diag gpio \<pinnum\>
|
||||
Return the current value of the gpio.
|
||||
|
||||
Note: \<pinnum\> is an integer that combines port and pin into a single,
|
||||
contiguous number space as follows:
|
||||
```
|
||||
pinnum = (port * 32) + pin
|
||||
```
|
||||
See also the [`NRF_GPIO_PIN_MAP`](../../../third_party/NordicSemiconductor/hal/nrf_gpio.h) macro.
|
||||
|
||||
```bash
|
||||
> diag gpio 47
|
||||
gpio 47 = 0
|
||||
```
|
||||
|
||||
### diag gpio out \<pinnum\>
|
||||
Set the given GPIO to the output mode.
|
||||
```bash
|
||||
> diag gpio out 47
|
||||
gpio 47: out
|
||||
```
|
||||
|
||||
### diag gpio in \<pinnum\>
|
||||
Sets the given GPIO to the input mode with no pull variant.
|
||||
```bash
|
||||
> diag gpio in 47
|
||||
gpio 47: in no pull
|
||||
```
|
||||
|
||||
### diag gpio set \<pinnum\>
|
||||
Sets the given output gpio to high.
|
||||
```bash
|
||||
> diag gpio set 47
|
||||
gpio 47 = 1
|
||||
```
|
||||
|
||||
### diag gpio clr \<pinnum\>
|
||||
Sets the given output gpio to low.
|
||||
```bash
|
||||
> diag gpio clr 47
|
||||
gpio 47 = 0
|
||||
```
|
||||
|
||||
### diag id
|
||||
Get board ID.
|
||||
|
||||
### diag id \<id\>
|
||||
Set board ID.
|
||||
|
||||
Value range: 0 to 32767.
|
||||
|
||||
Default: `-1`.
|
||||
|
||||
### diag listen
|
||||
Get the listen state.
|
||||
|
||||
### diag listen \<listen\>
|
||||
Set the listen state.
|
||||
|
||||
`0` disables the listen state.<br />
|
||||
`1` enables the listen state.
|
||||
|
||||
By default, the listen state is disabled.
|
||||
|
||||
### diag temp
|
||||
Get the temperature from the internal temperature sensor (in degrees Celsius).
|
||||
|
||||
### diag transmit
|
||||
Get the message count and the interval between the messages that will be transmitted after `diag transmit start`.
|
||||
|
||||
### diag transmit interval \<interval\>
|
||||
Set the interval in ms between the transmitted messages.
|
||||
|
||||
Value range: 1 to 4294967295.
|
||||
|
||||
Default: `1`.
|
||||
|
||||
### diag transmit count \<count\>
|
||||
Set the number of messages to be transmitted.
|
||||
|
||||
Value range: 1 to 2147483647<br />
|
||||
or<br />
|
||||
For continuous transmission: `-1`
|
||||
|
||||
Default: `1`
|
||||
|
||||
### diag transmit stop
|
||||
Stop the ongoing transmission regardless of the remaining number of messages to be sent.
|
||||
|
||||
### diag transmit start
|
||||
Start transmiting messages with specified interval.
|
||||
|
||||
### diag transmit carrier
|
||||
Start transmitting continuous carrier wave.
|
||||
|
||||
[DIAG]: ./../../../src/core/diags/README.md
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 includes front end module platform-specific functions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_FEM_H_
|
||||
#define PLATFORM_FEM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define PLATFORM_FEM_DEFAULT_PA_PIN 26 /**< Default Power Amplifier pin. */
|
||||
#define PLATFORM_FEM_DEFAULT_LNA_PIN 27 /**< Default Low Noise Amplifier pin. */
|
||||
#define PLATFORM_FEM_DEFAULT_SET_PPI_CHANNEL 15 /**< Default PPI channel for pin setting. */
|
||||
#define PLATFORM_FEM_DEFAULT_CLR_PPI_CHANNEL 16 /**< Default PPI channel for pin clearing. */
|
||||
#define PLATFORM_FEM_DEFAULT_TIMER_MATCH_PPI_GROUP 4 /**< Default PPI channel group used to disable timer match PPI. */
|
||||
#define PLATFORM_FEM_DEFAULT_RADIO_DISABLED_PPI_GROUP 5 /**< Default PPI channel group used to disable radio disabled PPI. */
|
||||
#define PLATFORM_FEM_DEFAULT_LNA_GPIOTE_CHANNEL 6 /**< Default LNA GPIOTE channel for FEM control. */
|
||||
#define PLATFORM_FEM_DEFAULT_PA_GPIOTE_CHANNEL 7 /**< Default PA GPIOTE channel for FEM control. */
|
||||
|
||||
// clang-format on
|
||||
|
||||
#define PLATFORM_FEM_DEFAULT_CONFIG \
|
||||
((PlatformFemConfigParams){ \
|
||||
.mPaCfg = \
|
||||
{ \
|
||||
.mEnable = 1, \
|
||||
.mActiveHigh = 1, \
|
||||
.mGpioPin = PLATFORM_FEM_DEFAULT_PA_PIN, \
|
||||
}, \
|
||||
.mLnaCfg = \
|
||||
{ \
|
||||
.mEnable = 1, \
|
||||
.mActiveHigh = 1, \
|
||||
.mGpioPin = PLATFORM_FEM_DEFAULT_LNA_PIN, \
|
||||
}, \
|
||||
.mPpiChIdClr = PLATFORM_FEM_DEFAULT_CLR_PPI_CHANNEL, \
|
||||
.mPpiChIdSet = PLATFORM_FEM_DEFAULT_SET_PPI_CHANNEL, \
|
||||
.mGpiotePaChId = PLATFORM_FEM_DEFAULT_PA_GPIOTE_CHANNEL, \
|
||||
.mGpioteLnaChId = PLATFORM_FEM_DEFAULT_LNA_GPIOTE_CHANNEL, \
|
||||
})
|
||||
|
||||
/**
|
||||
* @brief Configuration parameters for the PA and LNA.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t mEnable : 1; /**< Enable toggling for this amplifier */
|
||||
uint8_t mActiveHigh : 1; /**< Set the pin to be active high */
|
||||
uint8_t mGpioPin : 6; /**< The GPIO pin to toggle for this amplifier */
|
||||
} PlatformFemConfigPaLna;
|
||||
|
||||
/**
|
||||
* @brief PA & LNA GPIO toggle configuration
|
||||
*
|
||||
* This option configures the nRF 802.15.4 radio driver to toggle pins when the radio
|
||||
* is active for use with a power amplifier and/or a low noise amplifier.
|
||||
*
|
||||
* Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided
|
||||
* by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled.
|
||||
*
|
||||
* @note Changing this configuration while the radio is in use may have undefined
|
||||
* consequences and must be avoided by the application.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PlatformFemConfigPaLna mPaCfg; /**< Power Amplifier configuration */
|
||||
PlatformFemConfigPaLna mLnaCfg; /**< Low Noise Amplifier configuration */
|
||||
uint8_t mPpiChIdSet; /**< PPI channel used for radio pin setting */
|
||||
uint8_t mPpiChIdClr; /**< PPI channel used for radio pin clearing */
|
||||
uint8_t mGpiotePaChId; /**< GPIOTE channel used for radio PA pin toggling */
|
||||
uint8_t mGpioteLnaChId; /**< GPIOTE channel used for radio LNA pin toggling */
|
||||
} PlatformFemConfigParams;
|
||||
|
||||
/**
|
||||
* Function used to set parameters of FEM.
|
||||
*
|
||||
*/
|
||||
void PlatformFemSetConfigParams(const PlatformFemConfigParams *aConfig);
|
||||
|
||||
#endif // PLATFORM_FEM_H_
|
||||
@@ -1,892 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 radio communication.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#include <platform-config.h>
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/diag.h>
|
||||
#include <openthread/platform/logging.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
#include <openthread/platform/time.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
#include "platform-nrf5.h"
|
||||
|
||||
#include <nrf.h>
|
||||
#include <nrf_802154.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
#include <openthread/random_noncrypto.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define SHORT_ADDRESS_SIZE 2 ///< Size of MAC short address.
|
||||
#define US_PER_MS 1000ULL ///< Microseconds in millisecond.
|
||||
|
||||
#define ACK_REQUEST_OFFSET 1 ///< Byte containing Ack request bit (+1 for frame length byte).
|
||||
#define ACK_REQUEST_BIT (1 << 5) ///< Ack request bit.
|
||||
#define FRAME_PENDING_OFFSET 1 ///< Byte containing pending bit (+1 for frame length byte).
|
||||
#define FRAME_PENDING_BIT (1 << 4) ///< Frame Pending bit.
|
||||
|
||||
// clang-format on
|
||||
|
||||
enum
|
||||
{
|
||||
NRF52840_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
};
|
||||
|
||||
static bool sDisabled;
|
||||
|
||||
static otError sReceiveError = OT_ERROR_NONE;
|
||||
static otRadioFrame sReceivedFrames[NRF_802154_RX_BUFFERS];
|
||||
static otRadioFrame sTransmitFrame;
|
||||
static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1];
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
static otRadioIeInfo sTransmitIeInfo;
|
||||
static otInstance * sInstance = NULL;
|
||||
#endif
|
||||
|
||||
static otRadioFrame sAckFrame;
|
||||
static bool sAckedWithFramePending;
|
||||
|
||||
static int8_t sDefaultTxPower;
|
||||
|
||||
static uint32_t sEnergyDetectionTime;
|
||||
static uint8_t sEnergyDetectionChannel;
|
||||
static int8_t sEnergyDetected;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kPendingEventSleep, // Requested to enter Sleep state.
|
||||
kPendingEventFrameTransmitted, // Transmitted frame and received ACK (if requested).
|
||||
kPendingEventChannelAccessFailure, // Failed to transmit frame (channel busy).
|
||||
kPendingEventInvalidOrNoAck, // Failed to transmit frame (received invalid or no ACK).
|
||||
kPendingEventReceiveFailed, // Failed to receive a valid frame.
|
||||
kPendingEventEnergyDetectionStart, // Requested to start Energy Detection procedure.
|
||||
kPendingEventEnergyDetected, // Energy Detection finished.
|
||||
} RadioPendingEvents;
|
||||
|
||||
static uint32_t sPendingEvents;
|
||||
|
||||
static void dataInit(void)
|
||||
{
|
||||
sDisabled = true;
|
||||
|
||||
sTransmitFrame.mPsdu = sTransmitPsdu + 1;
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
|
||||
#endif
|
||||
|
||||
sReceiveError = OT_ERROR_NONE;
|
||||
|
||||
for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++)
|
||||
{
|
||||
sReceivedFrames[i].mPsdu = NULL;
|
||||
}
|
||||
|
||||
memset(&sAckFrame, 0, sizeof(sAckFrame));
|
||||
}
|
||||
|
||||
static void convertShortAddress(uint8_t *aTo, uint16_t aFrom)
|
||||
{
|
||||
aTo[0] = (uint8_t)aFrom;
|
||||
aTo[1] = (uint8_t)(aFrom >> 8);
|
||||
}
|
||||
|
||||
static inline bool isPendingEventSet(RadioPendingEvents aEvent)
|
||||
{
|
||||
return sPendingEvents & (1UL << aEvent);
|
||||
}
|
||||
|
||||
static void setPendingEvent(RadioPendingEvents aEvent)
|
||||
{
|
||||
volatile uint32_t pendingEvents;
|
||||
uint32_t bitToSet = 1UL << aEvent;
|
||||
|
||||
do
|
||||
{
|
||||
pendingEvents = __LDREXW((unsigned long volatile *)&sPendingEvents);
|
||||
pendingEvents |= bitToSet;
|
||||
} while (__STREXW(pendingEvents, (unsigned long volatile *)&sPendingEvents));
|
||||
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
|
||||
static void resetPendingEvent(RadioPendingEvents aEvent)
|
||||
{
|
||||
volatile uint32_t pendingEvents;
|
||||
uint32_t bitsToRemain = ~(1UL << aEvent);
|
||||
|
||||
do
|
||||
{
|
||||
pendingEvents = __LDREXW((unsigned long volatile *)&sPendingEvents);
|
||||
pendingEvents &= bitsToRemain;
|
||||
} while (__STREXW(pendingEvents, (unsigned long volatile *)&sPendingEvents));
|
||||
}
|
||||
|
||||
static inline void clearPendingEvents(void)
|
||||
{
|
||||
// Clear pending events that could cause race in the MAC layer.
|
||||
volatile uint32_t pendingEvents;
|
||||
uint32_t bitsToRemain = ~(0UL);
|
||||
|
||||
bitsToRemain &= ~(1UL << kPendingEventSleep);
|
||||
|
||||
do
|
||||
{
|
||||
pendingEvents = __LDREXW((unsigned long volatile *)&sPendingEvents);
|
||||
pendingEvents &= bitsToRemain;
|
||||
} while (__STREXW(pendingEvents, (unsigned long volatile *)&sPendingEvents));
|
||||
}
|
||||
|
||||
#if !OPENTHREAD_CONFIG_ENABLE_PLATFORM_EUI64_CUSTOM_SOURCE
|
||||
void otPlatRadioGetIeeeEui64(otInstance *aInstance, uint8_t *aIeeeEui64)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
uint64_t factoryAddress;
|
||||
uint32_t index = 0;
|
||||
|
||||
// Set the MAC Address Block Larger (MA-L) formerly called OUI.
|
||||
aIeeeEui64[index++] = (OPENTHREAD_CONFIG_STACK_VENDOR_OUI >> 16) & 0xff;
|
||||
aIeeeEui64[index++] = (OPENTHREAD_CONFIG_STACK_VENDOR_OUI >> 8) & 0xff;
|
||||
aIeeeEui64[index++] = OPENTHREAD_CONFIG_STACK_VENDOR_OUI & 0xff;
|
||||
|
||||
// Use device identifier assigned during the production.
|
||||
factoryAddress = (uint64_t)NRF_FICR->DEVICEID[0] << 32;
|
||||
factoryAddress |= NRF_FICR->DEVICEID[1];
|
||||
memcpy(aIeeeEui64 + index, &factoryAddress, sizeof(factoryAddress) - index);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_EUI64_CUSTOM_SOURCE
|
||||
|
||||
void otPlatRadioSetPanId(otInstance *aInstance, uint16_t aPanId)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
uint8_t address[SHORT_ADDRESS_SIZE];
|
||||
convertShortAddress(address, aPanId);
|
||||
|
||||
nrf_802154_pan_id_set(address);
|
||||
}
|
||||
|
||||
void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aExtAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
nrf_802154_extended_address_set(aExtAddress->m8);
|
||||
}
|
||||
|
||||
void otPlatRadioSetShortAddress(otInstance *aInstance, uint16_t aShortAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
uint8_t address[SHORT_ADDRESS_SIZE];
|
||||
convertShortAddress(address, aShortAddress);
|
||||
|
||||
nrf_802154_short_address_set(address);
|
||||
}
|
||||
|
||||
void nrf5RadioInit(void)
|
||||
{
|
||||
dataInit();
|
||||
nrf_802154_init();
|
||||
}
|
||||
|
||||
void nrf5RadioDeinit(void)
|
||||
{
|
||||
nrf_802154_sleep();
|
||||
nrf_802154_deinit();
|
||||
sPendingEvents = 0;
|
||||
}
|
||||
|
||||
otRadioState otPlatRadioGetState(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
if (sDisabled)
|
||||
{
|
||||
return OT_RADIO_STATE_DISABLED;
|
||||
}
|
||||
|
||||
switch (nrf_802154_state_get())
|
||||
{
|
||||
case NRF_802154_STATE_SLEEP:
|
||||
return OT_RADIO_STATE_SLEEP;
|
||||
|
||||
case NRF_802154_STATE_RECEIVE:
|
||||
case NRF_802154_STATE_ENERGY_DETECTION:
|
||||
return OT_RADIO_STATE_RECEIVE;
|
||||
|
||||
case NRF_802154_STATE_TRANSMIT:
|
||||
case NRF_802154_STATE_CCA:
|
||||
case NRF_802154_STATE_CONTINUOUS_CARRIER:
|
||||
return OT_RADIO_STATE_TRANSMIT;
|
||||
|
||||
default:
|
||||
assert(false); // Make sure driver returned valid state.
|
||||
}
|
||||
|
||||
return OT_RADIO_STATE_RECEIVE; // It is the default state. Return it in case of unknown.
|
||||
}
|
||||
|
||||
bool otPlatRadioIsEnabled(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return !sDisabled;
|
||||
}
|
||||
|
||||
otError otPlatRadioEnable(otInstance *aInstance)
|
||||
{
|
||||
otError error;
|
||||
|
||||
#if !OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
#else
|
||||
sInstance = aInstance;
|
||||
#endif
|
||||
|
||||
if (sDisabled)
|
||||
{
|
||||
sDisabled = false;
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioDisable(otInstance *aInstance)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
otEXPECT(otPlatRadioIsEnabled(aInstance));
|
||||
otEXPECT_ACTION(otPlatRadioGetState(aInstance) == OT_RADIO_STATE_SLEEP || isPendingEventSet(kPendingEventSleep),
|
||||
error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
sDisabled = true;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioSleep(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
if (nrf_802154_sleep())
|
||||
{
|
||||
clearPendingEvents();
|
||||
}
|
||||
else
|
||||
{
|
||||
clearPendingEvents();
|
||||
setPendingEvent(kPendingEventSleep);
|
||||
}
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
bool result;
|
||||
|
||||
nrf_802154_channel_set(aChannel);
|
||||
nrf_802154_tx_power_set(sDefaultTxPower);
|
||||
result = nrf_802154_receive();
|
||||
clearPendingEvents();
|
||||
|
||||
return result ? OT_ERROR_NONE : OT_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
aFrame->mPsdu[-1] = aFrame->mLength;
|
||||
|
||||
nrf_802154_channel_set(aFrame->mChannel);
|
||||
|
||||
if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
|
||||
{
|
||||
nrf_802154_transmit_csma_ca_raw(&aFrame->mPsdu[-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = nrf_802154_transmit_raw(&aFrame->mPsdu[-1], false);
|
||||
}
|
||||
|
||||
clearPendingEvents();
|
||||
otPlatRadioTxStarted(aInstance, aFrame);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
setPendingEvent(kPendingEventChannelAccessFailure);
|
||||
}
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return &sTransmitFrame;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetRssi(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return nrf_802154_rssi_last_get();
|
||||
}
|
||||
|
||||
otRadioCaps otPlatRadioGetCaps(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return (otRadioCaps)(OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF);
|
||||
}
|
||||
|
||||
bool otPlatRadioGetPromiscuous(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return nrf_802154_promiscuous_get();
|
||||
}
|
||||
|
||||
void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
nrf_802154_promiscuous_set(aEnable);
|
||||
}
|
||||
|
||||
void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
nrf_802154_auto_pending_bit_set(aEnable);
|
||||
}
|
||||
|
||||
otError otPlatRadioAddSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error;
|
||||
|
||||
uint8_t shortAddress[SHORT_ADDRESS_SIZE];
|
||||
convertShortAddress(shortAddress, aShortAddress);
|
||||
|
||||
if (nrf_802154_pending_bit_for_addr_set(shortAddress, false))
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_NO_BUFS;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioAddSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error;
|
||||
|
||||
if (nrf_802154_pending_bit_for_addr_set(aExtAddress->m8, true))
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_NO_BUFS;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioClearSrcMatchShortEntry(otInstance *aInstance, const uint16_t aShortAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error;
|
||||
|
||||
uint8_t shortAddress[SHORT_ADDRESS_SIZE];
|
||||
convertShortAddress(shortAddress, aShortAddress);
|
||||
|
||||
if (nrf_802154_pending_bit_for_addr_clear(shortAddress, false))
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_NO_ADDRESS;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioClearSrcMatchExtEntry(otInstance *aInstance, const otExtAddress *aExtAddress)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error;
|
||||
|
||||
if (nrf_802154_pending_bit_for_addr_clear(aExtAddress->m8, true))
|
||||
{
|
||||
error = OT_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_NO_ADDRESS;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatRadioClearSrcMatchShortEntries(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
nrf_802154_pending_bit_for_addr_reset(false);
|
||||
}
|
||||
|
||||
void otPlatRadioClearSrcMatchExtEntries(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
nrf_802154_pending_bit_for_addr_reset(true);
|
||||
}
|
||||
|
||||
otError otPlatRadioEnergyScan(otInstance *aInstance, uint8_t aScanChannel, uint16_t aScanDuration)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sEnergyDetectionTime = (uint32_t)aScanDuration * 1000UL;
|
||||
sEnergyDetectionChannel = aScanChannel;
|
||||
|
||||
clearPendingEvents();
|
||||
|
||||
nrf_802154_channel_set(aScanChannel);
|
||||
|
||||
if (nrf_802154_energy_detection(sEnergyDetectionTime))
|
||||
{
|
||||
resetPendingEvent(kPendingEventEnergyDetectionStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
setPendingEvent(kPendingEventEnergyDetectionStart);
|
||||
}
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError otPlatRadioGetTransmitPower(otInstance *aInstance, int8_t *aPower)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (aPower == NULL)
|
||||
{
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
*aPower = sDefaultTxPower;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sDefaultTxPower = aPower;
|
||||
nrf_802154_tx_power_set(aPower);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
void nrf5RadioProcess(otInstance *aInstance)
|
||||
{
|
||||
bool isEventPending = false;
|
||||
|
||||
for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++)
|
||||
{
|
||||
if (sReceivedFrames[i].mPsdu != NULL)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, &sReceivedFrames[i], OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, &sReceivedFrames[i], OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
uint8_t *bufferAddress = &sReceivedFrames[i].mPsdu[-1];
|
||||
sReceivedFrames[i].mPsdu = NULL;
|
||||
nrf_802154_buffer_free_raw(bufferAddress);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventFrameTransmitted))
|
||||
{
|
||||
resetPendingEvent(kPendingEventFrameTransmitted);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otRadioFrame *ackPtr = (sAckFrame.mPsdu == NULL) ? NULL : &sAckFrame;
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, ackPtr, OT_ERROR_NONE);
|
||||
}
|
||||
|
||||
if (sAckFrame.mPsdu != NULL)
|
||||
{
|
||||
nrf_802154_buffer_free_raw(sAckFrame.mPsdu - 1);
|
||||
sAckFrame.mPsdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventChannelAccessFailure))
|
||||
{
|
||||
resetPendingEvent(kPendingEventChannelAccessFailure);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_CHANNEL_ACCESS_FAILURE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_CHANNEL_ACCESS_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventInvalidOrNoAck))
|
||||
{
|
||||
resetPendingEvent(kPendingEventInvalidOrNoAck);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_NO_ACK);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_NO_ACK);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventReceiveFailed))
|
||||
{
|
||||
resetPendingEvent(kPendingEventReceiveFailed);
|
||||
|
||||
#if OPENTHREAD_CONFIG_DIAG_ENABLE
|
||||
|
||||
if (otPlatDiagModeGet())
|
||||
{
|
||||
otPlatDiagRadioReceiveDone(aInstance, NULL, sReceiveError);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
otPlatRadioReceiveDone(aInstance, NULL, sReceiveError);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventEnergyDetected))
|
||||
{
|
||||
resetPendingEvent(kPendingEventEnergyDetected);
|
||||
|
||||
otPlatRadioEnergyScanDone(aInstance, sEnergyDetected);
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventSleep))
|
||||
{
|
||||
if (nrf_802154_sleep())
|
||||
{
|
||||
resetPendingEvent(kPendingEventSleep);
|
||||
}
|
||||
else
|
||||
{
|
||||
isEventPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPendingEventSet(kPendingEventEnergyDetectionStart))
|
||||
{
|
||||
nrf_802154_channel_set(sEnergyDetectionChannel);
|
||||
|
||||
if (nrf_802154_energy_detection(sEnergyDetectionTime))
|
||||
{
|
||||
resetPendingEvent(kPendingEventEnergyDetectionStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
isEventPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isEventPending)
|
||||
{
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
}
|
||||
|
||||
void nrf_802154_received_timestamp_raw(uint8_t *p_data, int8_t power, uint8_t lqi, uint32_t time)
|
||||
{
|
||||
otRadioFrame *receivedFrame = NULL;
|
||||
|
||||
for (uint32_t i = 0; i < NRF_802154_RX_BUFFERS; i++)
|
||||
{
|
||||
if (sReceivedFrames[i].mPsdu == NULL)
|
||||
{
|
||||
receivedFrame = &sReceivedFrames[i];
|
||||
|
||||
memset(receivedFrame, 0, sizeof(*receivedFrame));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(receivedFrame != NULL);
|
||||
|
||||
receivedFrame->mPsdu = &p_data[1];
|
||||
receivedFrame->mLength = p_data[0];
|
||||
receivedFrame->mInfo.mRxInfo.mRssi = power;
|
||||
receivedFrame->mInfo.mRxInfo.mLqi = lqi;
|
||||
receivedFrame->mChannel = nrf_802154_channel_get();
|
||||
|
||||
// Inform if this frame was acknowledged with frame pending set.
|
||||
if (p_data[ACK_REQUEST_OFFSET] & ACK_REQUEST_BIT)
|
||||
{
|
||||
receivedFrame->mInfo.mRxInfo.mAckedWithFramePending = sAckedWithFramePending;
|
||||
}
|
||||
else
|
||||
{
|
||||
receivedFrame->mInfo.mRxInfo.mAckedWithFramePending = false;
|
||||
}
|
||||
|
||||
// Get the timestamp when the SFD was received.
|
||||
#if !NRF_802154_TX_STARTED_NOTIFY_ENABLED
|
||||
#error "NRF_802154_TX_STARTED_NOTIFY_ENABLED is required!"
|
||||
#endif
|
||||
uint32_t offset =
|
||||
(int32_t)otPlatAlarmMicroGetNow() - (int32_t)nrf_802154_first_symbol_timestamp_get(time, p_data[0]);
|
||||
receivedFrame->mInfo.mRxInfo.mTimestamp = nrf5AlarmGetCurrentTime() - offset;
|
||||
|
||||
sAckedWithFramePending = false;
|
||||
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
|
||||
void nrf_802154_receive_failed(nrf_802154_rx_error_t error)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case NRF_802154_RX_ERROR_INVALID_FRAME:
|
||||
case NRF_802154_RX_ERROR_DELAYED_TIMEOUT:
|
||||
sReceiveError = OT_ERROR_NO_FRAME_RECEIVED;
|
||||
break;
|
||||
|
||||
case NRF_802154_RX_ERROR_INVALID_FCS:
|
||||
sReceiveError = OT_ERROR_FCS;
|
||||
break;
|
||||
|
||||
case NRF_802154_RX_ERROR_INVALID_DEST_ADDR:
|
||||
sReceiveError = OT_ERROR_DESTINATION_ADDRESS_FILTERED;
|
||||
break;
|
||||
|
||||
case NRF_802154_RX_ERROR_RUNTIME:
|
||||
case NRF_802154_RX_ERROR_TIMESLOT_ENDED:
|
||||
case NRF_802154_RX_ERROR_ABORTED:
|
||||
case NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED:
|
||||
case NRF_802154_RX_ERROR_INVALID_LENGTH:
|
||||
sReceiveError = OT_ERROR_FAILED;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
sAckedWithFramePending = false;
|
||||
|
||||
setPendingEvent(kPendingEventReceiveFailed);
|
||||
}
|
||||
|
||||
void nrf_802154_tx_ack_started(const uint8_t *p_data)
|
||||
{
|
||||
// Check if the frame pending bit is set in ACK frame.
|
||||
sAckedWithFramePending = p_data[FRAME_PENDING_OFFSET] & FRAME_PENDING_BIT;
|
||||
}
|
||||
|
||||
void nrf_802154_transmitted_raw(const uint8_t *aFrame, uint8_t *aAckPsdu, int8_t aPower, uint8_t aLqi)
|
||||
{
|
||||
assert(aFrame == sTransmitPsdu);
|
||||
|
||||
if (aAckPsdu == NULL)
|
||||
{
|
||||
sAckFrame.mPsdu = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sAckFrame.mPsdu = &aAckPsdu[1];
|
||||
sAckFrame.mLength = aAckPsdu[0];
|
||||
sAckFrame.mInfo.mRxInfo.mRssi = aPower;
|
||||
sAckFrame.mInfo.mRxInfo.mLqi = aLqi;
|
||||
sAckFrame.mChannel = nrf_802154_channel_get();
|
||||
}
|
||||
|
||||
setPendingEvent(kPendingEventFrameTransmitted);
|
||||
}
|
||||
|
||||
void nrf_802154_transmit_failed(const uint8_t *aFrame, nrf_802154_tx_error_t error)
|
||||
{
|
||||
assert(aFrame == sTransmitPsdu);
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case NRF_802154_TX_ERROR_BUSY_CHANNEL:
|
||||
case NRF_802154_TX_ERROR_TIMESLOT_ENDED:
|
||||
case NRF_802154_TX_ERROR_ABORTED:
|
||||
case NRF_802154_TX_ERROR_TIMESLOT_DENIED:
|
||||
setPendingEvent(kPendingEventChannelAccessFailure);
|
||||
break;
|
||||
|
||||
case NRF_802154_TX_ERROR_INVALID_ACK:
|
||||
case NRF_802154_TX_ERROR_NO_ACK:
|
||||
case NRF_802154_TX_ERROR_NO_MEM:
|
||||
setPendingEvent(kPendingEventInvalidOrNoAck);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void nrf_802154_energy_detected(uint8_t result)
|
||||
{
|
||||
sEnergyDetected = nrf_802154_dbm_from_energy_level_calculate(result);
|
||||
|
||||
setPendingEvent(kPendingEventEnergyDetected);
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
return NRF52840_RECEIVE_SENSITIVITY;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
void nrf_802154_tx_started(const uint8_t *aFrame)
|
||||
{
|
||||
bool notifyFrameUpdated = false;
|
||||
assert(aFrame == sTransmitPsdu);
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
|
||||
{
|
||||
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
|
||||
uint64_t time = otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
|
||||
|
||||
*timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
|
||||
|
||||
*(++timeIe) = (uint8_t)(time & 0xff);
|
||||
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
|
||||
{
|
||||
time = time >> 8;
|
||||
*(++timeIe) = (uint8_t)(time & 0xff);
|
||||
}
|
||||
|
||||
notifyFrameUpdated = true;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
|
||||
if (notifyFrameUpdated)
|
||||
{
|
||||
otPlatRadioFrameUpdated(sInstance, &sTransmitFrame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void nrf_802154_random_init(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
void nrf_802154_random_deinit(void)
|
||||
{
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
uint32_t nrf_802154_random_get(void)
|
||||
{
|
||||
return otRandomNonCryptoGetUint32();
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 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 SPIS communication.
|
||||
*
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
#include <openthread/platform/spi-slave.h>
|
||||
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include <nrfx.h>
|
||||
#include <nrfx_spis.h>
|
||||
#include <platform-nrf5.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
|
||||
|
||||
/**
|
||||
* SPI Slave transaction variables.
|
||||
*/
|
||||
static void * sContext = NULL;
|
||||
static uint8_t * sOutputBuf = NULL;
|
||||
static uint16_t sOutputBufLen = 0;
|
||||
static uint8_t * sInputBuf = NULL;
|
||||
static uint16_t sInputBufLen = 0;
|
||||
static bool sRequestTransactionFlag = false;
|
||||
static bool sFurtherProcessingFlag = false;
|
||||
static otPlatSpiSlaveTransactionProcessCallback sProcessCallback = NULL;
|
||||
static otPlatSpiSlaveTransactionCompleteCallback sCompleteCallback = NULL;
|
||||
static const nrfx_spis_t sSpiSlaveInstance = NRFX_SPIS_INSTANCE(SPIS_INSTANCE);
|
||||
|
||||
static void spisEventHandler(nrfx_spis_evt_t const *aEvent, void *aContext)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aContext);
|
||||
|
||||
switch (aEvent->evt_type)
|
||||
{
|
||||
case NRFX_SPIS_BUFFERS_SET_DONE:
|
||||
if (sRequestTransactionFlag)
|
||||
{
|
||||
// Host IRQ pin is active low.
|
||||
nrf_gpio_pin_clear(SPIS_PIN_HOST_IRQ);
|
||||
}
|
||||
break;
|
||||
|
||||
case NRFX_SPIS_XFER_DONE:
|
||||
// Ensure Host IRQ pin is set.
|
||||
nrf_gpio_pin_set(SPIS_PIN_HOST_IRQ);
|
||||
|
||||
// Execute application callback.
|
||||
if (sCompleteCallback(sContext, sOutputBuf, sOutputBufLen, sInputBuf, sInputBufLen, aEvent->rx_amount))
|
||||
{
|
||||
// Further processing is required.
|
||||
sFurtherProcessingFlag = true;
|
||||
|
||||
otSysEventSignalPending();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void nrf5SpiSlaveInit(void)
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
void nrf5SpiSlaveDeinit(void)
|
||||
{
|
||||
sOutputBuf = NULL;
|
||||
sOutputBufLen = 0;
|
||||
sInputBuf = NULL;
|
||||
sInputBufLen = 0;
|
||||
sRequestTransactionFlag = false;
|
||||
|
||||
otPlatSpiSlaveDisable();
|
||||
}
|
||||
|
||||
void nrf5SpiSlaveProcess(void)
|
||||
{
|
||||
otEXPECT(sFurtherProcessingFlag == true);
|
||||
|
||||
// Clear further processing flag.
|
||||
sFurtherProcessingFlag = false;
|
||||
|
||||
// Perform any further processing if necessary.
|
||||
sProcessCallback(sContext);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError otPlatSpiSlaveEnable(otPlatSpiSlaveTransactionCompleteCallback aCompleteCallback,
|
||||
otPlatSpiSlaveTransactionProcessCallback aProcessCallback,
|
||||
void * aContext)
|
||||
{
|
||||
otError result = OT_ERROR_NONE;
|
||||
nrfx_err_t error = NRFX_SUCCESS;
|
||||
nrfx_spis_config_t config = NRFX_SPIS_DEFAULT_CONFIG;
|
||||
|
||||
assert(aCompleteCallback != NULL);
|
||||
assert(aProcessCallback != NULL);
|
||||
|
||||
// Check if SPI Slave interface is already enabled.
|
||||
otEXPECT_ACTION(sCompleteCallback == NULL, error = OT_ERROR_ALREADY);
|
||||
|
||||
config.csn_pin = SPIS_PIN_CSN;
|
||||
config.miso_pin = SPIS_PIN_MISO;
|
||||
config.mosi_pin = SPIS_PIN_MOSI;
|
||||
config.sck_pin = SPIS_PIN_SCK;
|
||||
config.mode = SPIS_MODE;
|
||||
config.bit_order = SPIS_BIT_ORDER;
|
||||
config.irq_priority = SPIS_IRQ_PRIORITY;
|
||||
|
||||
error = nrfx_spis_init(&sSpiSlaveInstance, &config, spisEventHandler, NULL);
|
||||
assert(error == NRFX_SUCCESS);
|
||||
|
||||
// Set up Host IRQ pin.
|
||||
nrf_gpio_pin_set(SPIS_PIN_HOST_IRQ);
|
||||
nrf_gpio_cfg_output(SPIS_PIN_HOST_IRQ);
|
||||
|
||||
// Set proper callback and context.
|
||||
sProcessCallback = aProcessCallback;
|
||||
sCompleteCallback = aCompleteCallback;
|
||||
sContext = aContext;
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
void otPlatSpiSlaveDisable(void)
|
||||
{
|
||||
nrfx_spis_uninit(&sSpiSlaveInstance);
|
||||
}
|
||||
|
||||
otError otPlatSpiSlavePrepareTransaction(uint8_t *aOutputBuf,
|
||||
uint16_t aOutputBufLen,
|
||||
uint8_t *aInputBuf,
|
||||
uint16_t aInputBufLen,
|
||||
bool aRequestTransactionFlag)
|
||||
{
|
||||
otError result = OT_ERROR_NONE;
|
||||
nrfx_err_t error = NRFX_SUCCESS;
|
||||
nrf_spis_semstat_t semaphore_status = nrf_spis_semaphore_status_get(sSpiSlaveInstance.p_reg);
|
||||
|
||||
assert(sCompleteCallback != NULL);
|
||||
|
||||
otEXPECT_ACTION(((semaphore_status != NRF_SPIS_SEMSTAT_SPIS) && (semaphore_status != NRF_SPIS_SEMSTAT_CPUPENDING)),
|
||||
error = OT_ERROR_BUSY);
|
||||
|
||||
if (aOutputBuf != NULL)
|
||||
{
|
||||
sOutputBuf = aOutputBuf;
|
||||
sOutputBufLen = aOutputBufLen;
|
||||
}
|
||||
|
||||
if (aInputBuf != NULL)
|
||||
{
|
||||
sInputBuf = aInputBuf;
|
||||
sInputBufLen = aInputBufLen;
|
||||
}
|
||||
|
||||
sRequestTransactionFlag = aRequestTransactionFlag;
|
||||
|
||||
error = nrfx_spis_buffers_set(&sSpiSlaveInstance, sOutputBuf, sOutputBufLen, sInputBuf, sInputBufLen);
|
||||
assert(error == NRFX_SUCCESS);
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // SPIS_AS_SERIAL_TRANSPORT == 1
|
||||
@@ -1,6 +1,6 @@
|
||||
## Diagnostic module
|
||||
|
||||
nRF52811 port extends [OpenThread Diagnostics Module][DIAG].
|
||||
nRF52811 and nRF52840 ports extend [OpenThread Diagnostics Module][DIAG].
|
||||
|
||||
New commands allow for more accurate low level radio testing.
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#
|
||||
# Copyright (c) 2019, 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.
|
||||
#
|
||||
|
||||
# Use automake includes since we cannot use SUBDIRS feature due to cleanup
|
||||
# errors - few targets may use the same source file but dependency file is
|
||||
# created only once which leads to errors when auto-generated Makefile tries
|
||||
# to remove .Po files that were already removed
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52811
|
||||
include nrf52811/Makefile.am
|
||||
endif
|
||||
|
||||
if OPENTHREAD_EXAMPLES_NRF52840
|
||||
include nrf52840/Makefile.am
|
||||
endif
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
PRETTY_FILES = \
|
||||
src/*.c \
|
||||
src/platform-fem.h \
|
||||
src/platform-nrf5.h \
|
||||
nrf52840/*.h \
|
||||
nrf52811/*.h \
|
||||
$(NULL)
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
@@ -0,0 +1,13 @@
|
||||
# OpenThread on nRF528XX Example
|
||||
|
||||
This directory contains example platform drivers for [Nordic Semiconductor nRF52840 SoC][nRF52840] and [Nordic Semiconductor nRF52811 SoC][nRF52811].
|
||||
|
||||
[nRF52840]: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52840
|
||||
[nRF52811]: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52811
|
||||
|
||||
To learn more about building and running the examples please check:
|
||||
* [OpenThread on nRF52840 examples][nrf52840-page]
|
||||
* [OpenThread on nRF52811 examples][nrf52811-page]
|
||||
|
||||
[nrf52840-page]: ./nrf52840/README.md
|
||||
[nrf52811-page]: ./nrf52811/README.md
|
||||
+15
-22
@@ -40,10 +40,11 @@ override CXXFLAGS := $(filter-out -pedantic-e
|
||||
COMMONCPPFLAGS = \
|
||||
-DCONFIG_GPIO_AS_PINRESET \
|
||||
-DNRF52811_XXAA \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/examples/platforms \
|
||||
-I$(top_srcdir)/examples/platforms/nrf528xx/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor/cmsis \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor/dependencies \
|
||||
@@ -71,27 +72,22 @@ COMMONCPPFLAGS
|
||||
$(NULL)
|
||||
|
||||
PLATFORM_COMMON_SOURCES = \
|
||||
alarm.c \
|
||||
diag.c \
|
||||
entropy.c \
|
||||
fem.c \
|
||||
flash.c \
|
||||
logging.c \
|
||||
misc.c \
|
||||
openthread-core-nrf52811-config.h \
|
||||
openthread-core-nrf52811-config-check.h \
|
||||
platform-config.h \
|
||||
platform-fem.h \
|
||||
platform-nrf5.h \
|
||||
radio.c \
|
||||
temp.c \
|
||||
spi-slave.c \
|
||||
system.c \
|
||||
uart.c \
|
||||
src/alarm.c \
|
||||
src/diag.c \
|
||||
src/entropy.c \
|
||||
src/fem.c \
|
||||
src/flash.c \
|
||||
src/logging.c \
|
||||
src/misc.c \
|
||||
src/radio.c \
|
||||
src/spi-slave.c \
|
||||
src/system.c \
|
||||
src/temp.c \
|
||||
src/uart.c \
|
||||
$(NULL)
|
||||
|
||||
SINGLEPHY_SOURCES = \
|
||||
flash_nosd.c \
|
||||
src/flash_nosd.c \
|
||||
$(NULL)
|
||||
|
||||
SINGLEPHY_CPPFLAGS = \
|
||||
@@ -122,9 +118,6 @@ libopenthread_nrf52811_sdk_a_SOURCES
|
||||
$(SINGLEPHY_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
PRETTY_FILES = \
|
||||
$(PLATFORM_COMMON_SOURCES) \
|
||||
$(NULL)
|
||||
Dash = -
|
||||
|
||||
libopenthread_nrf52811_a_LIBADD = \
|
||||
+2
-2
@@ -31,7 +31,7 @@
|
||||
#
|
||||
|
||||
LDADD_COMMON += \
|
||||
$(top_builddir)/examples/platforms/nrf52811/libopenthread-nrf52811.a \
|
||||
$(top_builddir)/examples/platforms/nrf528xx/libopenthread-nrf52811.a \
|
||||
$(top_builddir)/third_party/NordicSemiconductor/libnordicsemi-nrf52811-sdk.a \
|
||||
$(top_builddir)/third_party/NordicSemiconductor/libnordicsemi-nrf52811-radio-driver.a \
|
||||
$(NULL)
|
||||
@@ -42,6 +42,6 @@ LDFLAGS_COMMON
|
||||
$(NULL)
|
||||
else
|
||||
LDFLAGS_COMMON += \
|
||||
-T $(top_srcdir)/examples/platforms/nrf52811/nrf52811.ld \
|
||||
-T $(top_srcdir)/examples/platforms/nrf528xx/nrf52811/nrf52811.ld \
|
||||
$(NULL)
|
||||
endif
|
||||
+20
-28
@@ -41,10 +41,11 @@ override CXXFLAGS := $(filter-out -pedantic-e
|
||||
COMMONCPPFLAGS = \
|
||||
-DCONFIG_GPIO_AS_PINRESET \
|
||||
-DNRF52840_XXAA \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/examples/platforms \
|
||||
-I$(top_srcdir)/examples/platforms/nrf528xx/src \
|
||||
-I$(top_srcdir)/src/core \
|
||||
-I$(srcdir) \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor/cmsis \
|
||||
-I$(top_srcdir)/third_party/NordicSemiconductor/dependencies \
|
||||
@@ -79,35 +80,29 @@ COMMONCPPFLAGS
|
||||
$(NULL)
|
||||
|
||||
PLATFORM_COMMON_SOURCES = \
|
||||
alarm.c \
|
||||
diag.c \
|
||||
entropy.c \
|
||||
fem.c \
|
||||
flash.c \
|
||||
logging.c \
|
||||
misc.c \
|
||||
openthread-core-nrf52840-config.h \
|
||||
openthread-core-nrf52840-config-check.h \
|
||||
platform-config.h \
|
||||
platform-fem.h \
|
||||
platform-nrf5.h \
|
||||
radio.c \
|
||||
temp.c \
|
||||
spi-slave.c \
|
||||
system.c \
|
||||
uart.c \
|
||||
usb-cdc-uart.c \
|
||||
src/alarm.c \
|
||||
src/diag.c \
|
||||
src/entropy.c \
|
||||
src/fem.c \
|
||||
src/flash.c \
|
||||
src/logging.c \
|
||||
src/misc.c \
|
||||
src/radio.c \
|
||||
src/spi-slave.c \
|
||||
src/system.c \
|
||||
src/temp.c \
|
||||
src/uart.c \
|
||||
src/usb-cdc-uart.c \
|
||||
$(NULL)
|
||||
|
||||
SINGLEPHY_SOURCES = \
|
||||
flash_nosd.c \
|
||||
src/flash_nosd.c \
|
||||
$(NULL)
|
||||
|
||||
SOFTDEVICE_SOURCES = \
|
||||
flash_sd.c \
|
||||
platform-softdevice.h \
|
||||
softdevice.c \
|
||||
softdevice.h \
|
||||
src/flash_sd.c \
|
||||
src/softdevice.c \
|
||||
src/softdevice.h \
|
||||
$(NULL)
|
||||
|
||||
SOFTDEVICE_CPPFLAGS = \
|
||||
@@ -164,10 +159,6 @@ libopenthread_nrf52840_softdevice_sdk_a_SOURCES
|
||||
$(HWCRYPTO_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
PRETTY_FILES = \
|
||||
$(PLATFORM_COMMON_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
Dash = -
|
||||
|
||||
libopenthread_nrf52840_a_LIBADD = \
|
||||
@@ -179,4 +170,5 @@ libopenthread_nrf52840_sdk_a_LIBADD
|
||||
|
||||
libopenthread_nrf52840_softdevice_sdk_a_LIBADD = \
|
||||
$(shell find $(top_builddir)/examples/platforms/utils $(Dash)type f $(Dash)name "*.o")
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
|
||||
+2
-2
@@ -31,7 +31,7 @@
|
||||
#
|
||||
|
||||
LDADD_COMMON += \
|
||||
$(top_builddir)/examples/platforms/nrf52840/libopenthread-nrf52840.a \
|
||||
$(top_builddir)/examples/platforms/nrf528xx/libopenthread-nrf52840.a \
|
||||
$(top_builddir)/third_party/NordicSemiconductor/libnordicsemi-nrf52840-sdk.a \
|
||||
$(top_builddir)/third_party/NordicSemiconductor/libnordicsemi-nrf52840-radio-driver.a \
|
||||
$(top_srcdir)/third_party/NordicSemiconductor/libraries/nrf_cc310/lib/libnrf_cc310_0.9.10.a \
|
||||
@@ -43,6 +43,6 @@ LDFLAGS_COMMON
|
||||
$(NULL)
|
||||
else
|
||||
LDFLAGS_COMMON += \
|
||||
-T $(top_srcdir)/examples/platforms/nrf52840/nrf52840.ld \
|
||||
-T $(top_srcdir)/examples/platforms/nrf528xx/nrf52840/nrf52840.ld \
|
||||
$(NULL)
|
||||
endif
|
||||
+3
-3
@@ -26,18 +26,18 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <utils/code_utils.h>
|
||||
#include <utils/flash.h>
|
||||
|
||||
#include "hal/nrf_nvmc.h"
|
||||
#include "platform-nrf5.h"
|
||||
#include "hal/nrf_nvmc.h"
|
||||
|
||||
otError nrf5FlashPageErase(uint32_t aAddress)
|
||||
{
|
||||
+18
-24
@@ -26,12 +26,12 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
|
||||
@@ -41,10 +41,11 @@
|
||||
#include "platform-nrf5.h"
|
||||
#include "softdevice.h"
|
||||
|
||||
#define FLASH_PAGE_SIZE 4096
|
||||
#define FLASH_TIMEOUT 500
|
||||
#define FLASH_PAGE_SIZE 4096
|
||||
#define FLASH_TIMEOUT 500
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
FLASH_STATE_IDLE,
|
||||
FLASH_STATE_WAITING_FOR_IDLE,
|
||||
FLASH_STATE_PENDING,
|
||||
@@ -109,8 +110,7 @@ static void waitInState(SdFlashState state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (otPlatAlarmMilliGetNow() - startTime < FLASH_TIMEOUT);
|
||||
} while (otPlatAlarmMilliGetNow() - startTime < FLASH_TIMEOUT);
|
||||
}
|
||||
|
||||
static otError sdFlashSingleWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
@@ -206,8 +206,8 @@ bool nrf5FlashIsBusy(void)
|
||||
|
||||
uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint32_t result = 0;
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint32_t result = 0;
|
||||
uint32_t remainder = (aAddress % sizeof(uint32_t));
|
||||
uint32_t blockSize;
|
||||
uint32_t blockValue;
|
||||
@@ -223,16 +223,14 @@ uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
|
||||
memcpy((uint8_t *)&blockValue + remainder, aData, blockSize);
|
||||
|
||||
error = sdFlashSingleWrite(aAddress - remainder,
|
||||
(uint8_t *)&blockValue,
|
||||
sizeof(blockValue) / sizeof(uint32_t));
|
||||
error = sdFlashSingleWrite(aAddress - remainder, (uint8_t *)&blockValue, sizeof(blockValue) / sizeof(uint32_t));
|
||||
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
aAddress += blockSize;
|
||||
aData += blockSize;
|
||||
aSize -= blockSize;
|
||||
result += blockSize;
|
||||
aData += blockSize;
|
||||
aSize -= blockSize;
|
||||
result += blockSize;
|
||||
}
|
||||
|
||||
otEXPECT(aSize);
|
||||
@@ -241,16 +239,14 @@ uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
remainder = aSize % sizeof(uint32_t);
|
||||
blockSize = aSize - remainder;
|
||||
|
||||
error = sdFlashSingleWrite(aAddress,
|
||||
aData,
|
||||
blockSize / sizeof(uint32_t));
|
||||
error = sdFlashSingleWrite(aAddress, aData, blockSize / sizeof(uint32_t));
|
||||
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
aAddress += blockSize;
|
||||
aData += blockSize;
|
||||
aSize -= blockSize;
|
||||
result += blockSize;
|
||||
aData += blockSize;
|
||||
aSize -= blockSize;
|
||||
result += blockSize;
|
||||
|
||||
// Store any additional bytes that didn't fit into middle block.
|
||||
if (remainder)
|
||||
@@ -259,9 +255,7 @@ uint32_t nrf5FlashWrite(uint32_t aAddress, const uint8_t *aData, uint32_t aSize)
|
||||
|
||||
memcpy((uint8_t *)&blockValue, aData, remainder);
|
||||
|
||||
error = sdFlashSingleWrite(aAddress,
|
||||
(uint8_t *)&blockValue,
|
||||
sizeof(blockValue) / sizeof(uint32_t));
|
||||
error = sdFlashSingleWrite(aAddress, (uint8_t *)&blockValue, sizeof(blockValue) / sizeof(uint32_t));
|
||||
|
||||
otEXPECT(error == OT_ERROR_NONE);
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
|
||||
#if SOFTDEVICE_PRESENT
|
||||
#include "softdevice.h"
|
||||
#endif
|
||||
#endif // SOFTDEVICE_PRESENT
|
||||
|
||||
static uint32_t sResetReason;
|
||||
|
||||
bool gPlatformPseudoResetWasRequested;
|
||||
|
||||
#if NRF52840_XXAA
|
||||
__WEAK void nrf5CryptoInit(void)
|
||||
{
|
||||
// This function is defined as weak so it could be overridden with external implementation.
|
||||
@@ -51,6 +52,7 @@ __WEAK void nrf5CryptoDeinit(void)
|
||||
{
|
||||
// This function is defined as weak so it could be overridden with external implementation.
|
||||
}
|
||||
#endif
|
||||
|
||||
void nrf5MiscInit(void)
|
||||
{
|
||||
@@ -102,12 +104,17 @@ otPlatResetReason otPlatGetResetReason(otInstance *aInstance)
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_FAULT;
|
||||
}
|
||||
else if ((sResetReason & POWER_RESETREAS_OFF_Msk) || (sResetReason & POWER_RESETREAS_LPCOMP_Msk) ||
|
||||
(sResetReason & POWER_RESETREAS_DIF_Msk) || (sResetReason & POWER_RESETREAS_NFC_Msk) ||
|
||||
else if ((sResetReason & POWER_RESETREAS_OFF_Msk) || (sResetReason & POWER_RESETREAS_DIF_Msk))
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_OTHER;
|
||||
}
|
||||
#if NRF52840_XXAA
|
||||
else if ((sResetReason & POWER_RESETREAS_LPCOMP_Msk) || (sResetReason & POWER_RESETREAS_NFC_Msk) ||
|
||||
(sResetReason & POWER_RESETREAS_VBUS_Msk))
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_OTHER;
|
||||
}
|
||||
#endif // NRF52840_XXAA
|
||||
else
|
||||
{
|
||||
reason = OT_PLAT_RESET_REASON_POWER_ON;
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
NRF52811_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
NRF528XX_RECEIVE_SENSITIVITY = -100, // dBm
|
||||
};
|
||||
|
||||
static bool sDisabled;
|
||||
@@ -840,7 +840,8 @@ void nrf_802154_energy_detected(uint8_t result)
|
||||
int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return NRF52811_RECEIVE_SENSITIVITY;
|
||||
|
||||
return NRF528XX_RECEIVE_SENSITIVITY;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT
|
||||
+3
-3
@@ -32,17 +32,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
#include <openthread-core-config.h>
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "softdevice.h"
|
||||
#include "platform-softdevice.h"
|
||||
#include "platform-nrf5.h"
|
||||
#include "platform-softdevice.h"
|
||||
#include "softdevice.h"
|
||||
|
||||
#include <nrf_raal_softdevice.h>
|
||||
|
||||
@@ -63,9 +63,11 @@ void otSysInit(int argc, char *argv[])
|
||||
otSysDeinit();
|
||||
}
|
||||
|
||||
#if !SOFTDEVICE_PRESENT
|
||||
#if ((!SOFTDEVICE_PRESENT) && (NRF52840_XXAA))
|
||||
// Enable I-code cache
|
||||
NRF_NVMC->ICACHECNF = NVMC_ICACHECNF_CACHEEN_Enabled;
|
||||
#elif (DCDC_ENABLE)
|
||||
NRF_POWER->DCDCEN = 1;
|
||||
#endif
|
||||
|
||||
nrf_drv_clock_init();
|
||||
@@ -81,7 +83,9 @@ void otSysInit(int argc, char *argv[])
|
||||
#if ((UART_AS_SERIAL_TRANSPORT == 1) || (USB_CDC_AS_SERIAL_TRANSPORT == 1))
|
||||
nrf5UartInit();
|
||||
#endif
|
||||
#if NRF52840_XXAA
|
||||
nrf5CryptoInit();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -114,7 +118,9 @@ void otSysDeinit(void)
|
||||
#endif
|
||||
if (!gPlatformPseudoResetWasRequested)
|
||||
{
|
||||
#if NRF52840_XXAA
|
||||
nrf5CryptoDeinit();
|
||||
#endif
|
||||
#if ((UART_AS_SERIAL_TRANSPORT == 1) || (USB_CDC_AS_SERIAL_TRANSPORT == 1))
|
||||
nrf5UartDeinit();
|
||||
#endif
|
||||
@@ -138,10 +144,10 @@ void otSysProcessDrivers(otInstance *aInstance)
|
||||
#if ((UART_AS_SERIAL_TRANSPORT == 1) || (USB_CDC_AS_SERIAL_TRANSPORT == 1))
|
||||
nrf5UartProcess();
|
||||
#endif
|
||||
nrf5TempProcess();
|
||||
#if (SPIS_AS_SERIAL_TRANSPORT == 1)
|
||||
nrf5SpiSlaveProcess();
|
||||
#endif
|
||||
nrf5TempProcess();
|
||||
nrf5AlarmProcess(aInstance);
|
||||
}
|
||||
|
||||
+2
-2
@@ -90,7 +90,7 @@ COMMONCPPFLAGS
|
||||
NRF52840_CPPFLAGS = \
|
||||
-DNRF52840_XXAA \
|
||||
-DNRF_802154_PROJECT_CONFIG=\"platform-config.h\" \
|
||||
-I$(top_srcdir)/examples/platforms/nrf52840 \
|
||||
-I$(top_srcdir)/examples/platforms/nrf528xx/nrf52840/ \
|
||||
$(NULL)
|
||||
|
||||
NRF52811_CPPFLAGS = \
|
||||
@@ -98,7 +98,7 @@ NRF52811_CPPFLAGS
|
||||
-DNRF_802154_PROJECT_CONFIG=\"platform-config.h\" \
|
||||
-D__HEAP_SIZE=0 \
|
||||
-D__STACK_SIZE=2048 \
|
||||
-I$(top_srcdir)/examples/platforms/nrf52811 \
|
||||
-I$(top_srcdir)/examples/platforms/nrf528xx/nrf52811 \
|
||||
$(NULL)
|
||||
|
||||
NORDICSEMI_COMMON_SOURCES = \
|
||||
|
||||
Reference in New Issue
Block a user