Skip to content

Commit

Permalink
STM32F4 platform change: add uPortUartWrite() timeout. (#571)
Browse files Browse the repository at this point in the history
Occasionally, on the ubxlib test farm, we find that uPortUartWrite() on the STM32F4 platform gets stuck because LL_USART_IsActiveFlag_TXE() never returns 1 after a data byte has been written to the UART TX HW with LL_USART_TransmitData8(). It is unclear whether this is occurring because the attached module has pulled the CTS line high irretrievably or is due to some subtle issue on the MCU-side.

Anyway, it is not desirable to stop the entire system because of an IO issue and hence the compilation flag U_PORT_UART_WRITE_TIMEOUT_MS (deliberately set to a nice long 30 seconds, since we don't want normal flow control operation to be affected) is introduced in u_port_uart.h and is applied in the STM32F4 implementation of u_port_uart.c. At that time the UART will return the number of characters that have been successfully written to the caller.
  • Loading branch information
RobMeades committed May 24, 2022
1 parent 9af82ea commit 668e93b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
13 changes: 13 additions & 0 deletions port/api/u_port_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ extern "C" {
# define U_PORT_UART_EVENT_QUEUE_SIZE 20
#endif

#ifndef U_PORT_UART_WRITE_TIMEOUT_MS
/** uPortUartWrite() should always succeed in sending all characters;
* however, when flow control is enabled, it is possible that the
* receiving UART at the far end blocks transmission, potentially
* indefinitely, causing uPortUartWrite() to hang. It is not
* desirable to cause the whole application to fail because of an
* IO function; this [deliberately very large] defensive time-out
* may be employed by an implementation of uPortUartWrite()
* as a guard against that.
*/
# define U_PORT_UART_WRITE_TIMEOUT_MS 30000
#endif

/** The event which means that received data is available; this
* will be sent if the receive buffer goes from empty to containing
* one or more bytes of received data. It is used as a bit-mask.
Expand Down
29 changes: 19 additions & 10 deletions port/platform/stm32cube/src/u_port_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1307,23 +1307,25 @@ int32_t uPortUartWrite(int32_t handle,
const void *pBuffer,
size_t sizeBytes)
{
int32_t sizeOrErrorCode = (int32_t) U_ERROR_COMMON_NOT_INITIALISED;
const uint8_t *pDataPtr = pBuffer;
uErrorCode_t sizeOrErrorCode = U_ERROR_COMMON_NOT_INITIALISED;
uPortUartData_t *pUartData;
USART_TypeDef *pReg;
bool txOk = true;
int64_t startTimeMs;

if (gMutex != NULL) {

U_PORT_MUTEX_LOCK(gMutex);

sizeOrErrorCode = U_ERROR_COMMON_INVALID_PARAMETER;
sizeOrErrorCode = (int32_t) U_ERROR_COMMON_INVALID_PARAMETER;
pUartData = pGetUartDataByHandle(handle);
if (pUartData != NULL) {
pReg = gUartCfg[pUartData->uart].pReg;
sizeOrErrorCode = sizeBytes;

// Do the blocking send
while (sizeBytes > 0) {
sizeOrErrorCode = (int32_t) sizeBytes;
startTimeMs = uPortGetTickTimeMs();
while ((sizeBytes > 0) && (txOk)) {
LL_USART_TransmitData8(pReg, *pDataPtr);
// Hint when debugging: if your code stops dead here
// it is because the CTS line of this MCU's UART HW
Expand All @@ -1333,17 +1335,24 @@ int32_t uPortUartWrite(int32_t handle,
// it or the CTS pin when configuring this UART
// was wrong and it's not connected to the right
// thing.
while (!LL_USART_IsActiveFlag_TXE(pReg)) {}
pDataPtr++;
sizeBytes--;
while (!(txOk = LL_USART_IsActiveFlag_TXE(pReg)) &&
(uPortGetTickTimeMs() - startTimeMs < U_PORT_UART_WRITE_TIMEOUT_MS)) {}
if (txOk) {
pDataPtr++;
sizeBytes--;
}
}
while (!LL_USART_IsActiveFlag_TC(pReg)) {}
// Wait for transmission to complete so that we don't
// write over stuff the next time
while (!LL_USART_IsActiveFlag_TC(pReg) &&
(uPortGetTickTimeMs() - startTimeMs < U_PORT_UART_WRITE_TIMEOUT_MS)) {}
sizeOrErrorCode -= (int32_t) sizeBytes;
}

U_PORT_MUTEX_UNLOCK(gMutex);
}

return (int32_t) sizeOrErrorCode;
return sizeOrErrorCode;
}

// Set an event callback.
Expand Down

0 comments on commit 668e93b

Please sign in to comment.