@@ -1485,6 +1485,72 @@ void ulog_flush(void)
14851485 }
14861486}
14871487
1488+ /**
1489+ * @brief Safely dumps pending ulog async logs to a single specified backend.
1490+ *
1491+ * This function is designed for use in critical error handlers (e.g., stack
1492+ * overflow, hard fault, assertion failures). It avoids calling the general
1493+ * `ulog_flush()` function, which could trigger unstable backends (like
1494+ * filesystems or network sockets) and cause secondary crashes. Instead, it
1495+ * finds a specific, trusted backend by name and directly invokes its output
1496+ * and flush functions.
1497+ *
1498+ * @param[in] backend_name The name of the target backend to dump logs to.
1499+ * For maximum safety, this should be a simple,
1500+ * polling-based UART console backend (e.g., "console").
1501+ *
1502+ * @note This function will have no effect if the ulog asynchronous output
1503+ * (`ULOG_USING_ASYNC_OUTPUT`) feature is not enabled.
1504+ */
1505+ void ulog_emergency_dump_to (const char * backend_name )
1506+ {
1507+ rt_rbb_blk_t log_blk ;
1508+ ulog_frame_t log_frame ;
1509+ ulog_backend_t target_backend = RT_NULL ;
1510+
1511+ if (!ulog .init_ok || !backend_name )
1512+ {
1513+ return ;
1514+ }
1515+
1516+ target_backend = ulog_backend_find (backend_name );
1517+ if (target_backend == RT_NULL )
1518+ {
1519+ return ;
1520+ }
1521+
1522+ #ifdef ULOG_USING_ASYNC_OUTPUT
1523+ while ((log_blk = rt_rbb_blk_get (ulog .async_rbb )) != RT_NULL )
1524+ {
1525+ log_frame = (ulog_frame_t ) log_blk -> buf ;
1526+ if (log_frame -> magic == ULOG_FRAME_MAGIC )
1527+ {
1528+ target_backend -> output (target_backend , log_frame -> level , log_frame -> tag ,
1529+ log_frame -> is_raw , log_frame -> log , log_frame -> log_len );
1530+ }
1531+ rt_rbb_blk_free (ulog .async_rbb , log_blk );
1532+ }
1533+
1534+ rt_size_t log_len = rt_ringbuffer_data_len (ulog .async_rb );
1535+ if (ulog .async_rb && log_len > 0 )
1536+ {
1537+ char * log = rt_malloc (log_len + 1 );
1538+ if (log )
1539+ {
1540+ rt_size_t len = rt_ringbuffer_get (ulog .async_rb , (rt_uint8_t * )log , (rt_uint16_t )log_len );
1541+ log [log_len ] = '\0' ;
1542+ ulog_output_to_all_backend (LOG_LVL_DBG , "" , RT_TRUE , log , len );
1543+ rt_free (log );
1544+ }
1545+ }
1546+ #endif
1547+
1548+ if (target_backend -> flush )
1549+ {
1550+ target_backend -> flush (target_backend );
1551+ }
1552+ }
1553+
14881554/**
14891555 * @brief ulog initialization
14901556 *
0 commit comments