mirror of
https://github.com/espressif/openthread.git
synced 2026-09-24 18:07:36 +00:00
Change API to require all calls be from the same context. (#78)
* Remove atomic driver and all uses of otPlatAtomic* in OpenThread. * Change posix example to only use a single thread of execution.
This commit is contained in:
@@ -44,7 +44,6 @@ soc_LDADD = \
|
||||
$(top_builddir)/src/cli/libopenthread-cli.a \
|
||||
$(top_builddir)/examples/platform/posix/libopenthread-posix.a \
|
||||
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
|
||||
-lpthread \
|
||||
$(NULL)
|
||||
|
||||
soc_SOURCES = \
|
||||
|
||||
+2
-16
@@ -32,7 +32,6 @@
|
||||
|
||||
#include <openthread.h>
|
||||
#include <cli/cli_serial.hpp>
|
||||
#include <platform/atomic.h>
|
||||
#include <platform.h>
|
||||
|
||||
struct gengetopt_args_info args_info;
|
||||
@@ -45,32 +44,19 @@ void otSignalTaskletPending(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32_t atomic_state;
|
||||
|
||||
if (cmdline_parser(argc, argv, &args_info) != 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hwAlarmInit();
|
||||
hwRadioInit();
|
||||
hwRandomInit();
|
||||
|
||||
PlatformInit();
|
||||
otInit();
|
||||
sCliServer.Start();
|
||||
|
||||
while (1)
|
||||
{
|
||||
otProcessNextTasklet();
|
||||
|
||||
atomic_state = otPlatAtomicBegin();
|
||||
|
||||
if (!otAreTaskletsPending())
|
||||
{
|
||||
hwSleep();
|
||||
}
|
||||
|
||||
otPlatAtomicEnd(atomic_state);
|
||||
PlatformProcessDrivers();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -45,7 +45,6 @@ ncp_LDADD = \
|
||||
$(top_builddir)/src/core/libopenthread.a \
|
||||
$(top_builddir)/examples/platform/posix/libopenthread-posix.a \
|
||||
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
|
||||
-lpthread \
|
||||
$(NULL)
|
||||
|
||||
ncp_SOURCES = main.cpp
|
||||
|
||||
+2
-18
@@ -30,7 +30,6 @@
|
||||
#include <platform/posix/cmdline.h>
|
||||
|
||||
#include <ncp/ncp.hpp>
|
||||
#include <platform/atomic.h>
|
||||
#include <platform.h>
|
||||
|
||||
struct gengetopt_args_info args_info;
|
||||
@@ -43,19 +42,12 @@ void otSignalTaskletPending(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32_t atomic_state;
|
||||
|
||||
memset(&args_info, 0, sizeof(args_info));
|
||||
|
||||
if (cmdline_parser(argc, argv, &args_info) != 0)
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
|
||||
hwAlarmInit();
|
||||
hwRadioInit();
|
||||
hwRandomInit();
|
||||
|
||||
PlatformInit();
|
||||
otInit();
|
||||
|
||||
sNcp.Start();
|
||||
@@ -63,15 +55,7 @@ int main(int argc, char *argv[])
|
||||
while (1)
|
||||
{
|
||||
otProcessNextTasklet();
|
||||
|
||||
atomic_state = otPlatAtomicBegin();
|
||||
|
||||
if (!otAreTaskletsPending())
|
||||
{
|
||||
hwSleep();
|
||||
}
|
||||
|
||||
otPlatAtomicEnd(atomic_state);
|
||||
PlatformProcessDrivers();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -52,9 +52,9 @@ libopenthread_posix_a_CXXFLAGS = \
|
||||
|
||||
libopenthread_posix_a_SOURCES = \
|
||||
alarm.c \
|
||||
atomic.c \
|
||||
cmdline.c \
|
||||
logging.c \
|
||||
platform.c \
|
||||
radio.cpp \
|
||||
random.c \
|
||||
serial.c \
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -34,20 +33,13 @@
|
||||
|
||||
#include <platform/alarm.h>
|
||||
|
||||
static void *alarm_thread(void *arg);
|
||||
|
||||
static bool s_is_running = false;
|
||||
static uint32_t s_alarm = 0;
|
||||
static struct timeval s_start;
|
||||
|
||||
static pthread_t s_thread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
void hwAlarmInit(void)
|
||||
void PlatformAlarmInit(void)
|
||||
{
|
||||
gettimeofday(&s_start, NULL);
|
||||
pthread_create(&s_thread, NULL, alarm_thread, NULL);
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmGetNow(void)
|
||||
@@ -62,65 +54,58 @@ uint32_t otPlatAlarmGetNow(void)
|
||||
|
||||
void otPlatAlarmStartAt(uint32_t t0, uint32_t dt)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_alarm = t0 + dt;
|
||||
s_is_running = true;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void otPlatAlarmStop(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
void *alarm_thread(void *arg)
|
||||
void PlatformAlarmUpdateTimeout(struct timeval *aTimeout)
|
||||
{
|
||||
int32_t remaining;
|
||||
struct timeval tva;
|
||||
struct timeval tvb;
|
||||
struct timespec ts;
|
||||
|
||||
while (1)
|
||||
if (aTimeout == NULL)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_is_running)
|
||||
if (s_is_running)
|
||||
{
|
||||
remaining = s_alarm - otPlatAlarmGetNow();
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
// alarm is not running, wait indefinitely
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
aTimeout->tv_sec = remaining / 1000;
|
||||
aTimeout->tv_usec = (remaining % 1000) * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm is running
|
||||
remaining = s_alarm - otPlatAlarmGetNow();
|
||||
aTimeout->tv_sec = 0;
|
||||
aTimeout->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aTimeout->tv_sec = 10;
|
||||
aTimeout->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining > 0)
|
||||
{
|
||||
// alarm has not passed, wait
|
||||
gettimeofday(&tva, NULL);
|
||||
tvb.tv_sec = remaining / 1000;
|
||||
tvb.tv_usec = (remaining % 1000) * 1000;
|
||||
timeradd(&tva, &tvb, &tva);
|
||||
void PlatformAlarmProcess(void)
|
||||
{
|
||||
int32_t remaining;
|
||||
|
||||
ts.tv_sec = tva.tv_sec;
|
||||
ts.tv_nsec = tva.tv_usec * 1000;
|
||||
if (s_is_running)
|
||||
{
|
||||
remaining = s_alarm - otPlatAlarmGetNow();
|
||||
|
||||
pthread_cond_timedwait(&s_cond, &s_mutex, &ts);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alarm has passed, signal
|
||||
s_is_running = false;
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
otPlatAlarmSignalFired();
|
||||
}
|
||||
if (remaining <= 0)
|
||||
{
|
||||
s_is_running = false;
|
||||
otPlatAlarmFired();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -26,28 +26,51 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#include <platform/atomic.h>
|
||||
#include <platform/posix/platform.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
#include <openthread.h>
|
||||
#include <platform/alarm.h>
|
||||
#include "platform.h"
|
||||
|
||||
uint32_t otPlatAtomicBegin(void)
|
||||
void PlatformInit(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
return 0;
|
||||
PlatformAlarmInit();
|
||||
PlatformRadioInit();
|
||||
PlatformRandomInit();
|
||||
}
|
||||
|
||||
void otPlatAtomicEnd(uint32_t state)
|
||||
void PlatformProcessDrivers(void)
|
||||
{
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
int max_fd = -1;
|
||||
struct timeval timeout;
|
||||
int rval;
|
||||
|
||||
void hwSleep(void)
|
||||
{
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
|
||||
PlatformSerialUpdateFdSet(&read_fds, &write_fds, &max_fd);
|
||||
PlatformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
|
||||
PlatformAlarmUpdateTimeout(&timeout);
|
||||
|
||||
if (!otAreTaskletsPending())
|
||||
{
|
||||
rval = select(max_fd + 1, &read_fds, &write_fds, NULL, &timeout);
|
||||
assert(rval >= 0 && errno != ETIME);
|
||||
}
|
||||
|
||||
PlatformSerialProcess();
|
||||
PlatformRadioProcess();
|
||||
PlatformAlarmProcess();
|
||||
}
|
||||
@@ -36,34 +36,94 @@
|
||||
#define PLATFORM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This method performs all platform-specific initialization.
|
||||
*
|
||||
*/
|
||||
void PlatformInit(void);
|
||||
|
||||
/**
|
||||
* This method performs all platform-specific processing.
|
||||
*
|
||||
*/
|
||||
void PlatformProcessDrivers(void);
|
||||
|
||||
/**
|
||||
* This method initializes the alarm service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwAlarmInit(void);
|
||||
void PlatformAlarmInit(void);
|
||||
|
||||
/**
|
||||
* This method retrieves the time remaining until the alarm fires.
|
||||
*
|
||||
* @param[out] aTimeval A pointer to the timeval struct.
|
||||
*
|
||||
*/
|
||||
void PlatformAlarmUpdateTimeout(struct timeval *tv);
|
||||
|
||||
/**
|
||||
* This method performs alarm driver processing.
|
||||
*
|
||||
*/
|
||||
void PlatformAlarmProcess(void);
|
||||
|
||||
/**
|
||||
* This method initializes the radio service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRadioInit(void);
|
||||
void PlatformRadioInit(void);
|
||||
|
||||
/**
|
||||
* This method updates the file descriptor sets with file descriptors used by the radio driver.
|
||||
*
|
||||
* @param[inout] aReadFdSet A pointer to the read file descriptors.
|
||||
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
|
||||
* @param[inout] aMaxFd A pointer to the max file descriptor.
|
||||
*
|
||||
*/
|
||||
void PlatformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
|
||||
|
||||
/**
|
||||
* This method performs radio driver processing.
|
||||
*
|
||||
*/
|
||||
void PlatformRadioProcess(void);
|
||||
|
||||
/**
|
||||
* This method initializes the random number service used by OpenThread.
|
||||
*
|
||||
*/
|
||||
void hwRandomInit(void);
|
||||
void PlatformRandomInit(void);
|
||||
|
||||
/**
|
||||
* This method updates the file descriptor sets with file descriptors used by the serial driver.
|
||||
*
|
||||
* @param[inout] aReadFdSet A pointer to the read file descriptors.
|
||||
* @param[inout] aWriteFdSet A pointer to the write file descriptors.
|
||||
* @param[inout] aMaxFd A pointer to the max file descriptor.
|
||||
*
|
||||
*/
|
||||
void PlatformSerialUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd);
|
||||
|
||||
/**
|
||||
* This method performs radio driver processing.
|
||||
*
|
||||
*/
|
||||
void PlatformSerialProcess(void);
|
||||
|
||||
/**
|
||||
* This method puts the thread executing OpenThread to sleep.
|
||||
*
|
||||
*/
|
||||
void hwSleep(void);
|
||||
void PlatformSleep(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
+168
-186
@@ -28,8 +28,8 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -70,7 +70,8 @@ struct RadioMessage
|
||||
uint8_t mPsdu[Mac::Frame::kMTU];
|
||||
} __attribute__((packed));
|
||||
|
||||
static void *phy_receive_thread(void *arg);
|
||||
static void radioSendAck(void);
|
||||
static void radioProcessFrame(void);
|
||||
|
||||
static PhyState s_state = kStateDisabled;
|
||||
static RadioPacket *s_receive_frame = NULL;
|
||||
@@ -82,9 +83,6 @@ static uint8_t s_extended_address[8];
|
||||
static uint16_t s_short_address;
|
||||
static uint16_t s_panid;
|
||||
|
||||
static pthread_t s_pthread;
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_condition_variable = PTHREAD_COND_INITIALIZER;
|
||||
static int s_sockfd;
|
||||
|
||||
ThreadError otPlatRadioSetPanId(uint16_t panid)
|
||||
@@ -109,7 +107,7 @@ ThreadError otPlatRadioSetShortAddress(uint16_t address)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
void hwRadioInit()
|
||||
void PlatformRadioInit(void)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
@@ -119,58 +117,44 @@ void hwRadioInit()
|
||||
|
||||
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
pthread_create(&s_pthread, NULL, &phy_receive_thread, NULL);
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable()
|
||||
ThreadError otPlatRadioEnable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateDisabled, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable()
|
||||
ThreadError otPlatRadioDisable(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateDisabled;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep()
|
||||
ThreadError otPlatRadioSleep(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioIdle()
|
||||
ThreadError otPlatRadioIdle(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateSleep:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
@@ -180,7 +164,6 @@ ThreadError otPlatRadioIdle()
|
||||
case kStateTransmit:
|
||||
case kStateAckWait:
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
break;
|
||||
|
||||
case kStateDisabled:
|
||||
@@ -189,7 +172,6 @@ ThreadError otPlatRadioIdle()
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -197,32 +179,135 @@ ThreadError otPlatRadioReceive(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateListen;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_receive_frame = packet;
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
struct sockaddr_in sockaddr;
|
||||
RadioMessage message;
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateTransmit;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
|
||||
s_transmit_frame = packet;
|
||||
s_data_pending = false;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
otRadioCaps otPlatRadioGetCaps(void)
|
||||
{
|
||||
return kRadioCapsNone;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
|
||||
|
||||
s_state = kStateIdle;
|
||||
|
||||
if (rxPending != NULL)
|
||||
{
|
||||
*rxPending = s_data_pending;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void radioReceive(void)
|
||||
{
|
||||
RadioPacket receive_frame;
|
||||
RadioMessage message;
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
uint8_t command_id;
|
||||
int rval;
|
||||
|
||||
VerifyOrExit(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen ||
|
||||
s_state == kStateAckWait, ;);
|
||||
|
||||
rval = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
|
||||
assert(rval >= 0);
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateDisabled:
|
||||
case kStateSleep:
|
||||
case kStateIdle:
|
||||
case kStateTransmit:
|
||||
break;
|
||||
|
||||
case kStateAckWait:
|
||||
receive_frame.mLength = rval - 1;
|
||||
memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
|
||||
|
||||
if (command_id == Mac::Frame::kMacCmdDataRequest)
|
||||
{
|
||||
s_data_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
s_state = kStateIdle;
|
||||
otPlatRadioTransmitDone(s_data_pending, kThreadError_None);
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
if (s_receive_frame->mChannel != message.mChannel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s_state = kStateReceive;
|
||||
s_receive_frame->mLength = rval - 1;
|
||||
memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
|
||||
|
||||
radioProcessFrame();
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
int radioTransmit(void)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
RadioMessage message;
|
||||
int rval;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
@@ -238,7 +323,9 @@ ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
rval = sendto(s_sockfd, &message, 1 + s_transmit_frame->mLength, 0, (struct sockaddr *)&sockaddr,
|
||||
sizeof(sockaddr));
|
||||
assert(rval >= 0);
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetAckRequest())
|
||||
@@ -247,154 +334,56 @@ ThreadError otPlatRadioTransmit(RadioPacket *packet)
|
||||
}
|
||||
else
|
||||
{
|
||||
otPlatRadioSignalTransmitDone();
|
||||
s_state = kStateIdle;
|
||||
otPlatRadioTransmitDone(false, kThreadError_None);
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
return error;
|
||||
return rval;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor()
|
||||
void PlatformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
|
||||
{
|
||||
if (aReadFdSet != NULL &&
|
||||
(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen || s_state == kStateAckWait))
|
||||
{
|
||||
FD_SET(s_sockfd, aReadFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
|
||||
{
|
||||
*aMaxFd = s_sockfd;
|
||||
}
|
||||
}
|
||||
|
||||
if (aWriteFdSet != NULL && s_state == kStateTransmit)
|
||||
{
|
||||
FD_SET(s_sockfd, aWriteFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
|
||||
{
|
||||
*aMaxFd = s_sockfd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int PlatformRadioProcess(void)
|
||||
{
|
||||
const int flags = POLLRDNORM | POLLERR | POLLNVAL | POLLHUP;
|
||||
struct pollfd pollfd = { s_sockfd, flags, 0 };
|
||||
|
||||
if (poll(&pollfd, 1, 0) > 0 && (pollfd.revents & flags) != 0)
|
||||
{
|
||||
radioReceive();
|
||||
}
|
||||
|
||||
if (s_state == kStateTransmit)
|
||||
{
|
||||
radioTransmit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
otRadioCaps otPlatRadioGetCaps()
|
||||
{
|
||||
return kRadioCapsNone;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *rxPending)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateTransmit || s_state == kStateAckWait, error = kThreadError_InvalidState);
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
s_state = kStateIdle;
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
if (rxPending != NULL)
|
||||
{
|
||||
*rxPending = s_data_pending;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void *phy_receive_thread(void *arg)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
RadioPacket receive_frame;
|
||||
int length;
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
uint8_t command_id;
|
||||
RadioMessage message;
|
||||
|
||||
while (1)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_sockfd, &fds);
|
||||
|
||||
rval = select(s_sockfd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval < 0 || !FD_ISSET(s_sockfd, &fds))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
while (s_state == kStateIdle || s_state == kStateTransmit)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
switch (s_state)
|
||||
{
|
||||
case kStateDisabled:
|
||||
case kStateIdle:
|
||||
case kStateSleep:
|
||||
recvfrom(s_sockfd, NULL, 0, 0, NULL, NULL);
|
||||
break;
|
||||
|
||||
case kStateTransmit:
|
||||
break;
|
||||
|
||||
case kStateAckWait:
|
||||
length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
|
||||
receive_frame.mLength = length - 1;
|
||||
memcpy(receive_frame.mPsdu, message.mPsdu, receive_frame.mLength);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(&receive_frame)->GetType() != Mac::Frame::kFcfFrameAck)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
tx_sequence = reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetSequence();
|
||||
|
||||
rx_sequence = reinterpret_cast<Mac::Frame *>(&receive_frame)->GetSequence();
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetType() == Mac::Frame::kFcfFrameMacCmd)
|
||||
{
|
||||
reinterpret_cast<Mac::Frame *>(s_transmit_frame)->GetCommandId(command_id);
|
||||
|
||||
if (command_id == Mac::Frame::kMacCmdDataRequest)
|
||||
{
|
||||
s_data_pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
otPlatRadioSignalTransmitDone();
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
length = recvfrom(s_sockfd, &message, sizeof(message), 0, NULL, NULL);
|
||||
|
||||
if (s_receive_frame->mChannel != message.mChannel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s_state = kStateReceive;
|
||||
s_receive_frame->mLength = length - 1;
|
||||
memcpy(s_receive_frame->mPsdu, message.mPsdu, s_receive_frame->mLength);
|
||||
|
||||
otPlatRadioSignalReceiveDone();
|
||||
|
||||
while (s_state == kStateReceive)
|
||||
{
|
||||
pthread_cond_wait(&s_condition_variable, &s_mutex);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void send_ack()
|
||||
void radioSendAck(void)
|
||||
{
|
||||
Mac::Frame *ack_frame;
|
||||
RadioMessage message;
|
||||
@@ -426,17 +415,14 @@ void send_ack()
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioHandleReceiveDone()
|
||||
void radioProcessFrame(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Mac::Frame *receive_frame;
|
||||
uint16_t dstpan;
|
||||
Mac::Address dstaddr;
|
||||
|
||||
VerifyOrExit(s_state == kStateReceive, error = kThreadError_InvalidState);
|
||||
|
||||
receive_frame = reinterpret_cast<Mac::Frame *>(s_receive_frame);
|
||||
|
||||
receive_frame->GetDstAddr(dstaddr);
|
||||
|
||||
switch (dstaddr.mLength)
|
||||
@@ -468,21 +454,17 @@ ThreadError otPlatRadioHandleReceiveDone()
|
||||
// generate acknowledgment
|
||||
if (reinterpret_cast<Mac::Frame *>(s_receive_frame)->GetAckRequest())
|
||||
{
|
||||
send_ack();
|
||||
radioSendAck();
|
||||
}
|
||||
|
||||
exit:
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
|
||||
if (s_state != kStateDisabled)
|
||||
{
|
||||
s_state = kStateIdle;
|
||||
}
|
||||
|
||||
pthread_cond_signal(&s_condition_variable);
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
|
||||
return error;
|
||||
otPlatRadioReceiveDone(error);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -41,7 +41,7 @@ extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint32_t s_state = 1;
|
||||
|
||||
void hwRandomInit(void)
|
||||
void PlatformRandomInit(void)
|
||||
{
|
||||
s_state = args_info.nodeid_arg;
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@@ -37,8 +37,6 @@
|
||||
#include <platform/posix/cmdline.h>
|
||||
#include <platform/serial.h>
|
||||
|
||||
static void *serial_receive_thread(void *arg);
|
||||
|
||||
#ifdef OPENTHREAD_TARGET_LINUX
|
||||
int posix_openpt(int oflag);
|
||||
int grantpt(int fildes);
|
||||
@@ -49,20 +47,20 @@ char *ptsname(int fd);
|
||||
extern struct gengetopt_args_info args_info;
|
||||
|
||||
static uint8_t s_receive_buffer[128];
|
||||
static const uint8_t *s_write_buffer;
|
||||
static uint16_t s_write_length;
|
||||
static int s_in_fd;
|
||||
static int s_out_fd;
|
||||
static pthread_t s_pthread;
|
||||
static sem_t *s_semaphore;
|
||||
|
||||
static struct termios original_stdin_termios;
|
||||
static struct termios original_stdout_termios;
|
||||
|
||||
static void restore_stdin_termios()
|
||||
static void restore_stdin_termios(void)
|
||||
{
|
||||
tcsetattr(s_in_fd, TCSAFLUSH, &original_stdin_termios);
|
||||
}
|
||||
|
||||
static void restore_stdout_termios()
|
||||
static void restore_stdout_termios(void)
|
||||
{
|
||||
tcsetattr(s_out_fd, TCSAFLUSH, &original_stdout_termios);
|
||||
}
|
||||
@@ -72,7 +70,6 @@ ThreadError otPlatSerialEnable(void)
|
||||
ThreadError error = kThreadError_None;
|
||||
struct termios termios;
|
||||
char *path;
|
||||
char cmd[256];
|
||||
|
||||
if (args_info.stdserial_given == 1)
|
||||
{
|
||||
@@ -171,10 +168,6 @@ ThreadError otPlatSerialEnable(void)
|
||||
VerifyOrExit(tcsetattr(s_out_fd, TCSANOW, &termios) == 0, perror("tcsetattr"); error = kThreadError_Error);
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "thread_serial_semaphore_%d", args_info.nodeid_arg);
|
||||
s_semaphore = sem_open(cmd, O_CREAT, 0644, 0);
|
||||
pthread_create(&s_pthread, NULL, &serial_receive_thread, NULL);
|
||||
|
||||
return error;
|
||||
|
||||
exit:
|
||||
@@ -197,54 +190,56 @@ ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(write(s_out_fd, aBuf, aBufLength) >= 0, error = kThreadError_Error);
|
||||
otPlatSerialSignalSendDone();
|
||||
VerifyOrExit(s_write_length == 0, error = kThreadError_Busy);
|
||||
|
||||
s_write_buffer = aBuf;
|
||||
s_write_length = aBufLength;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleSendDone(void)
|
||||
void PlatformSerialUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
|
||||
{
|
||||
}
|
||||
|
||||
void *serial_receive_thread(void *aContext)
|
||||
{
|
||||
fd_set fds;
|
||||
int rval;
|
||||
|
||||
while (1)
|
||||
if (aReadFdSet != NULL)
|
||||
{
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(s_in_fd, &fds);
|
||||
FD_SET(s_in_fd, aReadFdSet);
|
||||
|
||||
rval = select(s_in_fd + 1, &fds, NULL, NULL, NULL);
|
||||
|
||||
if (rval >= 0 && FD_ISSET(s_in_fd, &fds))
|
||||
if (aMaxFd != NULL && *aMaxFd < s_in_fd)
|
||||
{
|
||||
otPlatSerialSignalReceive();
|
||||
sem_wait(s_semaphore);
|
||||
*aMaxFd = s_in_fd;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
if (aWriteFdSet != NULL && s_write_length > 0)
|
||||
{
|
||||
FD_SET(s_out_fd, aWriteFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_out_fd)
|
||||
{
|
||||
*aMaxFd = s_out_fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength)
|
||||
void PlatformSerialProcess(void)
|
||||
{
|
||||
size_t length;
|
||||
const int flags = POLLRDNORM | POLLERR | POLLNVAL | POLLHUP;
|
||||
struct pollfd pollfd = { s_in_fd, flags, 0 };
|
||||
int rval;
|
||||
|
||||
length = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
|
||||
|
||||
if (aBufLength != NULL)
|
||||
if (poll(&pollfd, 1, 0) > 0 && (pollfd.revents & flags) != 0)
|
||||
{
|
||||
*aBufLength = length;
|
||||
rval = read(s_in_fd, s_receive_buffer, sizeof(s_receive_buffer));
|
||||
assert(rval >= 0);
|
||||
otPlatSerialReceived(s_receive_buffer, rval);
|
||||
}
|
||||
|
||||
return s_receive_buffer;
|
||||
}
|
||||
|
||||
void otPlatSerialHandleReceiveDone(void)
|
||||
{
|
||||
sem_post(s_semaphore);
|
||||
if (s_write_length > 0)
|
||||
{
|
||||
rval = write(s_out_fd, s_write_buffer, s_write_length);
|
||||
assert(rval >= 0);
|
||||
s_write_length = 0;
|
||||
otPlatSerialSendDone();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user