mirror of
https://github.com/espressif/openthread.git
synced 2026-09-07 01:30:11 +00:00
[posix-app] expose mainloop APIs (#3490)
This commit is contained in:
+26
-2
@@ -28,9 +28,13 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <openthread-core-config.h>
|
||||
#include "openthread-core-config.h"
|
||||
#include "platform-posix.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/prctl.h>
|
||||
@@ -97,8 +101,28 @@ int main(int argc, char *argv[])
|
||||
|
||||
while (true)
|
||||
{
|
||||
otSysMainloopContext mainloop;
|
||||
|
||||
otTaskletsProcess(instance);
|
||||
otSysProcessDrivers(instance);
|
||||
|
||||
FD_ZERO(&mainloop.mReadFdSet);
|
||||
FD_ZERO(&mainloop.mWriteFdSet);
|
||||
FD_ZERO(&mainloop.mErrorFdSet);
|
||||
|
||||
mainloop.mMaxFd = -1;
|
||||
mainloop.mTimeout.tv_sec = 10;
|
||||
mainloop.mTimeout.tv_usec = 0;
|
||||
|
||||
otSysMainloopUpdate(instance, &mainloop);
|
||||
if (otSysMainloopPoll(&mainloop) >= 0)
|
||||
{
|
||||
otSysMainloopProcess(instance, &mainloop);
|
||||
}
|
||||
else if (errno != EINTR)
|
||||
{
|
||||
perror("select");
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
otInstanceFinalize(instance);
|
||||
|
||||
@@ -72,16 +72,49 @@ void otSysInitNetif(otInstance *aInstance);
|
||||
*/
|
||||
void otSysDeinit(void);
|
||||
|
||||
/**
|
||||
* This structure represents a context for a select() based mainloop.
|
||||
*
|
||||
*/
|
||||
typedef struct otSysMainloopContext
|
||||
{
|
||||
fd_set mReadFdSet; ///< The read file descriptors.
|
||||
fd_set mWriteFdSet; ///< The write file descriptors.
|
||||
fd_set mErrorFdSet; ///< The error file descriptors.
|
||||
int mMaxFd; ///< The max file descriptor.
|
||||
struct timeval mTimeout; ///< The timeout.
|
||||
} otSysMainloopContext;
|
||||
|
||||
/**
|
||||
* This function updates the file descriptor sets with file descriptors used by OpenThread drivers.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[inout] aMainloop A pointer to the mainloop context.
|
||||
*
|
||||
*/
|
||||
void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop);
|
||||
|
||||
/**
|
||||
* This function polls OpenThread's mainloop.
|
||||
*
|
||||
* @param[inout] aMainloop A pointer to the mainloop context.
|
||||
*
|
||||
* @returns value returned from select().
|
||||
*
|
||||
*/
|
||||
int otSysMainloopPoll(otSysMainloopContext *aMainloop);
|
||||
|
||||
/**
|
||||
* This function performs all platform-specific processing for OpenThread's example applications.
|
||||
*
|
||||
* @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function
|
||||
* in the main loop when processing OpenThread's drivers is most appropriate.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] aMainloop A pointer to the mainloop context.
|
||||
*
|
||||
*/
|
||||
void otSysProcessDrivers(otInstance *aInstance);
|
||||
void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop);
|
||||
|
||||
/**
|
||||
* This function is called whenever platform drivers needs processing.
|
||||
|
||||
@@ -200,7 +200,7 @@ void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMax
|
||||
* @param[in] aWriteFdSet A pointer to the write file descriptors.
|
||||
*
|
||||
*/
|
||||
void platformRadioProcess(otInstance *aInstance, fd_set *aReadFdSet, fd_set *aWriteFdSet);
|
||||
void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet);
|
||||
|
||||
/**
|
||||
* This function initializes the random number service used by OpenThread.
|
||||
|
||||
@@ -1455,7 +1455,7 @@ void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMax
|
||||
sRadioSpinel.UpdateFdSet(*aReadFdSet, *aWriteFdSet, *aMaxFd, *aTimeout);
|
||||
}
|
||||
|
||||
void platformRadioProcess(otInstance *aInstance, fd_set *aReadFdSet, fd_set *aWriteFdSet)
|
||||
void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet)
|
||||
{
|
||||
sRadioSpinel.Process(*aReadFdSet, *aWriteFdSet);
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
+39
-43
@@ -35,7 +35,6 @@
|
||||
#include "platform-posix.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <stddef.h>
|
||||
@@ -49,6 +48,8 @@
|
||||
#include <openthread/platform/alarm-milli.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#include "openthread-system.h"
|
||||
|
||||
uint64_t gNodeId = 0;
|
||||
|
||||
static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
|
||||
@@ -213,53 +214,50 @@ static int trySelect(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSe
|
||||
}
|
||||
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
|
||||
void otSysProcessDrivers(otInstance *aInstance)
|
||||
void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop)
|
||||
{
|
||||
fd_set readFdSet;
|
||||
fd_set writeFdSet;
|
||||
fd_set errorFdSet;
|
||||
struct timeval timeout;
|
||||
int maxFd = -1;
|
||||
int rval;
|
||||
|
||||
FD_ZERO(&readFdSet);
|
||||
FD_ZERO(&writeFdSet);
|
||||
FD_ZERO(&errorFdSet);
|
||||
|
||||
platformAlarmUpdateTimeout(&timeout);
|
||||
platformUartUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd);
|
||||
platformAlarmUpdateTimeout(&aMainloop->mTimeout);
|
||||
platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
|
||||
&aMainloop->mMaxFd);
|
||||
#if OPENTHREAD_ENABLE_PLATFORM_UDP
|
||||
platformUdpUpdateFdSet(aInstance, &readFdSet, &maxFd);
|
||||
platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd);
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_PLATFORM_NETIF
|
||||
platformNetifUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd);
|
||||
platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
|
||||
&aMainloop->mMaxFd);
|
||||
#endif
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
otSimUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd, &timeout);
|
||||
otSimUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd,
|
||||
&aMainloop->mTimeout);
|
||||
#else
|
||||
platformRadioUpdateFdSet(&readFdSet, &writeFdSet, &maxFd, &timeout);
|
||||
platformRadioUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout);
|
||||
#endif
|
||||
|
||||
if (otTaskletsArePending(aInstance))
|
||||
{
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
aMainloop->mTimeout.tv_sec = 0;
|
||||
aMainloop->mTimeout.tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int otSysMainloopPoll(otSysMainloopContext *aMainloop)
|
||||
{
|
||||
int rval;
|
||||
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
if (timerisset(&timeout))
|
||||
if (timerisset(&aMainloop->mTimeout))
|
||||
{
|
||||
// Make sure there are no data ready in UART
|
||||
rval = trySelect(&readFdSet, &writeFdSet, &errorFdSet, maxFd);
|
||||
rval = trySelect(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, aMainloop->mMaxFd);
|
||||
|
||||
if (rval == 0)
|
||||
{
|
||||
bool noWrite = true;
|
||||
|
||||
// If there are write requests, the device is supposed to wake soon
|
||||
for (int i = 0; i < maxFd + 1; ++i)
|
||||
for (int i = 0; i < aMainloop->mMaxFd + 1; ++i)
|
||||
{
|
||||
if (FD_ISSET(i, &writeFdSet))
|
||||
if (FD_ISSET(i, &aMainloop->mWriteFdSet))
|
||||
{
|
||||
noWrite = false;
|
||||
break;
|
||||
@@ -268,38 +266,36 @@ void otSysProcessDrivers(otInstance *aInstance)
|
||||
|
||||
if (noWrite)
|
||||
{
|
||||
otSimSendSleepEvent(&timeout);
|
||||
otSimSendSleepEvent(&aMainloop->mTimeout);
|
||||
}
|
||||
|
||||
rval = select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, NULL);
|
||||
assert(rval > 0);
|
||||
rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet,
|
||||
&aMainloop->mErrorFdSet, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rval = select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, &timeout);
|
||||
rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet,
|
||||
&aMainloop->mTimeout);
|
||||
}
|
||||
|
||||
if ((rval < 0) && (errno != EINTR))
|
||||
{
|
||||
perror("select");
|
||||
exit(OT_EXIT_FAILURE);
|
||||
}
|
||||
else if (rval >= 0)
|
||||
{
|
||||
return rval;
|
||||
}
|
||||
|
||||
void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
otSimProcess(aInstance, &readFdSet, &writeFdSet, &errorFdSet);
|
||||
otSimProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
|
||||
#else
|
||||
platformRadioProcess(aInstance, &readFdSet, &writeFdSet);
|
||||
platformRadioProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet);
|
||||
#endif
|
||||
platformUartProcess(&readFdSet, &writeFdSet, &errorFdSet);
|
||||
platformAlarmProcess(aInstance);
|
||||
platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
|
||||
platformAlarmProcess(aInstance);
|
||||
#if OPENTHREAD_ENABLE_PLATFORM_NETIF
|
||||
platformNetifProcess(&readFdSet, &writeFdSet, &errorFdSet);
|
||||
platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet);
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_PLATFORM_UDP
|
||||
platformUdpProcess(aInstance, &readFdSet);
|
||||
platformUdpProcess(aInstance, &aMainloop->mReadFdSet);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user