mirror of
https://github.com/espressif/openthread.git
synced 2026-09-11 03:30:09 +00:00
new radio fsm (#275)
* remove Idle calls * apply radio state changes to posix radio * apply radio state changes to cc2538
This commit is contained in:
committed by
Jonathan Hui
parent
d7c4a1a0be
commit
c595b240fb
+110
-145
@@ -74,17 +74,7 @@ static ThreadError sReceiveError;
|
||||
static uint8_t sTransmitPsdu[IEEE802154_MAX_LENGTH];
|
||||
static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH];
|
||||
|
||||
typedef enum PhyState
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateSleep,
|
||||
kStateIdle,
|
||||
kStateListen,
|
||||
kStateReceive,
|
||||
kStateTransmit,
|
||||
} PhyState;
|
||||
|
||||
static PhyState sState;
|
||||
static PhyState sState = kStateDisabled;
|
||||
static bool sIsReceiverEnabled = false;
|
||||
|
||||
void enableReceiver(void)
|
||||
@@ -128,28 +118,49 @@ void setChannel(uint8_t channel)
|
||||
|
||||
ThreadError otPlatRadioSetPanId(uint16_t panid)
|
||||
{
|
||||
HWREG(RFCORE_FFSM_PAN_ID0) = panid & 0xFF;
|
||||
HWREG(RFCORE_FFSM_PAN_ID1) = panid >> 8;
|
||||
return kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
HWREG(RFCORE_FFSM_PAN_ID0) = panid & 0xFF;
|
||||
HWREG(RFCORE_FFSM_PAN_ID1) = panid >> 8;
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetExtendedAddress(uint8_t *address)
|
||||
{
|
||||
int i;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
((volatile uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = address[i];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
((volatile uint32_t *)RFCORE_FFSM_EXT_ADDR0)[i] = address[i];
|
||||
}
|
||||
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetShortAddress(uint16_t address)
|
||||
{
|
||||
HWREG(RFCORE_FFSM_SHORT_ADDR0) = address & 0xFF;
|
||||
HWREG(RFCORE_FFSM_SHORT_ADDR1) = address >> 8;
|
||||
return kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
HWREG(RFCORE_FFSM_SHORT_ADDR0) = address & 0xFF;
|
||||
HWREG(RFCORE_FFSM_SHORT_ADDR1) = address >> 8;
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void cc2538RadioInit(void)
|
||||
@@ -181,76 +192,102 @@ void cc2538RadioInit(void)
|
||||
|
||||
ThreadError otPlatRadioEnable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(sState == kStateDisabled, error = kThreadError_Busy);
|
||||
sState = kStateSleep;
|
||||
if (sState == kStateSleep || sState == kStateDisabled)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateSleep;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(sState == kStateIdle, error = kThreadError_Busy);
|
||||
sState = kStateDisabled;
|
||||
if (sState == kStateDisabled || sState == kStateSleep)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateDisabled;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(error == kStateIdle, error = kThreadError_Busy);
|
||||
sState = kStateSleep;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioIdle(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
switch (sState)
|
||||
if (sState == kStateSleep || sState == kStateReceive)
|
||||
{
|
||||
case kStateSleep:
|
||||
sState = kStateIdle;
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
case kStateTransmit:
|
||||
error = kThreadError_None;
|
||||
sState = kStateSleep;
|
||||
disableReceiver();
|
||||
sState = kStateIdle;
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
case kStateDisabled:
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioReceive(uint8_t aChannel)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(sState == kStateIdle, error = kThreadError_Busy);
|
||||
sState = kStateListen;
|
||||
if (sState != kStateDisabled)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateReceive;
|
||||
setChannel(aChannel);
|
||||
sReceiveFrame.mChannel = aChannel;
|
||||
enableReceiver();
|
||||
}
|
||||
|
||||
setChannel(aChannel);
|
||||
sReceiveFrame.mChannel = aChannel;
|
||||
enableReceiver();
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(void)
|
||||
{
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState == kStateReceive)
|
||||
{
|
||||
int i;
|
||||
|
||||
error = kThreadError_None;
|
||||
sState = kStateTransmit;
|
||||
sTransmitError = kThreadError_None;
|
||||
|
||||
while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
||||
|
||||
// flush txfifo
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX;
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX;
|
||||
|
||||
// frame length
|
||||
HWREG(RFCORE_SFR_RFDATA) = sTransmitFrame.mLength;
|
||||
|
||||
// frame data
|
||||
for (i = 0; i < sTransmitFrame.mLength; i++)
|
||||
{
|
||||
HWREG(RFCORE_SFR_RFDATA) = sTransmitFrame.mPsdu[i];
|
||||
}
|
||||
|
||||
setChannel(sTransmitFrame.mChannel);
|
||||
|
||||
while ((HWREG(RFCORE_XREG_FSMSTAT1) & 1) == 0);
|
||||
|
||||
// wait for valid rssi
|
||||
while ((HWREG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0);
|
||||
|
||||
VerifyOrExit(HWREG(RFCORE_XREG_FSMSTAT1) & (RFCORE_XREG_FSMSTAT1_CCA | RFCORE_XREG_FSMSTAT1_SFD),
|
||||
sTransmitError = kThreadError_ChannelAccessFailure);
|
||||
|
||||
// begin transmit
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISTXON;
|
||||
|
||||
while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -261,56 +298,6 @@ RadioPacket *otPlatRadioGetTransmitBuffer(void)
|
||||
return &sTransmitFrame;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
int i;
|
||||
|
||||
VerifyOrExit(sState == kStateIdle, error = kThreadError_Busy);
|
||||
sState = kStateTransmit;
|
||||
sTransmitError = kThreadError_None;
|
||||
|
||||
while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
||||
|
||||
// flush txfifo
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX;
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX;
|
||||
|
||||
// frame length
|
||||
HWREG(RFCORE_SFR_RFDATA) = sTransmitFrame.mLength;
|
||||
|
||||
// frame data
|
||||
for (i = 0; i < sTransmitFrame.mLength; i++)
|
||||
{
|
||||
HWREG(RFCORE_SFR_RFDATA) = sTransmitFrame.mPsdu[i];
|
||||
}
|
||||
|
||||
setChannel(sTransmitFrame.mChannel);
|
||||
enableReceiver();
|
||||
|
||||
while ((HWREG(RFCORE_XREG_FSMSTAT1) & 1) == 0);
|
||||
|
||||
// wait for valid rssi
|
||||
while ((HWREG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0);
|
||||
|
||||
VerifyOrExit(HWREG(RFCORE_XREG_FSMSTAT1) & (RFCORE_XREG_FSMSTAT1_CCA | RFCORE_XREG_FSMSTAT1_SFD),
|
||||
sTransmitError = kThreadError_ChannelAccessFailure);
|
||||
|
||||
// begin transmit
|
||||
HWREG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISTXON;
|
||||
|
||||
while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
||||
|
||||
exit:
|
||||
|
||||
if (sTransmitError != kThreadError_None || (sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
|
||||
{
|
||||
disableReceiver();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -344,7 +331,7 @@ void readFrame(void)
|
||||
uint8_t crcCorr;
|
||||
int i;
|
||||
|
||||
VerifyOrExit(sState == kStateListen || sState == kStateTransmit, ;);
|
||||
VerifyOrExit(sState == kStateReceive || sState == kStateTransmit, ;);
|
||||
VerifyOrExit((HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) != 0, ;);
|
||||
|
||||
// read length
|
||||
@@ -382,50 +369,28 @@ void cc2538RadioProcess(void)
|
||||
{
|
||||
readFrame();
|
||||
|
||||
switch (sState)
|
||||
if ((sState == kStateReceive) && (sReceiveFrame.mLength > 0))
|
||||
{
|
||||
case kStateDisabled:
|
||||
break;
|
||||
otPlatRadioReceiveDone(&sReceiveFrame, sReceiveError);
|
||||
}
|
||||
|
||||
case kStateSleep:
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
case kStateReceive:
|
||||
if (sReceiveFrame.mLength > 0)
|
||||
{
|
||||
sState = kStateIdle;
|
||||
otPlatRadioReceiveDone(&sReceiveFrame, sReceiveError);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kStateTransmit:
|
||||
if (sState == kStateTransmit)
|
||||
{
|
||||
if (sTransmitError != kThreadError_None || (sTransmitFrame.mPsdu[0] & IEEE802154_ACK_REQUEST) == 0)
|
||||
{
|
||||
sState = kStateIdle;
|
||||
sState = kStateReceive;
|
||||
otPlatRadioTransmitDone(false, sTransmitError);
|
||||
}
|
||||
else if (sReceiveFrame.mLength == IEEE802154_ACK_LENGTH &&
|
||||
(sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_ACK &&
|
||||
(sReceiveFrame.mPsdu[IEEE802154_DSN_OFFSET] == sTransmitFrame.mPsdu[IEEE802154_DSN_OFFSET]))
|
||||
{
|
||||
sState = kStateIdle;
|
||||
sState = kStateReceive;
|
||||
otPlatRadioTransmitDone((sReceiveFrame.mPsdu[0] & IEEE802154_FRAME_PENDING) != 0, sTransmitError);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sReceiveFrame.mLength = 0;
|
||||
|
||||
if (sState == kStateIdle)
|
||||
{
|
||||
disableReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
void RFCoreRxTxIntHandler(void)
|
||||
|
||||
+183
-238
@@ -86,41 +86,31 @@ enum
|
||||
IEEE802154_MACCMD_DATA_REQ = 4,
|
||||
};
|
||||
|
||||
typedef enum PhyState
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateSleep = 1,
|
||||
kStateIdle = 2,
|
||||
kStateListen = 3,
|
||||
kStateReceive = 4,
|
||||
kStateTransmit = 5,
|
||||
kStateAckWait = 6,
|
||||
} PhyState;
|
||||
|
||||
struct OT_TOOL_PACKED_BEGIN RadioMessage
|
||||
{
|
||||
uint8_t mChannel;
|
||||
uint8_t mPsdu[kMaxPHYPacketSize];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
static void radioTransmit(const struct RadioMessage *msg, const struct RadioPacket *pkt);
|
||||
static void radioSendMessage(void);
|
||||
static void radioSendAck(void);
|
||||
static void radioProcessFrame(void);
|
||||
|
||||
static PhyState s_state = kStateDisabled;
|
||||
static struct RadioMessage s_receive_message;
|
||||
static struct RadioMessage s_transmit_message;
|
||||
static struct RadioMessage s_ack_message;
|
||||
static RadioPacket s_receive_frame;
|
||||
static RadioPacket s_transmit_frame;
|
||||
static RadioPacket s_ack_frame;
|
||||
static PhyState sState = kStateDisabled;
|
||||
static struct RadioMessage sReceiveMessage;
|
||||
static struct RadioMessage sTransmitMessage;
|
||||
static struct RadioMessage sAckMessage;
|
||||
static RadioPacket sReceiveFrame;
|
||||
static RadioPacket sTransmitFrame;
|
||||
static RadioPacket sAckFrame;
|
||||
|
||||
static uint8_t s_extended_address[OT_EXT_ADDRESS_SIZE];
|
||||
static uint16_t s_short_address;
|
||||
static uint16_t s_panid;
|
||||
|
||||
static int s_sockfd;
|
||||
|
||||
static bool s_promiscuous = false;
|
||||
static uint8_t sExtendedAddress[OT_EXT_ADDRESS_SIZE];
|
||||
static uint16_t sShortAddress;
|
||||
static uint16_t sPanid;
|
||||
static int sSockFd;
|
||||
static bool sPromiscuous = false;
|
||||
static bool sAckWait = false;
|
||||
|
||||
static inline bool isFrameTypeAck(const uint8_t *frame)
|
||||
{
|
||||
@@ -267,26 +257,52 @@ static inline void getExtAddress(const uint8_t *frame, otExtAddress *address)
|
||||
|
||||
ThreadError otPlatRadioSetPanId(uint16_t panid)
|
||||
{
|
||||
s_panid = panid;
|
||||
return kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
sPanid = panid;
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetExtendedAddress(uint8_t *address)
|
||||
{
|
||||
size_t i;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
for (i = 0; i < sizeof(s_extended_address); i++)
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
s_extended_address[i] = address[sizeof(s_extended_address) - 1 - i];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(sExtendedAddress); i++)
|
||||
{
|
||||
sExtendedAddress[i] = address[sizeof(sExtendedAddress) - 1 - i];
|
||||
}
|
||||
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSetShortAddress(uint16_t address)
|
||||
{
|
||||
s_short_address = address;
|
||||
return kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState != kStateTransmit)
|
||||
{
|
||||
sShortAddress = address;
|
||||
error = kThreadError_None;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void otPlatRadioSetPromiscuous(bool aEnable)
|
||||
{
|
||||
sPromiscuous = aEnable;
|
||||
}
|
||||
|
||||
void posixRadioInit(void)
|
||||
@@ -295,7 +311,7 @@ void posixRadioInit(void)
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
|
||||
if (s_promiscuous)
|
||||
if (sPromiscuous)
|
||||
{
|
||||
sockaddr.sin_port = htons(9000 + WELLKNOWN_NODE_ID);
|
||||
}
|
||||
@@ -306,96 +322,84 @@ void posixRadioInit(void)
|
||||
|
||||
sockaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
s_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(s_sockfd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
sSockFd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind(sSockFd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
|
||||
s_receive_frame.mPsdu = s_receive_message.mPsdu;
|
||||
s_transmit_frame.mPsdu = s_transmit_message.mPsdu;
|
||||
s_ack_frame.mPsdu = s_ack_message.mPsdu;
|
||||
sReceiveFrame.mPsdu = sReceiveMessage.mPsdu;
|
||||
sTransmitFrame.mPsdu = sTransmitMessage.mPsdu;
|
||||
sAckFrame.mPsdu = sAckMessage.mPsdu;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioEnable(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(s_state == kStateDisabled, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
if (sState == kStateSleep || sState == kStateDisabled)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateSleep;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioDisable(void)
|
||||
{
|
||||
s_state = kStateDisabled;
|
||||
return kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if (sState == kStateDisabled || sState == kStateSleep)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateDisabled;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioSleep(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateSleep;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioIdle(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
switch (s_state)
|
||||
if (sState == kStateSleep || sState == kStateReceive)
|
||||
{
|
||||
case kStateSleep:
|
||||
s_state = kStateIdle;
|
||||
break;
|
||||
|
||||
case kStateIdle:
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
case kStateTransmit:
|
||||
case kStateAckWait:
|
||||
s_state = kStateIdle;
|
||||
break;
|
||||
|
||||
case kStateDisabled:
|
||||
case kStateReceive:
|
||||
ExitNow(error = kThreadError_Busy);
|
||||
error = kThreadError_None;
|
||||
sState = kStateSleep;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioReceive(uint8_t aChannel)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateListen;
|
||||
s_receive_frame.mChannel = aChannel;
|
||||
if (sState != kStateDisabled)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateReceive;
|
||||
sAckWait = false;
|
||||
sReceiveFrame.mChannel = aChannel;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(void)
|
||||
{
|
||||
ThreadError error = kThreadError_Busy;
|
||||
|
||||
if ((sState == kStateTransmit && !sAckWait) || sState == kStateReceive)
|
||||
{
|
||||
error = kThreadError_None;
|
||||
sState = kStateTransmit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
RadioPacket *otPlatRadioGetTransmitBuffer(void)
|
||||
{
|
||||
return &s_transmit_frame;
|
||||
}
|
||||
|
||||
ThreadError otPlatRadioTransmit(void)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(s_state == kStateIdle, error = kThreadError_Busy);
|
||||
s_state = kStateTransmit;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return &sTransmitFrame;
|
||||
}
|
||||
|
||||
int8_t otPlatRadioGetNoiseFloor(void)
|
||||
@@ -408,139 +412,76 @@ otRadioCaps otPlatRadioGetCaps(void)
|
||||
return kRadioCapsNone;
|
||||
}
|
||||
|
||||
void otPlatRadioSetPromiscuous(bool aEnable)
|
||||
{
|
||||
s_promiscuous = aEnable;
|
||||
}
|
||||
|
||||
bool otPlatRadioGetPromiscuous(void)
|
||||
{
|
||||
return s_promiscuous;
|
||||
return sPromiscuous;
|
||||
}
|
||||
|
||||
void radioReceive(void)
|
||||
{
|
||||
uint8_t tx_sequence, rx_sequence;
|
||||
int rval;
|
||||
|
||||
VerifyOrExit(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen ||
|
||||
s_state == kStateAckWait, ;);
|
||||
|
||||
rval = recvfrom(s_sockfd, &s_receive_message, sizeof(s_receive_message), 0, NULL, NULL);
|
||||
int rval = recvfrom(sSockFd, &sReceiveMessage, sizeof(sReceiveMessage), 0, NULL, NULL);
|
||||
assert(rval >= 0);
|
||||
|
||||
switch (s_state)
|
||||
sReceiveFrame.mLength = rval - 1;
|
||||
|
||||
if (sAckWait)
|
||||
{
|
||||
case kStateDisabled:
|
||||
case kStateSleep:
|
||||
case kStateIdle:
|
||||
case kStateTransmit:
|
||||
break;
|
||||
|
||||
case kStateAckWait:
|
||||
s_receive_frame.mLength = rval - 1;
|
||||
|
||||
if (!isFrameTypeAck(s_receive_frame.mPsdu))
|
||||
if (isFrameTypeAck(sReceiveFrame.mPsdu))
|
||||
{
|
||||
break;
|
||||
uint8_t tx_sequence = getDsn(sTransmitFrame.mPsdu);
|
||||
uint8_t rx_sequence = getDsn(sReceiveFrame.mPsdu);
|
||||
|
||||
if (tx_sequence == rx_sequence)
|
||||
{
|
||||
sState = kStateReceive;
|
||||
sAckWait = false;
|
||||
otPlatRadioTransmitDone(isFramePending(sReceiveFrame.mPsdu), kThreadError_None);
|
||||
}
|
||||
}
|
||||
|
||||
tx_sequence = getDsn(s_transmit_frame.mPsdu);
|
||||
rx_sequence = getDsn(s_receive_frame.mPsdu);
|
||||
|
||||
if (tx_sequence != rx_sequence)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s_state = kStateIdle;
|
||||
otPlatRadioTransmitDone(isFramePending(s_receive_frame.mPsdu), kThreadError_None);
|
||||
break;
|
||||
|
||||
case kStateListen:
|
||||
if (s_receive_frame.mChannel != s_receive_message.mChannel)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
s_state = kStateReceive;
|
||||
s_receive_frame.mLength = rval - 1;
|
||||
|
||||
radioProcessFrame();
|
||||
break;
|
||||
|
||||
case kStateReceive:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
int radioTransmit(void)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
int rval = 0;
|
||||
uint32_t i;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
s_transmit_message.mChannel = s_transmit_frame.mChannel;
|
||||
|
||||
for (i = 1; i < WELLKNOWN_NODE_ID; i++)
|
||||
{
|
||||
if (NODE_ID == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
rval = sendto(s_sockfd, &s_transmit_message, 1 + s_transmit_frame.mLength, 0, (struct sockaddr *)&sockaddr,
|
||||
sizeof(sockaddr));
|
||||
assert(rval >= 0);
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + WELLKNOWN_NODE_ID);
|
||||
rval = sendto(s_sockfd, &s_transmit_message, 1 + s_transmit_frame.mLength, 0, (struct sockaddr *)&sockaddr,
|
||||
sizeof(sockaddr));
|
||||
assert(rval >= 0);
|
||||
|
||||
if (isAckRequested(s_transmit_frame.mPsdu))
|
||||
{
|
||||
s_state = kStateAckWait;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_state = kStateIdle;
|
||||
if (sReceiveFrame.mChannel == sReceiveMessage.mChannel)
|
||||
{
|
||||
radioProcessFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void radioSendMessage(void)
|
||||
{
|
||||
sTransmitMessage.mChannel = sTransmitFrame.mChannel;
|
||||
|
||||
radioTransmit(&sTransmitMessage, &sTransmitFrame);
|
||||
|
||||
sAckWait = isAckRequested(sTransmitFrame.mPsdu);
|
||||
|
||||
if (!sAckWait)
|
||||
{
|
||||
sState = kStateReceive;
|
||||
otPlatRadioTransmitDone(false, kThreadError_None);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
void posixRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
|
||||
{
|
||||
if (aReadFdSet != NULL &&
|
||||
(s_state == kStateDisabled || s_state == kStateSleep || s_state == kStateListen || s_state == kStateAckWait))
|
||||
if (aReadFdSet != NULL && (sState != kStateTransmit || sAckWait))
|
||||
{
|
||||
FD_SET(s_sockfd, aReadFdSet);
|
||||
FD_SET(sSockFd, aReadFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
|
||||
if (aMaxFd != NULL && *aMaxFd < sSockFd)
|
||||
{
|
||||
*aMaxFd = s_sockfd;
|
||||
*aMaxFd = sSockFd;
|
||||
}
|
||||
}
|
||||
|
||||
if (aWriteFdSet != NULL && s_state == kStateTransmit)
|
||||
if (aWriteFdSet != NULL && sState == kStateTransmit && !sAckWait)
|
||||
{
|
||||
FD_SET(s_sockfd, aWriteFdSet);
|
||||
FD_SET(sSockFd, aWriteFdSet);
|
||||
|
||||
if (aMaxFd != NULL && *aMaxFd < s_sockfd)
|
||||
if (aMaxFd != NULL && *aMaxFd < sSockFd)
|
||||
{
|
||||
*aMaxFd = s_sockfd;
|
||||
*aMaxFd = sSockFd;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -548,54 +489,63 @@ void posixRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMaxFd)
|
||||
void posixRadioProcess(void)
|
||||
{
|
||||
const int flags = POLLRDNORM | POLLERR | POLLNVAL | POLLHUP;
|
||||
struct pollfd pollfd = { s_sockfd, flags, 0 };
|
||||
struct pollfd pollfd = { sSockFd, flags, 0 };
|
||||
|
||||
if (poll(&pollfd, 1, 0) > 0 && (pollfd.revents & flags) != 0)
|
||||
{
|
||||
radioReceive();
|
||||
if (sAckWait || sState == kStateReceive)
|
||||
{
|
||||
radioReceive();
|
||||
}
|
||||
}
|
||||
|
||||
if (s_state == kStateTransmit)
|
||||
if (sState == kStateTransmit && !sAckWait)
|
||||
{
|
||||
radioTransmit();
|
||||
radioSendMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void radioSendAck(void)
|
||||
void radioTransmit(const struct RadioMessage *msg, const struct RadioPacket *pkt)
|
||||
{
|
||||
struct sockaddr_in sockaddr;
|
||||
uint32_t i;
|
||||
|
||||
s_ack_frame.mLength = IEEE802154_ACK_LENGTH;
|
||||
s_ack_message.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
||||
|
||||
if (isDataRequest(s_receive_frame.mPsdu))
|
||||
{
|
||||
s_ack_message.mPsdu[0] |= IEEE802154_FRAME_PENDING;
|
||||
}
|
||||
|
||||
s_ack_message.mPsdu[1] = 0;
|
||||
s_ack_message.mPsdu[2] = getDsn(s_receive_frame.mPsdu);
|
||||
struct sockaddr_in sockaddr;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
sockaddr.sin_family = AF_INET;
|
||||
inet_pton(AF_INET, "127.0.0.1", &sockaddr.sin_addr);
|
||||
|
||||
s_ack_message.mChannel = s_receive_frame.mChannel;
|
||||
|
||||
for (i = 1; i < WELLKNOWN_NODE_ID; i++)
|
||||
for (i = 1; i <= WELLKNOWN_NODE_ID; i++)
|
||||
{
|
||||
int rval;
|
||||
|
||||
if (NODE_ID == i)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + i);
|
||||
sendto(s_sockfd, &s_ack_message, 1 + s_ack_frame.mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
rval = sendto(sSockFd, msg, 1 + pkt->mLength,
|
||||
0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
assert(rval >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
void radioSendAck(void)
|
||||
{
|
||||
sAckFrame.mLength = IEEE802154_ACK_LENGTH;
|
||||
sAckMessage.mPsdu[0] = IEEE802154_FRAME_TYPE_ACK;
|
||||
|
||||
if (isDataRequest(sReceiveFrame.mPsdu))
|
||||
{
|
||||
sAckMessage.mPsdu[0] |= IEEE802154_FRAME_PENDING;
|
||||
}
|
||||
|
||||
sockaddr.sin_port = htons(9000 + WELLKNOWN_NODE_ID);
|
||||
sendto(s_sockfd, &s_ack_message, 1 + s_ack_frame.mLength, 0, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
|
||||
sAckMessage.mPsdu[1] = 0;
|
||||
sAckMessage.mPsdu[2] = getDsn(sReceiveFrame.mPsdu);
|
||||
|
||||
sAckMessage.mChannel = sReceiveFrame.mChannel;
|
||||
|
||||
radioTransmit(&sAckMessage, &sAckFrame);
|
||||
}
|
||||
|
||||
void radioProcessFrame(void)
|
||||
@@ -605,26 +555,26 @@ void radioProcessFrame(void)
|
||||
otShortAddress short_address;
|
||||
otExtAddress ext_address;
|
||||
|
||||
VerifyOrExit(s_promiscuous == false, error = kThreadError_None);
|
||||
VerifyOrExit(sPromiscuous == false, error = kThreadError_None);
|
||||
|
||||
switch (s_receive_frame.mPsdu[1] & IEEE802154_DST_ADDR_MASK)
|
||||
switch (sReceiveFrame.mPsdu[1] & IEEE802154_DST_ADDR_MASK)
|
||||
{
|
||||
case IEEE802154_DST_ADDR_NONE:
|
||||
break;
|
||||
|
||||
case IEEE802154_DST_ADDR_SHORT:
|
||||
dstpan = getDstPan(s_receive_frame.mPsdu);
|
||||
short_address = getShortAddress(s_receive_frame.mPsdu);
|
||||
VerifyOrExit((dstpan == IEEE802154_BROADCAST || dstpan == s_panid) &&
|
||||
(short_address == IEEE802154_BROADCAST || short_address == s_short_address),
|
||||
dstpan = getDstPan(sReceiveFrame.mPsdu);
|
||||
short_address = getShortAddress(sReceiveFrame.mPsdu);
|
||||
VerifyOrExit((dstpan == IEEE802154_BROADCAST || dstpan == sPanid) &&
|
||||
(short_address == IEEE802154_BROADCAST || short_address == sShortAddress),
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
case IEEE802154_DST_ADDR_EXT:
|
||||
dstpan = getDstPan(s_receive_frame.mPsdu);
|
||||
getExtAddress(s_receive_frame.mPsdu, &ext_address);
|
||||
VerifyOrExit((dstpan == IEEE802154_BROADCAST || dstpan == s_panid) &&
|
||||
memcmp(&ext_address, s_extended_address, sizeof(ext_address)) == 0,
|
||||
dstpan = getDstPan(sReceiveFrame.mPsdu);
|
||||
getExtAddress(sReceiveFrame.mPsdu, &ext_address);
|
||||
VerifyOrExit((dstpan == IEEE802154_BROADCAST || dstpan == sPanid) &&
|
||||
memcmp(&ext_address, sExtendedAddress, sizeof(ext_address)) == 0,
|
||||
error = kThreadError_Abort);
|
||||
break;
|
||||
|
||||
@@ -632,21 +582,16 @@ void radioProcessFrame(void)
|
||||
ExitNow(error = kThreadError_Abort);
|
||||
}
|
||||
|
||||
s_receive_frame.mPower = -20;
|
||||
s_receive_frame.mLqi = kPhyNoLqi;
|
||||
sReceiveFrame.mPower = -20;
|
||||
sReceiveFrame.mLqi = kPhyNoLqi;
|
||||
|
||||
// generate acknowledgment
|
||||
if (isAckRequested(s_receive_frame.mPsdu))
|
||||
if (isAckRequested(sReceiveFrame.mPsdu))
|
||||
{
|
||||
radioSendAck();
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (s_state != kStateDisabled)
|
||||
{
|
||||
s_state = kStateIdle;
|
||||
}
|
||||
|
||||
otPlatRadioReceiveDone(error == kThreadError_None ? &s_receive_frame : NULL, error);
|
||||
otPlatRadioReceiveDone(error == kThreadError_None ? &sReceiveFrame : NULL, error);
|
||||
}
|
||||
|
||||
+35
-21
@@ -104,6 +104,31 @@ typedef struct RadioPacket
|
||||
bool mSecurityValid; ///< Security Enabled flag is set and frame passes security checks.
|
||||
} RadioPacket;
|
||||
|
||||
/**
|
||||
* This structure represents the state of a radio.
|
||||
* Initially, a radio is in the Disabled state.
|
||||
*/
|
||||
typedef enum PhyState
|
||||
{
|
||||
kStateDisabled = 0,
|
||||
kStateSleep = 1,
|
||||
kStateReceive = 2,
|
||||
kStateTransmit = 3
|
||||
} PhyState;
|
||||
|
||||
/**
|
||||
* The following are valid radio state transitions:
|
||||
*
|
||||
* (Radio ON)
|
||||
* +----------+ Enable() +-------+ Receive() +---------+ Trasnmit() +----------+
|
||||
* | |----------->| |----------->| |-------------->| |
|
||||
* | Disabled | | Sleep | | Receive | | Transmit |
|
||||
* | |<-----------| |<-----------| |<--------------| |
|
||||
* +----------+ Disable() +-------+ Sleep() +---------+ Receive() +----------+
|
||||
* (Radio OFF) or
|
||||
* signal TransmitDone
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
@@ -164,7 +189,7 @@ ThreadError otPlatRadioSetShortAddress(uint16_t aShortAddress);
|
||||
/**
|
||||
* Enable the radio.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Idle.
|
||||
* @retval ::kThreadError_None Successfully transitioned to Sleep.
|
||||
* @retval ::kThreadError_Busy The radio was already enabled.
|
||||
*/
|
||||
ThreadError otPlatRadioEnable(void);
|
||||
@@ -177,33 +202,22 @@ ThreadError otPlatRadioEnable(void);
|
||||
ThreadError otPlatRadioDisable(void);
|
||||
|
||||
/**
|
||||
* Transition the radio to Sleep.
|
||||
* Transition the radio from Receive to Sleep.
|
||||
* Turn off the radio.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Sleep.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Idle state.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Receive state.
|
||||
*/
|
||||
ThreadError otPlatRadioSleep(void);
|
||||
|
||||
/**
|
||||
* Transition the radio to Idle.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Idle.
|
||||
* @retval ::kThreadError_Busy The radio was busy transmitting or receiving.
|
||||
*/
|
||||
ThreadError otPlatRadioIdle(void);
|
||||
|
||||
/**
|
||||
* Begins the receive sequence on the radio.
|
||||
*
|
||||
* The receive sequence consists of:
|
||||
* 1. Transitioning the radio to Receive from Idle.
|
||||
* 2. Remain in Receive until a packet is received or reception is aborted.
|
||||
* 3. Return to Idle.
|
||||
* Transitioning the radio from Sleep to Receive.
|
||||
* Turn on the radio.
|
||||
*
|
||||
* @param[in] aChannel The channel to use for receiving.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Receive.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Idle state.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Sleep state.
|
||||
*/
|
||||
ThreadError otPlatRadioReceive(uint8_t aChannel);
|
||||
|
||||
@@ -218,6 +232,7 @@ ThreadError otPlatRadioReceive(uint8_t aChannel);
|
||||
extern void otPlatRadioReceiveDone(RadioPacket *aPacket, ThreadError aError);
|
||||
|
||||
/**
|
||||
* The radio tranitions from Transmit to Receive.
|
||||
* This method returns a pointer to the transmit buffer.
|
||||
*
|
||||
* The caller forms the IEEE 802.15.4 frame in this buffer then calls otPlatRadioTransmit() to request transmission.
|
||||
@@ -234,12 +249,11 @@ RadioPacket *otPlatRadioGetTransmitBuffer(void);
|
||||
* requesting transmission. The channel and transmit power are also included in the RadioPacket structure.
|
||||
*
|
||||
* The transmit sequence consists of:
|
||||
* 1. Transitioning the radio to Transmit from Idle.
|
||||
* 1. Transitioning the radio to Transmit from Receive.
|
||||
* 2. Transmits the psdu on the given channel and at the given transmit power.
|
||||
* 3. Return to Idle.
|
||||
*
|
||||
* @retval ::kThreadError_None Successfully transitioned to Transmit.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Idle state.
|
||||
* @retval ::kThreadError_Busy The radio was not in the Receive state.
|
||||
*/
|
||||
ThreadError otPlatRadioTransmit(void);
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ void Mac::HandleBeginTransmit(void)
|
||||
Frame &sendFrame(*static_cast<Frame *>(otPlatRadioGetTransmitBuffer()));
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
if (otPlatRadioIdle() != kThreadError_None)
|
||||
if (otPlatRadioReceive(mChannel) != kThreadError_None)
|
||||
{
|
||||
mBeginTransmit.Post();
|
||||
ExitNow();
|
||||
@@ -543,7 +543,7 @@ void Mac::HandleAckTimer(void *aContext)
|
||||
|
||||
void Mac::HandleAckTimer(void)
|
||||
{
|
||||
otPlatRadioIdle();
|
||||
otPlatRadioReceive(mChannel);
|
||||
|
||||
switch (mState)
|
||||
{
|
||||
@@ -1020,7 +1020,7 @@ void Mac::SetPromiscuous(bool aPromiscuous)
|
||||
{
|
||||
otPlatRadioSetPromiscuous(aPromiscuous);
|
||||
|
||||
SuccessOrExit(otPlatRadioIdle());
|
||||
SuccessOrExit(otPlatRadioReceive(mChannel));
|
||||
NextOperation();
|
||||
|
||||
exit:
|
||||
|
||||
Reference in New Issue
Block a user