diff --git a/examples/platforms/cc2538/radio.c b/examples/platforms/cc2538/radio.c index 70293b4f5..a0138fa19 100644 --- a/examples/platforms/cc2538/radio.c +++ b/examples/platforms/cc2538/radio.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -433,6 +434,12 @@ void readFrame(void) length = HWREG(RFCORE_SFR_RFDATA); otEXPECT(IEEE802154_MIN_LENGTH <= length && length <= IEEE802154_MAX_LENGTH); +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + // read psdu for (i = 0; i < length - 2; i++) { diff --git a/examples/platforms/cc2650/radio.c b/examples/platforms/cc2650/radio.c index cec51aad5..845ac72c5 100644 --- a/examples/platforms/cc2650/radio.c +++ b/examples/platforms/cc2650/radio.c @@ -31,6 +31,7 @@ #include #include #include "cc2650_radio.h" +#include #include #include /* to seed the CSMA-CA funciton */ @@ -1776,6 +1777,12 @@ static void readFrame(void) if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE) { +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + sReceiveFrame.mLength = len; memcpy(sReceiveFrame.mPsdu, &(payload[1]), len - 2); sReceiveFrame.mChannel = sReceiveCmd.channel; diff --git a/examples/platforms/da15000/radio.c b/examples/platforms/da15000/radio.c index ffb1a197c..9b8fc8554 100644 --- a/examples/platforms/da15000/radio.c +++ b/examples/platforms/da15000/radio.c @@ -31,6 +31,7 @@ * Platform abstraction for radio communication. */ +#include #include #include #include @@ -616,6 +617,11 @@ void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength, if (frameHeader.frameType != FTDF_ACKNOWLEDGEMENT_FRAME) { +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif sReceiveFrame.mChannel = sChannel; sReceiveFrame.mLength = frameLength; sReceiveFrame.mLqi = lqi; @@ -626,6 +632,11 @@ void FTDF_rcvFrameTransparent(FTDF_DataLength frameLength, } else { +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrameAck.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrameAck.mUsec = 0; // Don't support microsecond timer for now. +#endif sReceiveFrameAck.mChannel = sChannel; sReceiveFrameAck.mLength = frameLength; sReceiveFrameAck.mLqi = lqi; diff --git a/examples/platforms/efr32/radio.c b/examples/platforms/efr32/radio.c index 7a598d6c3..847ff1cd6 100644 --- a/examples/platforms/efr32/radio.c +++ b/examples/platforms/efr32/radio.c @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -687,6 +688,12 @@ void RAILCb_RxPacketReceived(void *aRxPacketHandle) otLogInfoPlat(sInstance, "Received data:%d", rxPacketInfo->dataLength); +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + memcpy(sReceiveFrame.mPsdu, rxPacketInfo->dataPtr + 1, rxPacketInfo->dataLength); sReceiveFrame.mPower = rxPacketInfo->appendedInfo.rssiLatch; sReceiveFrame.mLqi = rxPacketInfo->appendedInfo.lqi; diff --git a/examples/platforms/emsk/radio.c b/examples/platforms/emsk/radio.c index 14681deb2..ee95ff8e6 100644 --- a/examples/platforms/emsk/radio.c +++ b/examples/platforms/emsk/radio.c @@ -35,7 +35,8 @@ #include "openthread/types.h" #include -#include "openthread/platform/radio.h" +#include +#include #include "platform-emsk.h" #include "device/device_hal/inc/dev_gpio.h" @@ -459,6 +460,12 @@ void readFrame(void) otEXPECT_ACTION(IEEE802154_MIN_LENGTH <= length && length <= IEEE802154_MAX_LENGTH, ;); +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + /* Read PSDU */ memcpy(sReceiveFrame.mPsdu, readBuffer, length - 2); diff --git a/examples/platforms/kw41z/radio.c b/examples/platforms/kw41z/radio.c index a0bc0ab0c..06e077b71 100644 --- a/examples/platforms/kw41z/radio.c +++ b/examples/platforms/kw41z/radio.c @@ -37,8 +37,10 @@ #include "fsl_device_registers.h" #include "openthread-core-kw41z-config.h" #include "fsl_xcvr.h" -#include "openthread/platform/radio.h" -#include "openthread/platform/diag.h" + +#include +#include +#include #include #define DOUBLE_BUFFERING (1) @@ -722,6 +724,12 @@ static bool rf_process_rx_frame(void) /* Check if frame is valid */ otEXPECT_ACTION((IEEE802154_MIN_LENGTH <= temp) && (temp <= IEEE802154_MAX_LENGTH), status = false); +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sRxFrame.mMsec = otPlatAlarmMilliGetNow(); + sRxFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + sRxFrame.mLength = temp; temp = (ZLL->LQI_AND_RSSI & ZLL_LQI_AND_RSSI_LQI_VALUE_MASK) >> ZLL_LQI_AND_RSSI_LQI_VALUE_SHIFT; sRxFrame.mLqi = rf_lqi_adjust(temp); diff --git a/examples/platforms/nrf52840/alarm.c b/examples/platforms/nrf52840/alarm.c index bf2cd0db1..9fd03f566 100644 --- a/examples/platforms/nrf52840/alarm.c +++ b/examples/platforms/nrf52840/alarm.c @@ -42,6 +42,7 @@ #include #include "platform-config.h" +#include "platform-nrf5.h" #include "cmsis/core_cmFunc.h" #include @@ -123,51 +124,9 @@ static inline uint64_t TicksToTime(uint32_t aTicks) return CEIL_DIV((US_PER_S * (uint64_t)aTicks), RTC_FREQUENCY); } -static inline uint64_t AlarmGetCurrentTime() -{ - uint32_t rtcValue1; - uint32_t rtcValue2; - uint32_t offset; - - rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE); - - __DMB(); - - offset = sTimeOffset; - - __DMB(); - - rtcValue2 = nrf_rtc_counter_get(RTC_INSTANCE); - - if ((rtcValue2 < rtcValue1) || (rtcValue1 == 0)) - { - // Overflow detected. Additional condition (rtcValue1 == 0) covers situation when overflow occurred in - // interrupt state, before this function was entered. But in general, this function shall not be called - // from interrupt other than alarm interrupt. - - // Wait at least 20 cycles, to ensure that if interrupt is going to be called, it will be called now. - for (uint32_t i = 0; i < 4; i++) - { - __NOP(); - __NOP(); - __NOP(); - } - - // If the event flag is still on, it means that the interrupt was not called, as we are in interrupt state. - if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) - { - HandleOverflow(); - } - - offset = sTimeOffset; - } - - return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2); -} - static inline uint32_t AlarmGetCurrentTimeRtcProtected(AlarmIndex aIndex) { - uint64_t usecTime = AlarmGetCurrentTime() + 2 * US_PER_TICK; + uint64_t usecTime = nrf5AlarmGetCurrentTime() + 2 * US_PER_TICK; uint32_t currentTime; if (aIndex == kMsTimer) @@ -198,7 +157,7 @@ static void HandleCompareMatch(AlarmIndex aIndex, bool aSkipCheck) { nrf_rtc_event_clear(RTC_INSTANCE, sChannelData[aIndex].mCompareEvent); - uint64_t usecTime = AlarmGetCurrentTime(); + uint64_t usecTime = nrf5AlarmGetCurrentTime(); uint32_t now; if (aIndex == kMsTimer) @@ -344,9 +303,51 @@ void nrf5AlarmProcess(otInstance *aInstance) } } +inline uint64_t nrf5AlarmGetCurrentTime() +{ + uint32_t rtcValue1; + uint32_t rtcValue2; + uint32_t offset; + + rtcValue1 = nrf_rtc_counter_get(RTC_INSTANCE); + + __DMB(); + + offset = sTimeOffset; + + __DMB(); + + rtcValue2 = nrf_rtc_counter_get(RTC_INSTANCE); + + if ((rtcValue2 < rtcValue1) || (rtcValue1 == 0)) + { + // Overflow detected. Additional condition (rtcValue1 == 0) covers situation when overflow occurred in + // interrupt state, before this function was entered. But in general, this function shall not be called + // from interrupt other than alarm interrupt. + + // Wait at least 20 cycles, to ensure that if interrupt is going to be called, it will be called now. + for (uint32_t i = 0; i < 4; i++) + { + __NOP(); + __NOP(); + __NOP(); + } + + // If the event flag is still on, it means that the interrupt was not called, as we are in interrupt state. + if (nrf_rtc_event_pending(RTC_INSTANCE, NRF_RTC_EVENT_OVERFLOW)) + { + HandleOverflow(); + } + + offset = sTimeOffset; + } + + return US_PER_MS * (uint64_t)offset + TicksToTime(rtcValue2); +} + uint32_t otPlatAlarmMilliGetNow(void) { - return (uint32_t)(AlarmGetCurrentTime() / US_PER_MS); + return (uint32_t)(nrf5AlarmGetCurrentTime() / US_PER_MS); } void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) @@ -366,7 +367,7 @@ void otPlatAlarmMilliStop(otInstance *aInstance) uint32_t otPlatAlarmMicroGetNow(void) { - return (uint32_t)AlarmGetCurrentTime(); + return (uint32_t)nrf5AlarmGetCurrentTime(); } void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) diff --git a/examples/platforms/nrf52840/platform-nrf5.h b/examples/platforms/nrf52840/platform-nrf5.h index 126fee66e..ef186d9f1 100644 --- a/examples/platforms/nrf52840/platform-nrf5.h +++ b/examples/platforms/nrf52840/platform-nrf5.h @@ -77,6 +77,12 @@ void nrf5AlarmDeinit(void); */ void nrf5AlarmProcess(otInstance *aInstance); +/** + * Function for geting current time in mircosecond. + * + */ +uint64_t nrf5AlarmGetCurrentTime(); + /** * Initialization of Random Number Generator. * diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index f71918291..8b08dafb3 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -50,6 +50,8 @@ #include #include +#include "platform-nrf5.h" + #include #include @@ -60,6 +62,7 @@ #define SHORT_ADDRESS_SIZE 2 #define EXTENDED_ADDRESS_SIZE 8 #define PENDING_BIT 0x10 +#define US_PER_MS 1000ULL enum { @@ -628,6 +631,11 @@ void nrf_drv_radio802154_received(uint8_t *p_data, int8_t power, int8_t lqi) receivedFrame->mPower = power; receivedFrame->mLqi = lqi; receivedFrame->mChannel = nrf_drv_radio802154_channel_get(); +#if OPENTHREAD_ENABLE_RAW_LINK_API + uint64_t timestamp = nrf5AlarmGetCurrentTime(); + receivedFrame->mMsec = timestamp / US_PER_MS; + receivedFrame->mUsec = timestamp - receivedFrame->mMsec * US_PER_MS; +#endif } void nrf_drv_radio802154_transmitted(uint8_t *aAckPsdu, int8_t aPower, int8_t aLqi) diff --git a/examples/platforms/posix/radio.c b/examples/platforms/posix/radio.c index e972c0bb1..56f786d44 100644 --- a/examples/platforms/posix/radio.c +++ b/examples/platforms/posix/radio.c @@ -28,6 +28,7 @@ #include "platform-posix.h" +#include #include #include @@ -496,6 +497,12 @@ void radioReceive(otInstance *aInstance) exit(EXIT_FAILURE); } +#if OPENTHREAD_ENABLE_RAW_LINK_API + // Timestamp + sReceiveFrame.mMsec = otPlatAlarmMilliGetNow(); + sReceiveFrame.mUsec = 0; // Don't support microsecond timer for now. +#endif + sReceiveFrame.mLength = (uint8_t)(rval - 1); if (sAckWait && diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 01eb57f6f..3430b829b 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -107,6 +107,10 @@ typedef struct otRadioFrame bool mSecurityValid: 1; ///< Security Enabled flag is set and frame passes security checks. bool mDidTX: 1; ///< Set to true if this frame sent from the radio. Ignored by radio driver. bool mIsARetx: 1; ///< Set to true if this frame is a retransmission. Should be ignored by radio driver. +#if OPENTHREAD_ENABLE_RAW_LINK_API + uint32_t mMsec; ///< The timestamp when the frame was received (milliseconds). + uint16_t mUsec; ///< The timestamp when the frame was received (microseconds, the offset to mMsec). +#endif } otRadioFrame; /** diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 38fca5967..d4726ed10 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -1139,6 +1139,8 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError) SPINEL_DATATYPE_STRUCT_S( // PHY-data SPINEL_DATATYPE_UINT8_S // 802.15.4 channel SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI + SPINEL_DATATYPE_UINT32_S // The timestamp milliseconds + SPINEL_DATATYPE_UINT16_S // The timestamp microseconds ) SPINEL_DATATYPE_STRUCT_S( // Vendor-data SPINEL_DATATYPE_UINT_PACKED_S @@ -1148,6 +1150,8 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError) flags, // Flags aFrame->mChannel, // Receive channel aFrame->mLqi, // Link quality indicator + aFrame->mMsec, // The timestamp milliseconds + aFrame->mUsec, // The timestamp microseconds, offset to mMsec aError // Receive error ));