mirror of
https://github.com/espressif/openthread.git
synced 2026-08-07 11:17:46 +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;
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Nest Labs, Inc.
|
||||
* 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 <pthread.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <platform/atomic.h>
|
||||
#include <platform/posix/platform.h>
|
||||
|
||||
static pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t s_cond = PTHREAD_COND_INITIALIZER;
|
||||
|
||||
uint32_t otPlatAtomicBegin(void)
|
||||
{
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void otPlatAtomicEnd(uint32_t state)
|
||||
{
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
pthread_cond_signal(&s_cond);
|
||||
}
|
||||
|
||||
void hwSleep(void)
|
||||
{
|
||||
pthread_cond_wait(&s_cond, &s_mutex);
|
||||
}
|
||||
@@ -29,46 +29,48 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the platform abstraction to support critical sections.
|
||||
* This file includes the platform-specific initializers.
|
||||
*/
|
||||
|
||||
#ifndef ATOMIC_H_
|
||||
#define ATOMIC_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <openthread.h>
|
||||
#include <platform/alarm.h>
|
||||
#include "platform.h"
|
||||
|
||||
/**
|
||||
* @defgroup atomic Atomic
|
||||
* @ingroup platform
|
||||
*
|
||||
* @brief
|
||||
* This module includes the platform abstraction to support critical sections.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
void PlatformInit(void)
|
||||
{
|
||||
PlatformAlarmInit();
|
||||
PlatformRadioInit();
|
||||
PlatformRandomInit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin critical section.
|
||||
*/
|
||||
uint32_t otPlatAtomicBegin(void);
|
||||
void PlatformProcessDrivers(void)
|
||||
{
|
||||
fd_set read_fds;
|
||||
fd_set write_fds;
|
||||
int max_fd = -1;
|
||||
struct timeval timeout;
|
||||
int rval;
|
||||
|
||||
/**
|
||||
* End critical section.
|
||||
*/
|
||||
void otPlatAtomicEnd(uint32_t state);
|
||||
FD_ZERO(&read_fds);
|
||||
FD_ZERO(&write_fds);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
PlatformSerialUpdateFdSet(&read_fds, &write_fds, &max_fd);
|
||||
PlatformRadioUpdateFdSet(&read_fds, &write_fds, &max_fd);
|
||||
PlatformAlarmUpdateTimeout(&timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
if (!otAreTaskletsPending())
|
||||
{
|
||||
rval = select(max_fd + 1, &read_fds, &write_fds, NULL, &timeout);
|
||||
assert(rval >= 0 && errno != ETIME);
|
||||
}
|
||||
|
||||
#endif // ATOMIC_H_
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
include_HEADERS = \
|
||||
atomic.h \
|
||||
alarm.h \
|
||||
logging.h \
|
||||
radio.h \
|
||||
|
||||
@@ -71,7 +71,7 @@ void otPlatAlarmStartAt(uint32_t aT0, uint32_t aDt);
|
||||
void otPlatAlarmStop(void);
|
||||
|
||||
/**
|
||||
* Get the current current time.
|
||||
* Get the current time.
|
||||
*
|
||||
* @returns The current time in milliseconds.
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ uint32_t otPlatAlarmGetNow(void);
|
||||
/**
|
||||
* Signal that the alarm has fired.
|
||||
*/
|
||||
extern void otPlatAlarmSignalFired(void);
|
||||
extern void otPlatAlarmFired(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
+12
-35
@@ -208,9 +208,6 @@ ThreadError otPlatRadioIdle(void);
|
||||
* 2. Remain in Receive until a packet is received or reception is aborted.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* Upon completion of the receive sequence, otPlatRadioSignalReceiveDone() is called to signal completion to the MAC
|
||||
* layer.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
@@ -221,21 +218,13 @@ ThreadError otPlatRadioIdle(void);
|
||||
ThreadError otPlatRadioReceive(RadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* Signal that a packet has been received.
|
||||
* The radio driver calls this method to notify OpenThread of a received packet.
|
||||
*
|
||||
* This may be called from interrupt context. The MAC layer will then schedule a call to otPlatRadioHandleReceive().
|
||||
*/
|
||||
|
||||
extern void otPlatRadioSignalReceiveDone(void);
|
||||
|
||||
/**
|
||||
* Complete the receive sequence.
|
||||
* @param[in] aError ::kThreadError_None when successfully received a frame, ::kThreadError_Abort when reception
|
||||
* was aborted and a frame was not received.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully received a frame.
|
||||
* @retval ::kThreadError_Abort Reception was aborted and a frame was not received.
|
||||
* @retval ::kThreadError_InvalidState The radio was not in Receive.
|
||||
*/
|
||||
ThreadError otPlatRadioHandleReceiveDone(void);
|
||||
extern void otPlatRadioReceiveDone(ThreadError error);
|
||||
|
||||
/**
|
||||
* Begins the transmit sequence on the radio.
|
||||
@@ -245,9 +234,6 @@ ThreadError otPlatRadioHandleReceiveDone(void);
|
||||
* 2. Transmits the psdu on the given channel and at the given transmit power.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* Upon completion of the transmit sequence, otPlatRadioSignalTransmitDone() is called to signal completion to the MAC
|
||||
* layer.
|
||||
*
|
||||
* @param[in] aPacket A pointer to a packet buffer.
|
||||
*
|
||||
* @note The channel is specified in @p aPacket.
|
||||
@@ -260,25 +246,16 @@ ThreadError otPlatRadioHandleReceiveDone(void);
|
||||
ThreadError otPlatRadioTransmit(RadioPacket *aPacket);
|
||||
|
||||
/**
|
||||
* Signal that the requested transmission is complete.
|
||||
* The radio driver calls this method to notify OpenThread that the transmission has completed.
|
||||
*
|
||||
* @param[in] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set.
|
||||
* @param[in] aError ::kThreadError_None when the frame was transmitted, ::kThreadError_NoAck when the frame was
|
||||
* transmitted but no ACK was received, ::kThreadError_ChannelAccessFailure when the transmission
|
||||
* could not take place due to activity on the channel, ::kThreadError_Abort when transmission was
|
||||
* aborted for other reasons.
|
||||
*
|
||||
* This may be called from interrupt context. OpenThread will then schedule a call to
|
||||
* otPlatRadio_handle_transmit_done().
|
||||
*/
|
||||
extern void otPlatRadioSignalTransmitDone(void);
|
||||
|
||||
/**
|
||||
* Complete the transmit sequence on the radio.
|
||||
*
|
||||
* @param[out] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set.
|
||||
*
|
||||
* @retval ::kThreadError_None The frame was transmitted.
|
||||
* @retval ::kThreadError_NoAck The frame was transmitted, but no ACK was received.
|
||||
* @retval ::kThreadError_CcaFailed The transmission was aborted due to CCA failure.
|
||||
* @retval ::kThreadError_Abort The transmission was aborted for other reasons.
|
||||
* @retval ::kThreadError_InvalidState The radio did not transmit a packet.
|
||||
*/
|
||||
ThreadError otPlatRadioHandleTransmitDone(bool *aFramePending);
|
||||
extern void otPlatRadioTransmitDone(bool aFramePending, ThreadError error);
|
||||
|
||||
/**
|
||||
* Get the most recent RSSI measurement.
|
||||
|
||||
@@ -82,38 +82,19 @@ ThreadError otPlatSerialDisable(void);
|
||||
ThreadError otPlatSerialSend(const uint8_t *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* Signal that the bytes send operation has completed.
|
||||
* The serial driver calls this method to notify OpenThread that the requested bytes have been sent.
|
||||
*
|
||||
* This may be called from interrupt context. This will schedule calls to otPlatSerialHandleSendDone().
|
||||
*/
|
||||
extern void otPlatSerialSignalSendDone(void);
|
||||
extern void otPlatSerialSendDone(void);
|
||||
|
||||
/**
|
||||
* Complete the send sequence.
|
||||
*/
|
||||
void otPlatSerialHandleSendDone(void);
|
||||
|
||||
/**
|
||||
* Signal that bytes have been received.
|
||||
* The serial driver calls this method to notify OpenThread that bytes have been received.
|
||||
*
|
||||
* This may be called from interrupt context. This will schedule calls to otPlatSerialGetReceivedBytes() and
|
||||
* otPlatSerialHandleReceiveDone().
|
||||
*/
|
||||
extern void otPlatSerialSignalReceive(void);
|
||||
|
||||
/**
|
||||
* Get a pointer to the received bytes.
|
||||
* @param[in] aBuf A pointer to the received bytes.
|
||||
* @param[in] aBufLength The number of bytes received.
|
||||
*
|
||||
* @param[out] aBufLength A pointer to a variable that this function will put the number of bytes received.
|
||||
*
|
||||
* @returns A pointer to the received bytes. NULL, if there are no received bytes to process.
|
||||
*/
|
||||
const uint8_t *otPlatSerialGetReceivedBytes(uint16_t *aBufLength);
|
||||
|
||||
/**
|
||||
* Release received bytes.
|
||||
*/
|
||||
void otPlatSerialHandleReceiveDone(void);
|
||||
extern void otPlatSerialReceived(const uint8_t *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
+9
-27
@@ -50,9 +50,6 @@ static const char sEraseString[] = {'\b', ' ', '\b'};
|
||||
static const char CRNL[] = {'\r', '\n'};
|
||||
static Serial *sServer;
|
||||
|
||||
Tasklet Serial::sReceiveTask(&ReceiveTask, NULL);
|
||||
Tasklet Serial::sSendDoneTask(&SendDoneTask, NULL);
|
||||
|
||||
Serial::Serial(void)
|
||||
{
|
||||
sServer = this;
|
||||
@@ -68,28 +65,20 @@ ThreadError Serial::Start(void)
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalReceive(void)
|
||||
extern "C" void otPlatSerialReceived(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
Serial::sReceiveTask.Post();
|
||||
sServer->ReceiveTask(aBuf, aBufLength);
|
||||
}
|
||||
|
||||
void Serial::ReceiveTask(void *aContext)
|
||||
void Serial::ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
sServer->ReceiveTask();
|
||||
}
|
||||
|
||||
void Serial::ReceiveTask(void)
|
||||
{
|
||||
uint16_t bufLength;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *end;
|
||||
|
||||
buf = otPlatSerialGetReceivedBytes(&bufLength);
|
||||
end = buf + bufLength;
|
||||
end = aBuf + aBufLength;
|
||||
|
||||
for (; buf < end; buf++)
|
||||
for (; aBuf < end; aBuf++)
|
||||
{
|
||||
switch (*buf)
|
||||
switch (*aBuf)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
@@ -115,13 +104,11 @@ void Serial::ReceiveTask(void)
|
||||
break;
|
||||
|
||||
default:
|
||||
Output(reinterpret_cast<const char *>(buf), 1);
|
||||
mRxBuffer[mRxLength++] = *buf;
|
||||
Output(reinterpret_cast<const char *>(aBuf), 1);
|
||||
mRxBuffer[mRxLength++] = *aBuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
otPlatSerialHandleReceiveDone();
|
||||
}
|
||||
|
||||
ThreadError Serial::ProcessCommand(void)
|
||||
@@ -201,12 +188,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalSendDone(void)
|
||||
{
|
||||
Serial::sSendDoneTask.Post();
|
||||
}
|
||||
|
||||
void Serial::SendDoneTask(void *aContext)
|
||||
extern "C" void otPlatSerialSendDone(void)
|
||||
{
|
||||
sServer->SendDoneTask();
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ public:
|
||||
*/
|
||||
int OutputFormat(const char *fmt, ...);
|
||||
|
||||
static Tasklet sReceiveTask;
|
||||
static Tasklet sSendDoneTask;
|
||||
void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength);
|
||||
void SendDoneTask(void);
|
||||
|
||||
private:
|
||||
enum
|
||||
@@ -91,12 +91,7 @@ private:
|
||||
kMaxLineLength = 128,
|
||||
};
|
||||
|
||||
static void ReceiveTask(void *aContext);
|
||||
static void SendDoneTask(void *aContext);
|
||||
|
||||
ThreadError ProcessCommand(void);
|
||||
void ReceiveTask(void);
|
||||
void SendDoneTask(void);
|
||||
void Send(void);
|
||||
|
||||
char mRxBuffer[kRxBufferSize];
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ public:
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxLineLength = 80,
|
||||
kMaxLineLength = 128,
|
||||
};
|
||||
|
||||
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <common/code_utils.hpp>
|
||||
#include <common/debug.hpp>
|
||||
#include <common/tasklet.hpp>
|
||||
#include <platform/atomic.h>
|
||||
|
||||
namespace Thread {
|
||||
|
||||
@@ -57,7 +56,6 @@ ThreadError Tasklet::Post(void)
|
||||
ThreadError TaskletScheduler::Post(Tasklet &aTasklet)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
uint32_t state = otPlatAtomicBegin();
|
||||
|
||||
VerifyOrExit(sTail != &aTasklet && aTasklet.mNext == NULL, error = kThreadError_Busy);
|
||||
|
||||
@@ -74,8 +72,6 @@ ThreadError TaskletScheduler::Post(Tasklet &aTasklet)
|
||||
}
|
||||
|
||||
exit:
|
||||
otPlatAtomicEnd(state);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -105,12 +101,9 @@ bool TaskletScheduler::AreTaskletsPending(void)
|
||||
|
||||
void TaskletScheduler::RunNextTasklet(void)
|
||||
{
|
||||
uint32_t state;
|
||||
Tasklet *task;
|
||||
|
||||
state = otPlatAtomicBegin();
|
||||
task = PopTasklet();
|
||||
otPlatAtomicEnd(state);
|
||||
|
||||
if (task != NULL)
|
||||
{
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
namespace Thread {
|
||||
|
||||
static Tasklet sTask(&TimerScheduler::FireTimers, NULL);
|
||||
static Timer *sHead = NULL;
|
||||
static Timer *sTail = NULL;
|
||||
|
||||
@@ -144,25 +143,18 @@ void TimerScheduler::SetAlarm(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (minRemaining <= 0)
|
||||
{
|
||||
sTask.Post();
|
||||
}
|
||||
else
|
||||
{
|
||||
otPlatAlarmStartAt(now, minRemaining);
|
||||
}
|
||||
otPlatAlarmStartAt(now, minRemaining);
|
||||
|
||||
exit:
|
||||
{}
|
||||
}
|
||||
|
||||
extern "C" void otPlatAlarmSignalFired(void)
|
||||
extern "C" void otPlatAlarmFired(void)
|
||||
{
|
||||
Thread::sTask.Post();
|
||||
TimerScheduler::FireTimers();
|
||||
}
|
||||
|
||||
void TimerScheduler::FireTimers(void *aContext)
|
||||
void TimerScheduler::FireTimers(void)
|
||||
{
|
||||
uint32_t now = otPlatAlarmGetNow();
|
||||
uint32_t elapsed;
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
static void FireTimers(void *aContext);
|
||||
static void FireTimers(void);
|
||||
|
||||
private:
|
||||
static void SetAlarm(void);
|
||||
|
||||
+12
-32
@@ -50,9 +50,6 @@ static const uint8_t sExtendedPanidInit[] = {0xde, 0xad, 0x00, 0xbe, 0xef, 0x00,
|
||||
static const char sNetworkNameInit[] = "OpenThread";
|
||||
static Mac *sMac;
|
||||
|
||||
static Tasklet sReceiveDoneTask(&Mac::ReceiveDoneTask, NULL);
|
||||
static Tasklet sTransmitDoneTask(&Mac::TransmitDoneTask, NULL);
|
||||
|
||||
void Mac::StartCsmaBackoff(void)
|
||||
{
|
||||
uint32_t backoffExponent = kMinBE + mTransmitAttempts + mCsmaAttempts;
|
||||
@@ -63,8 +60,8 @@ void Mac::StartCsmaBackoff(void)
|
||||
backoffExponent = kMaxBE;
|
||||
}
|
||||
|
||||
backoff = (kUnitBackoffPeriod * kPhyUsPerSymbol * (1 << backoffExponent)) / 1000;
|
||||
backoff = (otPlatRandomGet() % backoff) + kMinBackoff;
|
||||
backoff = kMinBackoff + (kUnitBackoffPeriod * kPhyUsPerSymbol * (1 << backoffExponent)) / 1000;
|
||||
backoff = (otPlatRandomGet() % backoff);
|
||||
|
||||
mBackoffTimer.Start(backoff);
|
||||
}
|
||||
@@ -481,26 +478,16 @@ exit:
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void otPlatRadioSignalTransmitDone(void)
|
||||
extern "C" void otPlatRadioTransmitDone(bool aRxPending, ThreadError aError)
|
||||
{
|
||||
sTransmitDoneTask.Post();
|
||||
sMac->TransmitDoneTask(aRxPending, aError);
|
||||
}
|
||||
|
||||
void Mac::TransmitDoneTask(void *aContext)
|
||||
void Mac::TransmitDoneTask(bool aRxPending, ThreadError aError)
|
||||
{
|
||||
sMac->TransmitDoneTask();
|
||||
}
|
||||
|
||||
void Mac::TransmitDoneTask(void)
|
||||
{
|
||||
ThreadError error;
|
||||
bool rxPending;
|
||||
|
||||
error = otPlatRadioHandleTransmitDone(&rxPending);
|
||||
|
||||
mAckTimer.Stop();
|
||||
|
||||
if (error == kThreadError_ChannelAccessFailure &&
|
||||
if (aError == kThreadError_ChannelAccessFailure &&
|
||||
mCsmaAttempts < kMaxCSMABackoffs)
|
||||
{
|
||||
mCsmaAttempts++;
|
||||
@@ -521,7 +508,7 @@ void Mac::TransmitDoneTask(void)
|
||||
break;
|
||||
|
||||
case kStateTransmitData:
|
||||
if (rxPending)
|
||||
if (aRxPending)
|
||||
{
|
||||
mReceiveTimer.Start(kDataPollTimeout);
|
||||
}
|
||||
@@ -530,7 +517,7 @@ void Mac::TransmitDoneTask(void)
|
||||
mReceiveTimer.Stop();
|
||||
}
|
||||
|
||||
SentFrame(error == kThreadError_None);
|
||||
SentFrame(aError == kThreadError_None);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -752,19 +739,13 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
extern "C" void otPlatRadioSignalReceiveDone(void)
|
||||
extern "C" void otPlatRadioReceiveDone(ThreadError aError)
|
||||
{
|
||||
sReceiveDoneTask.Post();
|
||||
sMac->ReceiveDoneTask(aError);
|
||||
}
|
||||
|
||||
void Mac::ReceiveDoneTask(void *aContext)
|
||||
void Mac::ReceiveDoneTask(ThreadError aError)
|
||||
{
|
||||
sMac->ReceiveDoneTask();
|
||||
}
|
||||
|
||||
void Mac::ReceiveDoneTask(void)
|
||||
{
|
||||
ThreadError error;
|
||||
Address srcaddr;
|
||||
Address dstaddr;
|
||||
PanId panid;
|
||||
@@ -772,8 +753,7 @@ void Mac::ReceiveDoneTask(void)
|
||||
Whitelist::Entry *entry;
|
||||
int8_t rssi;
|
||||
|
||||
error = otPlatRadioHandleReceiveDone();
|
||||
VerifyOrExit(error == kThreadError_None, ;);
|
||||
VerifyOrExit(aError == kThreadError_None, ;);
|
||||
|
||||
mReceiveFrame.GetSrcAddr(srcaddr);
|
||||
neighbor = mMle.GetNeighbor(srcaddr);
|
||||
|
||||
@@ -366,18 +366,23 @@ public:
|
||||
/**
|
||||
* This method is called to handle receive events.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aError ::kThreadError_None when successfully received a frame, ::kThreadError_Abort when reception
|
||||
* was aborted and a frame was not received.
|
||||
*
|
||||
*/
|
||||
static void ReceiveDoneTask(void *aContext);
|
||||
void ReceiveDoneTask(ThreadError aError);
|
||||
|
||||
/**
|
||||
* This method is called to handle transmit events.
|
||||
*
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
* @param[in] aFramePending TRUE if an ACK frame was received and the Frame Pending bit was set.
|
||||
* @param[in] aError ::kThreadError_None when the frame was transmitted, ::kThreadError_NoAck when the frame was
|
||||
* transmitted but no ACK was received, ::kThreadError_ChannelAccessFailure when the transmission
|
||||
* could not take place due to activity on the channel, ::kThreadError_Abort when transmission
|
||||
* was aborted for other reasons.
|
||||
*
|
||||
*/
|
||||
static void TransmitDoneTask(void *aContext);
|
||||
void TransmitDoneTask(bool aRxPending, ThreadError aError);
|
||||
|
||||
/**
|
||||
* This method returns if an active scan is in progress.
|
||||
@@ -406,9 +411,6 @@ private:
|
||||
|
||||
void StartCsmaBackoff(void);
|
||||
|
||||
void ReceiveDoneTask(void);
|
||||
void TransmitDoneTask(void);
|
||||
|
||||
Tasklet mBeginTransmit;
|
||||
Timer mAckTimer;
|
||||
Timer mBackoffTimer;
|
||||
|
||||
+6
-25
@@ -36,8 +36,6 @@
|
||||
|
||||
namespace Thread {
|
||||
|
||||
static Tasklet sSendDoneTask(&Ncp::SendDoneTask, NULL);
|
||||
static Tasklet sReceiveTask(&Ncp::ReceiveTask, NULL);
|
||||
static Ncp *sNcp;
|
||||
|
||||
Ncp::Ncp():
|
||||
@@ -146,17 +144,12 @@ Ncp::OutboundFrameSend(void)
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalSendDone()
|
||||
{
|
||||
sSendDoneTask.Post();
|
||||
}
|
||||
|
||||
void Ncp::SendDoneTask(void *context)
|
||||
extern "C" void otPlatSerialSendDone(void)
|
||||
{
|
||||
sNcp->SendDoneTask();
|
||||
}
|
||||
|
||||
void Ncp::SendDoneTask()
|
||||
void Ncp::SendDoneTask(void)
|
||||
{
|
||||
mSending = false;
|
||||
|
||||
@@ -169,26 +162,14 @@ void Ncp::SendDoneTask()
|
||||
super_t::HandleSendDone();
|
||||
}
|
||||
|
||||
extern "C" void otPlatSerialSignalReceive()
|
||||
extern "C" void otPlatSerialReceived(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
sReceiveTask.Post();
|
||||
sNcp->ReceiveTask(aBuf, aBufLength);
|
||||
}
|
||||
|
||||
void Ncp::ReceiveTask(void *context)
|
||||
void Ncp::ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength)
|
||||
{
|
||||
sNcp->ReceiveTask();
|
||||
}
|
||||
|
||||
void Ncp::ReceiveTask()
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint16_t bufLength;
|
||||
|
||||
buf = otPlatSerialGetReceivedBytes(&bufLength);
|
||||
|
||||
mFrameDecoder.Decode(buf, bufLength);
|
||||
|
||||
otPlatSerialHandleReceiveDone();
|
||||
mFrameDecoder.Decode(aBuf, aBufLength);
|
||||
}
|
||||
|
||||
void Ncp::HandleFrame(void *context, uint8_t *aBuf, uint16_t aBufLength)
|
||||
|
||||
+2
-4
@@ -57,13 +57,11 @@ public:
|
||||
virtual ThreadError OutboundFrameSend(void);
|
||||
|
||||
static void HandleFrame(void *context, uint8_t *aBuf, uint16_t aBufLength);
|
||||
static void SendDoneTask(void *context);
|
||||
static void ReceiveTask(void *context);
|
||||
void SendDoneTask(void);
|
||||
void ReceiveTask(const uint8_t *aBuf, uint16_t aBufLength);
|
||||
|
||||
private:
|
||||
void HandleFrame(uint8_t *aBuf, uint16_t aBufLength);
|
||||
void SendDoneTask();
|
||||
void ReceiveTask();
|
||||
|
||||
Hdlc::Encoder mFrameEncoder;
|
||||
Hdlc::Decoder mFrameDecoder;
|
||||
|
||||
Reference in New Issue
Block a user