mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-11 06:09:08 -07:00
Merge branch 'ofw-dev' into xfw-dev
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,50.2,,
|
||||
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,,
|
||||
@@ -160,7 +161,6 @@ Header,+,targets/f18/furi_hal/furi_hal_spi_config.h,,
|
||||
Header,+,targets/f18/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
@@ -170,8 +170,11 @@ Header,+,targets/f7/furi_hal/furi_hal_idle_timer.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_interrupt.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_os.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_pwm.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rtc.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_control.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_uart.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,,
|
||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||
@@ -190,7 +193,6 @@ Header,+,targets/furi_hal_include/furi_hal_mpu.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_power.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_random.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_region.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_rtc.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_spi.h,,
|
||||
@@ -787,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"
|
||||
@@ -1057,14 +1061,6 @@ Function,-,furi_hal_clock_switch_hse2hsi,void,
|
||||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
Function,+,furi_hal_console_printf,void,"const char[], ..."
|
||||
Function,+,furi_hal_console_puts,void,const char*
|
||||
Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*"
|
||||
Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize"
|
||||
Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp
|
||||
Function,+,furi_hal_cortex_delay_us,void,uint32_t
|
||||
@@ -1156,7 +1152,7 @@ Function,-,furi_hal_init,void,
|
||||
Function,-,furi_hal_init_early,void,
|
||||
Function,-,furi_hal_interrupt_init,void,
|
||||
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
|
||||
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, uint16_t, FuriHalInterruptISR, void*"
|
||||
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"
|
||||
Function,+,furi_hal_light_blink_set_color,void,Light
|
||||
Function,+,furi_hal_light_blink_start,void,"Light, uint8_t, uint16_t, uint16_t"
|
||||
Function,+,furi_hal_light_blink_stop,void,
|
||||
@@ -1239,6 +1235,8 @@ Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_timeformat,FuriHalRtcLocaleTimeFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_units,FuriHalRtcLocaleUnits,
|
||||
Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate,
|
||||
Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice,
|
||||
Function,+,furi_hal_rtc_get_log_level,uint8_t,
|
||||
Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
|
||||
@@ -1257,10 +1255,13 @@ Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
||||
Function,+,furi_hal_rtc_set_locale_dateformat,void,FuriHalRtcLocaleDateFormat
|
||||
Function,+,furi_hal_rtc_set_locale_timeformat,void,FuriHalRtcLocaleTimeFormat
|
||||
Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits
|
||||
Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate
|
||||
Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice
|
||||
Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||
Function,+,furi_hal_rtc_sync_shadow,void,
|
||||
Function,+,furi_hal_rtc_timestamp_to_datetime,void,"uint32_t, FuriHalRtcDateTime*"
|
||||
Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime*
|
||||
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
||||
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
||||
@@ -1270,6 +1271,31 @@ 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_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"
|
||||
Function,+,furi_hal_serial_tx_wait_complete,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_speaker_acquire,_Bool,uint32_t
|
||||
Function,-,furi_hal_speaker_deinit,void,
|
||||
Function,-,furi_hal_speaker_init,void,
|
||||
@@ -1293,13 +1319,6 @@ Function,-,furi_hal_spi_config_init_early,void,
|
||||
Function,-,furi_hal_spi_dma_init,void,
|
||||
Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle*
|
||||
Function,+,furi_hal_switch,void,void*
|
||||
Function,+,furi_hal_uart_deinit,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_init,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_resume,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_set_br,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_set_irq_cb,void,"FuriHalUartId, void (*)(UartIrqEvent, uint8_t, void*), void*"
|
||||
Function,+,furi_hal_uart_suspend,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_tx,void,"FuriHalUartId, uint8_t*, size_t"
|
||||
Function,+,furi_hal_usb_disable,void,
|
||||
Function,+,furi_hal_usb_enable,void,
|
||||
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
|
||||
@@ -1345,15 +1364,17 @@ Function,+,furi_kernel_is_running,_Bool,
|
||||
Function,+,furi_kernel_lock,int32_t,
|
||||
Function,+,furi_kernel_restore_lock,int32_t,int32_t
|
||||
Function,+,furi_kernel_unlock,int32_t,
|
||||
Function,+,furi_log_add_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_get_level,FuriLogLevel,
|
||||
Function,-,furi_log_init,void,
|
||||
Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*"
|
||||
Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**"
|
||||
Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..."
|
||||
Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..."
|
||||
Function,+,furi_log_puts,void,const char*
|
||||
Function,+,furi_log_remove_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_set_level,void,FuriLogLevel
|
||||
Function,-,furi_log_set_puts,void,FuriLogPuts
|
||||
Function,-,furi_log_set_timestamp,void,FuriLogTimestamp
|
||||
Function,+,furi_log_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_message_queue_alloc,FuriMessageQueue*,"uint32_t, uint32_t"
|
||||
Function,+,furi_message_queue_free,void,FuriMessageQueue*
|
||||
Function,+,furi_message_queue_get,FuriStatus,"FuriMessageQueue*, void*, uint32_t"
|
||||
@@ -2085,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"
|
||||
@@ -2417,10 +2438,10 @@ Function,-,utoa,char*,"unsigned, char*, int"
|
||||
Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*"
|
||||
Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,value_index_bool,size_t,"const _Bool, const _Bool[], size_t"
|
||||
Function,+,value_index_float,size_t,"const float, const float[], size_t"
|
||||
Function,+,value_index_int32,size_t,"const int32_t, const int32_t[], size_t"
|
||||
Function,+,value_index_uint32,size_t,"const uint32_t, const uint32_t[], size_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*"
|
||||
|
||||
|
@@ -43,7 +43,7 @@ void furi_hal_init() {
|
||||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_serial_control_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
furi_hal_flash_init();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,50.2,,
|
||||
Version,+,52.0,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/main/archive/helpers/archive_helpers_ext.h,,
|
||||
Header,+,applications/services/applications.h,,
|
||||
@@ -9,6 +9,7 @@ Header,+,applications/services/cli/cli_vcp.h,,
|
||||
Header,+,applications/services/dialogs/dialogs.h,,
|
||||
Header,+,applications/services/dolphin/dolphin.h,,
|
||||
Header,+,applications/services/dolphin/helpers/dolphin_state.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,,
|
||||
@@ -229,7 +230,6 @@ Header,+,lib/toolbox/version.h,,
|
||||
Header,+,lib/xtreme/xtreme.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
@@ -242,11 +242,14 @@ Header,+,targets/f7/furi_hal/furi_hal_os.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_pwm.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_resources.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rfid.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rtc.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_control.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_config.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_subghz.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_uart.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,,
|
||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||
@@ -267,7 +270,6 @@ Header,+,targets/furi_hal_include/furi_hal_nfc.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_power.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_random.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_region.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_rtc.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_spi.h,,
|
||||
@@ -923,6 +925,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"
|
||||
@@ -1211,14 +1215,6 @@ Function,-,furi_hal_clock_switch_hse2hsi,void,
|
||||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
Function,+,furi_hal_console_printf,void,"const char[], ..."
|
||||
Function,+,furi_hal_console_puts,void,const char*
|
||||
Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*"
|
||||
Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize"
|
||||
Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp
|
||||
Function,+,furi_hal_cortex_delay_us,void,uint32_t
|
||||
@@ -1330,7 +1326,7 @@ Function,-,furi_hal_init,void,
|
||||
Function,-,furi_hal_init_early,void,
|
||||
Function,-,furi_hal_interrupt_init,void,
|
||||
Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*"
|
||||
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, uint16_t, FuriHalInterruptISR, void*"
|
||||
Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*"
|
||||
Function,-,furi_hal_is_normal_boot,_Bool,
|
||||
Function,+,furi_hal_light_blink_set_color,void,Light
|
||||
Function,+,furi_hal_light_blink_start,void,"Light, uint8_t, uint16_t, uint16_t"
|
||||
@@ -1472,6 +1468,8 @@ Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
||||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_timeformat,FuriHalRtcLocaleTimeFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_units,FuriHalRtcLocaleUnits,
|
||||
Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate,
|
||||
Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice,
|
||||
Function,+,furi_hal_rtc_get_log_level,uint8_t,
|
||||
Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
|
||||
@@ -1490,10 +1488,13 @@ Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
||||
Function,+,furi_hal_rtc_set_locale_dateformat,void,FuriHalRtcLocaleDateFormat
|
||||
Function,+,furi_hal_rtc_set_locale_timeformat,void,FuriHalRtcLocaleTimeFormat
|
||||
Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits
|
||||
Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate
|
||||
Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice
|
||||
Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||
Function,+,furi_hal_rtc_sync_shadow,void,
|
||||
Function,+,furi_hal_rtc_timestamp_to_datetime,void,"uint32_t, FuriHalRtcDateTime*"
|
||||
Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime*
|
||||
Function,+,furi_hal_sd_get_card_state,FuriStatus,
|
||||
Function,+,furi_hal_sd_info,FuriStatus,FuriHalSdInfo*
|
||||
@@ -1503,6 +1504,31 @@ 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_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"
|
||||
Function,+,furi_hal_serial_tx_wait_complete,void,FuriHalSerialHandle*
|
||||
Function,-,furi_hal_set_is_normal_boot,void,_Bool
|
||||
Function,+,furi_hal_speaker_acquire,_Bool,uint32_t
|
||||
Function,-,furi_hal_speaker_deinit,void,
|
||||
@@ -1562,13 +1588,6 @@ Function,+,furi_hal_subghz_stop_async_tx,void,
|
||||
Function,+,furi_hal_subghz_tx,_Bool,
|
||||
Function,+,furi_hal_subghz_write_packet,void,"const uint8_t*, uint8_t"
|
||||
Function,+,furi_hal_switch,void,void*
|
||||
Function,+,furi_hal_uart_deinit,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_init,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_resume,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_set_br,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_set_irq_cb,void,"FuriHalUartId, void (*)(UartIrqEvent, uint8_t, void*), void*"
|
||||
Function,+,furi_hal_uart_suspend,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_tx,void,"FuriHalUartId, uint8_t*, size_t"
|
||||
Function,+,furi_hal_usb_disable,void,
|
||||
Function,+,furi_hal_usb_enable,void,
|
||||
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
|
||||
@@ -1619,15 +1638,17 @@ Function,+,furi_kernel_is_running,_Bool,
|
||||
Function,+,furi_kernel_lock,int32_t,
|
||||
Function,+,furi_kernel_restore_lock,int32_t,int32_t
|
||||
Function,+,furi_kernel_unlock,int32_t,
|
||||
Function,+,furi_log_add_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_get_level,FuriLogLevel,
|
||||
Function,-,furi_log_init,void,
|
||||
Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*"
|
||||
Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**"
|
||||
Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..."
|
||||
Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..."
|
||||
Function,+,furi_log_puts,void,const char*
|
||||
Function,+,furi_log_remove_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_set_level,void,FuriLogLevel
|
||||
Function,-,furi_log_set_puts,void,FuriLogPuts
|
||||
Function,-,furi_log_set_timestamp,void,FuriLogTimestamp
|
||||
Function,+,furi_log_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_message_queue_alloc,FuriMessageQueue*,"uint32_t, uint32_t"
|
||||
Function,+,furi_message_queue_free,void,FuriMessageQueue*
|
||||
Function,+,furi_message_queue_get,FuriStatus,"FuriMessageQueue*, void*, uint32_t"
|
||||
@@ -2778,7 +2799,7 @@ Function,+,roundf,float,float
|
||||
Function,-,roundl,long double,long double
|
||||
Function,+,rpc_get_sessions_count,size_t,Rpc*
|
||||
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"
|
||||
@@ -3348,10 +3369,10 @@ Function,-,utoa,char*,"unsigned, char*, int"
|
||||
Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*"
|
||||
Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,value_index_bool,size_t,"const _Bool, const _Bool[], size_t"
|
||||
Function,+,value_index_float,size_t,"const float, const float[], size_t"
|
||||
Function,+,value_index_int32,size_t,"const int32_t, const int32_t[], size_t"
|
||||
Function,+,value_index_uint32,size_t,"const uint32_t, const uint32_t[], size_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*"
|
||||
|
||||
|
@@ -43,7 +43,7 @@ void furi_hal_init() {
|
||||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_serial_control_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
furi_hal_flash_init();
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_uart.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalConsole"
|
||||
|
||||
#ifdef HEAP_PRINT_DEBUG
|
||||
#define CONSOLE_BAUDRATE 1843200
|
||||
#else
|
||||
#define CONSOLE_BAUDRATE 230400
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool alive;
|
||||
FuriHalConsoleTxCallback tx_callback;
|
||||
void* tx_callback_context;
|
||||
} FuriHalConsole;
|
||||
|
||||
FuriHalConsole furi_hal_console = {
|
||||
.alive = false,
|
||||
.tx_callback = NULL,
|
||||
.tx_callback_context = NULL,
|
||||
};
|
||||
|
||||
void furi_hal_console_init() {
|
||||
furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
|
||||
furi_hal_console.alive = true;
|
||||
}
|
||||
|
||||
void furi_hal_console_enable() {
|
||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
|
||||
furi_hal_console.alive = true;
|
||||
}
|
||||
|
||||
void furi_hal_console_disable() {
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
furi_hal_console.alive = false;
|
||||
}
|
||||
|
||||
void furi_hal_console_set_tx_callback(FuriHalConsoleTxCallback callback, void* context) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
furi_hal_console.tx_callback = callback;
|
||||
furi_hal_console.tx_callback_context = context;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
|
||||
if(!furi_hal_console.alive) return;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
// Transmit data
|
||||
|
||||
if(furi_hal_console.tx_callback) {
|
||||
furi_hal_console.tx_callback(buffer, buffer_size, furi_hal_console.tx_callback_context);
|
||||
}
|
||||
|
||||
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))
|
||||
;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size) {
|
||||
if(!furi_hal_console.alive) return;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
// Transmit data
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
|
||||
// Transmit new line symbols
|
||||
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))
|
||||
;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_printf(const char format[], ...) {
|
||||
FuriString* string;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
string = furi_string_alloc_vprintf(format, args);
|
||||
va_end(args);
|
||||
furi_hal_console_tx((const uint8_t*)furi_string_get_cstr(string), furi_string_size(string));
|
||||
furi_string_free(string);
|
||||
}
|
||||
|
||||
void furi_hal_console_puts(const char* data) {
|
||||
furi_hal_console_tx((const uint8_t*)data, strlen(data));
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*FuriHalConsoleTxCallback)(const uint8_t* buffer, size_t size, void* context);
|
||||
|
||||
void furi_hal_console_init();
|
||||
|
||||
void furi_hal_console_enable();
|
||||
|
||||
void furi_hal_console_disable();
|
||||
|
||||
void furi_hal_console_set_tx_callback(FuriHalConsoleTxCallback callback, void* context);
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* Printf-like plain uart interface
|
||||
* @warning Will not work in ISR context
|
||||
* @param format
|
||||
* @param ...
|
||||
*/
|
||||
void furi_hal_console_printf(const char format[], ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
|
||||
|
||||
void furi_hal_console_puts(const char* data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -411,7 +411,10 @@ static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
|
||||
LL_DMA_EnableIT_TC(INFRARED_DMA_CH1_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(
|
||||
INFRARED_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
|
||||
INFRARED_DMA_CH1_IRQ,
|
||||
FuriHalInterruptPriorityKamiSama,
|
||||
furi_hal_infrared_tx_dma_polarity_isr,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
|
||||
@@ -441,7 +444,7 @@ static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
|
||||
LL_DMA_EnableIT_HT(INFRARED_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_TE(INFRARED_DMA_CH2_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(INFRARED_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_fill_buffer_last(uint8_t buf_num) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <furi_hal_os.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <FreeRTOS.h>
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
#include <stm32wbxx_ll_tim.h>
|
||||
@@ -10,7 +11,7 @@
|
||||
|
||||
#define TAG "FuriHalInterrupt"
|
||||
|
||||
#define FURI_HAL_INTERRUPT_DEFAULT_PRIORITY 5
|
||||
#define FURI_HAL_INTERRUPT_DEFAULT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5)
|
||||
|
||||
typedef struct {
|
||||
FuriHalInterruptISR isr;
|
||||
@@ -58,6 +59,12 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
|
||||
// LPTIMx
|
||||
[FuriHalInterruptIdLpTim1] = LPTIM1_IRQn,
|
||||
[FuriHalInterruptIdLpTim2] = LPTIM2_IRQn,
|
||||
|
||||
// UARTx
|
||||
[FuriHalInterruptIdUart1] = USART1_IRQn,
|
||||
|
||||
// LPUARTx
|
||||
[FuriHalInterruptIdLpUart1] = LPUART1_IRQn,
|
||||
};
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
@@ -119,16 +126,21 @@ void furi_hal_interrupt_init() {
|
||||
}
|
||||
|
||||
void furi_hal_interrupt_set_isr(FuriHalInterruptId index, FuriHalInterruptISR isr, void* context) {
|
||||
furi_hal_interrupt_set_isr_ex(index, FURI_HAL_INTERRUPT_DEFAULT_PRIORITY, isr, context);
|
||||
furi_hal_interrupt_set_isr_ex(index, FuriHalInterruptPriorityNormal, isr, context);
|
||||
}
|
||||
|
||||
void furi_hal_interrupt_set_isr_ex(
|
||||
FuriHalInterruptId index,
|
||||
uint16_t priority,
|
||||
FuriHalInterruptPriority priority,
|
||||
FuriHalInterruptISR isr,
|
||||
void* context) {
|
||||
furi_check(index < FuriHalInterruptIdMax);
|
||||
furi_check(priority <= 15);
|
||||
furi_check(
|
||||
(priority >= FuriHalInterruptPriorityLowest &&
|
||||
priority <= FuriHalInterruptPriorityHighest) ||
|
||||
priority == FuriHalInterruptPriorityKamiSama);
|
||||
|
||||
uint16_t real_priority = FURI_HAL_INTERRUPT_DEFAULT_PRIORITY - priority;
|
||||
|
||||
if(isr) {
|
||||
// Pre ISR set
|
||||
@@ -146,7 +158,7 @@ void furi_hal_interrupt_set_isr_ex(
|
||||
if(isr) {
|
||||
// Post ISR set
|
||||
furi_hal_interrupt_clear_pending(index);
|
||||
furi_hal_interrupt_enable(index, priority);
|
||||
furi_hal_interrupt_enable(index, real_priority);
|
||||
} else {
|
||||
// Post ISR clear
|
||||
}
|
||||
@@ -328,3 +340,11 @@ void LPTIM1_IRQHandler() {
|
||||
void LPTIM2_IRQHandler() {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdLpTim2);
|
||||
}
|
||||
|
||||
void USART1_IRQHandler(void) {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdUart1);
|
||||
}
|
||||
|
||||
void LPUART1_IRQHandler(void) {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdLpUart1);
|
||||
}
|
||||
@@ -49,31 +49,64 @@ typedef enum {
|
||||
FuriHalInterruptIdLpTim1,
|
||||
FuriHalInterruptIdLpTim2,
|
||||
|
||||
//UARTx
|
||||
FuriHalInterruptIdUart1,
|
||||
|
||||
//LPUARTx
|
||||
FuriHalInterruptIdLpUart1,
|
||||
|
||||
// Service value
|
||||
FuriHalInterruptIdMax,
|
||||
} FuriHalInterruptId;
|
||||
|
||||
typedef enum {
|
||||
FuriHalInterruptPriorityLowest =
|
||||
-3, /**< Lowest priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityLower =
|
||||
-2, /**< Lower priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityLow =
|
||||
-1, /**< Low priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityNormal =
|
||||
0, /**< Normal(default) priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityHigh =
|
||||
1, /**< High priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityHigher =
|
||||
2, /**< Higher priority level, you can use ISR-safe OS primitives */
|
||||
FuriHalInterruptPriorityHighest =
|
||||
3, /**< Highest priority level, you can use ISR-safe OS primitives */
|
||||
|
||||
/* Special group, read docs first(ALL OF THEM: especially FreeRTOS configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY) */
|
||||
FuriHalInterruptPriorityKamiSama =
|
||||
6, /**< Forget about thread safety, you are god now. No one can prevent you from messing with OS critical section. You are not allowed to use any OS primitives, but who can stop you? Use this priority only for direct hardware interaction with LL HAL. */
|
||||
} FuriHalInterruptPriority;
|
||||
|
||||
/** Initialize interrupt subsystem */
|
||||
void furi_hal_interrupt_init();
|
||||
|
||||
/** Set ISR and enable interrupt with default priority
|
||||
* We don't clear interrupt flags for you, do it by your self.
|
||||
* @param index - interrupt ID
|
||||
* @param isr - your interrupt service routine or use NULL to clear
|
||||
* @param context - isr context
|
||||
*
|
||||
* @warning Interrupt flags are not cleared automatically. You may want to
|
||||
* ensure that your peripheral status flags are cleared.
|
||||
*
|
||||
* @param index - interrupt ID
|
||||
* @param isr - your interrupt service routine or use NULL to clear
|
||||
* @param context - isr context
|
||||
*/
|
||||
void furi_hal_interrupt_set_isr(FuriHalInterruptId index, FuriHalInterruptISR isr, void* context);
|
||||
|
||||
/** Set ISR and enable interrupt with custom priority
|
||||
* We don't clear interrupt flags for you, do it by your self.
|
||||
* @param index - interrupt ID
|
||||
* @param priority - 0 to 15, 0 highest
|
||||
* @param isr - your interrupt service routine or use NULL to clear
|
||||
* @param context - isr context
|
||||
*
|
||||
* @warning Interrupt flags are not cleared automatically. You may want to
|
||||
* ensure that your peripheral status flags are cleared.
|
||||
*
|
||||
* @param index - interrupt ID
|
||||
* @param priority - One of FuriHalInterruptPriority
|
||||
* @param isr - your interrupt service routine or use NULL to clear
|
||||
* @param context - isr context
|
||||
*/
|
||||
void furi_hal_interrupt_set_isr_ex(
|
||||
FuriHalInterruptId index,
|
||||
uint16_t priority,
|
||||
FuriHalInterruptPriority priority,
|
||||
FuriHalInterruptISR isr,
|
||||
void* context);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <furi_hal_os.h>
|
||||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_resources.h>
|
||||
@@ -208,8 +207,8 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
|
||||
|
||||
void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) {
|
||||
UNUSED(xTask);
|
||||
furi_hal_console_puts("\r\n\r\n stack overflow in ");
|
||||
furi_hal_console_puts(pcTaskName);
|
||||
furi_hal_console_puts("\r\n\r\n");
|
||||
furi_log_puts("\r\n\r\n stack overflow in ");
|
||||
furi_log_puts(pcTaskName);
|
||||
furi_log_puts("\r\n\r\n");
|
||||
furi_crash("StackOverflow");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <furi_hal_bt.h>
|
||||
#include <furi_hal_vibro.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_debug.h>
|
||||
|
||||
@@ -178,14 +178,12 @@ static inline void furi_hal_power_light_sleep() {
|
||||
|
||||
static inline void furi_hal_power_suspend_aux_periphs() {
|
||||
// Disable USART
|
||||
furi_hal_uart_suspend(FuriHalUartIdUSART1);
|
||||
furi_hal_uart_suspend(FuriHalUartIdLPUART1);
|
||||
furi_hal_serial_control_suspend();
|
||||
}
|
||||
|
||||
static inline void furi_hal_power_resume_aux_periphs() {
|
||||
// Re-enable USART
|
||||
furi_hal_uart_resume(FuriHalUartIdUSART1);
|
||||
furi_hal_uart_resume(FuriHalUartIdLPUART1);
|
||||
furi_hal_serial_control_resume();
|
||||
}
|
||||
|
||||
static inline void furi_hal_power_deep_sleep() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_light.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
@@ -34,7 +35,9 @@ typedef struct {
|
||||
FuriHalRtcLocaleUnits locale_units : 1;
|
||||
FuriHalRtcLocaleTimeFormat locale_timeformat : 1;
|
||||
FuriHalRtcLocaleDateFormat locale_dateformat : 2;
|
||||
uint8_t reserved : 6;
|
||||
FuriHalRtcLogDevice log_device : 2;
|
||||
FuriHalRtcLogBaudRate log_baud_rate : 3;
|
||||
uint8_t reserved : 1;
|
||||
} SystemReg;
|
||||
|
||||
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
|
||||
@@ -51,6 +54,24 @@ static const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] =
|
||||
|
||||
static const uint16_t furi_hal_rtc_days_per_year[] = {365, 366};
|
||||
|
||||
static const FuriHalSerialId furi_hal_rtc_log_devices[] = {
|
||||
[FuriHalRtcLogDeviceUsart] = FuriHalSerialIdUsart,
|
||||
[FuriHalRtcLogDeviceLpuart] = FuriHalSerialIdLpuart,
|
||||
[FuriHalRtcLogDeviceReserved] = FuriHalSerialIdMax,
|
||||
[FuriHalRtcLogDeviceNone] = FuriHalSerialIdMax,
|
||||
};
|
||||
|
||||
static const uint32_t furi_hal_rtc_log_baud_rates[] = {
|
||||
[FuriHalRtcLogBaudRate230400] = 230400,
|
||||
[FuriHalRtcLogBaudRate9600] = 9600,
|
||||
[FuriHalRtcLogBaudRate38400] = 38400,
|
||||
[FuriHalRtcLogBaudRate57600] = 57600,
|
||||
[FuriHalRtcLogBaudRate115200] = 115200,
|
||||
[FuriHalRtcLogBaudRate460800] = 460800,
|
||||
[FuriHalRtcLogBaudRate921600] = 921600,
|
||||
[FuriHalRtcLogBaudRate1843200] = 1843200,
|
||||
};
|
||||
|
||||
static void furi_hal_rtc_reset() {
|
||||
LL_RCC_ForceBackupDomainReset();
|
||||
LL_RCC_ReleaseBackupDomainReset();
|
||||
@@ -153,6 +174,9 @@ void furi_hal_rtc_init() {
|
||||
LL_RTC_Init(RTC, &RTC_InitStruct);
|
||||
|
||||
furi_log_set_level(furi_hal_rtc_get_log_level());
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
@@ -199,6 +223,40 @@ uint8_t furi_hal_rtc_get_log_level() {
|
||||
return data->log_level;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_log_device(FuriHalRtcLogDevice device) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
data->log_device = device;
|
||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
}
|
||||
|
||||
FuriHalRtcLogDevice furi_hal_rtc_get_log_device() {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
return data->log_device;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_log_baud_rate(FuriHalRtcLogBaudRate baud_rate) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
data->log_baud_rate = baud_rate;
|
||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
}
|
||||
|
||||
FuriHalRtcLogBaudRate furi_hal_rtc_get_log_baud_rate() {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
return data->log_baud_rate;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
@@ -424,6 +482,32 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) {
|
||||
uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY;
|
||||
|
||||
datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR;
|
||||
|
||||
while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) {
|
||||
days -= furi_hal_rtc_get_days_per_year(datetime->year);
|
||||
(datetime->year)++;
|
||||
}
|
||||
|
||||
datetime->month = 1;
|
||||
while(days >= furi_hal_rtc_get_days_per_month(
|
||||
furi_hal_rtc_is_leap_year(datetime->year), datetime->month)) {
|
||||
days -= furi_hal_rtc_get_days_per_month(
|
||||
furi_hal_rtc_is_leap_year(datetime->year), datetime->month);
|
||||
(datetime->month)++;
|
||||
}
|
||||
|
||||
datetime->day = days + 1;
|
||||
datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR;
|
||||
datetime->minute =
|
||||
(seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE;
|
||||
}
|
||||
|
||||
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year) {
|
||||
return furi_hal_rtc_days_per_year[furi_hal_rtc_is_leap_year(year) ? 1 : 0];
|
||||
}
|
||||
|
||||
@@ -64,32 +64,50 @@ typedef enum {
|
||||
} FuriHalRtcRegister;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleUnitsMetric = 0, /**< Metric measurement units */
|
||||
FuriHalRtcLocaleUnitsImperial = 1, /**< Imperial measurement units */
|
||||
FuriHalRtcLocaleUnitsMetric = 0x0, /**< Metric measurement units */
|
||||
FuriHalRtcLocaleUnitsImperial = 0x1, /**< Imperial measurement units */
|
||||
} FuriHalRtcLocaleUnits;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleTimeFormat24h = 0, /**< 24-hour format */
|
||||
FuriHalRtcLocaleTimeFormat12h = 1, /**< 12-hour format */
|
||||
FuriHalRtcLocaleTimeFormat24h = 0x0, /**< 24-hour format */
|
||||
FuriHalRtcLocaleTimeFormat12h = 0x1, /**< 12-hour format */
|
||||
} FuriHalRtcLocaleTimeFormat;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleDateFormatDMY = 0, /**< Day/Month/Year */
|
||||
FuriHalRtcLocaleDateFormatMDY = 1, /**< Month/Day/Year */
|
||||
FuriHalRtcLocaleDateFormatYMD = 2, /**< Year/Month/Day */
|
||||
FuriHalRtcLocaleDateFormatDMY = 0x0, /**< Day/Month/Year */
|
||||
FuriHalRtcLocaleDateFormatMDY = 0x1, /**< Month/Day/Year */
|
||||
FuriHalRtcLocaleDateFormatYMD = 0x2, /**< Year/Month/Day */
|
||||
} FuriHalRtcLocaleDateFormat;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLogDeviceUsart = 0x0, /**< Default: USART */
|
||||
FuriHalRtcLogDeviceLpuart = 0x1, /**< Default: LPUART */
|
||||
FuriHalRtcLogDeviceReserved = 0x2, /**< Reserved for future use */
|
||||
FuriHalRtcLogDeviceNone = 0x3, /**< None, disable serial logging */
|
||||
} FuriHalRtcLogDevice;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLogBaudRate230400 = 0x0, /**< 230400 baud */
|
||||
FuriHalRtcLogBaudRate9600 = 0x1, /**< 9600 baud */
|
||||
FuriHalRtcLogBaudRate38400 = 0x2, /**< 38400 baud */
|
||||
FuriHalRtcLogBaudRate57600 = 0x3, /**< 57600 baud */
|
||||
FuriHalRtcLogBaudRate115200 = 0x4, /**< 115200 baud */
|
||||
FuriHalRtcLogBaudRate460800 = 0x5, /**< 460800 baud */
|
||||
FuriHalRtcLogBaudRate921600 = 0x6, /**< 921600 baud */
|
||||
FuriHalRtcLogBaudRate1843200 = 0x7, /**< 1843200 baud */
|
||||
} FuriHalRtcLogBaudRate;
|
||||
|
||||
/** Early initialization */
|
||||
void furi_hal_rtc_init_early();
|
||||
void furi_hal_rtc_init_early(void);
|
||||
|
||||
/** Early de-initialization */
|
||||
void furi_hal_rtc_deinit_early();
|
||||
void furi_hal_rtc_deinit_early(void);
|
||||
|
||||
/** Initialize RTC subsystem */
|
||||
void furi_hal_rtc_init();
|
||||
void furi_hal_rtc_init(void);
|
||||
|
||||
/** Force sync shadow registers */
|
||||
void furi_hal_rtc_sync_shadow();
|
||||
void furi_hal_rtc_sync_shadow(void);
|
||||
|
||||
/** Reset ALL RTC registers content */
|
||||
void furi_hal_rtc_reset_registers();
|
||||
@@ -119,7 +137,31 @@ void furi_hal_rtc_set_log_level(uint8_t level);
|
||||
*
|
||||
* @return The Log Level value
|
||||
*/
|
||||
uint8_t furi_hal_rtc_get_log_level();
|
||||
uint8_t furi_hal_rtc_get_log_level(void);
|
||||
|
||||
/** Set logging device
|
||||
*
|
||||
* @param[in] device The device
|
||||
*/
|
||||
void furi_hal_rtc_set_log_device(FuriHalRtcLogDevice device);
|
||||
|
||||
/** Get logging device
|
||||
*
|
||||
* @return The furi hal rtc log device.
|
||||
*/
|
||||
FuriHalRtcLogDevice furi_hal_rtc_get_log_device(void);
|
||||
|
||||
/** Set logging baud rate
|
||||
*
|
||||
* @param[in] baud_rate The baud rate
|
||||
*/
|
||||
void furi_hal_rtc_set_log_baud_rate(FuriHalRtcLogBaudRate baud_rate);
|
||||
|
||||
/** Get logging baud rate
|
||||
*
|
||||
* @return The furi hal rtc log baud rate.
|
||||
*/
|
||||
FuriHalRtcLogBaudRate furi_hal_rtc_get_log_baud_rate(void);
|
||||
|
||||
/** Set RTC Flag
|
||||
*
|
||||
@@ -151,7 +193,7 @@ void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode);
|
||||
*
|
||||
* @return The RTC boot mode.
|
||||
*/
|
||||
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode();
|
||||
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode(void);
|
||||
|
||||
/** Set Heap Track mode
|
||||
*
|
||||
@@ -163,7 +205,7 @@ void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode);
|
||||
*
|
||||
* @return The RTC heap track mode.
|
||||
*/
|
||||
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode();
|
||||
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode(void);
|
||||
|
||||
/** Set locale units
|
||||
*
|
||||
@@ -175,7 +217,7 @@ void furi_hal_rtc_set_locale_units(FuriHalRtcLocaleUnits value);
|
||||
*
|
||||
* @return The RTC Locale Units.
|
||||
*/
|
||||
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units();
|
||||
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units(void);
|
||||
|
||||
/** Set RTC Locale Time Format
|
||||
*
|
||||
@@ -187,7 +229,7 @@ void furi_hal_rtc_set_locale_timeformat(FuriHalRtcLocaleTimeFormat value);
|
||||
*
|
||||
* @return The RTC Locale Time Format.
|
||||
*/
|
||||
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat();
|
||||
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat(void);
|
||||
|
||||
/** Set RTC Locale Date Format
|
||||
*
|
||||
@@ -199,7 +241,7 @@ void furi_hal_rtc_set_locale_dateformat(FuriHalRtcLocaleDateFormat value);
|
||||
*
|
||||
* @return The RTC Locale Date Format
|
||||
*/
|
||||
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat();
|
||||
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat(void);
|
||||
|
||||
/** Set RTC Date Time
|
||||
*
|
||||
@@ -231,7 +273,7 @@ void furi_hal_rtc_set_fault_data(uint32_t value);
|
||||
*
|
||||
* @return RTC Fault Data value
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_fault_data();
|
||||
uint32_t furi_hal_rtc_get_fault_data(void);
|
||||
|
||||
/** Set Pin Fails count
|
||||
*
|
||||
@@ -243,22 +285,33 @@ void furi_hal_rtc_set_pin_fails(uint32_t value);
|
||||
*
|
||||
* @return Pin Fails Count
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_pin_fails();
|
||||
uint32_t furi_hal_rtc_get_pin_fails(void);
|
||||
|
||||
/** Get UNIX Timestamp
|
||||
*
|
||||
* @return Unix Timestamp in seconds from UNIX epoch start
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_timestamp();
|
||||
uint32_t furi_hal_rtc_get_timestamp(void);
|
||||
|
||||
/** Convert DateTime to UNIX timestamp
|
||||
*
|
||||
* @warning Mind timezone when perform conversion
|
||||
*
|
||||
* @param datetime The datetime
|
||||
* @param datetime The datetime (UTC)
|
||||
*
|
||||
* @return UNIX Timestamp in seconds from UNIX epoch start
|
||||
*/
|
||||
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
|
||||
|
||||
/** Convert UNIX timestamp to DateTime
|
||||
*
|
||||
* @warning Mind timezone when perform conversion
|
||||
*
|
||||
* @param[in] timestamp UNIX Timestamp in seconds from UNIX epoch start
|
||||
* @param[out] datetime The datetime (UTC)
|
||||
*/
|
||||
void furi_hal_rtc_timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime);
|
||||
|
||||
/** Gets the number of days in the year according to the Gregorian calendar.
|
||||
*
|
||||
* @param year Input year.
|
||||
937
targets/f7/furi_hal/furi_hal_serial.c
Normal file
937
targets/f7/furi_hal/furi_hal_serial.c
Normal file
@@ -0,0 +1,937 @@
|
||||
#include <furi_hal_serial.h>
|
||||
#include "furi_hal_serial_types_i.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define FURI_HAL_SERIAL_USART_OVERSAMPLING LL_USART_OVERSAMPLING_16
|
||||
|
||||
#define FURI_HAL_SERIAL_USART_DMA_INSTANCE (DMA1)
|
||||
#define FURI_HAL_SERIAL_USART_DMA_CHANNEL (LL_DMA_CHANNEL_6)
|
||||
|
||||
#define FURI_HAL_SERIAL_LPUART_DMA_INSTANCE (DMA1)
|
||||
#define FURI_HAL_SERIAL_LPUART_DMA_CHANNEL (LL_DMA_CHANNEL_7)
|
||||
|
||||
typedef struct {
|
||||
uint8_t* buffer_rx_ptr;
|
||||
size_t buffer_rx_index_write;
|
||||
size_t buffer_rx_index_read;
|
||||
bool enabled;
|
||||
FuriHalSerialHandle* handle;
|
||||
FuriHalSerialAsyncRxCallback rx_byte_callback;
|
||||
FuriHalSerialDmaRxCallback rx_dma_callback;
|
||||
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);
|
||||
|
||||
static void furi_hal_serial_async_rx_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context);
|
||||
|
||||
static void furi_hal_serial_usart_irq_callback(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
FuriHalSerialRxEvent event = 0;
|
||||
// Notification flags
|
||||
if(USART1->ISR & USART_ISR_RXNE_RXFNE) {
|
||||
event |= FuriHalSerialRxEventData;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_IDLE) {
|
||||
USART1->ICR = USART_ICR_IDLECF;
|
||||
event |= FuriHalSerialRxEventIdle;
|
||||
}
|
||||
// Error flags
|
||||
if(USART1->ISR & USART_ISR_ORE) {
|
||||
USART1->ICR = USART_ICR_ORECF;
|
||||
event |= FuriHalSerialRxEventOverrunError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_NE) {
|
||||
USART1->ICR = USART_ICR_NECF;
|
||||
event |= FuriHalSerialRxEventNoiseError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_FE) {
|
||||
USART1->ICR = USART_ICR_FECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_PE) {
|
||||
USART1->ICR = USART_ICR_PECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr == NULL) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
event,
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
event,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_dma_rx_isr(void* context) {
|
||||
UNUSED(context);
|
||||
#if FURI_HAL_SERIAL_USART_DMA_CHANNEL == LL_DMA_CHANNEL_6
|
||||
if(LL_DMA_IsActiveFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write =
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE -
|
||||
LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
if((furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read >
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write) ||
|
||||
(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE / 4)) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
|
||||
} else if(LL_DMA_IsActiveFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE * 3 / 4) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_init_dma_rx(void) {
|
||||
/* USART1_RX_DMA Init */
|
||||
furi_check(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr == NULL);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write = 0;
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read = 0;
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr = malloc(FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetMemoryAddress(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
(uint32_t)furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr);
|
||||
LL_DMA_SetPeriphAddress(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
(uint32_t) & (USART1->RDR));
|
||||
|
||||
LL_DMA_ConfigTransfer(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE |
|
||||
LL_DMA_PRIORITY_HIGH);
|
||||
LL_DMA_SetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetPeriphRequest(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
LL_DMAMUX_REQ_USART1_RX);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch6, furi_hal_serial_usart_dma_rx_isr, NULL);
|
||||
|
||||
#if FURI_HAL_SERIAL_USART_DMA_CHANNEL == LL_DMA_CHANNEL_6
|
||||
if(LL_DMA_IsActiveFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TE6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TE6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_DMA_EnableIT_HT(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_EnableChannel(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_USART_EnableDMAReq_RX(USART1);
|
||||
|
||||
LL_USART_EnableIT_IDLE(USART1);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_deinit_dma_rx(void) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr != NULL) {
|
||||
LL_DMA_DisableChannel(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_USART_DisableDMAReq_RX(USART1);
|
||||
|
||||
LL_USART_DisableIT_IDLE(USART1);
|
||||
LL_DMA_DisableIT_TC(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_DMA_DisableIT_HT(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
|
||||
LL_DMA_DeInit(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch6, NULL, NULL);
|
||||
free(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_rx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
|
||||
LL_USART_InitTypeDef USART_InitStruct;
|
||||
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 = FURI_HAL_SERIAL_USART_OVERSAMPLING;
|
||||
LL_USART_Init(USART1, &USART_InitStruct);
|
||||
LL_USART_EnableFIFO(USART1);
|
||||
LL_USART_ConfigAsyncMode(USART1);
|
||||
|
||||
LL_USART_Enable(USART1);
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
|
||||
;
|
||||
|
||||
furi_hal_serial_set_br(handle, baud);
|
||||
LL_USART_DisableIT_ERROR(USART1);
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_irq_callback(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
FuriHalSerialRxEvent event = 0;
|
||||
// Notification flags
|
||||
if(LPUART1->ISR & USART_ISR_RXNE_RXFNE) {
|
||||
event |= FuriHalSerialRxEventData;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_IDLE) {
|
||||
LPUART1->ICR = USART_ICR_IDLECF;
|
||||
event |= FuriHalSerialRxEventIdle;
|
||||
}
|
||||
// Error flags
|
||||
if(LPUART1->ISR & USART_ISR_ORE) {
|
||||
LPUART1->ICR = USART_ICR_ORECF;
|
||||
event |= FuriHalSerialRxEventOverrunError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_NE) {
|
||||
LPUART1->ICR = USART_ICR_NECF;
|
||||
event |= FuriHalSerialRxEventNoiseError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_FE) {
|
||||
LPUART1->ICR = USART_ICR_FECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_PE) {
|
||||
LPUART1->ICR = USART_ICR_PECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr == NULL) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
event,
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
event,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_dma_rx_isr(void* context) {
|
||||
UNUSED(context);
|
||||
#if FURI_HAL_SERIAL_LPUART_DMA_CHANNEL == LL_DMA_CHANNEL_7
|
||||
if(LL_DMA_IsActiveFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write =
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE -
|
||||
LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
if((furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read >
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write) ||
|
||||
(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE / 4)) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
|
||||
} else if(LL_DMA_IsActiveFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE * 3 / 4) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_init_dma_rx(void) {
|
||||
/* LPUART1_RX_DMA Init */
|
||||
furi_check(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr == NULL);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write = 0;
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read = 0;
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr = malloc(FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetMemoryAddress(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
(uint32_t)furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr);
|
||||
LL_DMA_SetPeriphAddress(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
(uint32_t) & (LPUART1->RDR));
|
||||
|
||||
LL_DMA_ConfigTransfer(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE |
|
||||
LL_DMA_PRIORITY_HIGH);
|
||||
LL_DMA_SetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetPeriphRequest(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
LL_DMAMUX_REQ_LPUART1_RX);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch7, furi_hal_serial_lpuart_dma_rx_isr, NULL);
|
||||
|
||||
#if FURI_HAL_SERIAL_LPUART_DMA_CHANNEL == LL_DMA_CHANNEL_7
|
||||
if(LL_DMA_IsActiveFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TE7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TE7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_DMA_EnableIT_HT(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_EnableChannel(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_USART_EnableDMAReq_RX(LPUART1);
|
||||
|
||||
LL_USART_EnableIT_IDLE(LPUART1);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_deinit_dma_rx(void) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr != NULL) {
|
||||
LL_DMA_DisableChannel(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_USART_DisableDMAReq_RX(LPUART1);
|
||||
|
||||
LL_USART_DisableIT_IDLE(LPUART1);
|
||||
LL_DMA_DisableIT_TC(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_DMA_DisableIT_HT(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
|
||||
LL_DMA_DeInit(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch7, NULL, NULL);
|
||||
free(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusLPUART1);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc1,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
|
||||
LL_LPUART_InitTypeDef LPUART_InitStruct;
|
||||
LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
|
||||
LPUART_InitStruct.BaudRate = baud;
|
||||
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_EnableFIFO(LPUART1);
|
||||
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
|
||||
while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1))
|
||||
;
|
||||
|
||||
furi_hal_serial_set_br(handle, baud);
|
||||
LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
|
||||
void furi_hal_serial_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdLpuart) {
|
||||
furi_hal_serial_lpuart_init(handle, baud);
|
||||
} else if(handle->id == FuriHalSerialIdUsart) {
|
||||
furi_hal_serial_usart_init(handle, 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);
|
||||
uint32_t prescaler = 0;
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(FURI_HAL_SERIAL_USART_OVERSAMPLING == LL_USART_OVERSAMPLING_16) {
|
||||
divisor = (divisor / 16) >> 12;
|
||||
} else {
|
||||
divisor = (divisor / 8) >> 12;
|
||||
}
|
||||
if(divisor < 1) {
|
||||
prescaler = LL_USART_PRESCALER_DIV1;
|
||||
} else if(divisor < 2) {
|
||||
prescaler = LL_USART_PRESCALER_DIV2;
|
||||
} else if(divisor < 4) {
|
||||
prescaler = LL_USART_PRESCALER_DIV4;
|
||||
} else if(divisor < 6) {
|
||||
prescaler = LL_USART_PRESCALER_DIV6;
|
||||
} else if(divisor < 8) {
|
||||
prescaler = LL_USART_PRESCALER_DIV8;
|
||||
} else if(divisor < 10) {
|
||||
prescaler = LL_USART_PRESCALER_DIV10;
|
||||
} else if(divisor < 12) {
|
||||
prescaler = LL_USART_PRESCALER_DIV12;
|
||||
} else if(divisor < 16) {
|
||||
prescaler = LL_USART_PRESCALER_DIV16;
|
||||
} else if(divisor < 32) {
|
||||
prescaler = LL_USART_PRESCALER_DIV32;
|
||||
} else if(divisor < 64) {
|
||||
prescaler = LL_USART_PRESCALER_DIV64;
|
||||
} else if(divisor < 128) {
|
||||
prescaler = LL_USART_PRESCALER_DIV128;
|
||||
} else {
|
||||
prescaler = LL_USART_PRESCALER_DIV256;
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
divisor >>= 12;
|
||||
if(divisor < 1) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV1;
|
||||
} else if(divisor < 2) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV2;
|
||||
} else if(divisor < 4) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV4;
|
||||
} else if(divisor < 6) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV6;
|
||||
} else if(divisor < 8) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV8;
|
||||
} else if(divisor < 10) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV10;
|
||||
} else if(divisor < 12) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV12;
|
||||
} else if(divisor < 16) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV16;
|
||||
} else if(divisor < 32) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV32;
|
||||
} else if(divisor < 64) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV64;
|
||||
} else if(divisor < 128) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV128;
|
||||
} else {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV256;
|
||||
}
|
||||
}
|
||||
|
||||
return prescaler;
|
||||
}
|
||||
|
||||
void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_check(handle);
|
||||
uint32_t prescaler = furi_hal_serial_get_prescaler(handle, baud);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
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_SetPrescaler(USART1, prescaler);
|
||||
LL_USART_SetBaudRate(
|
||||
USART1, uartclk, prescaler, FURI_HAL_SERIAL_USART_OVERSAMPLING, baud);
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
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_LPUART1_CLKSOURCE);
|
||||
LL_LPUART_SetPrescaler(LPUART1, prescaler);
|
||||
LL_LPUART_SetBaudRate(LPUART1, uartclk, prescaler, baud);
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_serial_deinit(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
furi_hal_serial_async_rx_configure(handle, NULL, NULL);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusUSART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusUSART1);
|
||||
}
|
||||
if(LL_USART_IsEnabled(USART1)) {
|
||||
LL_USART_Disable(USART1);
|
||||
}
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
furi_hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusLPUART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusLPUART1);
|
||||
}
|
||||
if(LL_LPUART_IsEnabled(LPUART1)) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
}
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = false;
|
||||
}
|
||||
|
||||
void furi_hal_serial_suspend(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdLpuart && LL_LPUART_IsEnabled(LPUART1)) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
} else if(handle->id == FuriHalSerialIdUsart && LL_USART_IsEnabled(USART1)) {
|
||||
LL_USART_Disable(USART1);
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = false;
|
||||
}
|
||||
|
||||
void furi_hal_serial_resume(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(!furi_hal_serial[handle->id].enabled) {
|
||||
if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
} else if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_serial_tx(FuriHalSerialHandle* handle, const uint8_t* buffer, size_t buffer_size) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
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(handle->id == FuriHalSerialIdLpuart) {
|
||||
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_serial_tx_wait_complete(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabled(USART1) == 0) return;
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1) == 0) return;
|
||||
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_event_init(FuriHalSerialHandle* handle, bool report_errors) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_EnableIT_IDLE(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_EnableIT_IDLE(LPUART1);
|
||||
}
|
||||
|
||||
if(report_errors) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_EnableIT_ERROR(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_EnableIT_ERROR(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_event_deinit(FuriHalSerialHandle* handle) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabledIT_IDLE(USART1)) LL_USART_DisableIT_IDLE(USART1);
|
||||
if(LL_USART_IsEnabledIT_ERROR(USART1)) LL_USART_DisableIT_ERROR(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabledIT_IDLE(LPUART1)) LL_LPUART_DisableIT_IDLE(LPUART1);
|
||||
if(LL_LPUART_IsEnabledIT_ERROR(LPUART1)) LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_async_rx_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
} else {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
} else {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
}
|
||||
furi_hal_serial[handle->id].rx_byte_callback = callback;
|
||||
furi_hal_serial[handle->id].handle = handle;
|
||||
furi_hal_serial[handle->id].rx_dma_callback = NULL;
|
||||
furi_hal_serial[handle->id].context = context;
|
||||
}
|
||||
|
||||
void furi_hal_serial_async_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors) {
|
||||
furi_check(handle);
|
||||
furi_check(callback);
|
||||
|
||||
furi_hal_serial_event_init(handle, report_errors);
|
||||
furi_hal_serial_async_rx_configure(handle, callback, context);
|
||||
|
||||
// Assign different functions to different UARTs
|
||||
furi_check(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback !=
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback);
|
||||
}
|
||||
|
||||
void furi_hal_serial_async_rx_stop(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
furi_hal_serial_event_deinit(handle);
|
||||
furi_hal_serial_async_rx_configure(handle, NULL, NULL);
|
||||
}
|
||||
|
||||
uint8_t furi_hal_serial_async_rx(FuriHalSerialHandle* handle) {
|
||||
furi_check(FURI_IS_IRQ_MODE());
|
||||
furi_assert(handle->id < FuriHalSerialIdMax);
|
||||
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
return LL_USART_ReceiveData8(USART1);
|
||||
}
|
||||
return LL_LPUART_ReceiveData8(LPUART1);
|
||||
}
|
||||
|
||||
static size_t furi_hal_serial_dma_bytes_available(FuriHalSerialId ch) {
|
||||
size_t dma_remain = 0;
|
||||
if(ch == FuriHalSerialIdUsart) {
|
||||
dma_remain = LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
} else if(ch == FuriHalSerialIdLpuart) {
|
||||
dma_remain = LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
|
||||
furi_hal_serial[ch].buffer_rx_index_write = FURI_HAL_SERIAL_DMA_BUFFER_SIZE - dma_remain;
|
||||
if(furi_hal_serial[ch].buffer_rx_index_write >= furi_hal_serial[ch].buffer_rx_index_read) {
|
||||
return furi_hal_serial[ch].buffer_rx_index_write -
|
||||
furi_hal_serial[ch].buffer_rx_index_read;
|
||||
} else {
|
||||
return FURI_HAL_SERIAL_DMA_BUFFER_SIZE - furi_hal_serial[ch].buffer_rx_index_read +
|
||||
furi_hal_serial[ch].buffer_rx_index_write;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t furi_hal_serial_dma_rx_read_byte(FuriHalSerialHandle* handle) {
|
||||
uint8_t data = 0;
|
||||
data =
|
||||
furi_hal_serial[handle->id].buffer_rx_ptr[furi_hal_serial[handle->id].buffer_rx_index_read];
|
||||
furi_hal_serial[handle->id].buffer_rx_index_read++;
|
||||
if(furi_hal_serial[handle->id].buffer_rx_index_read >= FURI_HAL_SERIAL_DMA_BUFFER_SIZE) {
|
||||
furi_hal_serial[handle->id].buffer_rx_index_read = 0;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t furi_hal_serial_dma_rx(FuriHalSerialHandle* handle, uint8_t* data, size_t len) {
|
||||
furi_check(FURI_IS_IRQ_MODE());
|
||||
furi_assert(furi_hal_serial[handle->id].buffer_rx_ptr != NULL);
|
||||
size_t i = 0;
|
||||
size_t available = furi_hal_serial_dma_bytes_available(handle->id);
|
||||
if(available < len) {
|
||||
len = available;
|
||||
}
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = furi_hal_serial_dma_rx_read_byte(handle);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void furi_hal_serial_dma_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context) {
|
||||
furi_check(handle);
|
||||
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_usart_init_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
|
||||
} else {
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_lpuart_init_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
|
||||
} else {
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
}
|
||||
}
|
||||
furi_hal_serial[handle->id].rx_byte_callback = NULL;
|
||||
furi_hal_serial[handle->id].handle = handle;
|
||||
furi_hal_serial[handle->id].rx_dma_callback = callback;
|
||||
furi_hal_serial[handle->id].context = context;
|
||||
}
|
||||
|
||||
void furi_hal_serial_dma_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors) {
|
||||
furi_check(handle);
|
||||
furi_check(callback);
|
||||
|
||||
furi_hal_serial_event_init(handle, report_errors);
|
||||
furi_hal_serial_dma_configure(handle, callback, context);
|
||||
|
||||
// Assign different functions to different UARTs
|
||||
furi_check(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback !=
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback);
|
||||
}
|
||||
|
||||
void furi_hal_serial_dma_rx_stop(FuriHalSerialHandle* handle) {
|
||||
furi_check(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];
|
||||
}
|
||||
234
targets/f7/furi_hal/furi_hal_serial.h
Normal file
234
targets/f7/furi_hal/furi_hal_serial.h
Normal file
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
* @file furi_hal_serial.h
|
||||
*
|
||||
* Serial HAL API
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "furi_hal_serial_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Initialize Serial
|
||||
*
|
||||
* Configures GPIO, configures and enables transceiver.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param baud baud rate
|
||||
*/
|
||||
void furi_hal_serial_init(FuriHalSerialHandle* handle, uint32_t baud);
|
||||
|
||||
/** De-initialize Serial
|
||||
*
|
||||
* Configures GPIO to analog, clears callback and callback context, disables
|
||||
* hardware
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_deinit(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Suspend operation
|
||||
*
|
||||
* Suspend hardware, settings and callbacks are preserved
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_suspend(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Resume operation
|
||||
*
|
||||
* Resumes hardware from suspended state
|
||||
*
|
||||
* @param handle Serial 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
|
||||
* @param baud baud rate
|
||||
*/
|
||||
void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud);
|
||||
|
||||
/** Transmits data in semi-blocking mode
|
||||
*
|
||||
* Fills transmission pipe with data, returns as soon as all bytes from buffer
|
||||
* are in the pipe.
|
||||
*
|
||||
* Real transmission will be completed later. Use
|
||||
* `furi_hal_serial_tx_wait_complete` to wait for completion if you need it.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param buffer data
|
||||
* @param buffer_size data size (in bytes)
|
||||
*/
|
||||
void furi_hal_serial_tx(FuriHalSerialHandle* handle, const uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/** Wait until transmission is completed
|
||||
*
|
||||
* Ensures that all data has been sent.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_tx_wait_complete(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Serial RX events */
|
||||
typedef enum {
|
||||
FuriHalSerialRxEventData = (1 << 0), /**< Data: new data available */
|
||||
FuriHalSerialRxEventIdle = (1 << 1), /**< Idle: bus idle detected */
|
||||
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 */
|
||||
} FuriHalSerialRxEvent;
|
||||
|
||||
/** Receive callback
|
||||
*
|
||||
* @warning Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side.
|
||||
* @param handle Serial handle
|
||||
* @param event FuriHalSerialRxEvent
|
||||
* @param context Callback context provided earlier
|
||||
*/
|
||||
typedef void (*FuriHalSerialAsyncRxCallback)(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
void* context);
|
||||
|
||||
/** Start and sets Serial Receive callback
|
||||
*
|
||||
* @warning Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
* @param[in] report_errors report RX error
|
||||
*/
|
||||
void furi_hal_serial_async_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors);
|
||||
|
||||
/** Stop Serial Receive
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_async_rx_stop(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Get data Serial receive
|
||||
*
|
||||
* @warning This function must be called only from the callback
|
||||
* FuriHalSerialAsyncRxCallback
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*
|
||||
* @return data
|
||||
*/
|
||||
uint8_t furi_hal_serial_async_rx(FuriHalSerialHandle* handle);
|
||||
|
||||
/* DMA based Serial API */
|
||||
|
||||
#define FURI_HAL_SERIAL_DMA_BUFFER_SIZE (256u)
|
||||
|
||||
/** Receive DMA callback
|
||||
*
|
||||
* @warning DMA Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param event FuriHalSerialDmaRxEvent
|
||||
* @param data_len Received data
|
||||
* @param context Callback context provided earlier
|
||||
*/
|
||||
typedef void (*FuriHalSerialDmaRxCallback)(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
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
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
* @param[in] report_errors report RX error
|
||||
*/
|
||||
void furi_hal_serial_dma_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors);
|
||||
|
||||
/** Stop Serial receive DMA
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_dma_rx_stop(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Get data Serial receive DMA
|
||||
*
|
||||
* @warning This function must be called only from the callback
|
||||
* FuriHalSerialDmaRxCallback
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param data pointer to data buffer
|
||||
* @param len get data size (in bytes)
|
||||
*
|
||||
* @return size actual data receive (in bytes)
|
||||
*/
|
||||
size_t furi_hal_serial_dma_rx(FuriHalSerialHandle* handle, uint8_t* data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
365
targets/f7/furi_hal/furi_hal_serial_control.c
Normal file
365
targets/f7/furi_hal/furi_hal_serial_control.c
Normal file
@@ -0,0 +1,365 @@
|
||||
#include "furi_hal_serial_control.h"
|
||||
#include "furi_hal_serial_types_i.h"
|
||||
#include "furi_hal_serial.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <toolbox/api_lock.h>
|
||||
|
||||
#define TAG "FuriHalSerialControl"
|
||||
|
||||
typedef enum {
|
||||
FuriHalSerialControlMessageTypeStop,
|
||||
FuriHalSerialControlMessageTypeSuspend,
|
||||
FuriHalSerialControlMessageTypeResume,
|
||||
FuriHalSerialControlMessageTypeAcquire,
|
||||
FuriHalSerialControlMessageTypeRelease,
|
||||
FuriHalSerialControlMessageTypeLogging,
|
||||
FuriHalSerialControlMessageTypeExpansionSetCallback,
|
||||
FuriHalSerialControlMessageTypeExpansionIrq,
|
||||
} FuriHalSerialControlMessageType;
|
||||
|
||||
typedef struct {
|
||||
FuriHalSerialControlMessageType type;
|
||||
FuriApiLock api_lock;
|
||||
void* input;
|
||||
void* output;
|
||||
} FuriHalSerialControlMessage;
|
||||
|
||||
typedef struct {
|
||||
const FuriHalSerialId id;
|
||||
const uint32_t baud_rate;
|
||||
} FuriHalSerialControlMessageInputLogging;
|
||||
|
||||
typedef struct {
|
||||
const FuriHalSerialId id;
|
||||
const FuriHalSerialControlExpansionCallback callback;
|
||||
void* context;
|
||||
} FuriHalSerialControlMessageExpCallback;
|
||||
|
||||
typedef struct {
|
||||
FuriHalSerialHandle handles[FuriHalSerialIdMax];
|
||||
FuriMessageQueue* queue;
|
||||
FuriThread* thread;
|
||||
|
||||
// Logging
|
||||
FuriHalSerialId log_config_serial_id;
|
||||
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;
|
||||
|
||||
static void furi_hal_serial_control_log_callback(const uint8_t* data, size_t size, void* context) {
|
||||
FuriHalSerialHandle* handle = context;
|
||||
furi_hal_serial_tx(handle, data, size);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_control_log_set_handle(FuriHalSerialHandle* handle) {
|
||||
if(furi_hal_serial_control->log_serial) {
|
||||
furi_log_remove_handler(furi_hal_serial_control->log_handler);
|
||||
furi_hal_serial_deinit(furi_hal_serial_control->log_serial);
|
||||
furi_hal_serial_control->log_serial = NULL;
|
||||
}
|
||||
|
||||
if(handle) {
|
||||
furi_hal_serial_control->log_serial = handle;
|
||||
furi_hal_serial_init(
|
||||
furi_hal_serial_control->log_serial,
|
||||
furi_hal_serial_control->log_config_serial_baud_rate);
|
||||
furi_hal_serial_control->log_handler.callback = furi_hal_serial_control_log_callback;
|
||||
furi_hal_serial_control->log_handler.context = furi_hal_serial_control->log_serial;
|
||||
furi_log_add_handler(furi_hal_serial_control->log_handler);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
bool should_continue = true;
|
||||
while(should_continue || furi_message_queue_get_count(furi_hal_serial_control->queue) > 0) {
|
||||
FuriHalSerialControlMessage message = {0};
|
||||
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));
|
||||
|
||||
should_continue =
|
||||
furi_hal_serial_control_handlers[message.type](message.input, message.output);
|
||||
|
||||
if(message.api_lock != NULL) {
|
||||
api_lock_unlock(message.api_lock);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_init(void) {
|
||||
furi_check(furi_hal_serial_control == NULL);
|
||||
// Allocate resources
|
||||
furi_hal_serial_control = malloc(sizeof(FuriHalSerialControl));
|
||||
furi_hal_serial_control->handles[FuriHalSerialIdUsart].id = FuriHalSerialIdUsart;
|
||||
furi_hal_serial_control->handles[FuriHalSerialIdLpuart].id = FuriHalSerialIdLpuart;
|
||||
furi_hal_serial_control->queue =
|
||||
furi_message_queue_alloc(8, sizeof(FuriHalSerialControlMessage));
|
||||
furi_hal_serial_control->thread =
|
||||
furi_thread_alloc_ex("SerialControlDriver", 512, furi_hal_serial_control_thread, NULL);
|
||||
furi_thread_mark_as_service(furi_hal_serial_control->thread);
|
||||
furi_thread_set_priority(furi_hal_serial_control->thread, FuriThreadPriorityHighest);
|
||||
furi_hal_serial_control->log_config_serial_id = FuriHalSerialIdMax;
|
||||
// Start control plane thread
|
||||
furi_thread_start(furi_hal_serial_control->thread);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_deinit(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
// 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
|
||||
furi_thread_free(furi_hal_serial_control->thread);
|
||||
furi_message_queue_free(furi_hal_serial_control->queue);
|
||||
free(furi_hal_serial_control);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_suspend(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeSuspend;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
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_resume(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeResume;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
}
|
||||
|
||||
FuriHalSerialHandle* furi_hal_serial_control_acquire(FuriHalSerialId serial_id) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialHandle* output = NULL;
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeAcquire;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.input = &serial_id;
|
||||
message.output = &output;
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_release(FuriHalSerialHandle* handle) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
furi_check(handle);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeRelease;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.input = &handle;
|
||||
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_logging_config(FuriHalSerialId serial_id, uint32_t baud_rate) {
|
||||
furi_check(serial_id <= FuriHalSerialIdMax);
|
||||
furi_check(baud_rate >= 9600 && baud_rate <= 4000000);
|
||||
|
||||
// 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,
|
||||
};
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeLogging;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
67
targets/f7/furi_hal/furi_hal_serial_control.h
Normal file
67
targets/f7/furi_hal/furi_hal_serial_control.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "furi_hal_serial_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Initialize Serial Control */
|
||||
void furi_hal_serial_control_init(void);
|
||||
|
||||
/** De-Initialize Serial Control */
|
||||
void furi_hal_serial_control_deinit(void);
|
||||
|
||||
/** Suspend All Serial Interfaces */
|
||||
void furi_hal_serial_control_suspend(void);
|
||||
|
||||
/** Resume All Serial Interfaces */
|
||||
void furi_hal_serial_control_resume(void);
|
||||
|
||||
/** Acquire Serial Interface Handler
|
||||
*
|
||||
* @param[in] serial_id The serial transceiver identifier
|
||||
*
|
||||
* @return The Serial Interface Handle or null if interfaces is in use
|
||||
*/
|
||||
FuriHalSerialHandle* furi_hal_serial_control_acquire(FuriHalSerialId serial_id);
|
||||
|
||||
/** Release Serial Interface Handler
|
||||
*
|
||||
* @param handle The handle
|
||||
*/
|
||||
void furi_hal_serial_control_release(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Acquire Serial Interface Handler
|
||||
*
|
||||
* @param[in] serial_id The serial transceiver identifier. Use FuriHalSerialIdMax to disable logging.
|
||||
* @param[in] baud_rate The baud rate
|
||||
*
|
||||
* @return The Serial Interface Handle or null if interfaces is in use
|
||||
*/
|
||||
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
|
||||
22
targets/f7/furi_hal/furi_hal_serial_types.h
Normal file
22
targets/f7/furi_hal/furi_hal_serial_types.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
/**
|
||||
* UART channels
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalSerialIdUsart,
|
||||
FuriHalSerialIdLpuart,
|
||||
|
||||
FuriHalSerialIdMax,
|
||||
} FuriHalSerialId;
|
||||
|
||||
typedef enum {
|
||||
FuriHalSerialDirectionTx,
|
||||
FuriHalSerialDirectionRx,
|
||||
|
||||
FuriHalSerialDirectionMax,
|
||||
} FuriHalSerialDirection;
|
||||
|
||||
typedef struct FuriHalSerialHandle FuriHalSerialHandle;
|
||||
8
targets/f7/furi_hal/furi_hal_serial_types_i.h
Normal file
8
targets/f7/furi_hal/furi_hal_serial_types_i.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_serial_types.h>
|
||||
|
||||
struct FuriHalSerialHandle {
|
||||
FuriHalSerialId id;
|
||||
bool in_use;
|
||||
};
|
||||
@@ -36,7 +36,6 @@ typedef enum {
|
||||
SubGhzStateAsyncRx, /**< Async RX started */
|
||||
|
||||
SubGhzStateAsyncTx, /**< Async TX started, DMA and timer is on */
|
||||
SubGhzStateAsyncTxEnd, /**< Async TX complete, cleanup needed */
|
||||
|
||||
} SubGhzState;
|
||||
|
||||
@@ -305,12 +304,16 @@ void furi_hal_subghz_reset() {
|
||||
void furi_hal_subghz_idle() {
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
|
||||
cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
|
||||
//waiting for the chip to switch to IDLE mode
|
||||
furi_check(cc1101_wait_status_state(&furi_hal_spi_bus_handle_subghz, CC1101StateIDLE, 10000));
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
|
||||
}
|
||||
|
||||
void furi_hal_subghz_rx() {
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
|
||||
cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
|
||||
//waiting for the chip to switch to Rx mode
|
||||
furi_check(cc1101_wait_status_state(&furi_hal_spi_bus_handle_subghz, CC1101StateRX, 10000));
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
|
||||
}
|
||||
|
||||
@@ -318,6 +321,8 @@ bool furi_hal_subghz_tx() {
|
||||
if(furi_hal_subghz.regulation != SubGhzRegulationTxRx) return false;
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
|
||||
cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz);
|
||||
//waiting for the chip to switch to Tx mode
|
||||
furi_check(cc1101_wait_status_state(&furi_hal_spi_bus_handle_subghz, CC1101StateTX, 10000));
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
|
||||
return true;
|
||||
}
|
||||
@@ -405,10 +410,7 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
|
||||
uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value);
|
||||
cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
|
||||
|
||||
while(true) {
|
||||
CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
|
||||
if(status.STATE == CC1101StateIDLE) break;
|
||||
}
|
||||
furi_check(cc1101_wait_status_state(&furi_hal_spi_bus_handle_subghz, CC1101StateIDLE, 10000));
|
||||
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
|
||||
return real_frequency;
|
||||
@@ -678,7 +680,6 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
if(LL_DMA_IsActiveFlag_TC1(SUBGHZ_DMA)) {
|
||||
LL_DMA_ClearFlag_TC1(SUBGHZ_DMA);
|
||||
}
|
||||
LL_TIM_EnableIT_UPDATE(TIM2);
|
||||
break;
|
||||
} else {
|
||||
// Lowest possible value is 2us
|
||||
@@ -720,21 +721,6 @@ static void furi_hal_subghz_async_tx_dma_isr() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_subghz_async_tx_timer_isr() {
|
||||
if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) {
|
||||
LL_TIM_ClearFlag_UPDATE(TIM2);
|
||||
if(LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if(furi_hal_subghz.state == SubGhzStateAsyncTx) {
|
||||
furi_hal_subghz.state = SubGhzStateAsyncTxEnd;
|
||||
LL_DMA_DisableChannel(SUBGHZ_DMA_CH1_DEF);
|
||||
//forcibly pulls the pin to the ground so that there is no carrier
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
LL_TIM_DisableCounter(TIM2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* context) {
|
||||
furi_assert(furi_hal_subghz.state == SubGhzStateIdle);
|
||||
furi_assert(callback);
|
||||
@@ -755,7 +741,7 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
|
||||
// Connect CC1101_GD0 to TIM2 as output
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
|
||||
|
||||
// Configure DMA
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
@@ -769,7 +755,8 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
dma_config.NbData = FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
dma_config.Priority =
|
||||
LL_DMA_PRIORITY_VERYHIGH; // Ensure that ARR is updated before anyone else try to check it
|
||||
LL_DMA_Init(SUBGHZ_DMA_CH1_DEF, &dma_config);
|
||||
furi_hal_interrupt_set_isr(SUBGHZ_DMA_CH1_IRQ, furi_hal_subghz_async_tx_dma_isr, NULL);
|
||||
LL_DMA_EnableIT_TC(SUBGHZ_DMA_CH1_DEF);
|
||||
@@ -797,8 +784,6 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
LL_TIM_DisableMasterSlaveMode(TIM2);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_async_tx_timer_isr, NULL);
|
||||
|
||||
furi_hal_subghz_async_tx_middleware_idle(&furi_hal_subghz_async_tx.middleware);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL);
|
||||
@@ -806,15 +791,6 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
LL_TIM_EnableDMAReq_UPDATE(TIM2);
|
||||
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
|
||||
|
||||
// Start counter
|
||||
#ifdef FURI_HAL_SUBGHZ_TX_GPIO
|
||||
furi_hal_gpio_write(&FURI_HAL_SUBGHZ_TX_GPIO, true);
|
||||
#endif
|
||||
furi_hal_subghz_tx();
|
||||
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
|
||||
// Start debug
|
||||
if(furi_hal_subghz_start_debug()) {
|
||||
const GpioPin* gpio = furi_hal_subghz.async_mirror_pin;
|
||||
@@ -836,30 +812,36 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD;
|
||||
dma_config.NbData = 2;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_HIGH; // Ensure that it's updated after ARR
|
||||
LL_DMA_Init(SUBGHZ_DMA_CH2_DEF, &dma_config);
|
||||
LL_DMA_SetDataLength(SUBGHZ_DMA_CH2_DEF, 2);
|
||||
LL_DMA_EnableChannel(SUBGHZ_DMA_CH2_DEF);
|
||||
}
|
||||
|
||||
// Start counter
|
||||
#ifdef FURI_HAL_SUBGHZ_TX_GPIO
|
||||
furi_hal_gpio_write(&FURI_HAL_SUBGHZ_TX_GPIO, true);
|
||||
#endif
|
||||
furi_hal_subghz_tx();
|
||||
|
||||
LL_TIM_SetCounter(TIM2, 0);
|
||||
LL_TIM_EnableCounter(TIM2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool furi_hal_subghz_is_async_tx_complete() {
|
||||
return furi_hal_subghz.state == SubGhzStateAsyncTxEnd;
|
||||
return (furi_hal_subghz.state == SubGhzStateAsyncTx) && (LL_TIM_GetAutoReload(TIM2) == 0);
|
||||
}
|
||||
|
||||
void furi_hal_subghz_stop_async_tx() {
|
||||
furi_assert(
|
||||
furi_hal_subghz.state == SubGhzStateAsyncTx ||
|
||||
furi_hal_subghz.state == SubGhzStateAsyncTxEnd);
|
||||
|
||||
// Deinitialize GPIO
|
||||
// Keep in mind that cc1101 will try to pull it up in idle.
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
|
||||
furi_assert(furi_hal_subghz.state == SubGhzStateAsyncTx);
|
||||
|
||||
// Shutdown radio
|
||||
furi_hal_subghz_idle();
|
||||
|
||||
// Deinitialize GPIO
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
#ifdef FURI_HAL_SUBGHZ_TX_GPIO
|
||||
furi_hal_gpio_write(&FURI_HAL_SUBGHZ_TX_GPIO, false);
|
||||
#endif
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
#include <furi_hal_uart.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
static bool furi_hal_usart_prev_enabled[2];
|
||||
|
||||
static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context);
|
||||
static void* irq_ctx[2];
|
||||
|
||||
static void furi_hal_usart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_rx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
|
||||
LL_USART_InitTypeDef USART_InitStruct;
|
||||
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_EnableFIFO(USART1);
|
||||
LL_USART_ConfigAsyncMode(USART1);
|
||||
|
||||
LL_USART_Enable(USART1);
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
|
||||
;
|
||||
|
||||
LL_USART_DisableIT_ERROR(USART1);
|
||||
|
||||
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
}
|
||||
|
||||
static void furi_hal_lpuart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusLPUART1);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc1,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
|
||||
LL_LPUART_InitTypeDef LPUART_InitStruct;
|
||||
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_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_DisableIT_ERROR(LPUART1);
|
||||
|
||||
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 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_LPUART1_CLKSOURCE);
|
||||
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, NULL);
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusUSART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusUSART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusLPUART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusLPUART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_suspend(FuriHalUartId channel) {
|
||||
if(channel == FuriHalUartIdLPUART1 && LL_LPUART_IsEnabled(LPUART1)) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
furi_hal_usart_prev_enabled[channel] = true;
|
||||
} else if(channel == FuriHalUartIdUSART1 && LL_USART_IsEnabled(USART1)) {
|
||||
LL_USART_Disable(USART1);
|
||||
furi_hal_usart_prev_enabled[channel] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_resume(FuriHalUartId channel) {
|
||||
if(!furi_hal_usart_prev_enabled[channel]) {
|
||||
return;
|
||||
} else if(channel == FuriHalUartIdLPUART1) {
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
} else if(channel == FuriHalUartIdUSART1) {
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
|
||||
furi_hal_usart_prev_enabled[channel] = false;
|
||||
}
|
||||
|
||||
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, void* ctx),
|
||||
void* ctx) {
|
||||
if(cb == NULL) {
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_DisableIRQ(USART1_IRQn);
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_DisableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
irq_cb[ch] = cb;
|
||||
irq_ctx[ch] = ctx;
|
||||
} else {
|
||||
irq_ctx[ch] = ctx;
|
||||
irq_cb[ch] = cb;
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_EnableIRQ(USART1_IRQn);
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_EnableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LPUART1_IRQHandler(void) {
|
||||
if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) {
|
||||
uint8_t data = LL_LPUART_ReceiveData8(LPUART1);
|
||||
irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]);
|
||||
} else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) {
|
||||
LL_LPUART_ClearFlag_ORE(LPUART1);
|
||||
}
|
||||
}
|
||||
|
||||
void USART1_IRQHandler(void) {
|
||||
if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) {
|
||||
uint8_t data = LL_USART_ReceiveData8(USART1);
|
||||
irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]);
|
||||
} else if(LL_USART_IsActiveFlag_ORE(USART1)) {
|
||||
LL_USART_ClearFlag_ORE(USART1);
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* @file furi_hal_uart.h
|
||||
* @version 1.0
|
||||
* @date 2021-11-19
|
||||
*
|
||||
* UART HAL api interface
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* UART channels
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalUartIdUSART1,
|
||||
FuriHalUartIdLPUART1,
|
||||
} FuriHalUartId;
|
||||
|
||||
/**
|
||||
* UART events
|
||||
*/
|
||||
typedef enum {
|
||||
UartIrqEventRXNE,
|
||||
} UartIrqEvent;
|
||||
|
||||
/**
|
||||
* Init UART
|
||||
* Configures GPIO to UART function, configures UART hardware, enables UART hardware
|
||||
* @param channel UART channel
|
||||
* @param baud baudrate
|
||||
*/
|
||||
void furi_hal_uart_init(FuriHalUartId channel, uint32_t baud);
|
||||
|
||||
/**
|
||||
* Deinit UART
|
||||
* Configures GPIO to analog, clears callback and callback context, disables UART hardware
|
||||
* @param channel UART channel
|
||||
*/
|
||||
void furi_hal_uart_deinit(FuriHalUartId channel);
|
||||
|
||||
/**
|
||||
* Suspend UART operation
|
||||
* Disables UART hardware, settings and callbacks are preserved
|
||||
* @param channel UART channel
|
||||
*/
|
||||
void furi_hal_uart_suspend(FuriHalUartId channel);
|
||||
|
||||
/**
|
||||
* Resume UART operation
|
||||
* Resumes UART hardware from suspended state
|
||||
* @param channel UART channel
|
||||
*/
|
||||
void furi_hal_uart_resume(FuriHalUartId channel);
|
||||
|
||||
/**
|
||||
* Changes UART baudrate
|
||||
* @param channel UART channel
|
||||
* @param baud baudrate
|
||||
*/
|
||||
void furi_hal_uart_set_br(FuriHalUartId channel, uint32_t baud);
|
||||
|
||||
/**
|
||||
* Transmits data
|
||||
* @param channel UART channel
|
||||
* @param buffer data
|
||||
* @param buffer_size data size (in bytes)
|
||||
*/
|
||||
void furi_hal_uart_tx(FuriHalUartId channel, uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Sets UART event callback
|
||||
* @param channel UART channel
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
*/
|
||||
void furi_hal_uart_set_irq_cb(
|
||||
FuriHalUartId channel,
|
||||
void (*callback)(UartIrqEvent event, uint8_t data, void* context),
|
||||
void* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -14,7 +14,6 @@ struct STOP_EXTERNING_ME {};
|
||||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_dma.h>
|
||||
#include <furi_hal_os.h>
|
||||
@@ -36,7 +35,8 @@ struct STOP_EXTERNING_ME {};
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <furi_hal_usb_ccid.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
#include <furi_hal_serial.h>
|
||||
#include <furi_hal_info.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_target_hw.h>
|
||||
|
||||
Reference in New Issue
Block a user