Skip to content

Commit d38a363

Browse files
committed
Merge remote-tracking branch 'fork-ofw/fix/noisy-uart-hang' into mntm-dev --nobuild
2 parents f044a37 + 222c159 commit d38a363

File tree

3 files changed

+44
-29
lines changed

3 files changed

+44
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
- Fix card info not being parsed when using Extra Actions > Read Specific Card Type (by @WillyJL)
8282
- UL: Fix clipper date timestamp (by @luu176)
8383
- BadKB: Fix key combos main keys being case sensitive (by @WillyJL)
84+
- FuriHalSerial: Fix RXFNE interrupt hang, aka freezing with UART output when Expansion Modules are enabled (by @WillyJL)
8485
- Sub-GHz:
8586
- Fix possible frequency analyzer deadlock when holding Ok (by @WillyJL)
8687
- UL: Fix CAME 24bit decoder (by @xMasterX)

applications/services/expansion/expansion_worker.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ typedef enum {
3535
ExpansionWorkerFlagError = 1 << 2,
3636
} ExpansionWorkerFlag;
3737

38-
#define EXPANSION_ALL_FLAGS (ExpansionWorkerFlagData | ExpansionWorkerFlagStop)
38+
#define EXPANSION_ALL_FLAGS \
39+
(ExpansionWorkerFlagData | ExpansionWorkerFlagStop | ExpansionWorkerFlagError)
3940

4041
struct ExpansionWorker {
4142
FuriThread* thread;
@@ -361,6 +362,8 @@ static int32_t expansion_worker(void* context) {
361362
expansion_worker_state_machine(instance);
362363
}
363364

365+
furi_hal_serial_async_rx_stop(instance->serial_handle);
366+
364367
if(instance->state == ExpansionWorkerStateRpcActive) {
365368
expansion_worker_rpc_session_close(instance);
366369
}

targets/f7/furi_hal/furi_hal_serial.c

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -817,34 +817,39 @@ static void furi_hal_serial_async_rx_configure(
817817
FuriHalSerialHandle* handle,
818818
FuriHalSerialAsyncRxCallback callback,
819819
void* context) {
820+
// Disable RXFNE interrupts before unsetting the user callback that reads data
821+
// Otherwise interrupt runs without reading data and without clearing RXFNE flag
822+
// This would cause a system hang as the same interrupt runs in loop forever
823+
if(!callback) {
824+
if(handle->id == FuriHalSerialIdUsart) {
825+
LL_USART_DisableIT_RXNE_RXFNE(USART1);
826+
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
827+
furi_hal_serial_usart_deinit_dma_rx();
828+
} else if(handle->id == FuriHalSerialIdLpuart) {
829+
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
830+
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
831+
furi_hal_serial_lpuart_deinit_dma_rx();
832+
}
833+
}
834+
820835
// Handle must be configured before enabling RX interrupt
821836
// as it might be triggered right away on a misconfigured handle
822837
furi_hal_serial[handle->id].rx_byte_callback = callback;
823838
furi_hal_serial[handle->id].handle = handle;
824839
furi_hal_serial[handle->id].rx_dma_callback = NULL;
825840
furi_hal_serial[handle->id].context = context;
826841

827-
if(handle->id == FuriHalSerialIdUsart) {
828-
if(callback) {
842+
if(callback) {
843+
if(handle->id == FuriHalSerialIdUsart) {
829844
furi_hal_serial_usart_deinit_dma_rx();
830845
furi_hal_interrupt_set_isr(
831846
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
832847
LL_USART_EnableIT_RXNE_RXFNE(USART1);
833-
} else {
834-
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
835-
furi_hal_serial_usart_deinit_dma_rx();
836-
LL_USART_DisableIT_RXNE_RXFNE(USART1);
837-
}
838-
} else if(handle->id == FuriHalSerialIdLpuart) {
839-
if(callback) {
848+
} else if(handle->id == FuriHalSerialIdLpuart) {
840849
furi_hal_serial_lpuart_deinit_dma_rx();
841850
furi_hal_interrupt_set_isr(
842851
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
843852
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
844-
} else {
845-
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
846-
furi_hal_serial_lpuart_deinit_dma_rx();
847-
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
848853
}
849854
}
850855
}
@@ -944,33 +949,39 @@ static void furi_hal_serial_dma_configure(
944949
FuriHalSerialHandle* handle,
945950
FuriHalSerialDmaRxCallback callback,
946951
void* context) {
947-
furi_check(handle);
948-
949-
if(handle->id == FuriHalSerialIdUsart) {
950-
if(callback) {
951-
furi_hal_serial_usart_init_dma_rx();
952-
furi_hal_interrupt_set_isr(
953-
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
954-
} else {
952+
// Disable RXFNE interrupts before unsetting the user callback that reads data
953+
// Otherwise interrupt runs without reading data and without clearing RXFNE flag
954+
// This would cause a system hang as the same interrupt runs in loop forever
955+
if(!callback) {
956+
if(handle->id == FuriHalSerialIdUsart) {
955957
LL_USART_DisableIT_RXNE_RXFNE(USART1);
956958
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
957959
furi_hal_serial_usart_deinit_dma_rx();
958-
}
959-
} else if(handle->id == FuriHalSerialIdLpuart) {
960-
if(callback) {
961-
furi_hal_serial_lpuart_init_dma_rx();
962-
furi_hal_interrupt_set_isr(
963-
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
964-
} else {
960+
} else if(handle->id == FuriHalSerialIdLpuart) {
965961
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
966962
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
967963
furi_hal_serial_lpuart_deinit_dma_rx();
968964
}
969965
}
966+
967+
// Handle must be configured before enabling RX interrupt
968+
// as it might be triggered right away on a misconfigured handle
970969
furi_hal_serial[handle->id].rx_byte_callback = NULL;
971970
furi_hal_serial[handle->id].handle = handle;
972971
furi_hal_serial[handle->id].rx_dma_callback = callback;
973972
furi_hal_serial[handle->id].context = context;
973+
974+
if(callback) {
975+
if(handle->id == FuriHalSerialIdUsart) {
976+
furi_hal_serial_usart_init_dma_rx();
977+
furi_hal_interrupt_set_isr(
978+
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
979+
} else if(handle->id == FuriHalSerialIdLpuart) {
980+
furi_hal_serial_lpuart_init_dma_rx();
981+
furi_hal_interrupt_set_isr(
982+
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
983+
}
984+
}
974985
}
975986

976987
void furi_hal_serial_dma_rx_start(

0 commit comments

Comments
 (0)