Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Minaylov <nm29719@gmail.com>2021-10-26 21:41:56 +0300
committerGitHub <noreply@github.com>2021-10-26 21:41:56 +0300
commit732b9546fc29d0eee07d2230e52d035b32b89c81 (patch)
tree1d4bb55c0a670e351ed097a9db92684dbc40d600 /firmware
parentfae8d8f23ceb971cb08119d0dc8de48a06091a13 (diff)
[FL-1984] USB-UART improvements and fixes (#785)
* [FL-1984] USB-UART fixes * FuriHal: fix SOF wait on CDC0 * FuriHal: fixed stuck in UART IRQ with ORE event Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'firmware')
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-clock.c2
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-console.c99
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-console.h16
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-lpuart.c105
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-lpuart.h24
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-uart.c201
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-uart.h29
-rw-r--r--firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c10
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-clock.c2
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-console.c99
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-console.h16
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-lpuart.c105
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-lpuart.h24
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-uart.c197
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-uart.h29
-rw-r--r--firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c10
-rw-r--r--firmware/targets/furi-hal-include/furi-hal.h2
17 files changed, 503 insertions, 467 deletions
diff --git a/firmware/targets/f6/furi-hal/furi-hal-clock.c b/firmware/targets/f6/furi-hal/furi-hal-clock.c
index 2544c769..fd4899d4 100644
--- a/firmware/targets/f6/furi-hal/furi-hal-clock.c
+++ b/firmware/targets/f6/furi-hal/furi-hal-clock.c
@@ -84,6 +84,7 @@ void furi_hal_clock_init() {
LL_RCC_EnableRTC();
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
+ LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
@@ -117,6 +118,7 @@ void furi_hal_clock_init() {
// APB1
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
+ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
// APB2
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.c b/firmware/targets/f6/furi-hal/furi-hal-console.c
index 552f9e77..ffe340b9 100644
--- a/firmware/targets/f6/furi-hal/furi-hal-console.c
+++ b/firmware/targets/f6/furi-hal/furi-hal-console.c
@@ -1,5 +1,5 @@
#include <furi-hal-console.h>
-#include <furi-hal-lpuart.h>
+#include <furi-hal-uart.h>
#include <stdbool.h>
#include <stm32wbxx_ll_gpio.h>
@@ -12,98 +12,23 @@
volatile bool furi_hal_console_alive = false;
-static void (*irq_cb)(uint8_t ev, uint8_t data);
-
void furi_hal_console_init() {
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
- LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- LL_USART_InitTypeDef USART_InitStruct = {0};
- USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
- USART_InitStruct.BaudRate = CONSOLE_BAUDRATE;
- USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
- USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
- USART_InitStruct.Parity = LL_USART_PARITY_NONE;
- USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
- USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
- USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
- LL_USART_Init(USART1, &USART_InitStruct);
- LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
- LL_USART_EnableFIFO(USART1);
- LL_USART_ConfigAsyncMode(USART1);
-
- LL_USART_Enable(USART1);
-
- while(!LL_USART_IsActiveFlag_TEACK(USART1)) ;
-
- LL_USART_EnableIT_RXNE_RXFNE(USART1);
- LL_USART_EnableIT_IDLE(USART1);
- HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
-
+ furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
furi_hal_console_alive = true;
FURI_LOG_I("FuriHalConsole", "Init OK");
}
-void furi_hal_usart_init() {
- furi_hal_console_alive = false;
-}
-
-void furi_hal_usart_set_br(uint32_t baud) {
- if (LL_USART_IsEnabled(USART1)) {
- // Wait for transfer complete flag
- while (!LL_USART_IsActiveFlag_TC(USART1));
- LL_USART_Disable(USART1);
- uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
- LL_USART_SetBaudRate(USART1, uartclk, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baud);
- LL_USART_Enable(USART1);
- }
-}
-
-void furi_hal_usart_deinit() {
+void furi_hal_console_enable() {
+ furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL);
while (!LL_USART_IsActiveFlag_TC(USART1));
- furi_hal_usart_set_br(CONSOLE_BAUDRATE);
+ furi_hal_uart_set_br(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
furi_hal_console_alive = true;
}
-void furi_hal_usart_tx(const uint8_t* buffer, size_t buffer_size) {
- if (LL_USART_IsEnabled(USART1) == 0)
- return;
-
- while(buffer_size > 0) {
- while (!LL_USART_IsActiveFlag_TXE(USART1));
-
- LL_USART_TransmitData8(USART1, *buffer);
-
- buffer++;
- buffer_size--;
- }
-}
-
-void furi_hal_usart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data)) {
- irq_cb = cb;
- if (irq_cb == NULL)
- NVIC_DisableIRQ(USART1_IRQn);
- else
- NVIC_EnableIRQ(USART1_IRQn);
-}
-
-void USART1_IRQHandler(void) {
- if (LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
- uint8_t data = LL_USART_ReceiveData8(USART1);
- irq_cb(UartIrqEventRXNE, data);
- } else if (LL_USART_IsActiveFlag_IDLE(USART1)) {
- irq_cb(UartIrqEventIDLE, 0);
- LL_USART_ClearFlag_IDLE(USART1);
- }
-
- //TODO: more events
+void furi_hal_console_disable() {
+ while (!LL_USART_IsActiveFlag_TC(USART1));
+ furi_hal_console_alive = false;
}
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
@@ -111,7 +36,7 @@ void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
return;
// Transmit data
- furi_hal_usart_tx(buffer, buffer_size);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
// Wait for TC flag to be raised for last char
while (!LL_USART_IsActiveFlag_TC(USART1));
}
@@ -121,9 +46,9 @@ void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size
return;
// Transmit data
- furi_hal_usart_tx(buffer, buffer_size);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
// Transmit new line symbols
- furi_hal_usart_tx((const uint8_t*)"\r\n", 2);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)"\r\n", 2);
// Wait for TC flag to be raised for last char
while (!LL_USART_IsActiveFlag_TC(USART1));
}
@@ -140,4 +65,4 @@ void furi_hal_console_printf(const char format[], ...) {
void furi_hal_console_puts(const char *data) {
furi_hal_console_tx((const uint8_t*)data, strlen(data));
-} \ No newline at end of file
+}
diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.h b/firmware/targets/f6/furi-hal/furi-hal-console.h
index 013653ba..4c10d81e 100644
--- a/firmware/targets/f6/furi-hal/furi-hal-console.h
+++ b/firmware/targets/f6/furi-hal/furi-hal-console.h
@@ -15,6 +15,10 @@ typedef enum {
void furi_hal_console_init();
+void furi_hal_console_enable();
+
+void furi_hal_console_disable();
+
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size);
void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size);
@@ -29,18 +33,6 @@ void furi_hal_console_printf(const char format[], ...);
void furi_hal_console_puts(const char* data);
-
-void furi_hal_usart_init();
-
-void furi_hal_usart_deinit();
-
-void furi_hal_usart_set_br(uint32_t baud);
-
-void furi_hal_usart_tx(const uint8_t* buffer, size_t buffer_size);
-
-void furi_hal_usart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data));
-
-
#ifdef __cplusplus
}
#endif
diff --git a/firmware/targets/f6/furi-hal/furi-hal-lpuart.c b/firmware/targets/f6/furi-hal/furi-hal-lpuart.c
deleted file mode 100644
index 31aa8b86..00000000
--- a/firmware/targets/f6/furi-hal/furi-hal-lpuart.c
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <furi-hal-lpuart.h>
-#include <stdbool.h>
-#include <stm32wbxx_ll_gpio.h>
-#include <stm32wbxx_ll_lpuart.h>
-
-#include <furi.h>
-
-static void (*irq_cb)(uint8_t ev, uint8_t data);
-
-void furi_hal_lpuart_init() {
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = PC0_Pin|PC1_Pin;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
- LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
-
- LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
- LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
- LPUART_InitStruct.BaudRate = 115200;
- LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
- LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
- LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
- LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
- LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
- LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
- LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
- LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
- LL_LPUART_EnableFIFO(LPUART1);
-
- LL_LPUART_Enable(LPUART1);
-
- while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))));
-
- LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
- LL_LPUART_EnableIT_IDLE(LPUART1);
- HAL_NVIC_SetPriority(LPUART1_IRQn, 5, 0);
-
- FURI_LOG_I("FuriHalLpUart", "Init OK");
-}
-
-void furi_hal_lpuart_set_br(uint32_t baud) {
- if (LL_LPUART_IsEnabled(LPUART1)) {
- // Wait for transfer complete flag
- while (!LL_LPUART_IsActiveFlag_TC(LPUART1));
- LL_LPUART_Disable(LPUART1);
- uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_GetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1));
- if (uartclk/baud > 4095) {
- LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV32);
- LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV32, baud);
- } else {
- LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);
- LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV1, baud);
- }
-
- LL_LPUART_Enable(LPUART1);
- }
-}
-
-void furi_hal_lpuart_deinit() {
- furi_hal_lpuart_set_irq_cb(NULL);
- LL_GPIO_SetPinMode(GPIOC, PC0_Pin, LL_GPIO_MODE_ANALOG);
- LL_GPIO_SetPinMode(GPIOC, PC1_Pin, LL_GPIO_MODE_ANALOG);
- LL_LPUART_Disable(LPUART1);
- LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_LPUART1);
-}
-
-void furi_hal_lpuart_tx(const uint8_t* buffer, size_t buffer_size) {
- if (LL_LPUART_IsEnabled(LPUART1) == 0)
- return;
-
- while(buffer_size > 0) {
- while (!LL_LPUART_IsActiveFlag_TXE(LPUART1));
-
- LL_LPUART_TransmitData8(LPUART1, *buffer);
-
- buffer++;
- buffer_size--;
- }
-}
-
-void furi_hal_lpuart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data)) {
- irq_cb = cb;
- if (irq_cb == NULL)
- NVIC_DisableIRQ(LPUART1_IRQn);
- else
- NVIC_EnableIRQ(LPUART1_IRQn);
-}
-
-void LPUART1_IRQHandler(void) {
- if (LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
- uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
- irq_cb(UartIrqEventRXNE, data);
- } else if (LL_LPUART_IsActiveFlag_IDLE(LPUART1)) {
- irq_cb(UartIrqEventIDLE, 0);
- LL_LPUART_ClearFlag_IDLE(LPUART1);
- }
-
- //TODO: more events
-}
diff --git a/firmware/targets/f6/furi-hal/furi-hal-lpuart.h b/firmware/targets/f6/furi-hal/furi-hal-lpuart.h
deleted file mode 100644
index 118a9a9c..00000000
--- a/firmware/targets/f6/furi-hal/furi-hal-lpuart.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include "furi-hal-console.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-void furi_hal_lpuart_init();
-
-void furi_hal_lpuart_deinit();
-
-void furi_hal_lpuart_set_br(uint32_t baud);
-
-void furi_hal_lpuart_tx(const uint8_t* buffer, size_t buffer_size);
-
-void furi_hal_lpuart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data));
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/firmware/targets/f6/furi-hal/furi-hal-uart.c b/firmware/targets/f6/furi-hal/furi-hal-uart.c
new file mode 100644
index 00000000..ff2d94a7
--- /dev/null
+++ b/firmware/targets/f6/furi-hal/furi-hal-uart.c
@@ -0,0 +1,201 @@
+#include <furi-hal-uart.h>
+#include <stdbool.h>
+#include <stm32wbxx_ll_lpuart.h>
+#include <stm32wbxx_ll_usart.h>
+#include <furi-hal-resources.h>
+
+#include <furi.h>
+
+static void (*irq_cb[2])(uint8_t ev, uint8_t data);
+
+static void furi_hal_usart_init(uint32_t baud) {
+ hal_gpio_init_ex(
+ &gpio_usart_tx,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn7USART1);
+ hal_gpio_init_ex(
+ &gpio_usart_rx,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn7USART1);
+
+ LL_USART_InitTypeDef USART_InitStruct = {0};
+ USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
+ USART_InitStruct.BaudRate = baud;
+ USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
+ USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
+ USART_InitStruct.Parity = LL_USART_PARITY_NONE;
+ USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
+ USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
+ USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
+ LL_USART_Init(USART1, &USART_InitStruct);
+ LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
+ LL_USART_EnableFIFO(USART1);
+ LL_USART_ConfigAsyncMode(USART1);
+
+ LL_USART_Enable(USART1);
+
+ while(!LL_USART_IsActiveFlag_TEACK(USART1));
+
+ LL_USART_EnableIT_RXNE_RXFNE(USART1);
+ LL_USART_EnableIT_IDLE(USART1);
+ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
+}
+
+static void furi_hal_lpuart_init(uint32_t baud) {
+ hal_gpio_init_ex(
+ &gpio_ext_pc0,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn8LPUART1);
+ hal_gpio_init_ex(
+ &gpio_ext_pc1,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn8LPUART1);
+
+ LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
+ LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
+ LPUART_InitStruct.BaudRate = 115200;
+ LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
+ LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
+ LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
+ LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
+ LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
+ LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
+ LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
+ LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
+ LL_LPUART_EnableFIFO(LPUART1);
+
+ LL_LPUART_Enable(LPUART1);
+
+ while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))));
+
+ furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
+
+ LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
+ LL_LPUART_EnableIT_IDLE(LPUART1);
+ HAL_NVIC_SetPriority(LPUART1_IRQn, 5, 0);
+}
+
+void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud) {
+ if (ch == FuriHalUartIdLPUART1)
+ furi_hal_lpuart_init(baud);
+ else if (ch == FuriHalUartIdUSART1)
+ furi_hal_usart_init(baud);
+}
+
+void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
+ if (ch == FuriHalUartIdUSART1) {
+ if (LL_USART_IsEnabled(USART1)) {
+ // Wait for transfer complete flag
+ while (!LL_USART_IsActiveFlag_TC(USART1));
+ LL_USART_Disable(USART1);
+ uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
+ LL_USART_SetBaudRate(USART1, uartclk, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baud);
+ LL_USART_Enable(USART1);
+ }
+ } else if (ch == FuriHalUartIdLPUART1) {
+ if (LL_LPUART_IsEnabled(LPUART1)) {
+ // Wait for transfer complete flag
+ while (!LL_LPUART_IsActiveFlag_TC(LPUART1));
+ LL_LPUART_Disable(LPUART1);
+ uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_GetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1));
+ if (uartclk/baud > 4095) {
+ LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV32);
+ LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV32, baud);
+ } else {
+ LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);
+ LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV1, baud);
+ }
+ LL_LPUART_Enable(LPUART1);
+ }
+ }
+}
+
+void furi_hal_uart_deinit(FuriHalUartId ch) {
+ furi_hal_uart_set_irq_cb(ch, NULL);
+ if (ch == FuriHalUartIdUSART1) {
+ LL_USART_Disable(USART1);
+ hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ } else if (ch == FuriHalUartIdLPUART1) {
+ LL_LPUART_Disable(LPUART1);
+ hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ }
+}
+
+void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) {
+ if (ch == FuriHalUartIdUSART1) {
+ if (LL_USART_IsEnabled(USART1) == 0)
+ return;
+
+ while(buffer_size > 0) {
+ while (!LL_USART_IsActiveFlag_TXE(USART1));
+
+ LL_USART_TransmitData8(USART1, *buffer);
+ buffer++;
+ buffer_size--;
+ }
+
+ } else if (ch == FuriHalUartIdLPUART1) {
+ if (LL_LPUART_IsEnabled(LPUART1) == 0)
+ return;
+
+ while(buffer_size > 0) {
+ while (!LL_LPUART_IsActiveFlag_TXE(LPUART1));
+
+ LL_LPUART_TransmitData8(LPUART1, *buffer);
+
+ buffer++;
+ buffer_size--;
+ }
+ }
+}
+
+void furi_hal_uart_set_irq_cb(FuriHalUartId ch, void (*cb)(UartIrqEvent ev, uint8_t data)) {
+ if (cb == NULL) {
+ if (ch == FuriHalUartIdUSART1)
+ NVIC_DisableIRQ(USART1_IRQn);
+ else if (ch == FuriHalUartIdLPUART1)
+ NVIC_DisableIRQ(LPUART1_IRQn);
+ irq_cb[ch] = cb;
+ } else {
+ irq_cb[ch] = cb;
+ if (ch == FuriHalUartIdUSART1)
+ NVIC_EnableIRQ(USART1_IRQn);
+ else if (ch == FuriHalUartIdLPUART1)
+ NVIC_EnableIRQ(LPUART1_IRQn);
+ }
+}
+
+void LPUART1_IRQHandler(void) {
+ if (LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
+ uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
+ irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data);
+ } else if (LL_LPUART_IsActiveFlag_IDLE(LPUART1)) {
+ irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0);
+ LL_LPUART_ClearFlag_IDLE(LPUART1);
+ } else if (LL_LPUART_IsActiveFlag_ORE(LPUART1)) {
+ LL_LPUART_ClearFlag_ORE(LPUART1);
+ }
+ //TODO: more events
+}
+
+void USART1_IRQHandler(void) {
+ if (LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
+ uint8_t data = LL_USART_ReceiveData8(USART1);
+ irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data);
+ } else if (LL_USART_IsActiveFlag_IDLE(USART1)) {
+ irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0);
+ LL_USART_ClearFlag_IDLE(USART1);
+ } else if (LL_USART_IsActiveFlag_ORE(USART1)) {
+ LL_USART_ClearFlag_ORE(USART1);
+ }
+}
diff --git a/firmware/targets/f6/furi-hal/furi-hal-uart.h b/firmware/targets/f6/furi-hal/furi-hal-uart.h
new file mode 100644
index 00000000..6be156b7
--- /dev/null
+++ b/firmware/targets/f6/furi-hal/furi-hal-uart.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include "furi-hal-console.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ FuriHalUartIdUSART1,
+ FuriHalUartIdLPUART1,
+} FuriHalUartId;
+
+
+void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud);
+
+void furi_hal_uart_deinit(FuriHalUartId ch);
+
+void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud);
+
+void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size);
+
+void furi_hal_uart_set_irq_cb(FuriHalUartId ch, void (*cb)(UartIrqEvent ev, uint8_t data));
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c
index e643fe57..9386b100 100644
--- a/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c
+++ b/firmware/targets/f6/furi-hal/furi-hal-usb-cdc.c
@@ -7,12 +7,12 @@
#include "usb_cdc.h"
#define CDC0_RXD_EP 0x01
-#define CDC0_TXD_EP 0x82
-#define CDC0_NTF_EP 0x83
+#define CDC0_TXD_EP 0x81
+#define CDC0_NTF_EP 0x82
-#define CDC1_RXD_EP 0x04
-#define CDC1_TXD_EP 0x85
-#define CDC1_NTF_EP 0x86
+#define CDC1_RXD_EP 0x03
+#define CDC1_TXD_EP 0x83
+#define CDC1_NTF_EP 0x84
#define CDC_NTF_SZ 0x08
diff --git a/firmware/targets/f7/furi-hal/furi-hal-clock.c b/firmware/targets/f7/furi-hal/furi-hal-clock.c
index 2544c769..fd4899d4 100644
--- a/firmware/targets/f7/furi-hal/furi-hal-clock.c
+++ b/firmware/targets/f7/furi-hal/furi-hal-clock.c
@@ -84,6 +84,7 @@ void furi_hal_clock_init() {
LL_RCC_EnableRTC();
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
+ LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
@@ -117,6 +118,7 @@ void furi_hal_clock_init() {
// APB1
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
+ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
// APB2
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
diff --git a/firmware/targets/f7/furi-hal/furi-hal-console.c b/firmware/targets/f7/furi-hal/furi-hal-console.c
index 552f9e77..ffe340b9 100644
--- a/firmware/targets/f7/furi-hal/furi-hal-console.c
+++ b/firmware/targets/f7/furi-hal/furi-hal-console.c
@@ -1,5 +1,5 @@
#include <furi-hal-console.h>
-#include <furi-hal-lpuart.h>
+#include <furi-hal-uart.h>
#include <stdbool.h>
#include <stm32wbxx_ll_gpio.h>
@@ -12,98 +12,23 @@
volatile bool furi_hal_console_alive = false;
-static void (*irq_cb)(uint8_t ev, uint8_t data);
-
void furi_hal_console_init() {
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
- LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
-
- LL_USART_InitTypeDef USART_InitStruct = {0};
- USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
- USART_InitStruct.BaudRate = CONSOLE_BAUDRATE;
- USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
- USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
- USART_InitStruct.Parity = LL_USART_PARITY_NONE;
- USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
- USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
- USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
- LL_USART_Init(USART1, &USART_InitStruct);
- LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
- LL_USART_EnableFIFO(USART1);
- LL_USART_ConfigAsyncMode(USART1);
-
- LL_USART_Enable(USART1);
-
- while(!LL_USART_IsActiveFlag_TEACK(USART1)) ;
-
- LL_USART_EnableIT_RXNE_RXFNE(USART1);
- LL_USART_EnableIT_IDLE(USART1);
- HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
-
+ furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
furi_hal_console_alive = true;
FURI_LOG_I("FuriHalConsole", "Init OK");
}
-void furi_hal_usart_init() {
- furi_hal_console_alive = false;
-}
-
-void furi_hal_usart_set_br(uint32_t baud) {
- if (LL_USART_IsEnabled(USART1)) {
- // Wait for transfer complete flag
- while (!LL_USART_IsActiveFlag_TC(USART1));
- LL_USART_Disable(USART1);
- uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
- LL_USART_SetBaudRate(USART1, uartclk, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baud);
- LL_USART_Enable(USART1);
- }
-}
-
-void furi_hal_usart_deinit() {
+void furi_hal_console_enable() {
+ furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL);
while (!LL_USART_IsActiveFlag_TC(USART1));
- furi_hal_usart_set_br(CONSOLE_BAUDRATE);
+ furi_hal_uart_set_br(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
furi_hal_console_alive = true;
}
-void furi_hal_usart_tx(const uint8_t* buffer, size_t buffer_size) {
- if (LL_USART_IsEnabled(USART1) == 0)
- return;
-
- while(buffer_size > 0) {
- while (!LL_USART_IsActiveFlag_TXE(USART1));
-
- LL_USART_TransmitData8(USART1, *buffer);
-
- buffer++;
- buffer_size--;
- }
-}
-
-void furi_hal_usart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data)) {
- irq_cb = cb;
- if (irq_cb == NULL)
- NVIC_DisableIRQ(USART1_IRQn);
- else
- NVIC_EnableIRQ(USART1_IRQn);
-}
-
-void USART1_IRQHandler(void) {
- if (LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
- uint8_t data = LL_USART_ReceiveData8(USART1);
- irq_cb(UartIrqEventRXNE, data);
- } else if (LL_USART_IsActiveFlag_IDLE(USART1)) {
- irq_cb(UartIrqEventIDLE, 0);
- LL_USART_ClearFlag_IDLE(USART1);
- }
-
- //TODO: more events
+void furi_hal_console_disable() {
+ while (!LL_USART_IsActiveFlag_TC(USART1));
+ furi_hal_console_alive = false;
}
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
@@ -111,7 +36,7 @@ void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
return;
// Transmit data
- furi_hal_usart_tx(buffer, buffer_size);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
// Wait for TC flag to be raised for last char
while (!LL_USART_IsActiveFlag_TC(USART1));
}
@@ -121,9 +46,9 @@ void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size
return;
// Transmit data
- furi_hal_usart_tx(buffer, buffer_size);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
// Transmit new line symbols
- furi_hal_usart_tx((const uint8_t*)"\r\n", 2);
+ furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)"\r\n", 2);
// Wait for TC flag to be raised for last char
while (!LL_USART_IsActiveFlag_TC(USART1));
}
@@ -140,4 +65,4 @@ void furi_hal_console_printf(const char format[], ...) {
void furi_hal_console_puts(const char *data) {
furi_hal_console_tx((const uint8_t*)data, strlen(data));
-} \ No newline at end of file
+}
diff --git a/firmware/targets/f7/furi-hal/furi-hal-console.h b/firmware/targets/f7/furi-hal/furi-hal-console.h
index 013653ba..4c10d81e 100644
--- a/firmware/targets/f7/furi-hal/furi-hal-console.h
+++ b/firmware/targets/f7/furi-hal/furi-hal-console.h
@@ -15,6 +15,10 @@ typedef enum {
void furi_hal_console_init();
+void furi_hal_console_enable();
+
+void furi_hal_console_disable();
+
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size);
void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size);
@@ -29,18 +33,6 @@ void furi_hal_console_printf(const char format[], ...);
void furi_hal_console_puts(const char* data);
-
-void furi_hal_usart_init();
-
-void furi_hal_usart_deinit();
-
-void furi_hal_usart_set_br(uint32_t baud);
-
-void furi_hal_usart_tx(const uint8_t* buffer, size_t buffer_size);
-
-void furi_hal_usart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data));
-
-
#ifdef __cplusplus
}
#endif
diff --git a/firmware/targets/f7/furi-hal/furi-hal-lpuart.c b/firmware/targets/f7/furi-hal/furi-hal-lpuart.c
deleted file mode 100644
index 31aa8b86..00000000
--- a/firmware/targets/f7/furi-hal/furi-hal-lpuart.c
+++ /dev/null
@@ -1,105 +0,0 @@
-#include <furi-hal-lpuart.h>
-#include <stdbool.h>
-#include <stm32wbxx_ll_gpio.h>
-#include <stm32wbxx_ll_lpuart.h>
-
-#include <furi.h>
-
-static void (*irq_cb)(uint8_t ev, uint8_t data);
-
-void furi_hal_lpuart_init() {
- LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
- GPIO_InitStruct.Pin = PC0_Pin|PC1_Pin;
- GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
- GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
- GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
- GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
- LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
- LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
-
- LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
- LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
- LPUART_InitStruct.BaudRate = 115200;
- LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
- LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
- LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
- LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
- LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
- LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
- LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
- LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
- LL_LPUART_EnableFIFO(LPUART1);
-
- LL_LPUART_Enable(LPUART1);
-
- while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))));
-
- LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
- LL_LPUART_EnableIT_IDLE(LPUART1);
- HAL_NVIC_SetPriority(LPUART1_IRQn, 5, 0);
-
- FURI_LOG_I("FuriHalLpUart", "Init OK");
-}
-
-void furi_hal_lpuart_set_br(uint32_t baud) {
- if (LL_LPUART_IsEnabled(LPUART1)) {
- // Wait for transfer complete flag
- while (!LL_LPUART_IsActiveFlag_TC(LPUART1));
- LL_LPUART_Disable(LPUART1);
- uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_GetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1));
- if (uartclk/baud > 4095) {
- LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV32);
- LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV32, baud);
- } else {
- LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);
- LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV1, baud);
- }
-
- LL_LPUART_Enable(LPUART1);
- }
-}
-
-void furi_hal_lpuart_deinit() {
- furi_hal_lpuart_set_irq_cb(NULL);
- LL_GPIO_SetPinMode(GPIOC, PC0_Pin, LL_GPIO_MODE_ANALOG);
- LL_GPIO_SetPinMode(GPIOC, PC1_Pin, LL_GPIO_MODE_ANALOG);
- LL_LPUART_Disable(LPUART1);
- LL_APB1_GRP2_DisableClock(LL_APB1_GRP2_PERIPH_LPUART1);
-}
-
-void furi_hal_lpuart_tx(const uint8_t* buffer, size_t buffer_size) {
- if (LL_LPUART_IsEnabled(LPUART1) == 0)
- return;
-
- while(buffer_size > 0) {
- while (!LL_LPUART_IsActiveFlag_TXE(LPUART1));
-
- LL_LPUART_TransmitData8(LPUART1, *buffer);
-
- buffer++;
- buffer_size--;
- }
-}
-
-void furi_hal_lpuart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data)) {
- irq_cb = cb;
- if (irq_cb == NULL)
- NVIC_DisableIRQ(LPUART1_IRQn);
- else
- NVIC_EnableIRQ(LPUART1_IRQn);
-}
-
-void LPUART1_IRQHandler(void) {
- if (LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
- uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
- irq_cb(UartIrqEventRXNE, data);
- } else if (LL_LPUART_IsActiveFlag_IDLE(LPUART1)) {
- irq_cb(UartIrqEventIDLE, 0);
- LL_LPUART_ClearFlag_IDLE(LPUART1);
- }
-
- //TODO: more events
-}
diff --git a/firmware/targets/f7/furi-hal/furi-hal-lpuart.h b/firmware/targets/f7/furi-hal/furi-hal-lpuart.h
deleted file mode 100644
index 118a9a9c..00000000
--- a/firmware/targets/f7/furi-hal/furi-hal-lpuart.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include "furi-hal-console.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-void furi_hal_lpuart_init();
-
-void furi_hal_lpuart_deinit();
-
-void furi_hal_lpuart_set_br(uint32_t baud);
-
-void furi_hal_lpuart_tx(const uint8_t* buffer, size_t buffer_size);
-
-void furi_hal_lpuart_set_irq_cb(void (*cb)(UartIrqEvent ev, uint8_t data));
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/firmware/targets/f7/furi-hal/furi-hal-uart.c b/firmware/targets/f7/furi-hal/furi-hal-uart.c
new file mode 100644
index 00000000..c6e74101
--- /dev/null
+++ b/firmware/targets/f7/furi-hal/furi-hal-uart.c
@@ -0,0 +1,197 @@
+#include <furi-hal-uart.h>
+#include <stdbool.h>
+#include <stm32wbxx_ll_lpuart.h>
+#include <stm32wbxx_ll_usart.h>
+#include <furi-hal-resources.h>
+
+#include <furi.h>
+
+static void (*irq_cb[2])(uint8_t ev, uint8_t data);
+
+static void furi_hal_usart_init(uint32_t baud) {
+ hal_gpio_init_ex(
+ &gpio_usart_tx,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn7USART1);
+ hal_gpio_init_ex(
+ &gpio_usart_rx,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn7USART1);
+
+ LL_USART_InitTypeDef USART_InitStruct = {0};
+ USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
+ USART_InitStruct.BaudRate = baud;
+ USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
+ USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
+ USART_InitStruct.Parity = LL_USART_PARITY_NONE;
+ USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
+ USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
+ USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
+ LL_USART_Init(USART1, &USART_InitStruct);
+ LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
+ LL_USART_EnableFIFO(USART1);
+ LL_USART_ConfigAsyncMode(USART1);
+
+ LL_USART_Enable(USART1);
+
+ while(!LL_USART_IsActiveFlag_TEACK(USART1));
+
+ LL_USART_EnableIT_RXNE_RXFNE(USART1);
+ LL_USART_EnableIT_IDLE(USART1);
+ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
+}
+
+static void furi_hal_lpuart_init(uint32_t baud) {
+ hal_gpio_init_ex(
+ &gpio_ext_pc0,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn8LPUART1);
+ hal_gpio_init_ex(
+ &gpio_ext_pc1,
+ GpioModeAltFunctionPushPull,
+ GpioPullUp,
+ GpioSpeedVeryHigh,
+ GpioAltFn8LPUART1);
+
+ LL_LPUART_InitTypeDef LPUART_InitStruct = {0};
+ LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
+ LPUART_InitStruct.BaudRate = 115200;
+ LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
+ LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
+ LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
+ LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
+ LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
+ LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
+ LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
+ LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
+ LL_LPUART_EnableFIFO(LPUART1);
+
+ LL_LPUART_Enable(LPUART1);
+
+ while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))));
+
+ furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
+
+ LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
+ LL_LPUART_EnableIT_IDLE(LPUART1);
+ HAL_NVIC_SetPriority(LPUART1_IRQn, 5, 0);
+}
+
+void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud) {
+ if (ch == FuriHalUartIdLPUART1)
+ furi_hal_lpuart_init(baud);
+ else if (ch == FuriHalUartIdUSART1)
+ furi_hal_usart_init(baud);
+}
+
+void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
+ if (ch == FuriHalUartIdUSART1) {
+ if (LL_USART_IsEnabled(USART1)) {
+ // Wait for transfer complete flag
+ while (!LL_USART_IsActiveFlag_TC(USART1));
+ LL_USART_Disable(USART1);
+ uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
+ LL_USART_SetBaudRate(USART1, uartclk, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baud);
+ LL_USART_Enable(USART1);
+ }
+ } else if (ch == FuriHalUartIdLPUART1) {
+ if (LL_LPUART_IsEnabled(LPUART1)) {
+ // Wait for transfer complete flag
+ while (!LL_LPUART_IsActiveFlag_TC(LPUART1));
+ LL_LPUART_Disable(LPUART1);
+ uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_GetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1));
+ if (uartclk/baud > 4095) {
+ LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV32);
+ LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV32, baud);
+ } else {
+ LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);
+ LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV1, baud);
+ }
+ LL_LPUART_Enable(LPUART1);
+ }
+ }
+}
+
+void furi_hal_uart_deinit(FuriHalUartId ch) {
+ furi_hal_uart_set_irq_cb(ch, NULL);
+ if (ch == FuriHalUartIdUSART1) {
+ LL_USART_Disable(USART1);
+ hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ } else if (ch == FuriHalUartIdLPUART1) {
+ LL_LPUART_Disable(LPUART1);
+ hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
+ }
+}
+
+void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) {
+ if (ch == FuriHalUartIdUSART1) {
+ if (LL_USART_IsEnabled(USART1) == 0)
+ return;
+
+ while(buffer_size > 0) {
+ while (!LL_USART_IsActiveFlag_TXE(USART1));
+
+ LL_USART_TransmitData8(USART1, *buffer);
+ buffer++;
+ buffer_size--;
+ }
+
+ } else if (ch == FuriHalUartIdLPUART1) {
+ if (LL_LPUART_IsEnabled(LPUART1) == 0)
+ return;
+
+ while(buffer_size > 0) {
+ while (!LL_LPUART_IsActiveFlag_TXE(LPUART1));
+
+ LL_LPUART_TransmitData8(LPUART1, *buffer);
+
+ buffer++;
+ buffer_size--;
+ }
+ }
+}
+
+void furi_hal_uart_set_irq_cb(FuriHalUartId ch, void (*cb)(UartIrqEvent ev, uint8_t data)) {
+ if (cb == NULL) {
+ if (ch == FuriHalUartIdUSART1)
+ NVIC_DisableIRQ(USART1_IRQn);
+ else if (ch == FuriHalUartIdLPUART1)
+ NVIC_DisableIRQ(LPUART1_IRQn);
+ irq_cb[ch] = cb;
+ } else {
+ irq_cb[ch] = cb;
+ if (ch == FuriHalUartIdUSART1)
+ NVIC_EnableIRQ(USART1_IRQn);
+ else if (ch == FuriHalUartIdLPUART1)
+ NVIC_EnableIRQ(LPUART1_IRQn);
+ }
+}
+
+void LPUART1_IRQHandler(void) {
+ if (LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
+ uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
+ irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data);
+ } else if (LL_LPUART_IsActiveFlag_IDLE(LPUART1)) {
+ irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0);
+ LL_LPUART_ClearFlag_IDLE(LPUART1);
+ }
+ //TODO: more events
+}
+
+void USART1_IRQHandler(void) {
+ if (LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
+ uint8_t data = LL_USART_ReceiveData8(USART1);
+ irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data);
+ } else if (LL_USART_IsActiveFlag_IDLE(USART1)) {
+ irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0);
+ LL_USART_ClearFlag_IDLE(USART1);
+ }
+}
diff --git a/firmware/targets/f7/furi-hal/furi-hal-uart.h b/firmware/targets/f7/furi-hal/furi-hal-uart.h
new file mode 100644
index 00000000..6be156b7
--- /dev/null
+++ b/firmware/targets/f7/furi-hal/furi-hal-uart.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include "furi-hal-console.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ FuriHalUartIdUSART1,
+ FuriHalUartIdLPUART1,
+} FuriHalUartId;
+
+
+void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud);
+
+void furi_hal_uart_deinit(FuriHalUartId ch);
+
+void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud);
+
+void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size);
+
+void furi_hal_uart_set_irq_cb(FuriHalUartId ch, void (*cb)(UartIrqEvent ev, uint8_t data));
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c
index e643fe57..9386b100 100644
--- a/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c
+++ b/firmware/targets/f7/furi-hal/furi-hal-usb-cdc.c
@@ -7,12 +7,12 @@
#include "usb_cdc.h"
#define CDC0_RXD_EP 0x01
-#define CDC0_TXD_EP 0x82
-#define CDC0_NTF_EP 0x83
+#define CDC0_TXD_EP 0x81
+#define CDC0_NTF_EP 0x82
-#define CDC1_RXD_EP 0x04
-#define CDC1_TXD_EP 0x85
-#define CDC1_NTF_EP 0x86
+#define CDC1_RXD_EP 0x03
+#define CDC1_TXD_EP 0x83
+#define CDC1_NTF_EP 0x84
#define CDC_NTF_SZ 0x08
diff --git a/firmware/targets/furi-hal-include/furi-hal.h b/firmware/targets/furi-hal-include/furi-hal.h
index 4ac95d82..eb1fefeb 100644
--- a/firmware/targets/furi-hal-include/furi-hal.h
+++ b/firmware/targets/furi-hal-include/furi-hal.h
@@ -36,7 +36,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
#include "furi-hal-usb.h"
#include "furi-hal-usb-hid.h"
#include "furi-hal-compress.h"
-#include "furi-hal-lpuart.h"
+#include "furi-hal-uart.h"
/** Init furi-hal */
void furi_hal_init();