mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
[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:
@@ -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);
|
||||
|
||||
@@ -16,7 +16,9 @@ extern "C" {
|
||||
|
||||
/** Initialize Serial
|
||||
*
|
||||
* Configures GPIO, configures and enables transceiver.
|
||||
* Configures GPIO, configures and enables transceiver. Default framing settings
|
||||
* are used: 8 data bits, no parity, 1 stop bit. Override them with
|
||||
* `furi_hal_serial_configure_framing`.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param baud baud rate
|
||||
@@ -64,6 +66,20 @@ bool furi_hal_serial_is_baud_rate_supported(FuriHalSerialHandle* handle, uint32_
|
||||
*/
|
||||
void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud);
|
||||
|
||||
/**
|
||||
* @brief Configures framing of a serial interface
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param data_bits Data bits
|
||||
* @param parity Parity
|
||||
* @param stop_bits Stop bits
|
||||
*/
|
||||
void furi_hal_serial_configure_framing(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDataBits data_bits,
|
||||
FuriHalSerialParity parity,
|
||||
FuriHalSerialStopBits stop_bits);
|
||||
|
||||
/** Transmits data in semi-blocking mode
|
||||
*
|
||||
* Fills transmission pipe with data, returns as soon as all bytes from buffer
|
||||
@@ -93,6 +109,7 @@ typedef enum {
|
||||
FuriHalSerialRxEventFrameError = (1 << 2), /**< Framing Error: incorrect frame detected */
|
||||
FuriHalSerialRxEventNoiseError = (1 << 3), /**< Noise Error: noise on the line detected */
|
||||
FuriHalSerialRxEventOverrunError = (1 << 4), /**< Overrun Error: no space for received data */
|
||||
FuriHalSerialRxEventParityError = (1 << 5), /**< Parity Error: incorrect parity bit received */
|
||||
} FuriHalSerialRxEvent;
|
||||
|
||||
/** Receive callback
|
||||
@@ -172,7 +189,7 @@ typedef void (*FuriHalSerialDmaRxCallback)(
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* @brief Enable an input/output directon
|
||||
* @brief Enable an input/output direction
|
||||
*
|
||||
* Takes over the respective pin by reconfiguring it to
|
||||
* the appropriate alternative function.
|
||||
@@ -185,7 +202,7 @@ void furi_hal_serial_enable_direction(
|
||||
FuriHalSerialDirection direction);
|
||||
|
||||
/**
|
||||
* @brief Disable an input/output directon
|
||||
* @brief Disable an input/output direction
|
||||
*
|
||||
* Releases the respective pin by reconfiguring it to
|
||||
* initial state, making possible its use for other purposes.
|
||||
|
||||
@@ -19,4 +19,39 @@ typedef enum {
|
||||
FuriHalSerialDirectionMax,
|
||||
} FuriHalSerialDirection;
|
||||
|
||||
/**
|
||||
* @brief Actual data bits, i.e. not including start/stop and parity bits
|
||||
* @note 6 data bits are only permitted when parity is enabled
|
||||
* @note 9 data bits are only permitted when parity is disabled
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalSerialDataBits6,
|
||||
FuriHalSerialDataBits7,
|
||||
FuriHalSerialDataBits8,
|
||||
FuriHalSerialDataBits9,
|
||||
|
||||
FuriHalSerialDataBitsMax,
|
||||
} FuriHalSerialDataBits;
|
||||
|
||||
typedef enum {
|
||||
FuriHalSerialParityNone,
|
||||
FuriHalSerialParityEven,
|
||||
FuriHalSerialParityOdd,
|
||||
|
||||
FuriHalSerialParityMax,
|
||||
} FuriHalSerialParity;
|
||||
|
||||
/**
|
||||
* @brief Stop bit length
|
||||
* @note LPUART only supports whole stop bit lengths (i.e. 1 and 2, but not 0.5 and 1.5)
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalSerialStopBits0_5,
|
||||
FuriHalSerialStopBits1,
|
||||
FuriHalSerialStopBits1_5,
|
||||
FuriHalSerialStopBits2,
|
||||
|
||||
FuriHalSerialStopBits2Max,
|
||||
} FuriHalSerialStopBits;
|
||||
|
||||
typedef struct FuriHalSerialHandle FuriHalSerialHandle;
|
||||
|
||||
Reference in New Issue
Block a user