diff --git a/examples/platforms/cc1352/uart.c b/examples/platforms/cc1352/uart.c index 99881eb9f..34cd86504 100644 --- a/examples/platforms/cc1352/uart.c +++ b/examples/platforms/cc1352/uart.c @@ -192,10 +192,7 @@ static void processReceive(void) } } -/** - * @brief process the transmit side of the buffers - */ -static void processTransmit(void) +otError otPlatUartFlush(void) { otEXPECT(sSendBuffer != NULL); @@ -207,10 +204,20 @@ static void processTransmit(void) sSendBuffer = NULL; sSendLen = 0; - otPlatUartSendDone(); + + return OT_ERROR_NONE; exit: - return; + return OT_ERROR_INVALID_STATE; +} + +/** + * @brief process the transmit side of the buffers + */ +static void processTransmit(void) +{ + otPlatUartFlush(); + otPlatUartSendDone(); } /** diff --git a/examples/platforms/cc2538/uart.c b/examples/platforms/cc2538/uart.c index d709b840f..992af65d5 100644 --- a/examples/platforms/cc2538/uart.c +++ b/examples/platforms/cc2538/uart.c @@ -179,7 +179,7 @@ void processReceive(void) } } -void processTransmit(void) +otError otPlatUartFlush(void) { otEXPECT(sTransmitBuffer != NULL); @@ -192,10 +192,16 @@ void processTransmit(void) } sTransmitBuffer = NULL; - otPlatUartSendDone(); + return OT_ERROR_NONE; exit: - return; + return OT_ERROR_INVALID_STATE; +} + +void processTransmit(void) +{ + otPlatUartFlush(); + otPlatUartSendDone(); } void cc2538UartProcess(void) diff --git a/examples/platforms/cc2650/uart.c b/examples/platforms/cc2650/uart.c index fe8b38840..d6f048325 100644 --- a/examples/platforms/cc2650/uart.c +++ b/examples/platforms/cc2650/uart.c @@ -147,10 +147,7 @@ static void processReceive(void) } } -/** - * @brief process the transmit side of the buffers - */ -static void processTransmit(void) +otError otPlatUartFlush(void) { otEXPECT(sSendBuffer != NULL); @@ -162,10 +159,20 @@ static void processTransmit(void) sSendBuffer = NULL; sSendLen = 0; - otPlatUartSendDone(); + + return OT_ERROR_NONE; exit: - return; + return OT_ERROR_INVALID_STATE; +} + +/** + * @brief process the transmit side of the buffers + */ +static void processTransmit(void) +{ + otPlatUartFlush(); + otPlatUartSendDone(); } /** diff --git a/examples/platforms/cc2652/uart.c b/examples/platforms/cc2652/uart.c index 493aa0870..b342a5275 100644 --- a/examples/platforms/cc2652/uart.c +++ b/examples/platforms/cc2652/uart.c @@ -192,10 +192,7 @@ static void processReceive(void) } } -/** - * @brief process the transmit side of the buffers - */ -static void processTransmit(void) +otError otPlatUartFlush(void) { otEXPECT(sSendBuffer != NULL); @@ -207,10 +204,20 @@ static void processTransmit(void) sSendBuffer = NULL; sSendLen = 0; - otPlatUartSendDone(); + + return OT_ERROR_NONE; exit: - return; + return OT_ERROR_INVALID_STATE; +} + +/** + * @brief process the transmit side of the buffers + */ +static void processTransmit(void) +{ + otPlatUartFlush(); + otPlatUartSendDone(); } /** diff --git a/examples/platforms/efr32mg12/uart.c b/examples/platforms/efr32mg12/uart.c index 36858acd8..5576d469b 100644 --- a/examples/platforms/efr32mg12/uart.c +++ b/examples/platforms/efr32mg12/uart.c @@ -253,6 +253,11 @@ static void processReceive(void) CORE_EXIT_NVIC(); } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + static void processTransmit(void) { if (sTransmitBuffer != NULL && sTransmitLength == 0) diff --git a/examples/platforms/efr32mg21/uart.c b/examples/platforms/efr32mg21/uart.c index cffafc00c..98c67ee84 100644 --- a/examples/platforms/efr32mg21/uart.c +++ b/examples/platforms/efr32mg21/uart.c @@ -250,6 +250,11 @@ static void processReceive(void) CORE_EXIT_NVIC(); } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + static void processTransmit(void) { if (sTransmitBuffer != NULL && sTransmitLength == 0) diff --git a/examples/platforms/gp712/uart-posix.c b/examples/platforms/gp712/uart-posix.c index 7f80c203c..fee2e217c 100644 --- a/examples/platforms/gp712/uart-posix.c +++ b/examples/platforms/gp712/uart-posix.c @@ -207,6 +207,11 @@ exit: return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + void platformUartProcess(void) { ssize_t rval; diff --git a/examples/platforms/gp712/uart-socket.c b/examples/platforms/gp712/uart-socket.c index 36b9f1c43..754d56eb3 100644 --- a/examples/platforms/gp712/uart-socket.c +++ b/examples/platforms/gp712/uart-socket.c @@ -149,6 +149,11 @@ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + void platformUartInit(void) { } diff --git a/examples/platforms/kw41z/uart.c b/examples/platforms/kw41z/uart.c index 6f2b671b1..226e04e16 100644 --- a/examples/platforms/kw41z/uart.c +++ b/examples/platforms/kw41z/uart.c @@ -120,6 +120,11 @@ exit: return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + static void processTransmit(void) { if (sTransmitBuffer && sTransmitDone) diff --git a/examples/platforms/nrf52811/uart.c b/examples/platforms/nrf52811/uart.c index c56bae881..73383162d 100644 --- a/examples/platforms/nrf52811/uart.c +++ b/examples/platforms/nrf52811/uart.c @@ -119,6 +119,11 @@ exit: return; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + /** * Function for notifying application about transmission being done. */ diff --git a/examples/platforms/nrf52840/uart.c b/examples/platforms/nrf52840/uart.c index d871b402e..c9b1ff59a 100644 --- a/examples/platforms/nrf52840/uart.c +++ b/examples/platforms/nrf52840/uart.c @@ -119,6 +119,11 @@ exit: return; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + /** * Function for notifying application about transmission being done. */ diff --git a/examples/platforms/nrf52840/usb-cdc-uart.c b/examples/platforms/nrf52840/usb-cdc-uart.c index 8c325b1ed..48e0ce361 100644 --- a/examples/platforms/nrf52840/usb-cdc-uart.c +++ b/examples/platforms/nrf52840/usb-cdc-uart.c @@ -362,4 +362,9 @@ exit: return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + #endif // USB_CDC_AS_SERIAL_TRANSPORT == 1 diff --git a/examples/platforms/posix/sim/platform-sim.c b/examples/platforms/posix/sim/platform-sim.c index 6d38e0824..87936c651 100644 --- a/examples/platforms/posix/sim/platform-sim.c +++ b/examples/platforms/posix/sim/platform-sim.c @@ -165,6 +165,11 @@ otError otPlatUartSend(const uint8_t *aData, uint16_t aLength) return error; } + +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} #endif // OPENTHREAD_POSIX_VIRTUAL_TIME_UART static void socket_init(void) diff --git a/examples/platforms/posix/uart-posix.c b/examples/platforms/posix/uart-posix.c index 391b4b118..af375dcae 100644 --- a/examples/platforms/posix/uart-posix.c +++ b/examples/platforms/posix/uart-posix.c @@ -222,6 +222,11 @@ void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aE } } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + void platformUartProcess(void) { ssize_t rval; diff --git a/examples/platforms/qpg6095/uart.c b/examples/platforms/qpg6095/uart.c index eaf027dc6..c5336a260 100644 --- a/examples/platforms/qpg6095/uart.c +++ b/examples/platforms/qpg6095/uart.c @@ -57,6 +57,11 @@ otError otPlatUartDisable(void) return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength) { otError error = OT_ERROR_NONE; diff --git a/examples/platforms/samr21/uart.c b/examples/platforms/samr21/uart.c index 3c7da8547..8f8aa1eaa 100644 --- a/examples/platforms/samr21/uart.c +++ b/examples/platforms/samr21/uart.c @@ -97,6 +97,11 @@ static void processReceive(void) } } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + static void processTransmit(void) { if (sTransmitDone) diff --git a/include/openthread/platform/uart.h b/include/openthread/platform/uart.h index c6a89b460..6366dfefc 100644 --- a/include/openthread/platform/uart.h +++ b/include/openthread/platform/uart.h @@ -83,6 +83,19 @@ otError otPlatUartDisable(void); */ otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength); +/** + * Flush the outgoing transmit buffer and wait for the data to be sent. + * This is called when the CLI UART interface has a full buffer but still + * wishes to send more data. + * + * @retval OT_ERROR_NONE Flush succeeded, we can proceed to write more + * data to the buffer. + * + * @retval OT_ERROR_NOT_IMPLEMENTED Driver does not support synchronous flush. + * @retval OT_ERROR_INVALID_STATE Driver has no data to flush. + */ +otError otPlatUartFlush(void); + /** * The UART driver calls this method to notify OpenThread that the requested bytes have been sent. * diff --git a/src/cli/cli_uart.cpp b/src/cli/cli_uart.cpp index 9818a9d5d..097561a6e 100644 --- a/src/cli/cli_uart.cpp +++ b/src/cli/cli_uart.cpp @@ -237,25 +237,52 @@ otError Uart::ProcessCommand(void) int Uart::Output(const char *aBuf, uint16_t aBufLength) { OT_CLI_UART_OUTPUT_LOCK(); - uint16_t remaining = kTxBufferSize - mTxLength; - uint16_t tail; + uint16_t sent = 0; - if (aBufLength > remaining) + while (aBufLength > 0) { - aBufLength = remaining; + uint16_t remaining = kTxBufferSize - mTxLength; + uint16_t tail; + uint16_t sendLength = aBufLength; + + if (sendLength > remaining) + { + sendLength = remaining; + } + + for (uint16_t i = 0; i < sendLength; i++) + { + tail = (mTxHead + mTxLength) % kTxBufferSize; + mTxBuffer[tail] = *aBuf++; + aBufLength--; + mTxLength++; + } + + Send(); + + sent += sendLength; + + if (aBufLength > 0) + { + // More to send, so flush what's waiting now + otError err = otPlatUartFlush(); + + if (err == OT_ERROR_NONE) + { + // Flush successful, reset the pointers + SendDoneTask(); + } + else + { + // Flush did not succeed, so abort here. + break; + } + } } - for (int i = 0; i < aBufLength; i++) - { - tail = (mTxHead + mTxLength) % kTxBufferSize; - mTxBuffer[tail] = *aBuf++; - mTxLength++; - } - - Send(); OT_CLI_UART_OUTPUT_UNLOCK(); - return aBufLength; + return sent; } void Uart::Send(void) diff --git a/src/posix/platform/uart.c b/src/posix/platform/uart.c index 93859ff82..4534ceee0 100644 --- a/src/posix/platform/uart.c +++ b/src/posix/platform/uart.c @@ -157,6 +157,11 @@ exit: return error; } +otError otPlatUartFlush(void) +{ + return OT_ERROR_NOT_IMPLEMENTED; +} + void platformUartUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSet, int *aMaxFd) { otEXPECT(sEnabled);