[FL-3669] Expansion module protocol (#3250)

* ApiSymbols: add furi_record_destroy
* FuriHal: cleanup serial API, add logging configuration in RTC
* FuriHal: hide private part in _i header. Toolbox: cleanup value index. SystemSettings: logging device and baudrate.
* FuriHal: RTC logging method documentation
* Synchronize API Symbols
* Furi: mark HEAP_PRINT_DEBUG as broken
* FuriHal: furi_hal_serial, add custom IRQ func
* Fix PR review issues
* Implement basic external module detection and echo
* Update api symbols for f18
* Minimally working implementation (can create directory via rpc)
* Make expansion protocol parser a header-only library
* Rename a function
* Improve thread syncronisation
* Implement multi-packet transmissions
* Improve test application
* Clean up expansion worker code
* Send heartbeat when host is ready
* Update API symbols
* Add draft documentation
* Expansion worker: proper timeout and error handling
* Expansion worker: correct TX, do not disable expansion callback
* Expansion protocol: pc side test script
* PC side expansion test: trying to change baudrate
* Working comms between 2 flippers
* Cleaner exit from expansion worker thread
* Better checks
* Add debug logs
* Remove unneeded delays
* Use USART as default expansion port
* Refactor furi_hal_serial_control, fix crash
* Improve furi_hal abstraction, wait for stable rx pin
* Remove rogue include
* Set proper exit reason on RPC error
* Remove rogue comment
* Remove RX stability check as potentially problematic
* Improve expansion_test application
* Remove rogue define
* Give up on TODO
* Implement expansion protocol checksum support
* Update ExpansionModules.md
* RPC: reverse input
* Assets: sync protobuf
* Fix typos
* FuriHal: UART add reception DMA (#3220)
* FuriHal: add DMA serial rx mode
* usb_uart_bridge: switch to working with DMA
* Sync api symbol versions
* FuriHal: update serial docs and api
* FuriHal: Selial added similar API for simple reception mode as with DMA
* FuriHal: Update API target H18
* API: ver API H7
* FuriHal: Serial error processing
* FuriHal: fix furi_hal_serial set baudrate
* Sync api symbols
* FuriHal: cleanup serial isr and various flag handling procedures
* FuriHal: cleanup and simplify serial API
* Debug: update UART Echo serial related flags
* FuriHal: update serial API symbols naming
* Make expansion_test compile
* Remove unneeded file
* Make PVS-studio happy
* Optimise stack usage
* Optimise heap usage, improve api signature
* Fix typo
* Clean up code
* Update expansion_protocol.h
* Fix unit tests
* Add doxygen comments to expansion.h
* Update/add doxygen comments
* Update ExpansionModules.md
* Github: new global code owner
* FuriHal: naming in serial control
* Expansion: check mutex acquire return result

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Co-authored-by: hedger <hedger@users.noreply.github.com>
Co-authored-by: SkorP <skorpionm@yandex.ru>
Co-authored-by: SG <who.just.the.doctor@gmail.com>
Co-authored-by: Skorpionm <85568270+Skorpionm@users.noreply.github.com>
This commit is contained in:
Georgii Surkov
2024-01-16 18:18:56 +09:00
committed by GitHub
co-authored by Aleksandr Kutuzov hedger SkorP SG Skorpionm
parent f9f67e6d54
commit 95737958ad
30 changed files with 2279 additions and 114 deletions
+13 -5
View File
@@ -1,10 +1,11 @@
entry,status,name,type,params
Version,+,51.0,,
Version,+,52.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
Header,+,applications/services/dialogs/dialogs.h,,
Header,+,applications/services/dolphin/dolphin.h,,
Header,+,applications/services/expansion/expansion.h,,
Header,+,applications/services/gui/elements.h,,
Header,+,applications/services/gui/gui.h,,
Header,+,applications/services/gui/icon_i.h,,
@@ -788,6 +789,8 @@ Function,-,exp10f,float,float
Function,-,exp2,double,double
Function,-,exp2f,float,float
Function,-,exp2l,long double,long double
Function,+,expansion_disable,void,Expansion*
Function,+,expansion_enable,void,"Expansion*, FuriHalSerialId"
Function,-,expf,float,float
Function,-,expl,long double,long double
Function,-,explicit_bzero,void,"void*, size_t"
@@ -1268,22 +1271,27 @@ Function,+,furi_hal_sd_max_mount_retry_count,uint8_t,
Function,+,furi_hal_sd_presence_init,void,
Function,+,furi_hal_sd_read_blocks,FuriStatus,"uint32_t*, uint32_t, uint32_t"
Function,+,furi_hal_sd_write_blocks,FuriStatus,"const uint32_t*, uint32_t, uint32_t"
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_control_acquire,FuriHalSerialHandle*,FuriHalSerialId
Function,+,furi_hal_serial_control_deinit,void,
Function,+,furi_hal_serial_control_init,void,
Function,+,furi_hal_serial_control_release,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_control_resume,void,
Function,+,furi_hal_serial_control_set_expansion_callback,void,"FuriHalSerialId, FuriHalSerialControlExpansionCallback, void*"
Function,+,furi_hal_serial_control_set_logging_config,void,"FuriHalSerialId, uint32_t"
Function,+,furi_hal_serial_control_suspend,void,
Function,+,furi_hal_serial_deinit,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_disable_direction,void,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_dma_rx,size_t,"FuriHalSerialHandle*, uint8_t*, size_t"
Function,+,furi_hal_serial_dma_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool"
Function,+,furi_hal_serial_dma_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_enable_direction,void,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_get_gpio_pin,const GpioPin*,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_init,void,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_is_baud_rate_supported,_Bool,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_resume,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_set_br,void,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_suspend,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_tx,void,"FuriHalSerialHandle*, const uint8_t*, size_t"
@@ -2098,7 +2106,7 @@ Function,-,round,double,double
Function,+,roundf,float,float
Function,-,roundl,long double,long double
Function,+,rpc_session_close,void,RpcSession*
Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t"
Function,+,rpc_session_feed,size_t,"RpcSession*, const uint8_t*, size_t, uint32_t"
Function,+,rpc_session_get_available_size,size_t,RpcSession*
Function,+,rpc_session_get_owner,RpcOwner,RpcSession*
Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner"
1 entry status name type params
2 Version + 51.0 52.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
6 Header + applications/services/dialogs/dialogs.h
7 Header + applications/services/dolphin/dolphin.h
8 Header + applications/services/expansion/expansion.h
9 Header + applications/services/gui/elements.h
10 Header + applications/services/gui/gui.h
11 Header + applications/services/gui/icon_i.h
789 Function - exp2 double double
790 Function - exp2f float float
791 Function - exp2l long double long double
792 Function + expansion_disable void Expansion*
793 Function + expansion_enable void Expansion*, FuriHalSerialId
794 Function - expf float float
795 Function - expl long double long double
796 Function - explicit_bzero void void*, size_t
1271 Function + furi_hal_sd_presence_init void
1272 Function + furi_hal_sd_read_blocks FuriStatus uint32_t*, uint32_t, uint32_t
1273 Function + furi_hal_sd_write_blocks FuriStatus const uint32_t*, uint32_t, uint32_t
1274 Function + furi_hal_serial_async_rx uint8_t FuriHalSerialHandle*
1275 Function + furi_hal_serial_async_rx_start void FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool
1276 Function + furi_hal_serial_async_rx_stop void FuriHalSerialHandle*
1277 Function + furi_hal_serial_control_acquire FuriHalSerialHandle* FuriHalSerialId
1278 Function + furi_hal_serial_control_deinit void
1279 Function + furi_hal_serial_control_init void
1280 Function + furi_hal_serial_control_release void FuriHalSerialHandle*
1281 Function + furi_hal_serial_control_resume void
1282 Function + furi_hal_serial_control_set_expansion_callback void FuriHalSerialId, FuriHalSerialControlExpansionCallback, void*
1283 Function + furi_hal_serial_control_set_logging_config void FuriHalSerialId, uint32_t
1284 Function + furi_hal_serial_control_suspend void
1285 Function + furi_hal_serial_deinit void FuriHalSerialHandle*
1286 Function + furi_hal_serial_disable_direction void FuriHalSerialHandle*, FuriHalSerialDirection
1287 Function + furi_hal_serial_dma_rx size_t FuriHalSerialHandle*, uint8_t*, size_t
1288 Function + furi_hal_serial_dma_rx_start void FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool
1289 Function + furi_hal_serial_dma_rx_stop void FuriHalSerialHandle*
1290 Function + furi_hal_serial_enable_direction void FuriHalSerialHandle*, FuriHalSerialDirection
1291 Function + furi_hal_serial_get_gpio_pin const GpioPin* FuriHalSerialHandle*, FuriHalSerialDirection
1292 Function + furi_hal_serial_init void FuriHalSerialHandle*, uint32_t
1293 Function + furi_hal_serial_is_baud_rate_supported _Bool FuriHalSerialHandle*, uint32_t
1294 Function + furi_hal_serial_resume void FuriHalSerialHandle*
Function + furi_hal_serial_async_rx uint8_t FuriHalSerialHandle*
Function + furi_hal_serial_async_rx_start void FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool
Function + furi_hal_serial_async_rx_stop void FuriHalSerialHandle*
1295 Function + furi_hal_serial_set_br void FuriHalSerialHandle*, uint32_t
1296 Function + furi_hal_serial_suspend void FuriHalSerialHandle*
1297 Function + furi_hal_serial_tx void FuriHalSerialHandle*, const uint8_t*, size_t
2106 Function + roundf float float
2107 Function - roundl long double long double
2108 Function + rpc_session_close void RpcSession*
2109 Function + rpc_session_feed size_t RpcSession*, uint8_t*, size_t, uint32_t RpcSession*, const uint8_t*, size_t, uint32_t
2110 Function + rpc_session_get_available_size size_t RpcSession*
2111 Function + rpc_session_get_owner RpcOwner RpcSession*
2112 Function + rpc_session_open RpcSession* Rpc*, RpcOwner
+13 -5
View File
@@ -1,11 +1,12 @@
entry,status,name,type,params
Version,+,51.0,,
Version,+,52.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
Header,+,applications/services/dialogs/dialogs.h,,
Header,+,applications/services/dolphin/dolphin.h,,
Header,+,applications/services/expansion/expansion.h,,
Header,+,applications/services/gui/elements.h,,
Header,+,applications/services/gui/gui.h,,
Header,+,applications/services/gui/icon_i.h,,
@@ -877,6 +878,8 @@ Function,-,exp10f,float,float
Function,-,exp2,double,double
Function,-,exp2f,float,float
Function,-,exp2l,long double,long double
Function,+,expansion_disable,void,Expansion*
Function,+,expansion_enable,void,"Expansion*, FuriHalSerialId"
Function,-,expf,float,float
Function,-,expl,long double,long double
Function,-,explicit_bzero,void,"void*, size_t"
@@ -1434,22 +1437,27 @@ Function,+,furi_hal_sd_max_mount_retry_count,uint8_t,
Function,+,furi_hal_sd_presence_init,void,
Function,+,furi_hal_sd_read_blocks,FuriStatus,"uint32_t*, uint32_t, uint32_t"
Function,+,furi_hal_sd_write_blocks,FuriStatus,"const uint32_t*, uint32_t, uint32_t"
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_control_acquire,FuriHalSerialHandle*,FuriHalSerialId
Function,+,furi_hal_serial_control_deinit,void,
Function,+,furi_hal_serial_control_init,void,
Function,+,furi_hal_serial_control_release,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_control_resume,void,
Function,+,furi_hal_serial_control_set_expansion_callback,void,"FuriHalSerialId, FuriHalSerialControlExpansionCallback, void*"
Function,+,furi_hal_serial_control_set_logging_config,void,"FuriHalSerialId, uint32_t"
Function,+,furi_hal_serial_control_suspend,void,
Function,+,furi_hal_serial_deinit,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_disable_direction,void,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_dma_rx,size_t,"FuriHalSerialHandle*, uint8_t*, size_t"
Function,+,furi_hal_serial_dma_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool"
Function,+,furi_hal_serial_dma_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_enable_direction,void,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_get_gpio_pin,const GpioPin*,"FuriHalSerialHandle*, FuriHalSerialDirection"
Function,+,furi_hal_serial_init,void,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_is_baud_rate_supported,_Bool,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_resume,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_set_br,void,"FuriHalSerialHandle*, uint32_t"
Function,+,furi_hal_serial_suspend,void,FuriHalSerialHandle*
Function,+,furi_hal_serial_tx,void,"FuriHalSerialHandle*, const uint8_t*, size_t"
@@ -2682,7 +2690,7 @@ Function,-,round,double,double
Function,+,roundf,float,float
Function,-,roundl,long double,long double
Function,+,rpc_session_close,void,RpcSession*
Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t"
Function,+,rpc_session_feed,size_t,"RpcSession*, const uint8_t*, size_t, uint32_t"
Function,+,rpc_session_get_available_size,size_t,RpcSession*
Function,+,rpc_session_get_owner,RpcOwner,RpcSession*
Function,+,rpc_session_open,RpcSession*,"Rpc*, RpcOwner"
1 entry status name type params
2 Version + 51.0 52.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
6 Header + applications/services/cli/cli_vcp.h
7 Header + applications/services/dialogs/dialogs.h
8 Header + applications/services/dolphin/dolphin.h
9 Header + applications/services/expansion/expansion.h
10 Header + applications/services/gui/elements.h
11 Header + applications/services/gui/gui.h
12 Header + applications/services/gui/icon_i.h
878 Function - exp2 double double
879 Function - exp2f float float
880 Function - exp2l long double long double
881 Function + expansion_disable void Expansion*
882 Function + expansion_enable void Expansion*, FuriHalSerialId
883 Function - expf float float
884 Function - expl long double long double
885 Function - explicit_bzero void void*, size_t
1437 Function + furi_hal_sd_presence_init void
1438 Function + furi_hal_sd_read_blocks FuriStatus uint32_t*, uint32_t, uint32_t
1439 Function + furi_hal_sd_write_blocks FuriStatus const uint32_t*, uint32_t, uint32_t
1440 Function + furi_hal_serial_async_rx uint8_t FuriHalSerialHandle*
1441 Function + furi_hal_serial_async_rx_start void FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool
1442 Function + furi_hal_serial_async_rx_stop void FuriHalSerialHandle*
1443 Function + furi_hal_serial_control_acquire FuriHalSerialHandle* FuriHalSerialId
1444 Function + furi_hal_serial_control_deinit void
1445 Function + furi_hal_serial_control_init void
1446 Function + furi_hal_serial_control_release void FuriHalSerialHandle*
1447 Function + furi_hal_serial_control_resume void
1448 Function + furi_hal_serial_control_set_expansion_callback void FuriHalSerialId, FuriHalSerialControlExpansionCallback, void*
1449 Function + furi_hal_serial_control_set_logging_config void FuriHalSerialId, uint32_t
1450 Function + furi_hal_serial_control_suspend void
1451 Function + furi_hal_serial_deinit void FuriHalSerialHandle*
1452 Function + furi_hal_serial_disable_direction void FuriHalSerialHandle*, FuriHalSerialDirection
1453 Function + furi_hal_serial_dma_rx size_t FuriHalSerialHandle*, uint8_t*, size_t
1454 Function + furi_hal_serial_dma_rx_start void FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool
1455 Function + furi_hal_serial_dma_rx_stop void FuriHalSerialHandle*
1456 Function + furi_hal_serial_enable_direction void FuriHalSerialHandle*, FuriHalSerialDirection
1457 Function + furi_hal_serial_get_gpio_pin const GpioPin* FuriHalSerialHandle*, FuriHalSerialDirection
1458 Function + furi_hal_serial_init void FuriHalSerialHandle*, uint32_t
1459 Function + furi_hal_serial_is_baud_rate_supported _Bool FuriHalSerialHandle*, uint32_t
1460 Function + furi_hal_serial_resume void FuriHalSerialHandle*
Function + furi_hal_serial_async_rx uint8_t FuriHalSerialHandle*
Function + furi_hal_serial_async_rx_start void FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool
Function + furi_hal_serial_async_rx_stop void FuriHalSerialHandle*
1461 Function + furi_hal_serial_set_br void FuriHalSerialHandle*, uint32_t
1462 Function + furi_hal_serial_suspend void FuriHalSerialHandle*
1463 Function + furi_hal_serial_tx void FuriHalSerialHandle*, const uint8_t*, size_t
2690 Function + roundf float float
2691 Function - roundl long double long double
2692 Function + rpc_session_close void RpcSession*
2693 Function + rpc_session_feed size_t RpcSession*, uint8_t*, size_t, uint32_t RpcSession*, const uint8_t*, size_t, uint32_t
2694 Function + rpc_session_get_available_size size_t RpcSession*
2695 Function + rpc_session_get_owner RpcOwner RpcSession*
2696 Function + rpc_session_open RpcSession* Rpc*, RpcOwner
+99
View File
@@ -31,6 +31,59 @@ typedef struct {
void* context;
} FuriHalSerial;
typedef void (*FuriHalSerialControlFunc)(USART_TypeDef*);
typedef struct {
USART_TypeDef* periph;
GpioAltFn alt_fn;
const GpioPin* gpio[FuriHalSerialDirectionMax];
FuriHalSerialControlFunc enable[FuriHalSerialDirectionMax];
FuriHalSerialControlFunc disable[FuriHalSerialDirectionMax];
} FuriHalSerialConfig;
static const FuriHalSerialConfig furi_hal_serial_config[FuriHalSerialIdMax] = {
[FuriHalSerialIdUsart] =
{
.periph = USART1,
.alt_fn = GpioAltFn7USART1,
.gpio =
{
[FuriHalSerialDirectionTx] = &gpio_usart_tx,
[FuriHalSerialDirectionRx] = &gpio_usart_rx,
},
.enable =
{
[FuriHalSerialDirectionTx] = LL_USART_EnableDirectionTx,
[FuriHalSerialDirectionRx] = LL_USART_EnableDirectionRx,
},
.disable =
{
[FuriHalSerialDirectionTx] = LL_USART_DisableDirectionTx,
[FuriHalSerialDirectionRx] = LL_USART_DisableDirectionRx,
},
},
[FuriHalSerialIdLpuart] =
{
.periph = LPUART1,
.alt_fn = GpioAltFn8LPUART1,
.gpio =
{
[FuriHalSerialDirectionTx] = &gpio_ext_pc1,
[FuriHalSerialDirectionRx] = &gpio_ext_pc0,
},
.enable =
{
[FuriHalSerialDirectionTx] = LL_LPUART_EnableDirectionTx,
[FuriHalSerialDirectionRx] = LL_LPUART_EnableDirectionRx,
},
.disable =
{
[FuriHalSerialDirectionTx] = LL_LPUART_DisableDirectionTx,
[FuriHalSerialDirectionRx] = LL_LPUART_DisableDirectionRx,
},
},
};
static FuriHalSerial furi_hal_serial[FuriHalSerialIdMax] = {0};
static size_t furi_hal_serial_dma_bytes_available(FuriHalSerialId ch);
@@ -451,6 +504,11 @@ void furi_hal_serial_init(FuriHalSerialHandle* handle, uint32_t baud) {
}
}
bool furi_hal_serial_is_baud_rate_supported(FuriHalSerialHandle* handle, uint32_t baud) {
furi_check(handle);
return baud >= 9600UL && baud <= 4000000UL;
}
static uint32_t furi_hal_serial_get_prescaler(FuriHalSerialHandle* handle, uint32_t baud) {
uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
uint32_t divisor = (uartclk / baud);
@@ -836,3 +894,44 @@ void furi_hal_serial_dma_rx_stop(FuriHalSerialHandle* handle) {
furi_hal_serial_event_deinit(handle);
furi_hal_serial_dma_configure(handle, NULL, NULL);
}
void furi_hal_serial_enable_direction(
FuriHalSerialHandle* handle,
FuriHalSerialDirection direction) {
furi_check(handle);
furi_check(handle->id < FuriHalSerialIdMax);
furi_check(direction < FuriHalSerialDirectionMax);
USART_TypeDef* periph = furi_hal_serial_config[handle->id].periph;
furi_hal_serial_config[handle->id].enable[direction](periph);
const GpioPin* gpio = furi_hal_serial_config[handle->id].gpio[direction];
const GpioAltFn alt_fn = furi_hal_serial_config[handle->id].alt_fn;
furi_hal_gpio_init_ex(
gpio, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, alt_fn);
}
void furi_hal_serial_disable_direction(
FuriHalSerialHandle* handle,
FuriHalSerialDirection direction) {
furi_check(handle);
furi_check(handle->id < FuriHalSerialIdMax);
furi_check(direction < FuriHalSerialDirectionMax);
USART_TypeDef* periph = furi_hal_serial_config[handle->id].periph;
furi_hal_serial_config[handle->id].disable[direction](periph);
const GpioPin* gpio = furi_hal_serial_config[handle->id].gpio[direction];
furi_hal_gpio_init(gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
}
const GpioPin*
furi_hal_serial_get_gpio_pin(FuriHalSerialHandle* handle, FuriHalSerialDirection direction) {
furi_check(handle);
furi_check(handle->id < FuriHalSerialIdMax);
furi_check(direction < FuriHalSerialDirectionMax);
return furi_hal_serial_config[handle->id].gpio[direction];
}
+45
View File
@@ -48,6 +48,15 @@ void furi_hal_serial_suspend(FuriHalSerialHandle* handle);
*/
void furi_hal_serial_resume(FuriHalSerialHandle* handle);
/**
* @brief Determine whether a certain baud rate is supported
*
* @param handle Serial handle
* @param baud baud rate to be checked
* @returns true if baud rate is supported, false otherwise.
*/
bool furi_hal_serial_is_baud_rate_supported(FuriHalSerialHandle* handle, uint32_t baud);
/** Changes baud rate
*
* @param handle Serial handle
@@ -152,6 +161,42 @@ typedef void (*FuriHalSerialDmaRxCallback)(
size_t data_len,
void* context);
/**
* @brief Enable an input/output directon
*
* Takes over the respective pin by reconfiguring it to
* the appropriate alternative function.
*
* @param handle Serial handle
* @param direction Direction to enable
*/
void furi_hal_serial_enable_direction(
FuriHalSerialHandle* handle,
FuriHalSerialDirection direction);
/**
* @brief Disable an input/output directon
*
* Releases the respective pin by reconfiguring it to
* initial state, making possible its use for other purposes.
*
* @param handle Serial handle
* @param direction Direction to disable
*/
void furi_hal_serial_disable_direction(
FuriHalSerialHandle* handle,
FuriHalSerialDirection direction);
/**
* @brief Get the GPIO pin associated with a serial
*
* @param handle Serial handle
* @param direction Direction to query
* @returns pointer to the respective pin instance
*/
const GpioPin*
furi_hal_serial_get_gpio_pin(FuriHalSerialHandle* handle, FuriHalSerialDirection direction);
/** Start and sets Serial event callback receive DMA
*
* @param handle Serial handle
+184 -52
View File
@@ -14,6 +14,8 @@ typedef enum {
FuriHalSerialControlMessageTypeAcquire,
FuriHalSerialControlMessageTypeRelease,
FuriHalSerialControlMessageTypeLogging,
FuriHalSerialControlMessageTypeExpansionSetCallback,
FuriHalSerialControlMessageTypeExpansionIrq,
} FuriHalSerialControlMessageType;
typedef struct {
@@ -28,6 +30,12 @@ typedef struct {
const uint32_t baud_rate;
} FuriHalSerialControlMessageInputLogging;
typedef struct {
const FuriHalSerialId id;
const FuriHalSerialControlExpansionCallback callback;
void* context;
} FuriHalSerialControlMessageExpCallback;
typedef struct {
FuriHalSerialHandle handles[FuriHalSerialIdMax];
FuriMessageQueue* queue;
@@ -38,6 +46,10 @@ typedef struct {
uint32_t log_config_serial_baud_rate;
FuriLogHandler log_handler;
FuriHalSerialHandle* log_serial;
// Expansion detection
FuriHalSerialControlExpansionCallback expansion_cb;
void* expansion_ctx;
} FuriHalSerialControl;
FuriHalSerialControl* furi_hal_serial_control = NULL;
@@ -65,6 +77,150 @@ static void furi_hal_serial_control_log_set_handle(FuriHalSerialHandle* handle)
}
}
static void furi_hal_serial_control_expansion_irq_callback(void* context) {
UNUSED(context);
FuriHalSerialControlMessage message;
message.type = FuriHalSerialControlMessageTypeExpansionIrq;
message.api_lock = NULL;
furi_message_queue_put(furi_hal_serial_control->queue, &message, 0);
}
static bool furi_hal_serial_control_handler_stop(void* input, void* output) {
UNUSED(input);
UNUSED(output);
return false;
}
static bool furi_hal_serial_control_handler_suspend(void* input, void* output) {
UNUSED(input);
UNUSED(output);
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
furi_hal_serial_tx_wait_complete(&furi_hal_serial_control->handles[i]);
furi_hal_serial_suspend(&furi_hal_serial_control->handles[i]);
}
return true;
}
static bool furi_hal_serial_control_handler_resume(void* input, void* output) {
UNUSED(input);
UNUSED(output);
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
furi_hal_serial_resume(&furi_hal_serial_control->handles[i]);
}
return true;
}
static bool furi_hal_serial_control_handler_acquire(void* input, void* output) {
FuriHalSerialId serial_id = *(FuriHalSerialId*)input;
if(furi_hal_serial_control->handles[serial_id].in_use) {
*(FuriHalSerialHandle**)output = NULL;
} else {
// Logging
if(furi_hal_serial_control->log_config_serial_id == serial_id) {
furi_hal_serial_control_log_set_handle(NULL);
}
// Return handle
furi_hal_serial_control->handles[serial_id].in_use = true;
*(FuriHalSerialHandle**)output = &furi_hal_serial_control->handles[serial_id];
}
return true;
}
static bool furi_hal_serial_control_handler_release(void* input, void* output) {
UNUSED(output);
FuriHalSerialHandle* handle = *(FuriHalSerialHandle**)input;
furi_assert(handle->in_use);
furi_hal_serial_deinit(handle);
handle->in_use = false;
// Return back logging
if(furi_hal_serial_control->log_config_serial_id == handle->id) {
furi_hal_serial_control_log_set_handle(handle);
}
return true;
}
static bool furi_hal_serial_control_handler_logging(void* input, void* output) {
UNUSED(output);
// Set new configuration
FuriHalSerialControlMessageInputLogging* message_input = input;
furi_hal_serial_control->log_config_serial_id = message_input->id;
furi_hal_serial_control->log_config_serial_baud_rate = message_input->baud_rate;
// Apply new configuration
FuriHalSerialHandle* handle = NULL;
if(furi_hal_serial_control->log_config_serial_id < FuriHalSerialIdMax) {
if(!furi_hal_serial_control->handles[furi_hal_serial_control->log_config_serial_id].in_use) {
handle =
&furi_hal_serial_control->handles[furi_hal_serial_control->log_config_serial_id];
}
}
furi_hal_serial_control_log_set_handle(handle);
return true;
}
static bool furi_hal_serial_control_handler_expansion_set_callback(void* input, void* output) {
UNUSED(output);
FuriHalSerialControlMessageExpCallback* message_input = input;
FuriHalSerialHandle* handle = &furi_hal_serial_control->handles[message_input->id];
const GpioPin* gpio = furi_hal_serial_get_gpio_pin(handle, FuriHalSerialDirectionRx);
if(message_input->callback) {
furi_check(furi_hal_serial_control->expansion_cb == NULL);
furi_hal_serial_disable_direction(handle, FuriHalSerialDirectionRx);
furi_hal_gpio_add_int_callback(gpio, furi_hal_serial_control_expansion_irq_callback, NULL);
furi_hal_gpio_init(gpio, GpioModeInterruptFall, GpioPullUp, GpioSpeedLow);
} else {
furi_check(furi_hal_serial_control->expansion_cb != NULL);
furi_hal_gpio_remove_int_callback(gpio);
furi_hal_serial_enable_direction(handle, FuriHalSerialDirectionRx);
}
furi_hal_serial_control->expansion_cb = message_input->callback;
furi_hal_serial_control->expansion_ctx = message_input->context;
return true;
}
static bool furi_hal_serial_control_handler_expansion_irq(void* input, void* output) {
UNUSED(input);
UNUSED(output);
if(furi_hal_serial_control->expansion_cb) {
void* context = furi_hal_serial_control->expansion_ctx;
furi_hal_serial_control->expansion_cb(context);
}
return true;
}
typedef bool (*FuriHalSerialControlCommandHandler)(void* input, void* output);
static const FuriHalSerialControlCommandHandler furi_hal_serial_control_handlers[] = {
[FuriHalSerialControlMessageTypeStop] = furi_hal_serial_control_handler_stop,
[FuriHalSerialControlMessageTypeSuspend] = furi_hal_serial_control_handler_suspend,
[FuriHalSerialControlMessageTypeResume] = furi_hal_serial_control_handler_resume,
[FuriHalSerialControlMessageTypeAcquire] = furi_hal_serial_control_handler_acquire,
[FuriHalSerialControlMessageTypeRelease] = furi_hal_serial_control_handler_release,
[FuriHalSerialControlMessageTypeLogging] = furi_hal_serial_control_handler_logging,
[FuriHalSerialControlMessageTypeExpansionSetCallback] =
furi_hal_serial_control_handler_expansion_set_callback,
[FuriHalSerialControlMessageTypeExpansionIrq] = furi_hal_serial_control_handler_expansion_irq,
};
static int32_t furi_hal_serial_control_thread(void* args) {
UNUSED(args);
@@ -74,61 +230,13 @@ static int32_t furi_hal_serial_control_thread(void* args) {
FuriStatus status =
furi_message_queue_get(furi_hal_serial_control->queue, &message, FuriWaitForever);
furi_check(status == FuriStatusOk);
furi_check(message.type < COUNT_OF(furi_hal_serial_control_handlers));
if(message.type == FuriHalSerialControlMessageTypeStop) {
should_continue = false;
} else if(message.type == FuriHalSerialControlMessageTypeSuspend) {
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
furi_hal_serial_tx_wait_complete(&furi_hal_serial_control->handles[i]);
furi_hal_serial_suspend(&furi_hal_serial_control->handles[i]);
}
api_lock_unlock(message.api_lock);
} else if(message.type == FuriHalSerialControlMessageTypeResume) {
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
furi_hal_serial_resume(&furi_hal_serial_control->handles[i]);
}
api_lock_unlock(message.api_lock);
} else if(message.type == FuriHalSerialControlMessageTypeAcquire) {
FuriHalSerialId serial_id = *(FuriHalSerialId*)message.input;
if(furi_hal_serial_control->handles[serial_id].in_use) {
*(FuriHalSerialHandle**)message.output = NULL;
} else {
// Logging
if(furi_hal_serial_control->log_config_serial_id == serial_id) {
furi_hal_serial_control_log_set_handle(NULL);
}
// Return handle
furi_hal_serial_control->handles[serial_id].in_use = true;
*(FuriHalSerialHandle**)message.output =
&furi_hal_serial_control->handles[serial_id];
}
api_lock_unlock(message.api_lock);
} else if(message.type == FuriHalSerialControlMessageTypeRelease) {
FuriHalSerialHandle* handle = *(FuriHalSerialHandle**)message.input;
furi_assert(handle->in_use);
furi_hal_serial_deinit(handle);
handle->in_use = false;
should_continue =
furi_hal_serial_control_handlers[message.type](message.input, message.output);
// Return back logging
if(furi_hal_serial_control->log_config_serial_id == handle->id) {
furi_hal_serial_control_log_set_handle(handle);
}
if(message.api_lock != NULL) {
api_lock_unlock(message.api_lock);
} else if(message.type == FuriHalSerialControlMessageTypeLogging) {
// Set new configuration
FuriHalSerialControlMessageInputLogging* message_input = message.input;
furi_hal_serial_control->log_config_serial_id = message_input->id;
furi_hal_serial_control->log_config_serial_baud_rate = message_input->baud_rate;
// Apply new configuration
FuriHalSerialHandle* handle = NULL;
if(furi_hal_serial_control->log_config_serial_id < FuriHalSerialIdMax) {
handle = &furi_hal_serial_control
->handles[furi_hal_serial_control->log_config_serial_id];
}
furi_hal_serial_control_log_set_handle(handle);
api_lock_unlock(message.api_lock);
} else {
furi_crash("Invalid parameter");
}
}
@@ -157,6 +265,7 @@ void furi_hal_serial_control_deinit(void) {
// Stop control plane thread
FuriHalSerialControlMessage message;
message.type = FuriHalSerialControlMessageTypeStop;
message.api_lock = NULL;
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
furi_thread_join(furi_hal_serial_control->thread);
// Release resources
@@ -220,6 +329,9 @@ void furi_hal_serial_control_set_logging_config(FuriHalSerialId serial_id, uint3
// Very special case of updater, where RTC initialized before kernel start
if(!furi_hal_serial_control) return;
furi_check(furi_hal_serial_is_baud_rate_supported(
&furi_hal_serial_control->handles[serial_id], baud_rate));
FuriHalSerialControlMessageInputLogging message_input = {
.id = serial_id,
.baud_rate = baud_rate,
@@ -231,3 +343,23 @@ void furi_hal_serial_control_set_logging_config(FuriHalSerialId serial_id, uint3
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
api_lock_wait_unlock_and_free(message.api_lock);
}
void furi_hal_serial_control_set_expansion_callback(
FuriHalSerialId serial_id,
FuriHalSerialControlExpansionCallback callback,
void* context) {
furi_check(serial_id <= FuriHalSerialIdMax);
furi_check(furi_hal_serial_control);
FuriHalSerialControlMessageExpCallback message_input = {
.id = serial_id,
.callback = callback,
.context = context,
};
FuriHalSerialControlMessage message;
message.type = FuriHalSerialControlMessageTypeExpansionSetCallback;
message.api_lock = api_lock_alloc_locked();
message.input = &message_input;
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
api_lock_wait_unlock_and_free(message.api_lock);
}
@@ -41,6 +41,27 @@ void furi_hal_serial_control_release(FuriHalSerialHandle* handle);
*/
void furi_hal_serial_control_set_logging_config(FuriHalSerialId serial_id, uint32_t baud_rate);
/**
* @brief Expansion module detection callback type.
*
* @param[in,out] context Pointer to the user-defined context object.
*/
typedef void (*FuriHalSerialControlExpansionCallback)(void* context);
/**
* @brief Enable expansion module detection for a given serial interface.
*
* Passing NULL as the callback parameter disables external module detection.
*
* @param[in] serial_id Identifier of the serial interface to be used.
* @param[in] callback Pointer to the callback function to be called upon module detection.
* @param[in,out] context Pointer to the user-defined context object. Will be passed to the callback function.
*/
void furi_hal_serial_control_set_expansion_callback(
FuriHalSerialId serial_id,
FuriHalSerialControlExpansionCallback callback,
void* context);
#ifdef __cplusplus
}
#endif
@@ -12,4 +12,11 @@ typedef enum {
FuriHalSerialIdMax,
} FuriHalSerialId;
typedef enum {
FuriHalSerialDirectionTx,
FuriHalSerialDirectionRx,
FuriHalSerialDirectionMax,
} FuriHalSerialDirection;
typedef struct FuriHalSerialHandle FuriHalSerialHandle;