From 59b3c511844f3c6c404f5c10ae31539eb67ba711 Mon Sep 17 00:00:00 2001 From: Diego Ismirlian Date: Wed, 25 Dec 2019 15:52:16 -0300 Subject: [PATCH] [efr32] Radio: correctly set mAckedWithFramePending (#4484) --- examples/platforms/efr32mg12/radio.c | 124 +++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 15 deletions(-) diff --git a/examples/platforms/efr32mg12/radio.c b/examples/platforms/efr32mg12/radio.c index e3beb84ae..fc13cf07f 100644 --- a/examples/platforms/efr32mg12/radio.c +++ b/examples/platforms/efr32mg12/radio.c @@ -59,14 +59,19 @@ enum { - IEEE802154_MIN_LENGTH = 5, - IEEE802154_MAX_LENGTH = 127, - IEEE802154_ACK_LENGTH = 5, - IEEE802154_FRAME_TYPE_MASK = 0x7, - IEEE802154_FRAME_TYPE_ACK = 0x2, - IEEE802154_FRAME_PENDING = 1 << 4, - IEEE802154_ACK_REQUEST = 1 << 5, - IEEE802154_DSN_OFFSET = 2, + IEEE802154_MIN_LENGTH = 5, + IEEE802154_MAX_LENGTH = 127, + IEEE802154_ACK_LENGTH = 5, + + // FCF + DSN + dest PANID + dest addr + src PANID + src addr (without security header) + IEEE802154_MAX_MHR_LENGTH = 2 + 1 + 2 + 8 + 2 + 8, + + IEEE802154_FRAME_TYPE_MASK = 0x7, + IEEE802154_FRAME_TYPE_ACK = 0x2, + IEEE802154_FRAME_TYPE_MAC_COMMAND = 0x3, + IEEE802154_ACK_REQUEST = 1 << 5, + IEEE802154_DSN_OFFSET = 2, + IEEE802154_FCF_OFFSET = 0, }; enum @@ -106,10 +111,25 @@ typedef enum RAIL_Handle_t gRailHandle; -static volatile bool sTransmitBusy = false; -static bool sPromiscuous = false; -static bool sIsSrcMatchEnabled = false; -static otRadioState sState = OT_RADIO_STATE_DISABLED; +static volatile bool sTransmitBusy = false; +static bool sPromiscuous = false; +static otRadioState sState = OT_RADIO_STATE_DISABLED; + +enum +{ + ACKED_WITH_FP_MATCH_LENGTH = 1 + IEEE802154_MAX_MHR_LENGTH, // PHR and MHR + ACKED_WITH_FP_SLOTS = 16, // maximum number of Data Request packets in the RX FIFO. Length should be a power of 2. +}; + +typedef struct efr32AckedWithFP +{ + uint8_t mLength; + uint8_t mPacket[ACKED_WITH_FP_MATCH_LENGTH]; +} efr32AckedWithFP; +static bool sIsSrcMatchEnabled = false; +static efr32AckedWithFP sAckedWithFPFifo[ACKED_WITH_FP_SLOTS]; +static uint32_t sAckedWithFPReadIndex; +static volatile uint32_t sAckedWithFPWriteIndex; static uint8_t sReceivePsdu[IEEE802154_MAX_LENGTH]; static otRadioFrame sReceiveFrame; @@ -321,6 +341,10 @@ void efr32RadioInit(void) sCurrentBandConfig = efr32RadioGetBandConfig(OPENTHREAD_CONFIG_DEFAULT_CHANNEL); assert(sCurrentBandConfig != NULL); + memset(sAckedWithFPFifo, 0, sizeof(sAckedWithFPFifo)); + sAckedWithFPWriteIndex = 0; + sAckedWithFPReadIndex = 0; + efr32RadioSetTxPower(sTxPowerDbm); sEnergyScanStatus = ENERGY_SCAN_STATUS_IDLE; @@ -679,6 +703,74 @@ void otPlatRadioEnableSrcMatch(otInstance *aInstance, bool aEnable) sIsSrcMatchEnabled = aEnable; } +static bool sAckedWithFPFifoIsFull(void) +{ + return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == otARRAY_LENGTH(sAckedWithFPFifo); +} + +static bool sAckedWithFPFifoIsEmpty(void) +{ + return (uint32_t)(sAckedWithFPWriteIndex - sAckedWithFPReadIndex) == 0; +} + +static efr32AckedWithFP *sAckedWithFPFifoGetWriteSlot(void) +{ + uint32_t idx = sAckedWithFPWriteIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1); + return &sAckedWithFPFifo[idx]; +} + +static const efr32AckedWithFP *sAckedWithFPFifoGetReadSlot(void) +{ + uint32_t idx = sAckedWithFPReadIndex & (otARRAY_LENGTH(sAckedWithFPFifo) - 1); + return &sAckedWithFPFifo[idx]; +} + +static void insertIeee802154DataRequestCommand(RAIL_Handle_t aRailHandle) +{ + assert(!sAckedWithFPFifoIsFull()); + efr32AckedWithFP *const slot = sAckedWithFPFifoGetWriteSlot(); + + RAIL_RxPacketInfo_t packetInfo; + + RAIL_GetRxIncomingPacketInfo(aRailHandle, &packetInfo); + assert(packetInfo.packetBytes >= 4); // PHR + FCF + DSN + + if (packetInfo.packetBytes > sizeof(slot->mPacket)) + { + packetInfo.packetBytes = sizeof(slot->mPacket); + if (packetInfo.firstPortionBytes >= sizeof(slot->mPacket)) + { + packetInfo.firstPortionBytes = sizeof(slot->mPacket); + packetInfo.lastPortionData = NULL; + } + } + slot->mLength = packetInfo.packetBytes; + RAIL_CopyRxPacket(slot->mPacket, &packetInfo); + + ++sAckedWithFPWriteIndex; +} + +static bool wasAckedWithFramePending(const uint8_t *aPsdu, uint8_t aPsduLength) +{ + bool ackedWithFramePending = false; + uint16_t fcf = aPsdu[IEEE802154_FCF_OFFSET] | (aPsdu[IEEE802154_FCF_OFFSET + 1] << 8); + + otEXPECT((fcf & IEEE802154_FRAME_TYPE_MASK) == IEEE802154_FRAME_TYPE_MAC_COMMAND); + + while (!(ackedWithFramePending || sAckedWithFPFifoIsEmpty())) + { + const efr32AckedWithFP *const slot = sAckedWithFPFifoGetReadSlot(); + if ((slot->mPacket[0] == aPsduLength) && (memcmp(slot->mPacket + 1, aPsdu, slot->mLength - 1) == 0)) + { + ackedWithFramePending = true; + } + ++sAckedWithFPReadIndex; + } + +exit: + return ackedWithFramePending; +} + static void processNextRxPacket(otInstance *aInstance) { RAIL_RxPacketHandle_t packetHandle = RAIL_RX_PACKET_HANDLE_INVALID; @@ -761,9 +853,9 @@ static void processNextRxPacket(otInstance *aInstance) assert(status == RAIL_STATUS_NO_ERROR); sReceiveFrame.mInfo.mRxInfo.mTimestamp = packetDetails.timeReceived.packetTime; - // TODO Set this flag only when the packet is really acknowledged with frame pending set. - // See https://github.com/openthread/openthread/pull/3785 - sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = true; + // Set this flag only when the packet is really acknowledged with frame pending set. + sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending = + wasAckedWithFramePending(sReceiveFrame.mPsdu, sReceiveFrame.mLength); #if OPENTHREAD_CONFIG_DIAG_ENABLE @@ -810,12 +902,14 @@ static void ieee802154DataRequestCommand(RAIL_Handle_t aRailHandle) { status = RAIL_IEEE802154_SetFramePending(aRailHandle); assert(status == RAIL_STATUS_NO_ERROR); + insertIeee802154DataRequestCommand(aRailHandle); } } else { status = RAIL_IEEE802154_SetFramePending(aRailHandle); assert(status == RAIL_STATUS_NO_ERROR); + insertIeee802154DataRequestCommand(aRailHandle); } }