mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
[nexus] implement microsecond alarm platform APIs (#12580)
This commit implements the otPlatAlarmMicro* platform APIs in the Nexus simulation environment. It also transitions the simulation's internal time base from millisecond to microsecond granularity to ensure that both millisecond and microsecond alarms operate on a consistent and shared time reference. Changes include: - Enabled OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE in Nexus config. - Updated Nexus::Core to use a 64-bit microsecond time base (mNow). - Implemented otPlatAlarmMicroGetNow, otPlatAlarmMicroStartAt, and otPlatAlarmMicroStop. - Refactored Nexus::Node to support separate millisecond and microsecond alarm instances (mAlarmMilli and mAlarmMicro). - Updated radio timestamps and PCAP logging to use the new high- resolution microsecond time base. - Adjusted simulation time advancement and alarm triggering logic to handle both alarm types correctly.
This commit is contained in:
@@ -120,7 +120,7 @@
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_RADIO_STATS_ENABLE 0
|
||||
#define OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_SEEKER_ENABLE 1
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <openthread/platform/alarm-micro.h>
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
|
||||
#include "nexus_alarm.hpp"
|
||||
@@ -36,7 +37,7 @@ namespace ot {
|
||||
namespace Nexus {
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// otPlatAlarmMilli APIs
|
||||
// otPlatAlarm Milli and Micro APIs
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -44,15 +45,29 @@ uint32_t otPlatAlarmMilliGetNow(void) { return Core::Get().GetNow().GetValue();
|
||||
|
||||
void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
Alarm &alarm = AsNode(aInstance).mAlarm;
|
||||
Alarm &alarm = AsNode(aInstance).mAlarmMilli;
|
||||
|
||||
alarm.mScheduled = true;
|
||||
alarm.mAlarmTime.SetValue(aT0 + aDt);
|
||||
|
||||
Core::Get().UpdateNextAlarmTime(alarm);
|
||||
Core::Get().UpdateNextAlarmMilli(alarm);
|
||||
}
|
||||
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance) { AsNode(aInstance).mAlarm.mScheduled = false; }
|
||||
void otPlatAlarmMilliStop(otInstance *aInstance) { AsNode(aInstance).mAlarmMilli.mScheduled = false; }
|
||||
|
||||
uint32_t otPlatAlarmMicroGetNow(void) { return Core::Get().GetNowMicro().GetValue(); }
|
||||
|
||||
void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
{
|
||||
Alarm &alarm = AsNode(aInstance).mAlarmMicro;
|
||||
|
||||
alarm.mScheduled = true;
|
||||
alarm.mAlarmTime.SetValue(aT0 + aDt);
|
||||
|
||||
Core::Get().UpdateNextAlarmMicro(alarm);
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStop(otInstance *aInstance) { AsNode(aInstance).mAlarmMicro.mScheduled = false; }
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ struct Alarm
|
||||
{
|
||||
Alarm(void) { Reset(); }
|
||||
void Reset(void) { mScheduled = false; }
|
||||
bool ShouldTrigger(Time aNow) const { return mScheduled && (aNow >= mAlarmTime); }
|
||||
|
||||
bool mScheduled;
|
||||
Time mAlarmTime;
|
||||
|
||||
@@ -51,7 +51,7 @@ Core::Core(void)
|
||||
sCore = this;
|
||||
sInUse = true;
|
||||
|
||||
mNextAlarmTime = mNow.GetDistantFuture();
|
||||
mNextAlarmTime = NumericLimits<uint64_t>::kMax;
|
||||
|
||||
pcapFile = getenv("OT_NEXUS_PCAP_FILE");
|
||||
|
||||
@@ -256,27 +256,58 @@ Node &Core::CreateNode(void)
|
||||
return *node;
|
||||
}
|
||||
|
||||
void Core::UpdateNextAlarmTime(const Alarm &aAlarm)
|
||||
void Core::UpdateNextAlarmMilli(const Alarm &aAlarm)
|
||||
{
|
||||
if (aAlarm.mScheduled)
|
||||
{
|
||||
mNextAlarmTime = Min(mNextAlarmTime, Max(mNow, aAlarm.mAlarmTime));
|
||||
uint64_t alarmTime;
|
||||
|
||||
if (GetNow() >= aAlarm.mAlarmTime)
|
||||
{
|
||||
alarmTime = mNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarmTime = mNow - (mNow % 1000u) + (static_cast<uint64_t>(aAlarm.mAlarmTime - GetNow()) * 1000u);
|
||||
}
|
||||
|
||||
mNextAlarmTime = Min(mNextAlarmTime, alarmTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::UpdateNextAlarmMicro(const Alarm &aAlarm)
|
||||
{
|
||||
if (aAlarm.mScheduled)
|
||||
{
|
||||
uint64_t alarmTime;
|
||||
|
||||
if (GetNowMicro() >= aAlarm.mAlarmTime)
|
||||
{
|
||||
alarmTime = mNow;
|
||||
}
|
||||
else
|
||||
{
|
||||
alarmTime = mNow + static_cast<uint64_t>(aAlarm.mAlarmTime - GetNowMicro());
|
||||
}
|
||||
|
||||
mNextAlarmTime = Min(mNextAlarmTime, alarmTime);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::AdvanceTime(uint32_t aDuration)
|
||||
{
|
||||
TimeMilli targetTime = mNow + aDuration;
|
||||
uint64_t targetTime = mNow + (static_cast<uint64_t>(aDuration) * 1000u);
|
||||
|
||||
while (mPendingAction || (mNextAlarmTime <= targetTime))
|
||||
{
|
||||
mNextAlarmTime = mNow.GetDistantFuture();
|
||||
mNextAlarmTime = NumericLimits<uint64_t>::kMax;
|
||||
mPendingAction = false;
|
||||
|
||||
for (Node &node : mNodes)
|
||||
{
|
||||
Process(node);
|
||||
UpdateNextAlarmTime(node.mAlarm);
|
||||
UpdateNextAlarmMilli(node.mAlarmMilli);
|
||||
UpdateNextAlarmMicro(node.mAlarmMicro);
|
||||
}
|
||||
|
||||
if (!mPendingAction)
|
||||
@@ -298,11 +329,17 @@ void Core::Process(Node &aNode)
|
||||
ProcessTrel(aNode);
|
||||
#endif
|
||||
|
||||
if (aNode.mAlarm.ShouldTrigger(mNow))
|
||||
if (aNode.mAlarmMilli.mScheduled && (GetNow() >= aNode.mAlarmMilli.mAlarmTime))
|
||||
{
|
||||
aNode.mAlarm.mScheduled = false;
|
||||
aNode.mAlarmMilli.mScheduled = false;
|
||||
otPlatAlarmMilliFired(&aNode.GetInstance());
|
||||
}
|
||||
|
||||
if (aNode.mAlarmMicro.mScheduled && (GetNowMicro() >= aNode.mAlarmMicro.mAlarmTime))
|
||||
{
|
||||
aNode.mAlarmMicro.mScheduled = false;
|
||||
otPlatAlarmMicroFired(&aNode.GetInstance());
|
||||
}
|
||||
}
|
||||
|
||||
void Core::ProcessRadio(Node &aNode)
|
||||
@@ -326,7 +363,7 @@ void Core::ProcessRadio(Node &aNode)
|
||||
|
||||
ackRequested = aNode.mRadio.mTxFrame.GetAckRequest();
|
||||
|
||||
mPcap.WriteFrame(aNode.mRadio.mTxFrame, mNow.GetValue() * 1000ull);
|
||||
mPcap.WriteFrame(aNode.mRadio.mTxFrame, mNow);
|
||||
|
||||
otPlatRadioTxStarted(&aNode.GetInstance(), &aNode.mRadio.mTxFrame);
|
||||
|
||||
@@ -347,7 +384,7 @@ void Core::ProcessRadio(Node &aNode)
|
||||
|
||||
Radio::Frame rxFrame(aNode.mRadio.mTxFrame);
|
||||
|
||||
rxFrame.mInfo.mRxInfo.mTimestamp = (mNow.GetValue() * 1000u);
|
||||
rxFrame.mInfo.mRxInfo.mTimestamp = mNow;
|
||||
rxFrame.mInfo.mRxInfo.mRssi = kDefaultRxRssi;
|
||||
rxFrame.mInfo.mRxInfo.mLqi = 0;
|
||||
|
||||
@@ -388,7 +425,7 @@ void Core::ProcessRadio(Node &aNode)
|
||||
(ackMode == kSendAckFramePending));
|
||||
|
||||
ackFrame.UpdateFcs();
|
||||
mPcap.WriteFrame(ackFrame, mNow.GetValue() * 1000ull);
|
||||
mPcap.WriteFrame(ackFrame, mNow);
|
||||
|
||||
otPlatRadioTxDone(&aNode.GetInstance(), &aNode.mRadio.mTxFrame, &ackFrame, kErrorNone);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ public:
|
||||
Node &CreateNode(void);
|
||||
LinkedList<Node> &GetNodes(void) { return mNodes; }
|
||||
|
||||
TimeMilli GetNow(void) { return mNow; }
|
||||
TimeMilli GetNow(void) { return TimeMilli(static_cast<uint32_t>(mNow / 1000u)); }
|
||||
TimeMicro GetNowMicro(void) { return TimeMicro(static_cast<uint32_t>(mNow)); }
|
||||
void AdvanceTime(uint32_t aDuration);
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@@ -75,7 +76,8 @@ public:
|
||||
void SetActiveNode(Node *aNode) { mActiveNode = aNode; }
|
||||
Node *GetActiveNode(void) { return mActiveNode; }
|
||||
|
||||
void UpdateNextAlarmTime(const Alarm &aAlarm);
|
||||
void UpdateNextAlarmMilli(const Alarm &aAlarm);
|
||||
void UpdateNextAlarmMicro(const Alarm &aAlarm);
|
||||
void MarkPendingAction(void) { mPendingAction = true; }
|
||||
|
||||
private:
|
||||
@@ -117,8 +119,8 @@ private:
|
||||
Array<NetworkKey, 16> mNetworkKeys;
|
||||
uint16_t mCurNodeId;
|
||||
bool mPendingAction;
|
||||
TimeMilli mNow;
|
||||
TimeMilli mNextAlarmTime;
|
||||
uint64_t mNow;
|
||||
uint64_t mNextAlarmTime;
|
||||
Node *mActiveNode;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ void Node::Reset(void)
|
||||
uint32_t id = GetId();
|
||||
|
||||
mRadio.Reset();
|
||||
mAlarm.Reset();
|
||||
mAlarmMilli.Reset();
|
||||
mAlarmMicro.Reset();
|
||||
mMdns.Reset();
|
||||
mPendingTasklet = false;
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
|
||||
@@ -46,7 +46,8 @@ class Platform
|
||||
{
|
||||
public:
|
||||
Radio mRadio;
|
||||
Alarm mAlarm;
|
||||
Alarm mAlarmMilli;
|
||||
Alarm mAlarmMicro;
|
||||
Mdns mMdns;
|
||||
Settings mSettings;
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
@@ -121,7 +122,8 @@ public:
|
||||
|
||||
static Node &From(otInstance *aInstance) { return static_cast<Node &>(*aInstance); }
|
||||
|
||||
using Platform::mAlarm;
|
||||
using Platform::mAlarmMicro;
|
||||
using Platform::mAlarmMilli;
|
||||
using Platform::mMdns;
|
||||
using Platform::mPendingTasklet;
|
||||
using Platform::mRadio;
|
||||
|
||||
Reference in New Issue
Block a user