[Silabs] Fix some uart cli hang (#35723)
* Add macros to abstact eusart api between series
* Fix for uart cpp with irq handling with series3. Tweak uart and shell task priority.
* [MATTER-4132]force implementation of _read and _write from newlib to use our UartConsole api when SILABS_LOG_OUT_UART is enabled
* remove segger_rtt_syscalls when uartlog is enabled
* Apply suggestions from code review
Co-authored-by: Andrei Litvin <andy314@gmail.com>
* Restyled by gn
---------
Co-authored-by: Andrei Litvin <andy314@gmail.com>
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/platform/silabs/syscalls_stubs.cpp b/examples/platform/silabs/syscalls_stubs.cpp
index 685bd63..b5095bc 100644
--- a/examples/platform/silabs/syscalls_stubs.cpp
+++ b/examples/platform/silabs/syscalls_stubs.cpp
@@ -38,6 +38,7 @@
#include "uart.h"
#endif
+int _open(char * path, int flags, ...);
int _close(int file);
int _fstat(int file, struct stat * st);
int _isatty(int file);
@@ -47,6 +48,23 @@
/**************************************************************************
* @brief
+ * Open a file.
+ *
+ * @param[in] file
+ * File you want to open.
+ *
+ * @return
+ * Returns -1 since there is not logic here to open file.
+ **************************************************************************/
+
+int __attribute__((weak)) _open(char * path, int flags, ...)
+{
+ /* Pretend like we always fail */
+ return -1;
+}
+
+/**************************************************************************
+ * @brief
* Close a file.
*
* @param[in] file
@@ -170,17 +188,22 @@
* @return
* Number of characters that have been read.
*************************************************************************/
+#if SILABS_LOG_OUT_UART
+int _read(int file, char * ptr, int len)
+{
+ (void) file;
+ return uartConsoleRead(ptr, len);
+}
+#else
int __attribute__((weak)) _read(int file, char * ptr, int len)
{
(void) file;
-#if SILABS_LOG_OUT_UART
- return uartConsoleRead(ptr, len);
-#else
(void) ptr;
(void) len;
-#endif
+
return 0;
}
+#endif // SILABS_LOG_OUT_UART
/**************************************************************************
* @brief
@@ -198,17 +221,20 @@
* @return
* Number of characters that have been written.
**************************************************************************/
+#if SILABS_LOG_OUT_UART
+int _write(int file, const char * ptr, int len)
+{
+ (void) file;
+ return uartConsoleWrite(ptr, len);
+}
+#else
int __attribute__((weak)) _write(int file, const char * ptr, int len)
{
(void) file;
-#if SILABS_LOG_OUT_UART
- uartConsoleWrite(ptr, len);
-#else
(void) ptr;
-#endif
-
return len;
}
+#endif // SILABS_LOG_OUT_UART
#ifdef __cplusplus
}
diff --git a/examples/platform/silabs/uart.cpp b/examples/platform/silabs/uart.cpp
index a05dd70..a43a23f 100644
--- a/examples/platform/silabs/uart.cpp
+++ b/examples/platform/silabs/uart.cpp
@@ -40,8 +40,12 @@
#include "rsi_rom_egpio.h"
#include "sl_si91x_usart.h"
#else // For EFR32
+#if (_SILICON_LABS_32B_SERIES < 3)
#include "em_core.h"
#include "em_usart.h"
+#else
+#include "sl_hal_eusart.h"
+#endif //_SILICON_LABS_32B_SERIES
#include "uartdrv.h"
#ifdef SL_BOARD_NAME
#include "sl_board_control.h"
@@ -86,11 +90,34 @@
#define USART_IRQ HELPER2(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
#define USART_IRQHandler HELPER4(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
#define vcom_handle sl_uartdrv_eusart_vcom_handle
+
+#if (_SILICON_LABS_32B_SERIES < 3)
+#define EUSART_INT_ENABLE EUSART_IntEnable
+#define EUSART_INT_DISABLE EUSART_IntDisable
+#define EUSART_INT_CLEAR EUSART_IntClear
+#define EUSART_CLEAR_RX
+#define EUSART_GET_PENDING_INT EUSART_IntGet
+#define EUSART_ENABLE(eusart) EUSART_Enable(eusart, eusartEnable)
+#else
+#define EUSART_INT_ENABLE sl_hal_eusart_enable_interrupts
+#define EUSART_INT_DISABLE sl_hal_eusart_disable_interrupts
+#define EUSART_INT_SET sl_hal_eusart_set_interrupts
+#define EUSART_INT_CLEAR sl_hal_eusart_clear_interrupts
+#define EUSART_CLEAR_RX sl_hal_eusart_clear_rx
+#define EUSART_GET_PENDING_INT sl_hal_eusart_get_pending_interrupts
+#define EUSART_ENABLE(eusart) \
+ { \
+ sl_hal_eusart_enable(eusart); \
+ sl_hal_eusart_enable_tx(eusart); \
+ sl_hal_eusart_enable_rx(eusart); \
+ }
+#endif //_SILICON_LABS_32B_SERIES
+
#else
#define USART_IRQ HELPER2(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
#define USART_IRQHandler HELPER4(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
#define vcom_handle sl_uartdrv_usart_vcom_handle
-#endif // EFR32MG24
+#endif // SL_CATALOG_UARTDRV_EUSART_PRESENT
namespace {
// In order to reduce the probability of data loss during the dmaFull callback handler we use
@@ -118,7 +145,11 @@
#if SILABS_LOG_OUT_UART
#define UART_MAX_QUEUE_SIZE 125
#else
+#if (_SILICON_LABS_32B_SERIES < 3)
#define UART_MAX_QUEUE_SIZE 25
+#else
+#define UART_MAX_QUEUE_SIZE 50
+#endif
#endif
#ifdef CHIP_CONFIG_LOG_MESSAGE_MAX_SIZE
@@ -138,13 +169,7 @@
.cb_size = osThreadCbSize,
.stack_mem = uartStack,
.stack_size = kUartTaskSize,
-#if SLI_SI91X_MCU_INTERFACE
- // Reducing the priority of the UART task to avoid priority inversion
- .priority = osPriorityNormal
-#else
- .priority = osPriorityRealtime
-#endif // SLI_SI91X_MCU_INTERFACE
-};
+ .priority = osPriorityBelowNormal };
typedef struct
{
@@ -309,16 +334,17 @@
#ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT
// Clear previous RX interrupts
- EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+ EUSART_INT_CLEAR(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, (EUSART_IF_RXFL | EUSART_IF_RXOF));
+ EUSART_CLEAR_RX(SL_UARTDRV_EUSART_VCOM_PERIPHERAL);
// Enable RX interrupts
- EUSART_IntEnable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+ EUSART_INT_ENABLE(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
// Enable EUSART
- EUSART_Enable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, eusartEnable);
+ EUSART_ENABLE(SL_UARTDRV_EUSART_VCOM_PERIPHERAL);
#else
USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV);
-#endif // EFR32MG24
+#endif // SL_CATALOG_UARTDRV_EUSART_PRESENT
#endif // SLI_SI91X_MCU_INTERFACE == 0
}
@@ -344,9 +370,15 @@
#elif !defined(PW_RPC_ENABLED) && !defined(SL_WIFI)
otSysEventSignalPending();
#endif
-
#ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT
- EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+ // disable RXFL IRQ until data read by uartConsoleRead
+ EUSART_INT_DISABLE(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+ EUSART_INT_CLEAR(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+
+ if (EUSART_GET_PENDING_INT(SL_UARTDRV_EUSART_VCOM_PERIPHERAL) & EUSART_IF_RXOF)
+ {
+ EUSART_CLEAR_RX(SL_UARTDRV_EUSART_VCOM_PERIPHERAL);
+ }
#endif
}
@@ -418,7 +450,8 @@
memcpy(workBuffer.data, Buf, BufLength);
workBuffer.length = BufLength;
- if (osMessageQueuePut(sUartTxQueue, &workBuffer, osPriorityNormal, 0) == osOK)
+ // this is usually a command response. Wait on queue if full.
+ if (osMessageQueuePut(sUartTxQueue, &workBuffer, osPriorityNormal, osWaitForever) == osOK)
{
return BufLength;
}
@@ -445,6 +478,7 @@
memcpy(workBuffer.data + length, "\r\n", 2);
workBuffer.length = length + 2;
+ // Don't wait when queue is full. Drop the log and return UART_CONSOLE_ERR
if (osMessageQueuePut(sUartTxQueue, &workBuffer, osPriorityNormal, 0) == osOK)
{
return length;
@@ -462,6 +496,10 @@
{
uint8_t * data;
+#ifdef SL_CATALOG_UARTDRV_EUSART_PRESENT
+ EUSART_INT_ENABLE(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+#endif
+
if (Buf == NULL || NbBytesToRead < 1)
{
return UART_CONSOLE_ERR;
diff --git a/src/lib/shell/streamer_silabs.cpp b/src/lib/shell/streamer_silabs.cpp
index c6dcdf7..014649c 100644
--- a/src/lib/shell/streamer_silabs.cpp
+++ b/src/lib/shell/streamer_silabs.cpp
@@ -47,7 +47,13 @@
ssize_t streamer_efr_write(streamer_t * streamer, const char * buffer, size_t length)
{
(void) streamer;
- return uartConsoleWrite(buffer, (uint16_t) length);
+ int16_t bytesWritten = uartConsoleWrite(buffer, (uint16_t) length);
+ if (bytesWritten < 0) // The Write failed
+ {
+ bytesWritten = 0;
+ }
+
+ return bytesWritten;
}
static streamer_t streamer_efr = {
diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni
index 67428f5..d338ea7 100644
--- a/third_party/silabs/SiWx917_sdk.gni
+++ b/third_party/silabs/SiWx917_sdk.gni
@@ -773,8 +773,12 @@
public_deps = [
"${segger_rtt_root}:segger_rtt",
"${segger_rtt_root}:segger_rtt_printf",
- "${segger_rtt_root}:segger_rtt_syscalls",
]
+
+ if (!sl_uart_log_output) {
+ public_deps += [ "${segger_rtt_root}:segger_rtt_syscalls" ]
+ }
+
if (chip_crypto == "platform") {
if (sl_si91x_crypto_flavor == "tinycrypt") {
public_deps += [ ":siwx917_tinycrypt" ]
diff --git a/third_party/silabs/efr32_sdk.gni b/third_party/silabs/efr32_sdk.gni
index 9a29ad6..470c812 100644
--- a/third_party/silabs/efr32_sdk.gni
+++ b/third_party/silabs/efr32_sdk.gni
@@ -1072,9 +1072,12 @@
":efr32_mbedtls_config",
"${segger_rtt_root}:segger_rtt",
"${segger_rtt_root}:segger_rtt_printf",
- "${segger_rtt_root}:segger_rtt_syscalls",
]
+ if (!sl_uart_log_output) {
+ public_deps += [ "${segger_rtt_root}:segger_rtt_syscalls" ]
+ }
+
if (defined(invoker.sources)) {
sources += invoker.sources
}