From e0fdc20f479101b03127f2b07a96e113e4c1fb69 Mon Sep 17 00:00:00 2001 From: Marven Gilhespie <45208741+marvensilabs@users.noreply.github.com> Date: Mon, 29 Jul 2019 16:25:55 +0100 Subject: [PATCH] [efr32] revert uart.c to commit 4c06b47c34 (#4030) Fixes NCP often entering a uninitialized:fault state during reset. Readded otSysEventSignalPending to efr32mg12 uart.c --- examples/platforms/efr32mg12/uart.c | 206 +++++----------------------- examples/platforms/efr32mg21/uart.c | 200 +++++---------------------- 2 files changed, 73 insertions(+), 333 deletions(-) diff --git a/examples/platforms/efr32mg12/uart.c b/examples/platforms/efr32mg12/uart.c index 5576d469b..e81ebf052 100644 --- a/examples/platforms/efr32mg12/uart.c +++ b/examples/platforms/efr32mg12/uart.c @@ -41,23 +41,17 @@ #include "em_core.h" #include "uartdrv.h" -#include -#include #include "hal-config.h" enum { kReceiveFifoSize = 128, - kDmaBlockSize = 64 }; -#define USART_PORT USART0 -#define USART_PORT_RX_IRQn USART0_RX_IRQn - #define USART_INIT \ { \ - USART_PORT, /* USART port */ \ + USART0, /* USART port */ \ 115200, /* Baud rate */ \ BSP_SERIAL_APP_TX_LOC, /* USART Tx pin location number */ \ BSP_SERIAL_APP_RX_LOC, /* USART Rx pin location number */ \ @@ -79,107 +73,39 @@ enum DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_RX_BUFS, sUartRxQueue); DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_TX_BUFS, sUartTxQueue); -static CORE_DECLARE_NVIC_MASK(sRxNvicMask); static UARTDRV_HandleData_t sUartHandleData; static UARTDRV_Handle_t sUartHandle = &sUartHandleData; -static const uint8_t * sTransmitBuffer; -static volatile uint16_t sTransmitLength; -static volatile bool sReceiveDeferred; +static uint8_t sReceiveBuffer[2]; +static const uint8_t * sTransmitBuffer = NULL; +static volatile uint16_t sTransmitLength = 0; -// Using unwrapped indexes allows buffer full and buffer empty conditions to be easily distinguished. -// These values will eventually wrap themselves (due to an integer overflow). They should always be wrapped -// using %kReceiveFifoSize at the point of use, except if testing for a buffer empty condition (mReadEnd == mReadStart). -// kReceiveFifoSize must therefore also be specified to a length of a power of 2. typedef struct ReceiveFifo_t { // The data buffer uint8_t mBuffer[kReceiveFifoSize]; - // The offset of the first item to be read from the list (unwrapped) - uint16_t mReadStart; - // The offset of the last item to be read plus one (unwrapped) - volatile uint16_t mReadEnd; - // The offset of first unused item (unwrapped) - volatile uint16_t mWrite; + // The offset of the first item written to the list. + volatile uint16_t mHead; + // The offset of the next item to be written to the list. + volatile uint16_t mTail; } ReceiveFifo_t; static ReceiveFifo_t sReceiveFifo; -static bool enqueueNextReceive(void); - -static void updateReceiveProgress(uint8_t *aData, UARTDRV_Count_t aCount) -{ - assert(aData != NULL); - - const uint16_t blockStartWrapped = aData - sReceiveFifo.mBuffer; - const uint16_t readEndWrapped = sReceiveFifo.mReadEnd % kReceiveFifoSize; - - // Check readEndWrapped is within range of the current block. Required when mReadEnd was set to the end of - // the buffer on a previous call and readEndWrapped now wraps to 0. - if (readEndWrapped >= blockStartWrapped && readEndWrapped < blockStartWrapped + kDmaBlockSize) - { - sReceiveFifo.mReadEnd += blockStartWrapped + aCount - readEndWrapped; - } -} +static void processReceive(void); static void receiveDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount) { - updateReceiveProgress(aData, aCount); - - if (!enqueueNextReceive()) + // We can only write if incrementing mTail doesn't equal mHead + if (sReceiveFifo.mHead != (sReceiveFifo.mTail + 1) % kReceiveFifoSize) { - // A failure to enqueue the next receive is due to no free blocks remaining in the buffer. Defer enqueueing - // the next receive operation to processReceive() (running in the main execution context) where the - // contents of the buffer shall firstly be emptied. In the mean time, flow control RTS will be deasserted. - assert(sReceiveDeferred == false); - sReceiveDeferred = true; + sReceiveFifo.mBuffer[sReceiveFifo.mTail] = aData[0]; + sReceiveFifo.mTail = (sReceiveFifo.mTail + 1) % kReceiveFifoSize; } + UARTDRV_Receive(aHandle, aData, 1, receiveDone); otSysEventSignalPending(); } -static inline bool isBufferEmpty(uint16_t unwrappedReadStart, uint16_t unwrappedReadEnd) -{ - return (unwrappedReadStart == unwrappedReadEnd); -} - -static bool enqueueNextReceive(void) -{ - bool result; - const uint16_t wrappedWrite = sReceiveFifo.mWrite % kReceiveFifoSize; - const uint16_t wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - Ecode_t status; - - if (isBufferEmpty(sReceiveFifo.mReadStart, sReceiveFifo.mReadEnd)) - { - // Buffer is completely empty - result = true; - } - else if (wrappedReadStart == wrappedWrite) - { - // Buffer is completely full because it isn't empty and wrappedReadStart == wrappedWrite - result = false; - } - else if (wrappedReadStart > wrappedWrite) - { - // Read wrappedReadStart is ahead of wrappedWrite: the next block may or may not be fully vacant - result = (wrappedReadStart - wrappedWrite >= kDmaBlockSize); - } - else - { - // Read wrappedReadStart is behind wrappedWrite, so therefore there is at least one block free - result = true; - } - - otEXPECT(result); - - status = UARTDRV_Receive(sUartHandle, sReceiveFifo.mBuffer + wrappedWrite, kDmaBlockSize, receiveDone); - otEXPECT_ACTION(ECODE_OK == status, result = false); - - sReceiveFifo.mWrite += kDmaBlockSize; -exit: - return result; -} - static void transmitDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount) { sTransmitLength = 0; @@ -188,69 +114,26 @@ static void transmitDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aDa static void processReceive(void) { - uint16_t readEnd; - uint8_t * buffer; - UARTDRV_Count_t itemsReceived; - UARTDRV_Count_t itemsRemaining; - uint16_t wrappedReadStart; - uint16_t wrappedReadEnd; - uint16_t readLength; - CORE_DECLARE_NVIC_STATE; + // Copy tail to prevent multiple reads + uint16_t tail = sReceiveFifo.mTail; - CORE_ENTER_NVIC(&sRxNvicMask); - - UARTDRV_GetReceiveStatus(sUartHandle, &buffer, &itemsReceived, &itemsRemaining); - if (buffer != NULL) + // If the data wraps around, process the first part + if (sReceiveFifo.mHead > tail) { - // Only update the receive progress if a current receive is in progress (buffer not NULL) - updateReceiveProgress(buffer, itemsReceived); + otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, kReceiveFifoSize - sReceiveFifo.mHead); + + // Reset the buffer mHead back to zero. + sReceiveFifo.mHead = 0; } - readEnd = sReceiveFifo.mReadEnd; - - CORE_EXIT_NVIC(); - - wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - wrappedReadEnd = readEnd % kReceiveFifoSize; - - if (!isBufferEmpty(sReceiveFifo.mReadStart, readEnd)) + // For any data remaining, process it + if (sReceiveFifo.mHead != tail) { - if (wrappedReadStart >= wrappedReadEnd) - { - // The buffer isn't empty, and wrappedReadStart >= wrappedReadEnd. Firstly, data needs to be read - // from wrappedReadStart to the end of the buffer. Subsequently, data can then be read from the start - // of the buffer to wrappedReadEnd. - readLength = kReceiveFifoSize - wrappedReadStart; - otPlatUartReceived(sReceiveFifo.mBuffer + wrappedReadStart, readLength); + otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, tail - sReceiveFifo.mHead); - // Move the read start index by the amount of data read - sReceiveFifo.mReadStart += readLength; - } - - // mReadStart may have been modified above, so recalculate wrappedReadStart - wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - - if (!isBufferEmpty(sReceiveFifo.mReadStart, readEnd)) - { - // There is still data in the buffer (i.e. wrappedReadStart < wrappedReadEnd) - readLength = wrappedReadEnd - wrappedReadStart; - otPlatUartReceived(sReceiveFifo.mBuffer + wrappedReadStart, readLength); - - // All data has been read - sReceiveFifo.mReadStart = readEnd; - } + // Set mHead to the local tail we have cached + sReceiveFifo.mHead = tail; } - - CORE_ENTER_NVIC(&sRxNvicMask); - - // The buffer has been emptied, but it may have since filled up again just before entering this critical section. - // Attempt to enqueue any receive operations that previously failed to enqueue due to a full buffer. - if (sReceiveDeferred) - { - sReceiveDeferred = !enqueueNextReceive(); - } - - CORE_EXIT_NVIC(); } otError otPlatUartFlush(void) @@ -269,33 +152,19 @@ static void processTransmit(void) otError otPlatUartEnable(void) { - otError error = OT_ERROR_NONE; UARTDRV_Init_t uartInit = USART_INIT; - bool enqueuedReceive; - memset(&sRxNvicMask, 0, sizeof(sRxNvicMask)); - CORE_NvicMaskSetIRQ(LDMA_IRQn, &sRxNvicMask); - CORE_NvicMaskSetIRQ(USART_PORT_RX_IRQn, &sRxNvicMask); + sReceiveFifo.mHead = 0; + sReceiveFifo.mTail = 0; - sReceiveFifo.mReadStart = 0; - sReceiveFifo.mReadEnd = 0; - sReceiveFifo.mWrite = 0; - sTransmitLength = 0; - sTransmitBuffer = NULL; + UARTDRV_Init(sUartHandle, &uartInit); - otEXPECT_ACTION(ECODE_OK == UARTDRV_Init(sUartHandle, &uartInit), error = OT_ERROR_FAILED); + for (uint8_t i = 0; i < sizeof(sReceiveBuffer); i++) + { + UARTDRV_Receive(sUartHandle, &sReceiveBuffer[i], sizeof(sReceiveBuffer[i]), receiveDone); + } - CORE_DECLARE_NVIC_STATE; - CORE_ENTER_NVIC(&sRxNvicMask); - - enqueuedReceive = enqueueNextReceive(); - - CORE_EXIT_NVIC(); - - otEXPECT_ACTION(enqueuedReceive, error = OT_ERROR_FAILED); - -exit: - return error; + return OT_ERROR_NONE; } otError otPlatUartDisable(void) @@ -306,15 +175,14 @@ otError otPlatUartDisable(void) otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) { otError error = OT_ERROR_NONE; - Ecode_t status; otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY); sTransmitBuffer = aBuf; sTransmitLength = aBufLength; - status = UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone); - otEXPECT_ACTION(ECODE_OK == status, error = OT_ERROR_FAILED); + UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone); + exit: return error; } diff --git a/examples/platforms/efr32mg21/uart.c b/examples/platforms/efr32mg21/uart.c index 98c67ee84..ac7132106 100644 --- a/examples/platforms/efr32mg21/uart.c +++ b/examples/platforms/efr32mg21/uart.c @@ -40,15 +40,12 @@ #include "em_core.h" #include "uartdrv.h" -#include -#include #include "hal-config.h" enum { kReceiveFifoSize = 128, - kDmaBlockSize = 64 }; #define USART_PORT USART0 @@ -79,103 +76,36 @@ enum DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_RX_BUFS, sUartRxQueue); DEFINE_BUF_QUEUE(EMDRV_UARTDRV_MAX_CONCURRENT_TX_BUFS, sUartTxQueue); -static CORE_DECLARE_NVIC_MASK(sRxNvicMask); static UARTDRV_HandleData_t sUartHandleData; static UARTDRV_Handle_t sUartHandle = &sUartHandleData; -static const uint8_t * sTransmitBuffer; -static volatile uint16_t sTransmitLength; -static volatile bool sReceiveDeferred; +static uint8_t sReceiveBuffer[2]; +static const uint8_t * sTransmitBuffer = NULL; +static volatile uint16_t sTransmitLength = 0; -// Using unwrapped indexes allows buffer full and buffer empty conditions to be easily distinguished. -// These values will eventually wrap themselves (due to an integer overflow). They should always be wrapped -// using %kReceiveFifoSize at the point of use, except if testing for a buffer empty condition (mReadEnd == mReadStart). -// kReceiveFifoSize must therefore also be specified to a length of a power of 2. typedef struct ReceiveFifo_t { // The data buffer uint8_t mBuffer[kReceiveFifoSize]; - // The offset of the first item to be read from the list (unwrapped) - uint16_t mReadStart; - // The offset of the last item to be read plus one (unwrapped) - volatile uint16_t mReadEnd; - // The offset of first unused item (unwrapped) - volatile uint16_t mWrite; + // The offset of the first item written to the list. + volatile uint16_t mHead; + // The offset of the next item to be written to the list. + volatile uint16_t mTail; } ReceiveFifo_t; static ReceiveFifo_t sReceiveFifo; -static bool enqueueNextReceive(void); - -static void updateReceiveProgress(uint8_t *aData, UARTDRV_Count_t aCount) -{ - assert(aData != NULL); - - const uint16_t blockStartWrapped = aData - sReceiveFifo.mBuffer; - const uint16_t readEndWrapped = sReceiveFifo.mReadEnd % kReceiveFifoSize; - - // Check readEndWrapped is within range of the current block. Required when mReadEnd was set to the end of - // the buffer on a previous call and readEndWrapped now wraps to 0. - if (readEndWrapped >= blockStartWrapped && readEndWrapped < blockStartWrapped + kDmaBlockSize) - { - sReceiveFifo.mReadEnd += blockStartWrapped + aCount - readEndWrapped; - } -} +static void processReceive(void); static void receiveDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount) { - updateReceiveProgress(aData, aCount); - - if (!enqueueNextReceive()) + // We can only write if incrementing mTail doesn't equal mHead + if (sReceiveFifo.mHead != (sReceiveFifo.mTail + 1) % kReceiveFifoSize) { - // A failure to enqueue the next receive is due to no free blocks remaining in the buffer. Defer enqueueing - // the next receive operation to processReceive() (running in the main execution context) where the - // contents of the buffer shall firstly be emptied. In the mean time, flow control RTS will be deasserted. - assert(sReceiveDeferred == false); - sReceiveDeferred = true; - } -} - -static inline bool isBufferEmpty(uint16_t unwrappedReadStart, uint16_t unwrappedReadEnd) -{ - return (unwrappedReadStart == unwrappedReadEnd); -} - -static bool enqueueNextReceive(void) -{ - bool result; - const uint16_t wrappedWrite = sReceiveFifo.mWrite % kReceiveFifoSize; - const uint16_t wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - Ecode_t status; - - if (isBufferEmpty(sReceiveFifo.mReadStart, sReceiveFifo.mReadEnd)) - { - // Buffer is completely empty - result = true; - } - else if (wrappedReadStart == wrappedWrite) - { - // Buffer is completely full because it isn't empty and wrappedReadStart == wrappedWrite - result = false; - } - else if (wrappedReadStart > wrappedWrite) - { - // Read wrappedReadStart is ahead of wrappedWrite: the next block may or may not be fully vacant - result = (wrappedReadStart - wrappedWrite >= kDmaBlockSize); - } - else - { - // Read wrappedReadStart is behind wrappedWrite, so therefore there is at least one block free - result = true; + sReceiveFifo.mBuffer[sReceiveFifo.mTail] = aData[0]; + sReceiveFifo.mTail = (sReceiveFifo.mTail + 1) % kReceiveFifoSize; } - otEXPECT(result); - - status = UARTDRV_Receive(sUartHandle, sReceiveFifo.mBuffer + wrappedWrite, kDmaBlockSize, receiveDone); - otEXPECT_ACTION(ECODE_OK == status, result = false); - - sReceiveFifo.mWrite += kDmaBlockSize; -exit: - return result; + UARTDRV_Receive(aHandle, aData, 1, receiveDone); } static void transmitDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aData, UARTDRV_Count_t aCount) @@ -185,69 +115,26 @@ static void transmitDone(UARTDRV_Handle_t aHandle, Ecode_t aStatus, uint8_t *aDa static void processReceive(void) { - uint16_t readEnd; - uint8_t * buffer; - UARTDRV_Count_t itemsReceived; - UARTDRV_Count_t itemsRemaining; - uint16_t wrappedReadStart; - uint16_t wrappedReadEnd; - uint16_t readLength; - CORE_DECLARE_NVIC_STATE; + // Copy tail to prevent multiple reads + uint16_t tail = sReceiveFifo.mTail; - CORE_ENTER_NVIC(&sRxNvicMask); - - UARTDRV_GetReceiveStatus(sUartHandle, &buffer, &itemsReceived, &itemsRemaining); - if (buffer != NULL) + // If the data wraps around, process the first part + if (sReceiveFifo.mHead > tail) { - // Only update the receive progress if a current receive is in progress (buffer not NULL) - updateReceiveProgress(buffer, itemsReceived); + otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, kReceiveFifoSize - sReceiveFifo.mHead); + + // Reset the buffer mHead back to zero. + sReceiveFifo.mHead = 0; } - readEnd = sReceiveFifo.mReadEnd; - - CORE_EXIT_NVIC(); - - wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - wrappedReadEnd = readEnd % kReceiveFifoSize; - - if (!isBufferEmpty(sReceiveFifo.mReadStart, readEnd)) + // For any data remaining, process it + if (sReceiveFifo.mHead != tail) { - if (wrappedReadStart >= wrappedReadEnd) - { - // The buffer isn't empty, and wrappedReadStart >= wrappedReadEnd. Firstly, data needs to be read - // from wrappedReadStart to the end of the buffer. Subsequently, data can then be read from the start - // of the buffer to wrappedReadEnd. - readLength = kReceiveFifoSize - wrappedReadStart; - otPlatUartReceived(sReceiveFifo.mBuffer + wrappedReadStart, readLength); + otPlatUartReceived(sReceiveFifo.mBuffer + sReceiveFifo.mHead, tail - sReceiveFifo.mHead); - // Move the read start index by the amount of data read - sReceiveFifo.mReadStart += readLength; - } - - // mReadStart may have been modified above, so recalculate wrappedReadStart - wrappedReadStart = sReceiveFifo.mReadStart % kReceiveFifoSize; - - if (!isBufferEmpty(sReceiveFifo.mReadStart, readEnd)) - { - // There is still data in the buffer (i.e. wrappedReadStart < wrappedReadEnd) - readLength = wrappedReadEnd - wrappedReadStart; - otPlatUartReceived(sReceiveFifo.mBuffer + wrappedReadStart, readLength); - - // All data has been read - sReceiveFifo.mReadStart = readEnd; - } + // Set mHead to the local tail we have cached + sReceiveFifo.mHead = tail; } - - CORE_ENTER_NVIC(&sRxNvicMask); - - // The buffer has been emptied, but it may have since filled up again just before entering this critical section. - // Attempt to enqueue any receive operations that previously failed to enqueue due to a full buffer. - if (sReceiveDeferred) - { - sReceiveDeferred = !enqueueNextReceive(); - } - - CORE_EXIT_NVIC(); } otError otPlatUartFlush(void) @@ -266,33 +153,19 @@ static void processTransmit(void) otError otPlatUartEnable(void) { - otError error = OT_ERROR_NONE; UARTDRV_Init_t uartInit = USART_INIT; - bool enqueuedReceive; - memset(&sRxNvicMask, 0, sizeof(sRxNvicMask)); - CORE_NvicMaskSetIRQ(LDMA_IRQn, &sRxNvicMask); - CORE_NvicMaskSetIRQ(USART_PORT_RX_IRQn, &sRxNvicMask); + sReceiveFifo.mHead = 0; + sReceiveFifo.mTail = 0; - sReceiveFifo.mReadStart = 0; - sReceiveFifo.mReadEnd = 0; - sReceiveFifo.mWrite = 0; - sTransmitLength = 0; - sTransmitBuffer = NULL; + UARTDRV_Init(sUartHandle, &uartInit); - otEXPECT_ACTION(ECODE_OK == UARTDRV_Init(sUartHandle, &uartInit), error = OT_ERROR_FAILED); + for (uint8_t i = 0; i < sizeof(sReceiveBuffer); i++) + { + UARTDRV_Receive(sUartHandle, &sReceiveBuffer[i], sizeof(sReceiveBuffer[i]), receiveDone); + } - CORE_DECLARE_NVIC_STATE; - CORE_ENTER_NVIC(&sRxNvicMask); - - enqueuedReceive = enqueueNextReceive(); - - CORE_EXIT_NVIC(); - - otEXPECT_ACTION(enqueuedReceive, error = OT_ERROR_FAILED); - -exit: - return error; + return OT_ERROR_NONE; } otError otPlatUartDisable(void) @@ -303,15 +176,14 @@ otError otPlatUartDisable(void) otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) { otError error = OT_ERROR_NONE; - Ecode_t status; otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY); sTransmitBuffer = aBuf; sTransmitLength = aBufLength; - status = UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone); - otEXPECT_ACTION(ECODE_OK == status, error = OT_ERROR_FAILED); + UARTDRV_Transmit(sUartHandle, (uint8_t *)sTransmitBuffer, sTransmitLength, transmitDone); + exit: return error; }