Skip to content
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/platform/stm32wl/main-stm32wl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,38 @@ typedef struct __attribute__((packed)) ContextStateFrame {

static char hardfault_message_buffer[256];

// printf directly using srcwrapper's debug UART function.
// Bypasses uart_debug_write()'s HAL_GetTick() timeout (frozen inside a fault handler, since SysTick
// can't preempt it) using DWT->CYCCNT instead, which keeps ticking regardless of interrupt state.
static void faultSafeUartWrite(const uint8_t *data, size_t size)
{
USART_TypeDef *uart = Serial.getHandle()->Instance;
if (!uart || !(uart->CR1 & USART_CR1_UE))
return; // Not mapped, or Serial.begin() hasn't run yet - nothing we can do.

CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

// One shared deadline for the whole write (not per byte), so a wedged UART can't stretch this
// out to size * timeoutCycles.
const uint32_t timeoutCycles = SystemCoreClock / 5; // ~200ms - generous for a couple hundred bytes at any sane baud rate
const uint32_t start = DWT->CYCCNT;

for (size_t i = 0; i < size; i++) {
while (!(uart->ISR & USART_ISR_TXE_TXFNF)) {
if ((uint32_t)(DWT->CYCCNT - start) >= timeoutCycles)
return; // Give up rather than hang forever.
}
uart->TDR = data[i];
}

// Wait for the last byte to actually leave the shift register before returning, same reasoning.
while (!(uart->ISR & USART_ISR_TC)) {
if ((uint32_t)(DWT->CYCCNT - start) >= timeoutCycles)
return;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
}

// printf directly to the debug UART, fault-handler-safe (see faultSafeUartWrite() above).
static void debug_printf(const char *format, ...)
{
va_list args;
Expand All @@ -230,7 +261,7 @@ static void debug_printf(const char *format, ...)

if (length < 0)
return;
uart_debug_write((uint8_t *)hardfault_message_buffer, min((unsigned int)length, sizeof(hardfault_message_buffer) - 1));
faultSafeUartWrite((uint8_t *)hardfault_message_buffer, min((unsigned int)length, sizeof(hardfault_message_buffer) - 1));
}

// N picked by guessing
Expand Down