[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
     }