[FL-3734] UART framing mode selection (#4121)

* HAL: feat: uart framing
* JS: feat: uart framing
* fix formatting
* fix pvs warning
* HAL: flash impact reduction attempt 1
* HAL: flash impact reduction attempt 2
* fix compile error
* HAL: finalize flash impact reduction
* HAL: remove user-facing magic numbers

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
Anna Antonenko
2025-02-20 23:54:38 +04:00
committed by GitHub
parent 290a6dc1eb
commit 7c5c5d4749
15 changed files with 404 additions and 108 deletions

View File

@@ -120,7 +120,7 @@ static void furi_hal_serial_usart_irq_callback(void* context) {
}
if(USART1->ISR & USART_ISR_PE) {
USART1->ICR = USART_ICR_PECF;
event |= FuriHalSerialRxEventFrameError;
event |= FuriHalSerialRxEventParityError;
}
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr == NULL) {
@@ -321,7 +321,7 @@ static void furi_hal_serial_lpuart_irq_callback(void* context) {
}
if(LPUART1->ISR & USART_ISR_PE) {
LPUART1->ICR = USART_ICR_PECF;
event |= FuriHalSerialRxEventFrameError;
event |= FuriHalSerialRxEventParityError;
}
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr == NULL) {
@@ -605,6 +605,92 @@ void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud) {
}
}
// Avoid duplicating look-up tables between USART and LPUART
static_assert(LL_LPUART_DATAWIDTH_7B == LL_USART_DATAWIDTH_7B);
static_assert(LL_LPUART_DATAWIDTH_8B == LL_USART_DATAWIDTH_8B);
static_assert(LL_LPUART_DATAWIDTH_9B == LL_USART_DATAWIDTH_9B);
static_assert(LL_LPUART_PARITY_NONE == LL_USART_PARITY_NONE);
static_assert(LL_LPUART_PARITY_EVEN == LL_USART_PARITY_EVEN);
static_assert(LL_LPUART_PARITY_ODD == LL_USART_PARITY_ODD);
static_assert(LL_LPUART_STOPBITS_1 == LL_USART_STOPBITS_1);
static_assert(LL_LPUART_STOPBITS_2 == LL_USART_STOPBITS_2);
static const uint32_t serial_data_bits_lut[] = {
[FuriHalSerialDataBits7] = LL_USART_DATAWIDTH_7B,
[FuriHalSerialDataBits8] = LL_USART_DATAWIDTH_8B,
[FuriHalSerialDataBits9] = LL_USART_DATAWIDTH_9B,
};
static const uint32_t serial_parity_lut[] = {
[FuriHalSerialParityNone] = LL_USART_PARITY_NONE,
[FuriHalSerialParityEven] = LL_USART_PARITY_EVEN,
[FuriHalSerialParityOdd] = LL_USART_PARITY_ODD,
};
static const uint32_t serial_stop_bits_lut[] = {
[FuriHalSerialStopBits0_5] = LL_USART_STOPBITS_0_5,
[FuriHalSerialStopBits1] = LL_USART_STOPBITS_1,
[FuriHalSerialStopBits1_5] = LL_USART_STOPBITS_1_5,
[FuriHalSerialStopBits2] = LL_USART_STOPBITS_2,
};
static void furi_hal_serial_usart_configure_framing(
FuriHalSerialDataBits data_bits,
FuriHalSerialParity parity,
FuriHalSerialStopBits stop_bits) {
LL_USART_SetDataWidth(USART1, serial_data_bits_lut[data_bits]);
LL_USART_SetParity(USART1, serial_parity_lut[parity]);
LL_USART_SetStopBitsLength(USART1, serial_stop_bits_lut[stop_bits]);
}
static void furi_hal_serial_lpuart_configure_framing(
FuriHalSerialDataBits data_bits,
FuriHalSerialParity parity,
FuriHalSerialStopBits stop_bits) {
LL_LPUART_SetDataWidth(LPUART1, serial_data_bits_lut[data_bits]);
LL_LPUART_SetParity(LPUART1, serial_parity_lut[parity]);
// Unsupported non-whole stop bit numbers have been furi_check'ed away
LL_LPUART_SetStopBitsLength(LPUART1, serial_stop_bits_lut[stop_bits]);
}
void furi_hal_serial_configure_framing(
FuriHalSerialHandle* handle,
FuriHalSerialDataBits data_bits,
FuriHalSerialParity parity,
FuriHalSerialStopBits stop_bits) {
furi_check(handle);
// Unsupported combinations
if(data_bits == FuriHalSerialDataBits9) furi_check(parity == FuriHalSerialParityNone);
if(data_bits == FuriHalSerialDataBits6) furi_check(parity != FuriHalSerialParityNone);
// Extend data word to account for parity bit
if(parity != FuriHalSerialParityNone) data_bits++;
if(handle->id == FuriHalSerialIdUsart) {
if(LL_USART_IsEnabled(USART1)) {
// Wait for transfer complete flag
while(!LL_USART_IsActiveFlag_TC(USART1))
;
LL_USART_Disable(USART1);
furi_hal_serial_usart_configure_framing(data_bits, parity, stop_bits);
LL_USART_Enable(USART1);
}
} else if(handle->id == FuriHalSerialIdLpuart) {
// Unsupported configurations
furi_check(stop_bits == FuriHalSerialStopBits1 || stop_bits == FuriHalSerialStopBits2);
if(LL_LPUART_IsEnabled(LPUART1)) {
// Wait for transfer complete flag
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
;
LL_LPUART_Disable(LPUART1);
furi_hal_serial_lpuart_configure_framing(data_bits, parity, stop_bits);
LL_LPUART_Enable(LPUART1);
}
}
}
void furi_hal_serial_deinit(FuriHalSerialHandle* handle) {
furi_check(handle);
furi_hal_serial_async_rx_configure(handle, NULL, NULL);