Merge branch 'UFW_dev' into lfrfid_t5577

This commit is contained in:
gid9798 2023-05-30 11:20:01 +03:00
commit da4a8eb5c1
103 changed files with 3515 additions and 3480 deletions

22
.gitignore vendored
View File

@ -30,28 +30,26 @@ bindings/
.mxproject
Brewfile.lock.json
# Visual Studio Code
/.vscode/
# Kate
.kateproject
.kateconfig
# legendary cmake's
build
CMakeLists.txt
# bundle output
dist
# kde
.directory
null.d
# SCons
.sconsign.dblite
# Visual Studio Code
/.vscode
# bundle output
/dist
# SCons build dir
build/
/build
# Toolchain
/toolchain
@ -65,3 +63,5 @@ PVS-Studio.log
*.PVS-Studio.*
.gdbinit
/fbt_options_local.py

View File

@ -14,9 +14,7 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
furi_hal_rfid_comp_start();
furi_hal_rfid_pins_read();
furi_hal_rfid_tim_read(125000, 0.5);
furi_hal_rfid_tim_read_start();
furi_hal_rfid_tim_read_start(125000, 0.5);
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
}
@ -43,6 +41,5 @@ void lfrfid_debug_scene_tune_on_exit(void* context) {
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
furi_hal_rfid_tim_read_stop();
furi_hal_rfid_tim_reset();
furi_hal_rfid_pins_reset();
}

View File

@ -13,5 +13,4 @@ App(
fap_category="Tools",
fap_icon="images/badbt_10px.png",
fap_icon_assets="images",
fap_icon_assets_symbol="bad_bt",
)

View File

@ -28,7 +28,7 @@ const UART_TerminalItem items[NUM_MENU_ITEMS] = {
9,
{"115200", "2400", "9600", "19200", "38400", "57600", "230400", "460800", "921600"},
NO_ARGS,
FOCUS_CONSOLE_TOGGLE,
FOCUS_CONSOLE_END,
NO_TIP},
{"Send command", {""}, 1, {""}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},
{"Send AT command", {""}, 1, {"AT"}, INPUT_ARGS, FOCUS_CONSOLE_END, NO_TIP},

View File

@ -0,0 +1,19 @@
# WiFi Marauder companion app for Flipper Zero
## https://github.com/0xchocolate/flipperzero-wifi-marauder
Requires a connected dev board running Marauder FW. [See install instructions from UberGuidoZ here.](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard#marauder-install-information)
## Support
For app feedback, bugs, and feature requests, please [create an issue here](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion/issues).
You can find me (0xchocolate) on discord as @cococode#6011.
If you'd like to donate to the app development effort:
**ETH**: `0xf32A1F0CD6122C97d8953183E53cB889cc087C9b`
**BTC**: `bc1qtw7s25cwdkuaups22yna8sttfxn0usm2f35wc3`
Find more info about Marauder and support its developer (justcallmekoko aka WillStunForFood) here: https://github.com/justcallmekoko/ESP32Marauder
If you found the app preinstalled in a firmware release, consider supporting the maintainers!

View File

@ -4,7 +4,7 @@
extern "C" {
#endif
#define WIFI_MARAUDER_APP_VERSION "v0.3.7"
#define WIFI_MARAUDER_APP_VERSION "v0.4.0"
typedef struct WifiMarauderApp WifiMarauderApp;

View File

@ -11,7 +11,6 @@ void infrared_scene_universal_ac_on_enter(void* context) {
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/ac.ir"));
//TODO Improve A/C universal remote
button_panel_reserve(button_panel, 2, 3);
uint32_t i = 0;
button_panel_add_item(
@ -20,77 +19,74 @@ void infrared_scene_universal_ac_on_enter(void* context) {
0,
0,
3,
24,
&I_Power_25x27,
&I_Power_hvr_25x27,
22,
&I_Off_25x27,
&I_Off_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "POWER");
infrared_brute_force_add_record(brute_force, i++, "Off");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
24,
&I_Mode_25x27,
&I_Mode_hvr_25x27,
22,
&I_Dehumidify_25x27,
&I_Dehumidify_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "MODE");
infrared_brute_force_add_record(brute_force, i++, "Dh");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
66,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
59,
&I_CoolHi_25x27,
&I_CoolHi_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "TEMP+");
infrared_brute_force_add_record(brute_force, i++, "Cool_hi");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
66,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
59,
&I_HeatHi_25x27,
&I_HeatHi_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "TEMP-");
infrared_brute_force_add_record(brute_force, i++, "Heat_hi");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
98,
&I_Swing_25x27,
&I_Swing_hvr_25x27,
91,
&I_CoolLo_25x27,
&I_CoolLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "SWING");
infrared_brute_force_add_record(brute_force, i++, "Cool_lo");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
98,
&I_Timer_25x27,
&I_Timer_hvr_25x27,
91,
&I_HeatLo_25x27,
&I_HeatLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "TIMER");
infrared_brute_force_add_record(brute_force, i++, "Heat_lo");
button_panel_add_label(button_panel, 6, 11, FontPrimary, "AC remote");
button_panel_add_label(button_panel, 20, 63, FontSecondary, "Temp");
button_panel_add_label(button_panel, 8, 23, FontSecondary, "Pwr");
button_panel_add_label(button_panel, 40, 23, FontSecondary, "Mod");
button_panel_add_label(button_panel, 6, 10, FontPrimary, "AC remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@ -10,8 +10,8 @@ void infrared_scene_universal_audio_on_enter(void* context) {
InfraredBruteForce* brute_force = infrared->brute_force;
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/audio.ir"));
//TODO Improve Audio universal remote
button_panel_reserve(button_panel, 2, 2);
button_panel_reserve(button_panel, 2, 4);
uint32_t i = 0;
button_panel_add_item(
button_panel,
@ -19,51 +19,98 @@ void infrared_scene_universal_audio_on_enter(void* context) {
0,
0,
3,
19,
11,
&I_Power_25x27,
&I_Power_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "POWER");
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
19,
11,
&I_Mute_25x27,
&I_Mute_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "MUTE");
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
64,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
41,
&I_Play_25x27,
&I_Play_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL+");
infrared_brute_force_add_record(brute_force, i++, "Play");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
64,
41,
&I_Pause_25x27,
&I_Pause_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Pause");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
71,
&I_TrackPrev_25x27,
&I_TrackPrev_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Prev");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
71,
&I_TrackNext_25x27,
&I_TrackNext_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Next");
button_panel_add_item(
button_panel,
i,
0,
3,
3,
101,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL-");
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_item(
button_panel,
i,
1,
3,
36,
101,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_label(button_panel, 5, 11, FontSecondary, "Audio remote");
button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume");
button_panel_add_label(button_panel, 1, 8, FontPrimary, "Mus. remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);

View File

@ -25,7 +25,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Power_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "POWER");
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
@ -37,7 +37,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Mode_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "MODE");
infrared_brute_force_add_record(brute_force, i++, "Mode");
button_panel_add_item(
button_panel,
i,
@ -49,7 +49,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "SPEED+");
infrared_brute_force_add_record(brute_force, i++, "Speed_up");
button_panel_add_item(
button_panel,
i,
@ -61,7 +61,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "SPEED-");
infrared_brute_force_add_record(brute_force, i++, "Speed_dn");
button_panel_add_item(
button_panel,
i,
@ -73,7 +73,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Rotate_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "ROTATE");
infrared_brute_force_add_record(brute_force, i++, "Rotate");
button_panel_add_item(
button_panel,
i,
@ -85,7 +85,7 @@ void infrared_scene_universal_fan_on_enter(void* context) {
&I_Timer_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "TIMER");
infrared_brute_force_add_record(brute_force, i++, "Timer");
button_panel_add_label(button_panel, 5, 11, FontPrimary, "Fan remote");
button_panel_add_label(button_panel, 20, 63, FontSecondary, "Speed");

View File

@ -24,7 +24,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
&I_Power_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "POWER");
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
@ -36,7 +36,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
&I_Mute_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "MUTE");
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
@ -48,7 +48,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL+");
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_item(
button_panel,
i,
@ -60,7 +60,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL-");
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector");
button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume");

View File

@ -24,7 +24,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Power_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "POWER");
infrared_brute_force_add_record(brute_force, i++, "Power");
button_panel_add_item(
button_panel,
i,
@ -36,7 +36,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Mute_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "MUTE");
infrared_brute_force_add_record(brute_force, i++, "Mute");
button_panel_add_item(
button_panel,
i,
@ -48,7 +48,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL+");
infrared_brute_force_add_record(brute_force, i++, "Vol_up");
button_panel_add_item(
button_panel,
i,
@ -60,7 +60,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Up_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "CH+");
infrared_brute_force_add_record(brute_force, i++, "Ch_next");
button_panel_add_item(
button_panel,
i,
@ -72,7 +72,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "VOL-");
infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_item(
button_panel,
i,
@ -84,7 +84,7 @@ void infrared_scene_universal_tv_on_enter(void* context) {
&I_Down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "CH-");
infrared_brute_force_add_record(brute_force, i++, "Ch_prev");
button_panel_add_label(button_panel, 6, 11, FontPrimary, "TV remote");
button_panel_add_label(button_panel, 9, 64, FontSecondary, "Vol");

View File

@ -52,6 +52,7 @@ void nfc_scene_device_info_on_enter(void* context) {
}
} else if(
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
dev_data->protocol == NfcDeviceProtocolMifareDesfire ||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
furi_string_set(temp_str, nfc->dev->dev_data.parsed_data);
}

View File

@ -20,35 +20,40 @@ void nfc_scene_mf_desfire_read_success_on_enter(void* context) {
Widget* widget = nfc->widget;
// Prepare string for data display
FuriString* temp_str = furi_string_alloc_printf("\e#MIFARE DESfire\n");
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
}
uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1);
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
furi_string_cat_printf(temp_str, "\n%lu", bytes_total);
if(data->version.sw_storage & 1) {
furi_string_push_back(temp_str, '+');
}
furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free);
uint16_t n_apps = 0;
uint16_t n_files = 0;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
n_apps++;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
n_files++;
FuriString* temp_str = NULL;
if(furi_string_size(nfc->dev->dev_data.parsed_data)) {
temp_str = furi_string_alloc_set(nfc->dev->dev_data.parsed_data);
} else {
temp_str = furi_string_alloc_printf("\e#MIFARE DESFire\n");
furi_string_cat_printf(temp_str, "UID:");
for(size_t i = 0; i < nfc_data->uid_len; i++) {
furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]);
}
uint32_t bytes_total = 1UL << (data->version.sw_storage >> 1);
uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0;
furi_string_cat_printf(temp_str, "\n%lu", bytes_total);
if(data->version.sw_storage & 1) {
furi_string_push_back(temp_str, '+');
}
furi_string_cat_printf(temp_str, " bytes, %lu bytes free\n", bytes_free);
uint16_t n_apps = 0;
uint16_t n_files = 0;
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
n_apps++;
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
n_files++;
}
}
furi_string_cat_printf(temp_str, "%d Application", n_apps);
if(n_apps != 1) {
furi_string_push_back(temp_str, 's');
}
furi_string_cat_printf(temp_str, ", %d file", n_files);
if(n_files != 1) {
furi_string_push_back(temp_str, 's');
}
}
furi_string_cat_printf(temp_str, "%d Application", n_apps);
if(n_apps != 1) {
furi_string_push_back(temp_str, 's');
}
furi_string_cat_printf(temp_str, ", %d file", n_files);
if(n_files != 1) {
furi_string_push_back(temp_str, 's');
}
notification_message_block(nfc->notifications, &sequence_set_green_255);

View File

@ -51,7 +51,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) {
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type));
} else if(protocol == NfcDeviceProtocolMifareDesfire) {
furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n");
furi_string_cat_printf(temp_str, "\e#MIFARE DESFire\n");
} else if(protocol == NfcDeviceProtocolNfcV) {
switch(dev_data->nfcv_data.sub_type) {
case NfcVTypePlain:

View File

@ -152,6 +152,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) {
application_info_present = true;
} else if(
dev_data->protocol == NfcDeviceProtocolMifareClassic ||
dev_data->protocol == NfcDeviceProtocolMifareDesfire ||
dev_data->protocol == NfcDeviceProtocolMifareUl) {
application_info_present = nfc_supported_card_verify_and_parse(dev_data);
}

View File

@ -49,11 +49,32 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context)
canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8);
}
static void desktop_toggle_clock_view(Desktop* desktop, bool is_enabled) {
static void desktop_clock_upd_time(Desktop* desktop, bool forced) {
furi_assert(desktop);
// clock type upd after 1 minute
desktop->clock_type = (locale_get_time_format() == LocaleTimeFormat24h);
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
if(forced) {
desktop->clock_type = (locale_get_time_format() == LocaleTimeFormat24h);
}
if(forced || (desktop->minute != curr_dt.minute)) {
if(desktop->clock_type) {
desktop->hour = curr_dt.hour;
} else {
desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 :
((curr_dt.hour == 0) ? 12 : curr_dt.hour);
}
desktop->minute = curr_dt.minute;
view_port_update(desktop->clock_viewport);
}
}
static void desktop_clock_toggle_view(Desktop* desktop, bool is_enabled) {
furi_assert(desktop);
desktop_clock_upd_time(desktop, true);
if(is_enabled) { // && !furi_timer_is_running(desktop->update_clock_timer)) {
furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000));
@ -141,7 +162,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) {
// locking and unlocking
DESKTOP_SETTINGS_LOAD(&desktop->settings);
desktop_toggle_clock_view(desktop, desktop->settings.display_clock);
desktop_clock_toggle_view(desktop, desktop->settings.display_clock);
desktop_auto_lock_arm(desktop);
return true;
@ -208,24 +229,12 @@ static void desktop_auto_lock_inhibit(Desktop* desktop) {
}
}
static void desktop_update_clock_timer_callback(void* context) {
static void desktop_clock_timer_callback(void* context) {
furi_assert(context);
Desktop* desktop = context;
if(gui_get_count_of_enabled_view_port_in_layer(desktop->gui, GuiLayerStatusBarLeft) < 6) {
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
if(desktop->minute != curr_dt.minute) {
if(desktop->clock_type) {
desktop->hour = curr_dt.hour;
} else {
desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 :
((curr_dt.hour == 0) ? 12 : curr_dt.hour);
}
desktop->minute = curr_dt.minute;
view_port_update(desktop->clock_viewport);
}
desktop_clock_upd_time(desktop, false);
view_port_enabled_set(desktop->clock_viewport, true);
} else {
@ -424,18 +433,12 @@ Desktop* desktop_alloc() {
desktop->status_pubsub = furi_pubsub_alloc();
desktop->update_clock_timer =
furi_timer_alloc(desktop_update_clock_timer_callback, FuriTimerTypePeriodic, desktop);
furi_timer_alloc(desktop_clock_timer_callback, FuriTimerTypePeriodic, desktop);
FuriHalRtcDateTime curr_dt;
furi_hal_rtc_get_datetime(&curr_dt);
if(desktop->clock_type) {
desktop->hour = curr_dt.hour;
} else {
desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 :
((curr_dt.hour == 0) ? 12 : curr_dt.hour);
}
desktop->minute = curr_dt.minute;
desktop_clock_upd_time(desktop, true);
furi_record_create(RECORD_DESKTOP, desktop);
@ -483,7 +486,7 @@ int32_t desktop_srv(void* p) {
view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode);
desktop_toggle_clock_view(desktop, desktop->settings.display_clock);
desktop_clock_toggle_view(desktop, desktop->settings.display_clock);
desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode);
animation_manager_set_dummy_mode_state(

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

113
documentation/FuriHalBus.md Normal file
View File

@ -0,0 +1,113 @@
# Using FuriHalBus API
## Basic info
On system startup, most of the peripheral devices are under reset and not clocked by default. This is done to reduce power consumption and to guarantee that the device will always be in the same state before use.
Some crucial peripherals are enabled right away by the system, others must be explicitly enabled by the user code.
**NOTE:** Here and afterwards the word *"system"* refers to any code belonging to the operating system, hardware drivers or built-in applications.
To **ENABLE** a peripheral, call `furi_hal_bus_enable()`. At the time of the call, the peripheral in question MUST be disabled, otherwise a crash will occur to indicate improper use. This means that any given peripheral cannot be enabled twice or more without disabling it first.
To **DISABLE** a peripheral, call `furi_hal_bus_disable()`. Likewise, the peripheral in question MUST be enabled, otherwise a crash will occur.
To **RESET** a peripheral, call `furi_hal_bus_reset()`. The peripheral in question MUST be enabled, otherwise a crash will occur. This method is used whenever it is necessary to reset all the peripheral's registers to their initial states without disabling it.
## Peripherals
Built-in peripherals are divided into three categories:
- Enabled by the system on startup, never disabled;
- Enabled and disabled by the system on demand;
- Enabled and disabled by the user code.
### Always-on peripherals
Below is the list of peripherals that are enabled by the system. The user code must NEVER attempt to disable them. If a corresponding API is provided, the user code must employ it in order to access the peripheral.
*Table 1* - Peripherals enabled by the system
| Peripheral | Enabled at |
| :-----------: | :-----------------------: |
| DMA1 | `furi_hal_dma.c` |
| DMA2 | -- |
| DMAMUX | -- |
| GPIOA | `furi_hal_resources.c` |
| GPIOB | -- |
| GPIOC | -- |
| GPIOD | -- |
| GPIOE | -- |
| GPIOH | -- |
| PKA | `furi_hal_bt.c` |
| AES2 | -- |
| HSEM | -- |
| IPCC | -- |
| FLASH | enabled by hardware |
### On-demand system peripherals
Below is the list of peripherals that are enabled and disabled by the system. The user code must avoid using them directly, preferring the respective APIs instead.
When not using the API, these peripherals MUST be enabled by the user code and then disabled when not needed anymore.
*Table 2* - Peripherals enabled and disabled by the system
| Peripheral | API header file |
| :-----------: | :-------------------: |
| RNG | `furi_hal_random.h` |
| SPI1 | `furi_hal_spi.h` |
| SPI2 | -- |
| I2C1 | `furi_hal_i2c.h` |
| I2C3 | -- |
| USART1 | `furi_hal_uart.h` |
| LPUART1 | -- |
| USB | `furi_hal_usb.h` |
### On-demand shared peripherals
Below is the list of peripherals that are not enabled by default and MUST be enabled by the user code each time it accesses them.
Note that some of these peripherals may also be used by the system to implement its certain features.
The system will take over any given peripheral only when the respective feature is in use.
*Table 3* - Peripherals enabled and disabled by user
| Peripheral | System | Purpose |
| :-----------: | :-------: | ------------------------------------- |
| CRC | | |
| TSC | | |
| ADC | | |
| QUADSPI | | |
| TIM1 | yes | subghz, lfrfid, nfc, infrared, etc... |
| TIM2 | yes | -- |
| TIM16 | yes | speaker |
| TIM17 | | |
| LPTIM1 | yes | tickless idle timer |
| LPTIM2 | yes | pwm |
| SAI1 | | |
| LCD | | |
## DMA
The DMA1,2 peripherals are a special case in that they have multiple independent channels. Some of the channels may be in use by the system.
Below is the list of DMA channels and their usage by the system.
*Table 4* - DMA channels
| DMA | Channel | System | Purpose |
| :---: | :-------: | :-------: | ------------------------- |
| DMA1 | 1 | yes | digital signal |
| -- | 2 | yes | -- |
| -- | 3 | | |
| -- | 4 | yes | pulse reader |
| -- | 5 | | |
| -- | 6 | | |
| -- | 7 | | |
| DMA2 | 1 | yes | infrared, lfrfid, subghz |
| -- | 2 | yes | -- |
| -- | 3 | yes | SPI |
| -- | 4 | yes | SPI |
| -- | 5 | | |
| -- | 6 | | |
| -- | 7 | | |

View File

@ -114,6 +114,8 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio
Default configuration variables are set in the configuration file: `fbt_options.py`.
Values set in the command line have higher precedence over the configuration file.
You can also create a file called `fbt_options_local.py` that will be evaluated when loading default options file, enabling persisent overriding of default options without modifying default configuration.
You can find out available options with `./fbt -h`.
### Firmware application set

View File

@ -1,7 +1,9 @@
from pathlib import Path
import posixpath
# For more details on these options, run 'fbt -h'
FIRMWARE_ORIGIN = "Unleashed"
# Default hardware target
TARGET_HW = 7
@ -88,3 +90,8 @@ FIRMWARE_APPS = {
}
FIRMWARE_APP_SET = "default"
custom_options_fn = "fbt_options_local.py"
if Path(custom_options_fn).exists():
exec(compile(Path(custom_options_fn).read_text(), custom_options_fn, "exec"))

View File

@ -18,6 +18,7 @@ env = ENV.Clone(
"fbt_apps",
"pvsstudio",
"fbt_hwtarget",
"fbt_envhooks",
],
COMPILATIONDB_USE_ABSPATH=False,
BUILD_DIR=fw_build_meta["build_dir"],
@ -72,6 +73,8 @@ env = ENV.Clone(
_APP_ICONS=None,
)
env.PreConfigureFwEnvionment()
if env["IS_BASE_FIRMWARE"]:
env.Append(
FIRMWARE_BUILD_CFG="firmware",
@ -100,6 +103,13 @@ lib_targets = env.BuildModules(
],
)
# Configure firmware origin definitions
env.Append(
CPPDEFINES=[
env.subst("FW_ORIGIN_${FIRMWARE_ORIGIN}"),
]
)
# Now, env is fully set up with everything to build apps
fwenv = env.Clone(FW_ARTIFACTS=[])
@ -271,5 +281,6 @@ if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS):
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_all", fw_artifacts)
env.PostConfigureFwEnvionment()
Return("fwenv")

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,27.0,,
Version,+,28.1,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -40,8 +40,10 @@ Header,-,firmware/targets/f18/furi_hal/furi_hal_power_calibration.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_resources.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_spi_config.h,,
Header,+,firmware/targets/f18/furi_hal/furi_hal_target_hw.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,,
@ -873,6 +875,12 @@ Function,+,furi_hal_bt_stop_tone_tx,void,
Function,+,furi_hal_bt_unlock_core2,void,
Function,+,furi_hal_bt_update_battery_level,void,uint8_t
Function,+,furi_hal_bt_update_power_state,void,
Function,+,furi_hal_bus_deinit_early,void,
Function,+,furi_hal_bus_disable,void,FuriHalBus
Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@ -915,6 +923,8 @@ Function,+,furi_hal_debug_disable,void,
Function,+,furi_hal_debug_enable,void,
Function,+,furi_hal_debug_is_gdb_session_active,_Bool,
Function,-,furi_hal_deinit_early,void,
Function,+,furi_hal_dma_deinit_early,void,
Function,+,furi_hal_dma_init_early,void,
Function,-,furi_hal_flash_erase,void,uint8_t
Function,-,furi_hal_flash_get_base,size_t,
Function,-,furi_hal_flash_get_cycles_count,size_t,
@ -1033,6 +1043,7 @@ Function,+,furi_hal_pwm_start,void,"FuriHalPwmOutputId, uint32_t, uint8_t"
Function,+,furi_hal_pwm_stop,void,FuriHalPwmOutputId
Function,+,furi_hal_random_fill_buf,void,"uint8_t*, uint32_t"
Function,+,furi_hal_random_get,uint32_t,
Function,+,furi_hal_random_init,void,
Function,+,furi_hal_region_get,const FuriHalRegion*,
Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t
Function,+,furi_hal_region_get_name,const char*,
@ -1048,6 +1059,8 @@ Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
Function,-,furi_hal_rtc_deinit_early,void,
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
@ -1060,6 +1073,7 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
Function,-,furi_hal_rtc_init,void,
Function,-,furi_hal_rtc_init_early,void,
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
@ -1989,6 +2003,8 @@ Function,-,vdprintf,int,"int, const char*, __gnuc_va_list"
Function,+,version_get,const Version*,
Function,+,version_get_builddate,const char*,const Version*
Function,+,version_get_dirty_flag,_Bool,const Version*
Function,+,version_get_firmware_origin,const char*,const Version*
Function,+,version_get_git_origin,const char*,const Version*
Function,+,version_get_gitbranch,const char*,const Version*
Function,+,version_get_gitbranchnum,const char*,const Version*
Function,+,version_get_githash,const char*,const Version*

1 entry status name type params
2 Version + 27.0 28.1
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
40 Header + firmware/targets/f18/furi_hal/furi_hal_resources.h
41 Header + firmware/targets/f18/furi_hal/furi_hal_spi_config.h
42 Header + firmware/targets/f18/furi_hal/furi_hal_target_hw.h
43 Header + firmware/targets/f7/furi_hal/furi_hal_bus.h
44 Header + firmware/targets/f7/furi_hal/furi_hal_clock.h
45 Header + firmware/targets/f7/furi_hal/furi_hal_console.h
46 Header + firmware/targets/f7/furi_hal/furi_hal_dma.h
47 Header + firmware/targets/f7/furi_hal/furi_hal_flash.h
48 Header + firmware/targets/f7/furi_hal/furi_hal_gpio.h
49 Header + firmware/targets/f7/furi_hal/furi_hal_i2c_config.h
875 Function + furi_hal_bt_unlock_core2 void
876 Function + furi_hal_bt_update_battery_level void uint8_t
877 Function + furi_hal_bt_update_power_state void
878 Function + furi_hal_bus_deinit_early void
879 Function + furi_hal_bus_disable void FuriHalBus
880 Function + furi_hal_bus_enable void FuriHalBus
881 Function + furi_hal_bus_init_early void
882 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
883 Function + furi_hal_bus_reset void FuriHalBus
884 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
885 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
886 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
923 Function + furi_hal_debug_enable void
924 Function + furi_hal_debug_is_gdb_session_active _Bool
925 Function - furi_hal_deinit_early void
926 Function + furi_hal_dma_deinit_early void
927 Function + furi_hal_dma_init_early void
928 Function - furi_hal_flash_erase void uint8_t
929 Function - furi_hal_flash_get_base size_t
930 Function - furi_hal_flash_get_cycles_count size_t
1043 Function + furi_hal_pwm_stop void FuriHalPwmOutputId
1044 Function + furi_hal_random_fill_buf void uint8_t*, uint32_t
1045 Function + furi_hal_random_get uint32_t
1046 Function + furi_hal_random_init void
1047 Function + furi_hal_region_get const FuriHalRegion*
1048 Function + furi_hal_region_get_band const FuriHalRegionBand* uint32_t
1049 Function + furi_hal_region_get_name const char*
1059 Function - furi_hal_rtc_deinit_early void
1060 Function + furi_hal_rtc_get_boot_mode FuriHalRtcBootMode
1061 Function + furi_hal_rtc_get_datetime void FuriHalRtcDateTime*
1062 Function + furi_hal_rtc_get_days_per_month uint8_t _Bool, uint8_t
1063 Function + furi_hal_rtc_get_days_per_year uint16_t uint16_t
1064 Function + furi_hal_rtc_get_fault_data uint32_t
1065 Function + furi_hal_rtc_get_heap_track_mode FuriHalRtcHeapTrackMode
1066 Function + furi_hal_rtc_get_locale_dateformat FuriHalRtcLocaleDateFormat
1073 Function - furi_hal_rtc_init void
1074 Function - furi_hal_rtc_init_early void
1075 Function + furi_hal_rtc_is_flag_set _Bool FuriHalRtcFlag
1076 Function + furi_hal_rtc_is_leap_year _Bool uint16_t
1077 Function + furi_hal_rtc_reset_flag void FuriHalRtcFlag
1078 Function + furi_hal_rtc_set_boot_mode void FuriHalRtcBootMode
1079 Function + furi_hal_rtc_set_datetime void FuriHalRtcDateTime*
2003 Function + version_get const Version*
2004 Function + version_get_builddate const char* const Version*
2005 Function + version_get_dirty_flag _Bool const Version*
2006 Function + version_get_firmware_origin const char* const Version*
2007 Function + version_get_git_origin const char* const Version*
2008 Function + version_get_gitbranch const char* const Version*
2009 Function + version_get_gitbranchnum const char* const Version*
2010 Function + version_get_githash const char* const Version*

View File

@ -9,6 +9,8 @@
void furi_hal_init_early() {
furi_hal_cortex_init_early();
furi_hal_clock_init_early();
furi_hal_bus_init_early();
furi_hal_dma_init_early();
furi_hal_resources_init_early();
furi_hal_os_init();
furi_hal_spi_config_init_early();
@ -22,12 +24,15 @@ void furi_hal_deinit_early() {
furi_hal_i2c_deinit_early();
furi_hal_spi_config_deinit_early();
furi_hal_resources_deinit_early();
furi_hal_dma_deinit_early();
furi_hal_bus_deinit_early();
furi_hal_clock_deinit_early();
}
void furi_hal_init() {
furi_hal_mpu_init();
furi_hal_clock_init();
furi_hal_random_init();
furi_hal_console_init();
furi_hal_rtc_init();
furi_hal_interrupt_init();

View File

@ -1,4 +1,5 @@
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <furi.h>
#include <stm32wbxx_ll_rcc.h>
@ -118,6 +119,13 @@ static void furi_hal_resources_init_input_pins(GpioMode mode) {
}
void furi_hal_resources_init_early() {
furi_hal_bus_enable(FuriHalBusGPIOA);
furi_hal_bus_enable(FuriHalBusGPIOB);
furi_hal_bus_enable(FuriHalBusGPIOC);
furi_hal_bus_enable(FuriHalBusGPIOD);
furi_hal_bus_enable(FuriHalBusGPIOE);
furi_hal_bus_enable(FuriHalBusGPIOH);
furi_hal_resources_init_input_pins(GpioModeInput);
// SD Card stepdown control
@ -162,6 +170,12 @@ void furi_hal_resources_init_early() {
void furi_hal_resources_deinit_early() {
furi_hal_resources_init_input_pins(GpioModeAnalog);
furi_hal_bus_disable(FuriHalBusGPIOA);
furi_hal_bus_disable(FuriHalBusGPIOB);
furi_hal_bus_disable(FuriHalBusGPIOC);
furi_hal_bus_disable(FuriHalBusGPIOD);
furi_hal_bus_disable(FuriHalBusGPIOE);
furi_hal_bus_disable(FuriHalBusGPIOH);
}
void furi_hal_resources_init() {

View File

@ -1,5 +1,6 @@
#include <furi_hal_spi_config.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <furi_hal_spi.h>
#include <furi.h>
@ -96,28 +97,17 @@ void furi_hal_spi_config_init() {
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_r_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
furi_mutex_free(furi_hal_spi_bus_r_mutex);
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalSpiBusEventLock) {
furi_check(furi_mutex_acquire(furi_hal_spi_bus_r_mutex, FuriWaitForever) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventUnlock) {
furi_check(furi_mutex_release(furi_hal_spi_bus_r_mutex) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventActivate) {
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusSPI1);
} else if(event == FuriHalSpiBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusSPI1);
}
}
@ -131,28 +121,17 @@ FuriMutex* furi_hal_spi_bus_d_mutex = NULL;
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_d_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
furi_mutex_free(furi_hal_spi_bus_d_mutex);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalSpiBusEventLock) {
furi_check(furi_mutex_acquire(furi_hal_spi_bus_d_mutex, FuriWaitForever) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventUnlock) {
furi_check(furi_mutex_release(furi_hal_spi_bus_d_mutex) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventActivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusSPI2);
} else if(event == FuriHalSpiBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusSPI2);
}
}

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,27.1,,
Version,+,28.1,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -36,8 +36,10 @@ Header,+,applications/services/notification/notification_messages.h,,
Header,+,applications/services/power/power_service/power.h,,
Header,+,applications/services/rpc/rpc_app.h,,
Header,+,applications/services/storage/storage.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_bus.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_clock.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_console.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_dma.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_flash.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_gpio.h,,
Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_config.h,,
@ -1090,6 +1092,12 @@ Function,+,furi_hal_bt_stop_tone_tx,void,
Function,+,furi_hal_bt_unlock_core2,void,
Function,+,furi_hal_bt_update_battery_level,void,uint8_t
Function,+,furi_hal_bt_update_power_state,void,
Function,+,furi_hal_bus_deinit_early,void,
Function,+,furi_hal_bus_disable,void,FuriHalBus
Function,+,furi_hal_bus_enable,void,FuriHalBus
Function,+,furi_hal_bus_init_early,void,
Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
Function,+,furi_hal_bus_reset,void,FuriHalBus
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
@ -1132,6 +1140,8 @@ Function,+,furi_hal_debug_disable,void,
Function,+,furi_hal_debug_enable,void,
Function,+,furi_hal_debug_is_gdb_session_active,_Bool,
Function,-,furi_hal_deinit_early,void,
Function,+,furi_hal_dma_deinit_early,void,
Function,+,furi_hal_dma_init_early,void,
Function,-,furi_hal_flash_erase,void,uint8_t
Function,-,furi_hal_flash_get_base,size_t,
Function,-,furi_hal_flash_get_cycles_count,size_t,
@ -1300,6 +1310,7 @@ Function,+,furi_hal_pwm_start,void,"FuriHalPwmOutputId, uint32_t, uint8_t"
Function,+,furi_hal_pwm_stop,void,FuriHalPwmOutputId
Function,+,furi_hal_random_fill_buf,void,"uint8_t*, uint32_t"
Function,+,furi_hal_random_get,uint32_t,
Function,+,furi_hal_random_init,void,
Function,+,furi_hal_region_get,const FuriHalRegion*,
Function,+,furi_hal_region_get_band,const FuriHalRegionBand*,uint32_t
Function,+,furi_hal_region_get_name,const char*,
@ -1310,35 +1321,29 @@ Function,-,furi_hal_resources_deinit_early,void,
Function,+,furi_hal_resources_get_ext_pin_number,int32_t,const GpioPin*
Function,-,furi_hal_resources_init,void,
Function,-,furi_hal_resources_init_early,void,
Function,+,furi_hal_rfid_change_read_config,void,"float, float"
Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*"
Function,+,furi_hal_rfid_comp_start,void,
Function,+,furi_hal_rfid_comp_stop,void,
Function,-,furi_hal_rfid_init,void,
Function,+,furi_hal_rfid_pin_pull_pulldown,void,
Function,+,furi_hal_rfid_pin_pull_release,void,
Function,+,furi_hal_rfid_pins_emulate,void,
Function,+,furi_hal_rfid_pins_read,void,
Function,+,furi_hal_rfid_pins_reset,void,
Function,+,furi_hal_rfid_set_emulate_period,void,uint32_t
Function,+,furi_hal_rfid_set_emulate_pulse,void,uint32_t
Function,+,furi_hal_rfid_set_read_period,void,uint32_t
Function,+,furi_hal_rfid_set_read_pulse,void,uint32_t
Function,+,furi_hal_rfid_tim_emulate,void,float
Function,+,furi_hal_rfid_tim_emulate_dma_start,void,"uint32_t*, uint32_t*, size_t, FuriHalRfidDMACallback, void*"
Function,+,furi_hal_rfid_tim_emulate_dma_stop,void,
Function,+,furi_hal_rfid_tim_emulate_start,void,"FuriHalRfidEmulateCallback, void*"
Function,+,furi_hal_rfid_tim_emulate_stop,void,
Function,+,furi_hal_rfid_tim_read,void,"float, float"
Function,+,furi_hal_rfid_tim_read_capture_start,void,"FuriHalRfidReadCaptureCallback, void*"
Function,+,furi_hal_rfid_tim_read_capture_stop,void,
Function,+,furi_hal_rfid_tim_read_start,void,
Function,+,furi_hal_rfid_tim_read_continue,void,
Function,+,furi_hal_rfid_tim_read_pause,void,
Function,+,furi_hal_rfid_tim_read_start,void,"float, float"
Function,+,furi_hal_rfid_tim_read_stop,void,
Function,+,furi_hal_rfid_tim_reset,void,
Function,+,furi_hal_rtc_datetime_to_timestamp,uint32_t,FuriHalRtcDateTime*
Function,-,furi_hal_rtc_deinit_early,void,
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
Function,+,furi_hal_rtc_get_days_per_month,uint8_t,"_Bool, uint8_t"
Function,+,furi_hal_rtc_get_days_per_year,uint16_t,uint16_t
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
@ -1351,6 +1356,7 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
Function,-,furi_hal_rtc_init,void,
Function,-,furi_hal_rtc_init_early,void,
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime*
@ -2039,6 +2045,8 @@ Function,-,mf_df_cat_key_settings,void,"MifareDesfireKeySettings*, FuriString*"
Function,-,mf_df_cat_version,void,"MifareDesfireVersion*, FuriString*"
Function,-,mf_df_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t"
Function,-,mf_df_clear,void,MifareDesfireData*
Function,-,mf_df_get_application,MifareDesfireApplication*,"MifareDesfireData*, const uint8_t[3]*"
Function,-,mf_df_get_file,MifareDesfireFile*,"MifareDesfireApplication*, uint8_t"
Function,-,mf_df_parse_get_application_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireApplication**"
Function,-,mf_df_parse_get_file_ids_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile**"
Function,-,mf_df_parse_get_file_settings_response,_Bool,"uint8_t*, uint16_t, MifareDesfireFile*"
@ -3540,6 +3548,8 @@ Function,+,version_get,const Version*,
Function,+,version_get_builddate,const char*,const Version*
Function,+,version_get_custom_name,const char*,const Version*
Function,+,version_get_dirty_flag,_Bool,const Version*
Function,+,version_get_firmware_origin,const char*,const Version*
Function,+,version_get_git_origin,const char*,const Version*
Function,+,version_get_gitbranch,const char*,const Version*
Function,+,version_get_gitbranchnum,const char*,const Version*
Function,+,version_get_githash,const char*,const Version*

1 entry status name type params
2 Version + 27.1 28.1
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
36 Header + applications/services/power/power_service/power.h
37 Header + applications/services/rpc/rpc_app.h
38 Header + applications/services/storage/storage.h
39 Header + firmware/targets/f7/furi_hal/furi_hal_bus.h
40 Header + firmware/targets/f7/furi_hal/furi_hal_clock.h
41 Header + firmware/targets/f7/furi_hal/furi_hal_console.h
42 Header + firmware/targets/f7/furi_hal/furi_hal_dma.h
43 Header + firmware/targets/f7/furi_hal/furi_hal_flash.h
44 Header + firmware/targets/f7/furi_hal/furi_hal_gpio.h
45 Header + firmware/targets/f7/furi_hal/furi_hal_i2c_config.h
1092 Function + furi_hal_bt_unlock_core2 void
1093 Function + furi_hal_bt_update_battery_level void uint8_t
1094 Function + furi_hal_bt_update_power_state void
1095 Function + furi_hal_bus_deinit_early void
1096 Function + furi_hal_bus_disable void FuriHalBus
1097 Function + furi_hal_bus_enable void FuriHalBus
1098 Function + furi_hal_bus_init_early void
1099 Function + furi_hal_bus_is_enabled _Bool FuriHalBus
1100 Function + furi_hal_bus_reset void FuriHalBus
1101 Function + furi_hal_cdc_get_ctrl_line_state uint8_t uint8_t
1102 Function + furi_hal_cdc_get_port_settings usb_cdc_line_coding* uint8_t
1103 Function + furi_hal_cdc_receive int32_t uint8_t, uint8_t*, uint16_t
1140 Function + furi_hal_debug_enable void
1141 Function + furi_hal_debug_is_gdb_session_active _Bool
1142 Function - furi_hal_deinit_early void
1143 Function + furi_hal_dma_deinit_early void
1144 Function + furi_hal_dma_init_early void
1145 Function - furi_hal_flash_erase void uint8_t
1146 Function - furi_hal_flash_get_base size_t
1147 Function - furi_hal_flash_get_cycles_count size_t
1310 Function + furi_hal_pwm_stop void FuriHalPwmOutputId
1311 Function + furi_hal_random_fill_buf void uint8_t*, uint32_t
1312 Function + furi_hal_random_get uint32_t
1313 Function + furi_hal_random_init void
1314 Function + furi_hal_region_get const FuriHalRegion*
1315 Function + furi_hal_region_get_band const FuriHalRegionBand* uint32_t
1316 Function + furi_hal_region_get_name const char*
1321 Function + furi_hal_resources_get_ext_pin_number int32_t const GpioPin*
1322 Function - furi_hal_resources_init void
1323 Function - furi_hal_resources_init_early void
Function + furi_hal_rfid_change_read_config void float, float
1324 Function + furi_hal_rfid_comp_set_callback void FuriHalRfidCompCallback, void*
1325 Function + furi_hal_rfid_comp_start void
1326 Function + furi_hal_rfid_comp_stop void
1327 Function - furi_hal_rfid_init void
1328 Function + furi_hal_rfid_pin_pull_pulldown void
1329 Function + furi_hal_rfid_pin_pull_release void
Function + furi_hal_rfid_pins_emulate void
Function + furi_hal_rfid_pins_read void
1330 Function + furi_hal_rfid_pins_reset void
Function + furi_hal_rfid_set_emulate_period void uint32_t
Function + furi_hal_rfid_set_emulate_pulse void uint32_t
1331 Function + furi_hal_rfid_set_read_period void uint32_t
1332 Function + furi_hal_rfid_set_read_pulse void uint32_t
Function + furi_hal_rfid_tim_emulate void float
1333 Function + furi_hal_rfid_tim_emulate_dma_start void uint32_t*, uint32_t*, size_t, FuriHalRfidDMACallback, void*
1334 Function + furi_hal_rfid_tim_emulate_dma_stop void
Function + furi_hal_rfid_tim_emulate_start void FuriHalRfidEmulateCallback, void*
Function + furi_hal_rfid_tim_emulate_stop void
Function + furi_hal_rfid_tim_read void float, float
1335 Function + furi_hal_rfid_tim_read_capture_start void FuriHalRfidReadCaptureCallback, void*
1336 Function + furi_hal_rfid_tim_read_capture_stop void
1337 Function + furi_hal_rfid_tim_read_start furi_hal_rfid_tim_read_continue void
1338 Function + furi_hal_rfid_tim_read_pause void
1339 Function + furi_hal_rfid_tim_read_start void float, float
1340 Function + furi_hal_rfid_tim_read_stop void
Function + furi_hal_rfid_tim_reset void
1341 Function + furi_hal_rtc_datetime_to_timestamp uint32_t FuriHalRtcDateTime*
1342 Function - furi_hal_rtc_deinit_early void
1343 Function + furi_hal_rtc_get_boot_mode FuriHalRtcBootMode
1344 Function + furi_hal_rtc_get_datetime void FuriHalRtcDateTime*
1345 Function + furi_hal_rtc_get_days_per_month uint8_t _Bool, uint8_t
1346 Function + furi_hal_rtc_get_days_per_year uint16_t uint16_t
1347 Function + furi_hal_rtc_get_fault_data uint32_t
1348 Function + furi_hal_rtc_get_heap_track_mode FuriHalRtcHeapTrackMode
1349 Function + furi_hal_rtc_get_locale_dateformat FuriHalRtcLocaleDateFormat
1356 Function - furi_hal_rtc_init void
1357 Function - furi_hal_rtc_init_early void
1358 Function + furi_hal_rtc_is_flag_set _Bool FuriHalRtcFlag
1359 Function + furi_hal_rtc_is_leap_year _Bool uint16_t
1360 Function + furi_hal_rtc_reset_flag void FuriHalRtcFlag
1361 Function + furi_hal_rtc_set_boot_mode void FuriHalRtcBootMode
1362 Function + furi_hal_rtc_set_datetime void FuriHalRtcDateTime*
2045 Function - mf_df_cat_version void MifareDesfireVersion*, FuriString*
2046 Function - mf_df_check_card_type _Bool uint8_t, uint8_t, uint8_t
2047 Function - mf_df_clear void MifareDesfireData*
2048 Function - mf_df_get_application MifareDesfireApplication* MifareDesfireData*, const uint8_t[3]*
2049 Function - mf_df_get_file MifareDesfireFile* MifareDesfireApplication*, uint8_t
2050 Function - mf_df_parse_get_application_ids_response _Bool uint8_t*, uint16_t, MifareDesfireApplication**
2051 Function - mf_df_parse_get_file_ids_response _Bool uint8_t*, uint16_t, MifareDesfireFile**
2052 Function - mf_df_parse_get_file_settings_response _Bool uint8_t*, uint16_t, MifareDesfireFile*
3548 Function + version_get_builddate const char* const Version*
3549 Function + version_get_custom_name const char* const Version*
3550 Function + version_get_dirty_flag _Bool const Version*
3551 Function + version_get_firmware_origin const char* const Version*
3552 Function + version_get_git_origin const char* const Version*
3553 Function + version_get_gitbranch const char* const Version*
3554 Function + version_get_gitbranchnum const char* const Version*
3555 Function + version_get_githash const char* const Version*

View File

@ -9,6 +9,8 @@
void furi_hal_init_early() {
furi_hal_cortex_init_early();
furi_hal_clock_init_early();
furi_hal_bus_init_early();
furi_hal_dma_init_early();
furi_hal_resources_init_early();
furi_hal_os_init();
furi_hal_spi_config_init_early();
@ -22,12 +24,15 @@ void furi_hal_deinit_early() {
furi_hal_i2c_deinit_early();
furi_hal_spi_config_deinit_early();
furi_hal_resources_deinit_early();
furi_hal_dma_deinit_early();
furi_hal_bus_deinit_early();
furi_hal_clock_deinit_early();
}
void furi_hal_init() {
furi_hal_mpu_init();
furi_hal_clock_init();
furi_hal_random_init();
furi_hal_console_init();
furi_hal_rtc_init();
furi_hal_interrupt_init();

View File

@ -7,6 +7,7 @@
#include <furi_hal_version.h>
#include <furi_hal_bt_hid.h>
#include <furi_hal_bt_serial.h>
#include <furi_hal_bus.c>
#include "battery_service.h"
#include <furi.h>
@ -80,6 +81,11 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = {
FuriHalBtProfileConfig* current_profile = NULL;
void furi_hal_bt_init() {
furi_hal_bus_enable(FuriHalBusHSEM);
furi_hal_bus_enable(FuriHalBusIPCC);
furi_hal_bus_enable(FuriHalBusAES2);
furi_hal_bus_enable(FuriHalBusPKA);
if(!furi_hal_bt_core2_mtx) {
furi_hal_bt_core2_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
furi_assert(furi_hal_bt_core2_mtx);
@ -269,6 +275,11 @@ void furi_hal_bt_reinit() {
furi_delay_ms(100);
ble_glue_thread_stop();
furi_hal_bus_disable(FuriHalBusHSEM);
furi_hal_bus_disable(FuriHalBusIPCC);
furi_hal_bus_disable(FuriHalBusAES2);
furi_hal_bus_disable(FuriHalBusPKA);
FURI_LOG_I(TAG, "Start BT initialization");
furi_hal_bt_init();

View File

@ -0,0 +1,302 @@
#include <furi_hal_bus.h>
#include <furi.h>
#include <stm32wbxx_ll_bus.h>
/* Bus bitmask definitions */
#define FURI_HAL_BUS_IGNORE (0x0U)
#define FURI_HAL_BUS_AHB1_GRP1 \
(LL_AHB1_GRP1_PERIPH_DMA1 | LL_AHB1_GRP1_PERIPH_DMA2 | LL_AHB1_GRP1_PERIPH_DMAMUX1 | \
LL_AHB1_GRP1_PERIPH_CRC | LL_AHB1_GRP1_PERIPH_TSC)
#if defined(ADC_SUPPORT_5_MSPS)
#define FURI_HAL_BUS_AHB2_GRP1 \
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
LL_AHB2_GRP1_PERIPH_ADC | LL_AHB2_GRP1_PERIPH_AES1)
#define FURI_HAL_BUS_APB2_GRP1 \
(LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | LL_APB2_GRP1_PERIPH_USART1 | \
LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | LL_APB2_GRP1_PERIPH_SAI1)
#else
#define FURI_HAL_BUS_AHB2_GRP1 \
(LL_AHB2_GRP1_PERIPH_GPIOA | LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC | \
LL_AHB2_GRP1_PERIPH_GPIOD | LL_AHB2_GRP1_PERIPH_GPIOE | LL_AHB2_GRP1_PERIPH_GPIOH | \
LL_AHB2_GRP1_PERIPH_AES1)
#define FURI_HAL_BUS_APB2_GRP1 \
(LL_APB2_GRP1_PERIPH_ADC | LL_APB2_GRP1_PERIPH_TIM1 | LL_APB2_GRP1_PERIPH_SPI1 | \
LL_APB2_GRP1_PERIPH_USART1 | LL_APB2_GRP1_PERIPH_TIM16 | LL_APB2_GRP1_PERIPH_TIM17 | \
LL_APB2_GRP1_PERIPH_SAI1)
#endif
#define FURI_HAL_BUS_AHB3_GRP1 \
(LL_AHB3_GRP1_PERIPH_QUADSPI | LL_AHB3_GRP1_PERIPH_PKA | LL_AHB3_GRP1_PERIPH_AES2 | \
LL_AHB3_GRP1_PERIPH_RNG | LL_AHB3_GRP1_PERIPH_HSEM | LL_AHB3_GRP1_PERIPH_IPCC)
// LL_AHB3_GRP1_PERIPH_FLASH enabled by default
#define FURI_HAL_BUS_APB1_GRP1 \
(LL_APB1_GRP1_PERIPH_TIM2 | LL_APB1_GRP1_PERIPH_LCD | LL_APB1_GRP1_PERIPH_RTCAPB | \
LL_APB1_GRP1_PERIPH_SPI2 | LL_APB1_GRP1_PERIPH_I2C1 | LL_APB1_GRP1_PERIPH_I2C3 | \
LL_APB1_GRP1_PERIPH_CRS | LL_APB1_GRP1_PERIPH_USB | LL_APB1_GRP1_PERIPH_LPTIM1)
#define FURI_HAL_BUS_APB1_GRP2 (LL_APB1_GRP2_PERIPH_LPUART1 | LL_APB1_GRP2_PERIPH_LPTIM2)
#define FURI_HAL_BUS_APB3_GRP1 (LL_APB3_GRP1_PERIPH_RF)
/* Test macro definitions */
#define FURI_HAL_BUS_IS_ALL_CLEAR(reg, value) (READ_BIT((reg), (value)) == 0UL)
#define FURI_HAL_BUS_IS_ALL_SET(reg, value) (READ_BIT((reg), (value)) == (value))
#define FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, value, ...) \
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##ENR##__VA_ARGS__, (value)))
#define FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, value, ...) \
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##ENR##__VA_ARGS__, (value)))
#define FURI_HAL_BUS_IS_RESET_ASSERTED(bus, value, ...) \
(FURI_HAL_BUS_IS_ALL_SET(RCC->bus##RSTR##__VA_ARGS__, (value)))
#define FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, value, ...) \
(FURI_HAL_BUS_IS_ALL_CLEAR(RCC->bus##RSTR##__VA_ARGS__, (value)))
#define FURI_HAL_BUS_IS_PERIPH_ENABLED(bus, value, ...) \
(FURI_HAL_BUS_IS_RESET_DEASSERTED(bus, (value), __VA_ARGS__) && \
FURI_HAL_BUS_IS_CLOCK_ENABLED(bus, (value), __VA_ARGS__))
#define FURI_HAL_BUS_IS_PERIPH_DISABLED(bus, value, ...) \
(FURI_HAL_BUS_IS_CLOCK_DISABLED(bus, (value), __VA_ARGS__) && \
FURI_HAL_BUS_IS_RESET_ASSERTED(bus, (value), __VA_ARGS__))
/* Control macro definitions */
#define FURI_HAL_BUS_RESET_ASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ForceReset(value)
#define FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp) LL_##bus##_GRP##grp##_ReleaseReset(value)
#define FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp) LL_##bus##_GRP##grp##_EnableClock(value)
#define FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp) LL_##bus##_GRP##grp##_DisableClock(value)
#define FURI_HAL_BUS_PERIPH_ENABLE(bus, value, grp) \
FURI_HAL_BUS_CLOCK_ENABLE(bus, value, grp); \
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
#define FURI_HAL_BUS_PERIPH_DISABLE(bus, value, grp) \
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
FURI_HAL_BUS_CLOCK_DISABLE(bus, value, grp)
#define FURI_HAL_BUS_PERIPH_RESET(bus, value, grp) \
FURI_HAL_BUS_RESET_ASSERT(bus, value, grp); \
FURI_HAL_BUS_RESET_DEASSERT(bus, value, grp)
static const uint32_t furi_hal_bus[] = {
[FuriHalBusAHB1_GRP1] = FURI_HAL_BUS_AHB1_GRP1,
[FuriHalBusDMA1] = LL_AHB1_GRP1_PERIPH_DMA1,
[FuriHalBusDMA2] = LL_AHB1_GRP1_PERIPH_DMA2,
[FuriHalBusDMAMUX1] = LL_AHB1_GRP1_PERIPH_DMAMUX1,
[FuriHalBusCRC] = LL_AHB1_GRP1_PERIPH_CRC,
[FuriHalBusTSC] = LL_AHB1_GRP1_PERIPH_TSC,
[FuriHalBusAHB2_GRP1] = FURI_HAL_BUS_AHB2_GRP1,
[FuriHalBusGPIOA] = LL_AHB2_GRP1_PERIPH_GPIOA,
[FuriHalBusGPIOB] = LL_AHB2_GRP1_PERIPH_GPIOB,
[FuriHalBusGPIOC] = LL_AHB2_GRP1_PERIPH_GPIOC,
[FuriHalBusGPIOD] = LL_AHB2_GRP1_PERIPH_GPIOD,
[FuriHalBusGPIOE] = LL_AHB2_GRP1_PERIPH_GPIOE,
[FuriHalBusGPIOH] = LL_AHB2_GRP1_PERIPH_GPIOH,
#if defined(ADC_SUPPORT_5_MSPS)
[FuriHalBusADC] = LL_AHB2_GRP1_PERIPH_ADC,
#endif
[FuriHalBusAES1] = LL_AHB2_GRP1_PERIPH_AES1,
[FuriHalBusAHB3_GRP1] = FURI_HAL_BUS_AHB3_GRP1,
[FuriHalBusQUADSPI] = LL_AHB3_GRP1_PERIPH_QUADSPI,
[FuriHalBusPKA] = LL_AHB3_GRP1_PERIPH_PKA,
[FuriHalBusAES2] = LL_AHB3_GRP1_PERIPH_AES2,
[FuriHalBusRNG] = LL_AHB3_GRP1_PERIPH_RNG,
[FuriHalBusHSEM] = LL_AHB3_GRP1_PERIPH_HSEM,
[FuriHalBusIPCC] = LL_AHB3_GRP1_PERIPH_IPCC,
[FuriHalBusFLASH] = LL_AHB3_GRP1_PERIPH_FLASH,
[FuriHalBusAPB1_GRP1] = FURI_HAL_BUS_APB1_GRP1,
[FuriHalBusTIM2] = LL_APB1_GRP1_PERIPH_TIM2,
[FuriHalBusLCD] = LL_APB1_GRP1_PERIPH_LCD,
[FuriHalBusSPI2] = LL_APB1_GRP1_PERIPH_SPI2,
[FuriHalBusI2C1] = LL_APB1_GRP1_PERIPH_I2C1,
[FuriHalBusI2C3] = LL_APB1_GRP1_PERIPH_I2C3,
[FuriHalBusCRS] = LL_APB1_GRP1_PERIPH_CRS,
[FuriHalBusUSB] = LL_APB1_GRP1_PERIPH_USB,
[FuriHalBusLPTIM1] = LL_APB1_GRP1_PERIPH_LPTIM1,
[FuriHalBusAPB1_GRP2] = FURI_HAL_BUS_APB1_GRP2,
[FuriHalBusLPUART1] = LL_APB1_GRP2_PERIPH_LPUART1,
[FuriHalBusLPTIM2] = LL_APB1_GRP2_PERIPH_LPTIM2,
[FuriHalBusAPB2_GRP1] = FURI_HAL_BUS_APB2_GRP1,
#if defined(ADC_SUPPORT_2_5_MSPS)
[FuriHalBusADC] = LL_APB2_GRP1_PERIPH_ADC,
#endif
[FuriHalBusTIM1] = LL_APB2_GRP1_PERIPH_TIM1,
[FuriHalBusSPI1] = LL_APB2_GRP1_PERIPH_SPI1,
[FuriHalBusUSART1] = LL_APB2_GRP1_PERIPH_USART1,
[FuriHalBusTIM16] = LL_APB2_GRP1_PERIPH_TIM16,
[FuriHalBusTIM17] = LL_APB2_GRP1_PERIPH_TIM17,
[FuriHalBusSAI1] = LL_APB2_GRP1_PERIPH_SAI1,
[FuriHalBusAPB3_GRP1] = FURI_HAL_BUS_IGNORE, // APB3_GRP1 clocking cannot be changed
[FuriHalBusRF] = LL_APB3_GRP1_PERIPH_RF,
};
void furi_hal_bus_init_early() {
FURI_CRITICAL_ENTER();
FURI_HAL_BUS_PERIPH_DISABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
FURI_HAL_BUS_PERIPH_DISABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
FURI_HAL_BUS_PERIPH_DISABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
FURI_HAL_BUS_PERIPH_DISABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
FURI_HAL_BUS_PERIPH_DISABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
FURI_CRITICAL_EXIT();
}
void furi_hal_bus_deinit_early() {
FURI_CRITICAL_ENTER();
FURI_HAL_BUS_PERIPH_ENABLE(AHB1, FURI_HAL_BUS_AHB1_GRP1, 1);
FURI_HAL_BUS_PERIPH_ENABLE(AHB2, FURI_HAL_BUS_AHB2_GRP1, 1);
FURI_HAL_BUS_PERIPH_ENABLE(AHB3, FURI_HAL_BUS_AHB3_GRP1, 1);
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP1, 1);
FURI_HAL_BUS_PERIPH_ENABLE(APB1, FURI_HAL_BUS_APB1_GRP2, 2);
FURI_HAL_BUS_PERIPH_ENABLE(APB2, FURI_HAL_BUS_APB2_GRP1, 1);
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
FURI_CRITICAL_EXIT();
}
void furi_hal_bus_enable(FuriHalBus bus) {
furi_check(bus < FuriHalBusMAX);
const uint32_t value = furi_hal_bus[bus];
if(!value) {
return;
}
FURI_CRITICAL_ENTER();
if(bus < FuriHalBusAHB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB1, value));
FURI_HAL_BUS_PERIPH_ENABLE(AHB1, value, 1);
} else if(bus < FuriHalBusAHB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB2, value));
FURI_HAL_BUS_PERIPH_ENABLE(AHB2, value, 1);
} else if(bus < FuriHalBusAPB1_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(AHB3, value));
FURI_HAL_BUS_PERIPH_ENABLE(AHB3, value, 1);
} else if(bus < FuriHalBusAPB1_GRP2) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 1));
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 1);
} else if(bus < FuriHalBusAPB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB1, value, 2));
FURI_HAL_BUS_PERIPH_ENABLE(APB1, value, 2);
} else if(bus < FuriHalBusAPB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_DISABLED(APB2, value));
FURI_HAL_BUS_PERIPH_ENABLE(APB2, value, 1);
} else {
furi_check(FURI_HAL_BUS_IS_RESET_ASSERTED(APB3, value));
FURI_HAL_BUS_RESET_DEASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
}
FURI_CRITICAL_EXIT();
}
void furi_hal_bus_reset(FuriHalBus bus) {
furi_check(bus < FuriHalBusMAX);
const uint32_t value = furi_hal_bus[bus];
if(!value) {
return;
}
FURI_CRITICAL_ENTER();
if(bus < FuriHalBusAHB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
FURI_HAL_BUS_PERIPH_RESET(AHB1, value, 1);
} else if(bus < FuriHalBusAHB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
FURI_HAL_BUS_PERIPH_RESET(AHB2, value, 1);
} else if(bus < FuriHalBusAPB1_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
FURI_HAL_BUS_PERIPH_RESET(AHB3, value, 1);
} else if(bus < FuriHalBusAPB1_GRP2) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 1);
} else if(bus < FuriHalBusAPB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
FURI_HAL_BUS_PERIPH_RESET(APB1, value, 2);
} else if(bus < FuriHalBusAPB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
FURI_HAL_BUS_PERIPH_RESET(APB2, value, 1);
} else {
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
FURI_HAL_BUS_PERIPH_RESET(APB3, value, 1);
}
FURI_CRITICAL_EXIT();
}
void furi_hal_bus_disable(FuriHalBus bus) {
furi_check(bus < FuriHalBusMAX);
const uint32_t value = furi_hal_bus[bus];
if(!value) {
return;
}
FURI_CRITICAL_ENTER();
if(bus < FuriHalBusAHB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value));
FURI_HAL_BUS_PERIPH_DISABLE(AHB1, value, 1);
} else if(bus < FuriHalBusAHB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value));
FURI_HAL_BUS_PERIPH_DISABLE(AHB2, value, 1);
} else if(bus < FuriHalBusAPB1_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value));
FURI_HAL_BUS_PERIPH_DISABLE(AHB3, value, 1);
} else if(bus < FuriHalBusAPB1_GRP2) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1));
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 1);
} else if(bus < FuriHalBusAPB2_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2));
FURI_HAL_BUS_PERIPH_DISABLE(APB1, value, 2);
} else if(bus < FuriHalBusAPB3_GRP1) {
furi_check(FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value));
FURI_HAL_BUS_PERIPH_DISABLE(APB2, value, 1);
} else {
furi_check(FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value));
FURI_HAL_BUS_RESET_ASSERT(APB3, FURI_HAL_BUS_APB3_GRP1, 1);
}
FURI_CRITICAL_EXIT();
}
bool furi_hal_bus_is_enabled(FuriHalBus bus) {
furi_check(bus < FuriHalBusMAX);
const uint32_t value = furi_hal_bus[bus];
if(value == FURI_HAL_BUS_IGNORE) {
return true;
}
bool ret = false;
FURI_CRITICAL_ENTER();
if(bus < FuriHalBusAHB2_GRP1) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB1, value);
} else if(bus < FuriHalBusAHB3_GRP1) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB2, value);
} else if(bus < FuriHalBusAPB1_GRP1) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(AHB3, value);
} else if(bus < FuriHalBusAPB1_GRP2) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 1);
} else if(bus < FuriHalBusAPB2_GRP1) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB1, value, 2);
} else if(bus < FuriHalBusAPB3_GRP1) {
ret = FURI_HAL_BUS_IS_PERIPH_ENABLED(APB2, value);
} else {
ret = FURI_HAL_BUS_IS_RESET_DEASSERTED(APB3, value);
}
FURI_CRITICAL_EXIT();
return ret;
}

View File

@ -0,0 +1,112 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32wbxx.h"
#include "stdbool.h"
typedef enum {
FuriHalBusAHB1_GRP1,
FuriHalBusDMA1,
FuriHalBusDMA2,
FuriHalBusDMAMUX1,
FuriHalBusCRC,
FuriHalBusTSC,
FuriHalBusAHB2_GRP1,
FuriHalBusGPIOA,
FuriHalBusGPIOB,
FuriHalBusGPIOC,
FuriHalBusGPIOD,
FuriHalBusGPIOE,
FuriHalBusGPIOH,
#if defined(ADC_SUPPORT_5_MSPS)
FuriHalBusADC,
#endif
FuriHalBusAES1,
FuriHalBusAHB3_GRP1,
FuriHalBusQUADSPI,
FuriHalBusPKA,
FuriHalBusAES2,
FuriHalBusRNG,
FuriHalBusHSEM,
FuriHalBusIPCC,
FuriHalBusFLASH,
FuriHalBusAPB1_GRP1,
FuriHalBusTIM2,
FuriHalBusLCD,
FuriHalBusSPI2,
FuriHalBusI2C1,
FuriHalBusI2C3,
FuriHalBusCRS,
FuriHalBusUSB,
FuriHalBusLPTIM1,
FuriHalBusAPB1_GRP2,
FuriHalBusLPUART1,
FuriHalBusLPTIM2,
FuriHalBusAPB2_GRP1,
#if defined(ADC_SUPPORT_2_5_MSPS)
FuriHalBusADC,
#endif
FuriHalBusTIM1,
FuriHalBusSPI1,
FuriHalBusUSART1,
FuriHalBusTIM16,
FuriHalBusTIM17,
FuriHalBusSAI1,
FuriHalBusAPB3_GRP1,
FuriHalBusRF,
FuriHalBusMAX,
} FuriHalBus;
/** Early initialization */
void furi_hal_bus_init_early();
/** Early de-initialization */
void furi_hal_bus_deinit_early();
/**
* Enable a peripheral by turning the clocking on and deasserting the reset.
* @param [in] bus Peripheral to be enabled.
* @warning Peripheral must be in disabled state in order to be enabled.
*/
void furi_hal_bus_enable(FuriHalBus bus);
/**
* Reset a peripheral by sequentially asserting and deasserting the reset.
* @param [in] bus Peripheral to be reset.
* @warning Peripheral must be in enabled state in order to be reset.
*/
void furi_hal_bus_reset(FuriHalBus bus);
/**
* Disable a peripheral by turning the clocking off and asserting the reset.
* @param [in] bus Peripheral to be disabled.
* @warning Peripheral must be in enabled state in order to be disabled.
*/
void furi_hal_bus_disable(FuriHalBus bus);
/** Check if peripheral is enabled
*
* @warning FuriHalBusAPB3_GRP1 is a special group of shared peripherals, for
* core1 its clock is always on and the only status we can report is
* peripheral reset status. Check code and Reference Manual for
* details.
*
* @param[in] bus The peripheral to check
*
* @return true if enabled or always enabled, false otherwise
*/
bool furi_hal_bus_is_enabled(FuriHalBus bus);
#ifdef __cplusplus
}
#endif

View File

@ -6,7 +6,6 @@
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_cortex.h>
#include <stm32wbxx_ll_bus.h>
#define TAG "FuriHalClock"
@ -19,36 +18,9 @@
void furi_hal_clock_init_early() {
LL_SetSystemCoreClock(CPU_CLOCK_HZ_EARLY);
LL_Init1msTick(SystemCoreClock);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
}
void furi_hal_clock_deinit_early() {
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_I2C1);
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_I2C3);
LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_DisableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
}
void furi_hal_clock_init() {
@ -137,68 +109,12 @@ void furi_hal_clock_init() {
SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TICK_INT_PRIORITY, 0));
NVIC_EnableIRQ(SysTick_IRQn);
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLLSAI1);
LL_RCC_SetCLK48ClockSource(LL_RCC_CLK48_CLKSOURCE_PLLSAI1);
LL_RCC_HSI_EnableInStopMode(); // Ensure that MR is capable of work in STOP0
LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE);
LL_RCC_SetSMPSPrescaler(LL_RCC_SMPS_DIV_1);
LL_RCC_SetRFWKPClockSource(LL_RCC_RFWKP_CLKSOURCE_LSE);
// AHB1 GRP1
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMAMUX1);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_CRC);
// LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_TSC);
// AHB2 GRP1
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_AES1);
// AHB3 GRP1
// LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_QUADSPI);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_PKA);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_RNG);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_HSEM);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_IPCC);
LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_FLASH);
// APB1 GRP1
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LCD);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
// LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_WWDG);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_CRS);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USB);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1);
// APB1 GRP2
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
// APB2
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM16);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM17);
// LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SAI1);
FURI_LOG_I(TAG, "Init OK");
}

View File

@ -1,8 +1,9 @@
#include <furi_hal_crypto.h>
#include <furi_hal_bt.h>
#include <furi_hal_random.h>
#include <furi_hal_bus.h>
#include <stm32wbxx_ll_cortex.h>
#include <stm32wbxx_ll_bus.h>
#include <furi.h>
#include <interface/patterns/ble_thread/shci/shci.h>
@ -241,6 +242,8 @@ bool furi_hal_crypto_store_load_key(uint8_t slot, const uint8_t* iv) {
furi_assert(furi_hal_crypto_mutex);
furi_check(furi_mutex_acquire(furi_hal_crypto_mutex, FuriWaitForever) == FuriStatusOk);
furi_hal_bus_enable(FuriHalBusAES1);
if(!furi_hal_bt_is_alive()) {
return false;
}
@ -267,10 +270,7 @@ bool furi_hal_crypto_store_unload_key(uint8_t slot) {
SHCI_CmdStatus_t shci_state = SHCI_C2_FUS_UnloadUsrKey(slot);
furi_assert(shci_state == SHCI_Success);
FURI_CRITICAL_ENTER();
LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_AES1);
LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_AES1);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusAES1);
furi_check(furi_mutex_release(furi_hal_crypto_mutex) == FuriStatusOk);
return (shci_state == SHCI_Success);

View File

@ -0,0 +1,14 @@
#include <furi_hal_dma.h>
#include <furi_hal_bus.h>
void furi_hal_dma_init_early() {
furi_hal_bus_enable(FuriHalBusDMA1);
furi_hal_bus_enable(FuriHalBusDMA2);
furi_hal_bus_enable(FuriHalBusDMAMUX1);
}
void furi_hal_dma_deinit_early() {
furi_hal_bus_disable(FuriHalBusDMA1);
furi_hal_bus_disable(FuriHalBusDMA2);
furi_hal_bus_disable(FuriHalBusDMAMUX1);
}

View File

@ -0,0 +1,15 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** Early initialization */
void furi_hal_dma_init_early();
/** Early de-initialization */
void furi_hal_dma_deinit_early();
#ifdef __cplusplus
}
#endif

View File

@ -11,20 +11,20 @@
#define TAG "FuriHalFlash"
#define FURI_HAL_CRITICAL_MSG "Critical flash operation fail"
#define FURI_HAL_FLASH_READ_BLOCK 8
#define FURI_HAL_FLASH_WRITE_BLOCK 8
#define FURI_HAL_FLASH_PAGE_SIZE 4096
#define FURI_HAL_FLASH_CYCLES_COUNT 10000
#define FURI_HAL_FLASH_TIMEOUT 1000
#define FURI_HAL_FLASH_KEY1 0x45670123U
#define FURI_HAL_FLASH_KEY2 0xCDEF89ABU
#define FURI_HAL_FLASH_TOTAL_PAGES 256
#define FURI_HAL_FLASH_READ_BLOCK (8U)
#define FURI_HAL_FLASH_WRITE_BLOCK (8U)
#define FURI_HAL_FLASH_PAGE_SIZE (4096U)
#define FURI_HAL_FLASH_CYCLES_COUNT (10000U)
#define FURI_HAL_FLASH_TIMEOUT (1000U)
#define FURI_HAL_FLASH_KEY1 (0x45670123U)
#define FURI_HAL_FLASH_KEY2 (0xCDEF89ABU)
#define FURI_HAL_FLASH_TOTAL_PAGES (256U)
#define FURI_HAL_FLASH_SR_ERRORS \
(FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_SIZERR | \
FLASH_SR_PGSERR | FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_RDERR | FLASH_SR_OPTVERR)
#define FURI_HAL_FLASH_OPT_KEY1 0x08192A3B
#define FURI_HAL_FLASH_OPT_KEY2 0x4C5D6E7F
#define FURI_HAL_FLASH_OPT_KEY1 (0x08192A3BU)
#define FURI_HAL_FLASH_OPT_KEY2 (0x4C5D6E7FU)
#define FURI_HAL_FLASH_OB_TOTAL_WORDS (0x80 / (sizeof(uint32_t) * 2))
/* STM32CubeWB/Projects/P-NUCLEO-WB55.Nucleo/Applications/BLE/BLE_RfWithFlash/Core/Src/flash_driver.c
@ -35,7 +35,7 @@
> If for any reason this test is never passed, this means there is a failure in the system and there is no other
> way to recover than applying a device reset.
*/
#define FURI_HAL_FLASH_C2_LOCK_TIMEOUT_MS 3000u /* 3 seconds */
#define FURI_HAL_FLASH_C2_LOCK_TIMEOUT_MS (3000U) /* 3 seconds */
#define IS_ADDR_ALIGNED_64BITS(__VALUE__) (((__VALUE__)&0x7U) == (0x00UL))
#define IS_FLASH_PROGRAM_ADDRESS(__VALUE__) \

View File

@ -1,7 +1,8 @@
#include <furi_hal_i2c_config.h>
#include <furi_hal_resources.h>
#include <furi_hal_version.h>
#include <stm32wbxx_ll_bus.h>
#include <furi_hal_bus.h>
#include <stm32wbxx_ll_rcc.h>
/** Timing register value is computed with the STM32CubeMX Tool,
@ -21,17 +22,9 @@ FuriMutex* furi_hal_i2c_bus_power_mutex = NULL;
static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventInit) {
furi_hal_i2c_bus_power_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalI2cBusEventDeinit) {
furi_mutex_free(furi_hal_i2c_bus_power_mutex);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalI2cBusEventLock) {
furi_check(
furi_mutex_acquire(furi_hal_i2c_bus_power_mutex, FuriWaitForever) == FuriStatusOk);
@ -39,12 +32,11 @@ static void furi_hal_i2c_bus_power_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent
furi_check(furi_mutex_release(furi_hal_i2c_bus_power_mutex) == FuriStatusOk);
} else if(event == FuriHalI2cBusEventActivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
furi_hal_bus_enable(FuriHalBusI2C1);
LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalI2cBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusI2C1);
}
}
@ -58,17 +50,9 @@ FuriMutex* furi_hal_i2c_bus_external_mutex = NULL;
static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEvent event) {
if(event == FuriHalI2cBusEventInit) {
furi_hal_i2c_bus_external_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalI2cBusEventDeinit) {
furi_mutex_free(furi_hal_i2c_bus_external_mutex);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalI2cBusEventLock) {
furi_check(
furi_mutex_acquire(furi_hal_i2c_bus_external_mutex, FuriWaitForever) == FuriStatusOk);
@ -76,13 +60,11 @@ static void furi_hal_i2c_bus_external_event(FuriHalI2cBus* bus, FuriHalI2cBusEve
furi_check(furi_mutex_release(furi_hal_i2c_bus_external_mutex) == FuriStatusOk);
} else if(event == FuriHalI2cBusEventActivate) {
FURI_CRITICAL_ENTER();
furi_hal_bus_enable(FuriHalBusI2C3);
LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalI2cBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusI2C3);
}
}

View File

@ -1,14 +1,15 @@
#include <furi_hal_ibutton.h>
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_exti.h>
#include <furi.h>
#define TAG "FuriHalIbutton"
#define FURI_HAL_IBUTTON_TIMER TIM1
#define FURI_HAL_IBUTTON_TIMER_BUS FuriHalBusTIM1
#define FURI_HAL_IBUTTON_TIMER_IRQ FuriHalInterruptIdTim1UpTim16
typedef enum {
@ -49,9 +50,7 @@ void furi_hal_ibutton_emulate_start(
furi_hal_ibutton->callback = callback;
furi_hal_ibutton->context = context;
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FURI_HAL_IBUTTON_TIMER_BUS);
furi_hal_interrupt_set_isr(FURI_HAL_IBUTTON_TIMER_IRQ, furi_hal_ibutton_emulate_isr, NULL);
@ -81,10 +80,7 @@ void furi_hal_ibutton_emulate_stop() {
furi_hal_ibutton->state = FuriHalIbuttonStateIdle;
LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FURI_HAL_IBUTTON_TIMER_BUS);
furi_hal_interrupt_set_isr(FURI_HAL_IBUTTON_TIMER_IRQ, NULL, NULL);
furi_hal_ibutton->callback = NULL;

View File

@ -1,8 +1,10 @@
#pragma once
#include <stm32wbxx_ll_lptim.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
#include <furi_hal_bus.h>
// Timer used for tickless idle
#define FURI_HAL_IDLE_TIMER_MAX 0xFFFF
@ -10,6 +12,7 @@
#define FURI_HAL_IDLE_TIMER_IRQ LPTIM1_IRQn
static inline void furi_hal_idle_timer_init() {
furi_hal_bus_enable(FuriHalBusLPTIM1);
// Configure clock source
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE);
// There is a theoretical possibility that we need it
@ -40,7 +43,7 @@ static inline void furi_hal_idle_timer_start(uint32_t count) {
static inline void furi_hal_idle_timer_reset() {
// Hard reset timer
// THE ONLY RELIABLE WAY to stop it according to errata
LL_LPTIM_DeInit(FURI_HAL_IDLE_TIMER);
furi_hal_bus_reset(FuriHalBusLPTIM1);
// Prevent IRQ handler call
NVIC_ClearPendingIRQ(FURI_HAL_IDLE_TIMER_IRQ);
}

View File

@ -26,7 +26,7 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
property_value_out(&property_context, NULL, 2, "format", "minor", "1");
} else {
property_value_out(&property_context, NULL, 3, "device", "info", "major", "2");
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "1");
property_value_out(&property_context, NULL, 3, "device", "info", "minor", "2");
}
// Model name
@ -173,6 +173,24 @@ void furi_hal_info_get(PropertyValueCallback out, char sep, void* context) {
&property_context, "%d", 3, "firmware", "api", "major", api_version_major);
property_value_out(
&property_context, "%d", 3, "firmware", "api", "minor", api_version_minor);
property_value_out(
&property_context,
NULL,
3,
"firmware",
"origin",
"fork",
version_get_firmware_origin(firmware_version));
property_value_out(
&property_context,
NULL,
3,
"firmware",
"origin",
"git",
version_get_git_origin(firmware_version));
}
if(furi_hal_bt_is_alive()) {

View File

@ -1,14 +1,11 @@
#include <furi_hal_infrared.h>
#include <core/check.h>
#include "stm32wbxx_ll_dma.h"
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <stdint.h>
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_gpio.h>
#include <stm32wbxx_ll_dma.h>
#include <stdio.h>
#include <furi.h>
#include <math.h>
@ -21,13 +18,23 @@
(TIM_CCMR2_OC3PE | LL_TIM_OCMODE_FORCED_INACTIVE) /* Space time - force low */
/* DMA Channels definition */
#define IR_DMA DMA2
#define IR_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
#define IR_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
#define IR_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
#define IR_DMA_CH2_IRQ FuriHalInterruptIdDma2Ch2
#define IR_DMA_CH1_DEF IR_DMA, IR_DMA_CH1_CHANNEL
#define IR_DMA_CH2_DEF IR_DMA, IR_DMA_CH2_CHANNEL
#define INFRARED_DMA DMA2
#define INFRARED_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
#define INFRARED_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
#define INFRARED_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
#define INFRARED_DMA_CH2_IRQ FuriHalInterruptIdDma2Ch2
#define INFRARED_DMA_CH1_DEF INFRARED_DMA, INFRARED_DMA_CH1_CHANNEL
#define INFRARED_DMA_CH2_DEF INFRARED_DMA, INFRARED_DMA_CH2_CHANNEL
/* Timers definition */
#define INFRARED_RX_TIMER TIM2
#define INFRARED_DMA_TIMER TIM1
#define INFRARED_RX_TIMER_BUS FuriHalBusTIM2
#define INFRARED_DMA_TIMER_BUS FuriHalBusTIM1
/* Misc */
#define INFRARED_RX_GPIO_ALT GpioAltFn1TIM2
#define INFRARED_RX_IRQ FuriHalInterruptIdTIM2
typedef struct {
FuriHalInfraredRxCaptureCallback capture_callback;
@ -94,8 +101,8 @@ static void furi_hal_infrared_tim_rx_isr() {
static uint32_t previous_captured_ch2 = 0;
/* Timeout */
if(LL_TIM_IsActiveFlag_CC3(TIM2)) {
LL_TIM_ClearFlag_CC3(TIM2);
if(LL_TIM_IsActiveFlag_CC3(INFRARED_RX_TIMER)) {
LL_TIM_ClearFlag_CC3(INFRARED_RX_TIMER);
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
/* Timers CNT register starts to counting from 0 to ARR, but it is
@ -111,13 +118,13 @@ static void furi_hal_infrared_tim_rx_isr() {
}
/* Rising Edge */
if(LL_TIM_IsActiveFlag_CC1(TIM2)) {
LL_TIM_ClearFlag_CC1(TIM2);
if(LL_TIM_IsActiveFlag_CC1(INFRARED_RX_TIMER)) {
LL_TIM_ClearFlag_CC1(INFRARED_RX_TIMER);
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
if(READ_BIT(TIM2->CCMR1, TIM_CCMR1_CC1S)) {
if(READ_BIT(INFRARED_RX_TIMER->CCMR1, TIM_CCMR1_CC1S)) {
/* Low pin level is a Mark state of INFRARED signal. Invert level for further processing. */
uint32_t duration = LL_TIM_IC_GetCaptureCH1(TIM2) - previous_captured_ch2;
uint32_t duration = LL_TIM_IC_GetCaptureCH1(INFRARED_RX_TIMER) - previous_captured_ch2;
if(infrared_tim_rx.capture_callback)
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 1, duration);
} else {
@ -126,13 +133,13 @@ static void furi_hal_infrared_tim_rx_isr() {
}
/* Falling Edge */
if(LL_TIM_IsActiveFlag_CC2(TIM2)) {
LL_TIM_ClearFlag_CC2(TIM2);
if(LL_TIM_IsActiveFlag_CC2(INFRARED_RX_TIMER)) {
LL_TIM_ClearFlag_CC2(INFRARED_RX_TIMER);
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
if(READ_BIT(TIM2->CCMR1, TIM_CCMR1_CC2S)) {
if(READ_BIT(INFRARED_RX_TIMER->CCMR1, TIM_CCMR1_CC2S)) {
/* High pin level is a Space state of INFRARED signal. Invert level for further processing. */
uint32_t duration = LL_TIM_IC_GetCaptureCH2(TIM2);
uint32_t duration = LL_TIM_IC_GetCaptureCH2(INFRARED_RX_TIMER);
previous_captured_ch2 = duration;
if(infrared_tim_rx.capture_callback)
infrared_tim_rx.capture_callback(infrared_tim_rx.capture_context, 0, duration);
@ -146,62 +153,66 @@ void furi_hal_infrared_async_rx_start(void) {
furi_assert(furi_hal_infrared_state == InfraredStateIdle);
furi_hal_gpio_init_ex(
&gpio_infrared_rx, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2);
&gpio_infrared_rx,
GpioModeAltFunctionPushPull,
GpioPullNo,
GpioSpeedLow,
INFRARED_RX_GPIO_ALT);
furi_hal_bus_enable(INFRARED_RX_TIMER_BUS);
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64 - 1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM2, &TIM_InitStruct);
LL_TIM_Init(INFRARED_RX_TIMER, &TIM_InitStruct);
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_DisableARRPreload(TIM2);
LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI1FP1);
LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET);
LL_TIM_CC_DisableChannel(TIM2, LL_TIM_CHANNEL_CH2);
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
LL_TIM_DisableIT_TRIG(TIM2);
LL_TIM_DisableDMAReq_TRIG(TIM2);
LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET);
LL_TIM_EnableMasterSlaveMode(TIM2);
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_INDIRECTTI);
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
LL_TIM_SetClockSource(INFRARED_RX_TIMER, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_DisableARRPreload(INFRARED_RX_TIMER);
LL_TIM_SetTriggerInput(INFRARED_RX_TIMER, LL_TIM_TS_TI1FP1);
LL_TIM_SetSlaveMode(INFRARED_RX_TIMER, LL_TIM_SLAVEMODE_RESET);
LL_TIM_CC_DisableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2);
LL_TIM_IC_SetFilter(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_FALLING);
LL_TIM_DisableIT_TRIG(INFRARED_RX_TIMER);
LL_TIM_DisableDMAReq_TRIG(INFRARED_RX_TIMER);
LL_TIM_SetTriggerOutput(INFRARED_RX_TIMER, LL_TIM_TRGO_RESET);
LL_TIM_EnableMasterSlaveMode(INFRARED_RX_TIMER);
LL_TIM_IC_SetActiveInput(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_DIRECTTI);
LL_TIM_IC_SetPrescaler(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
LL_TIM_IC_SetFilter(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
LL_TIM_IC_SetPolarity(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_RISING);
LL_TIM_IC_SetActiveInput(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_INDIRECTTI);
LL_TIM_IC_SetPrescaler(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_infrared_tim_rx_isr, NULL);
furi_hal_interrupt_set_isr(INFRARED_RX_IRQ, furi_hal_infrared_tim_rx_isr, NULL);
furi_hal_infrared_state = InfraredStateAsyncRx;
LL_TIM_EnableIT_CC1(TIM2);
LL_TIM_EnableIT_CC2(TIM2);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2);
LL_TIM_EnableIT_CC1(INFRARED_RX_TIMER);
LL_TIM_EnableIT_CC2(INFRARED_RX_TIMER);
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH2);
LL_TIM_SetCounter(TIM2, 0);
LL_TIM_EnableCounter(TIM2);
LL_TIM_SetCounter(INFRARED_RX_TIMER, 0);
LL_TIM_EnableCounter(INFRARED_RX_TIMER);
}
void furi_hal_infrared_async_rx_stop(void) {
furi_assert(furi_hal_infrared_state == InfraredStateAsyncRx);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM2);
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
furi_hal_bus_disable(INFRARED_RX_TIMER_BUS);
furi_hal_interrupt_set_isr(INFRARED_RX_IRQ, NULL, NULL);
furi_hal_infrared_state = InfraredStateIdle;
FURI_CRITICAL_EXIT();
}
void furi_hal_infrared_async_rx_set_timeout(uint32_t timeout_us) {
LL_TIM_OC_SetCompareCH3(TIM2, timeout_us);
LL_TIM_OC_SetMode(TIM2, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_ACTIVE);
LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH3);
LL_TIM_EnableIT_CC3(TIM2);
LL_TIM_OC_SetCompareCH3(INFRARED_RX_TIMER, timeout_us);
LL_TIM_OC_SetMode(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_ACTIVE);
LL_TIM_CC_EnableChannel(INFRARED_RX_TIMER, LL_TIM_CHANNEL_CH3);
LL_TIM_EnableIT_CC3(INFRARED_RX_TIMER);
}
bool furi_hal_infrared_is_busy(void) {
@ -223,16 +234,16 @@ void furi_hal_infrared_async_rx_set_timeout_isr_callback(
}
static void furi_hal_infrared_tx_dma_terminate(void) {
LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF);
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
LL_DMA_DisableIT_TC(IR_DMA_CH2_DEF);
LL_DMA_DisableIT_TC(INFRARED_DMA_CH1_DEF);
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
LL_DMA_DisableIT_TC(INFRARED_DMA_CH2_DEF);
furi_assert(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress);
LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF);
LL_DMA_DisableChannel(IR_DMA_CH2_DEF);
LL_DMA_DisableChannel(IR_DMA_CH1_DEF);
LL_TIM_DisableCounter(TIM1);
LL_DMA_DisableIT_TC(INFRARED_DMA_CH1_DEF);
LL_DMA_DisableChannel(INFRARED_DMA_CH2_DEF);
LL_DMA_DisableChannel(INFRARED_DMA_CH1_DEF);
LL_TIM_DisableCounter(INFRARED_DMA_TIMER);
FuriStatus status = furi_semaphore_release(infrared_tim_tx.stop_semaphore);
furi_check(status == FuriStatusOk);
furi_hal_infrared_state = InfraredStateAsyncTxStopped;
@ -240,7 +251,7 @@ static void furi_hal_infrared_tx_dma_terminate(void) {
static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
uint8_t buf_num = 0;
uint32_t buffer_adr = LL_DMA_GetMemoryAddress(IR_DMA_CH2_DEF);
uint32_t buffer_adr = LL_DMA_GetMemoryAddress(INFRARED_DMA_CH2_DEF);
if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[0].data) {
buf_num = 0;
} else if(buffer_adr == (uint32_t)infrared_tim_tx.buffer[1].data) {
@ -252,13 +263,13 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
}
static void furi_hal_infrared_tx_dma_polarity_isr() {
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
if(LL_DMA_IsActiveFlag_TE1(IR_DMA)) {
LL_DMA_ClearFlag_TE1(IR_DMA);
#if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
if(LL_DMA_IsActiveFlag_TE1(INFRARED_DMA)) {
LL_DMA_ClearFlag_TE1(INFRARED_DMA);
furi_crash(NULL);
}
if(LL_DMA_IsActiveFlag_TC1(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH1_DEF)) {
LL_DMA_ClearFlag_TC1(IR_DMA);
if(LL_DMA_IsActiveFlag_TC1(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH1_DEF)) {
LL_DMA_ClearFlag_TC1(INFRARED_DMA);
furi_check(
(furi_hal_infrared_state == InfraredStateAsyncTx) ||
@ -274,23 +285,23 @@ static void furi_hal_infrared_tx_dma_polarity_isr() {
}
static void furi_hal_infrared_tx_dma_isr() {
#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
if(LL_DMA_IsActiveFlag_TE2(IR_DMA)) {
LL_DMA_ClearFlag_TE2(IR_DMA);
#if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
if(LL_DMA_IsActiveFlag_TE2(INFRARED_DMA)) {
LL_DMA_ClearFlag_TE2(INFRARED_DMA);
furi_crash(NULL);
}
if(LL_DMA_IsActiveFlag_HT2(IR_DMA) && LL_DMA_IsEnabledIT_HT(IR_DMA_CH2_DEF)) {
LL_DMA_ClearFlag_HT2(IR_DMA);
if(LL_DMA_IsActiveFlag_HT2(INFRARED_DMA) && LL_DMA_IsEnabledIT_HT(INFRARED_DMA_CH2_DEF)) {
LL_DMA_ClearFlag_HT2(INFRARED_DMA);
uint8_t buf_num = furi_hal_infrared_get_current_dma_tx_buffer();
uint8_t next_buf_num = !buf_num;
if(infrared_tim_tx.buffer[buf_num].last_packet_end) {
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
} else if(
!infrared_tim_tx.buffer[buf_num].packet_end ||
(furi_hal_infrared_state == InfraredStateAsyncTx)) {
furi_hal_infrared_tx_fill_buffer(next_buf_num, 0);
if(infrared_tim_tx.buffer[next_buf_num].last_packet_end) {
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
LL_DMA_DisableIT_HT(INFRARED_DMA_CH2_DEF);
}
} else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) {
/* fallthrough */
@ -298,8 +309,8 @@ static void furi_hal_infrared_tx_dma_isr() {
furi_crash(NULL);
}
}
if(LL_DMA_IsActiveFlag_TC2(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH2_DEF)) {
LL_DMA_ClearFlag_TC2(IR_DMA);
if(LL_DMA_IsActiveFlag_TC2(INFRARED_DMA) && LL_DMA_IsEnabledIT_TC(INFRARED_DMA_CH2_DEF)) {
LL_DMA_ClearFlag_TC2(INFRARED_DMA);
furi_check(
(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress) ||
(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) ||
@ -331,37 +342,42 @@ static void furi_hal_infrared_tx_dma_isr() {
}
static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
LL_TIM_DisableCounter(TIM1);
LL_TIM_SetRepetitionCounter(TIM1, 0);
LL_TIM_SetCounter(TIM1, 0);
LL_TIM_SetPrescaler(TIM1, 0);
LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
LL_TIM_EnableARRPreload(TIM1);
LL_TIM_DisableCounter(INFRARED_DMA_TIMER);
LL_TIM_SetRepetitionCounter(INFRARED_DMA_TIMER, 0);
LL_TIM_SetCounter(INFRARED_DMA_TIMER, 0);
LL_TIM_SetPrescaler(INFRARED_DMA_TIMER, 0);
LL_TIM_SetCounterMode(INFRARED_DMA_TIMER, LL_TIM_COUNTERMODE_UP);
LL_TIM_EnableARRPreload(INFRARED_DMA_TIMER);
LL_TIM_SetAutoReload(
TIM1, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM1), freq));
INFRARED_DMA_TIMER,
__LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(INFRARED_DMA_TIMER), freq));
if(infrared_external_output) {
LL_TIM_OC_SetCompareCH1(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
LL_TIM_OC_SetCompareCH1(
INFRARED_DMA_TIMER,
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
/* LL_TIM_OCMODE_PWM2 set by DMA */
LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1N);
LL_TIM_DisableIT_CC1(TIM1);
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_FORCED_INACTIVE);
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1);
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH1N);
LL_TIM_DisableIT_CC1(INFRARED_DMA_TIMER);
} else {
LL_TIM_OC_SetCompareCH3(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH3);
LL_TIM_OC_SetCompareCH3(
INFRARED_DMA_TIMER,
((LL_TIM_GetAutoReload(INFRARED_DMA_TIMER) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
/* LL_TIM_OCMODE_PWM2 set by DMA */
LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE);
LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH);
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH3);
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH3N);
LL_TIM_DisableIT_CC3(TIM1);
LL_TIM_OC_SetMode(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3, LL_TIM_OCMODE_FORCED_INACTIVE);
LL_TIM_OC_SetPolarity(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N, LL_TIM_OCPOLARITY_HIGH);
LL_TIM_OC_DisableFast(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3);
LL_TIM_CC_EnableChannel(INFRARED_DMA_TIMER, LL_TIM_CHANNEL_CH3N);
LL_TIM_DisableIT_CC3(INFRARED_DMA_TIMER);
}
LL_TIM_DisableMasterSlaveMode(TIM1);
LL_TIM_EnableAllOutputs(TIM1);
LL_TIM_DisableIT_UPDATE(TIM1);
LL_TIM_EnableDMAReq_UPDATE(TIM1);
LL_TIM_DisableMasterSlaveMode(INFRARED_DMA_TIMER);
LL_TIM_EnableAllOutputs(INFRARED_DMA_TIMER);
LL_TIM_DisableIT_UPDATE(INFRARED_DMA_TIMER);
LL_TIM_EnableDMAReq_UPDATE(INFRARED_DMA_TIMER);
NVIC_SetPriority(TIM1_UP_TIM16_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
@ -370,9 +386,9 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
LL_DMA_InitTypeDef dma_config = {0};
if(infrared_external_output) {
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR1);
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR1);
} else {
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR2);
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->CCMR2);
}
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
@ -385,24 +401,25 @@ static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
dma_config.NbData = 0;
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP;
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
LL_DMA_Init(IR_DMA_CH1_DEF, &dma_config);
LL_DMA_Init(INFRARED_DMA_CH1_DEF, &dma_config);
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
LL_DMA_ClearFlag_TE1(IR_DMA);
LL_DMA_ClearFlag_TC1(IR_DMA);
#if INFRARED_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
LL_DMA_ClearFlag_TE1(INFRARED_DMA);
LL_DMA_ClearFlag_TC1(INFRARED_DMA);
#else
#error Update this code. Would you kindly?
#endif
LL_DMA_EnableIT_TE(IR_DMA_CH1_DEF);
LL_DMA_EnableIT_TC(IR_DMA_CH1_DEF);
LL_DMA_EnableIT_TE(INFRARED_DMA_CH1_DEF);
LL_DMA_EnableIT_TC(INFRARED_DMA_CH1_DEF);
furi_hal_interrupt_set_isr_ex(IR_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
furi_hal_interrupt_set_isr_ex(
INFRARED_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
}
static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
LL_DMA_InitTypeDef dma_config = {0};
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->RCR);
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (INFRARED_DMA_TIMER->RCR);
dma_config.MemoryOrM2MDstAddress = (uint32_t)NULL;
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
dma_config.Mode = LL_DMA_MODE_NORMAL;
@ -413,21 +430,21 @@ static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
dma_config.NbData = 0;
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM1_UP;
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
LL_DMA_Init(IR_DMA_CH2_DEF, &dma_config);
LL_DMA_Init(INFRARED_DMA_CH2_DEF, &dma_config);
#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
LL_DMA_ClearFlag_TC2(IR_DMA);
LL_DMA_ClearFlag_HT2(IR_DMA);
LL_DMA_ClearFlag_TE2(IR_DMA);
#if INFRARED_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
LL_DMA_ClearFlag_TC2(INFRARED_DMA);
LL_DMA_ClearFlag_HT2(INFRARED_DMA);
LL_DMA_ClearFlag_TE2(INFRARED_DMA);
#else
#error Update this code. Would you kindly?
#endif
LL_DMA_EnableIT_TC(IR_DMA_CH2_DEF);
LL_DMA_EnableIT_HT(IR_DMA_CH2_DEF);
LL_DMA_EnableIT_TE(IR_DMA_CH2_DEF);
LL_DMA_EnableIT_TC(INFRARED_DMA_CH2_DEF);
LL_DMA_EnableIT_HT(INFRARED_DMA_CH2_DEF);
LL_DMA_EnableIT_TE(INFRARED_DMA_CH2_DEF);
furi_hal_interrupt_set_isr_ex(IR_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
furi_hal_interrupt_set_isr_ex(INFRARED_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
}
static void furi_hal_infrared_tx_fill_buffer_last(uint8_t buf_num) {
@ -529,14 +546,14 @@ static void furi_hal_infrared_tx_dma_set_polarity(uint8_t buf_num, uint8_t polar
furi_assert(buffer->polarity != NULL);
FURI_CRITICAL_ENTER();
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH1_DEF);
bool channel_enabled = LL_DMA_IsEnabledChannel(INFRARED_DMA_CH1_DEF);
if(channel_enabled) {
LL_DMA_DisableChannel(IR_DMA_CH1_DEF);
LL_DMA_DisableChannel(INFRARED_DMA_CH1_DEF);
}
LL_DMA_SetMemoryAddress(IR_DMA_CH1_DEF, (uint32_t)buffer->polarity);
LL_DMA_SetDataLength(IR_DMA_CH1_DEF, buffer->size + polarity_shift);
LL_DMA_SetMemoryAddress(INFRARED_DMA_CH1_DEF, (uint32_t)buffer->polarity);
LL_DMA_SetDataLength(INFRARED_DMA_CH1_DEF, buffer->size + polarity_shift);
if(channel_enabled) {
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
LL_DMA_EnableChannel(INFRARED_DMA_CH1_DEF);
}
FURI_CRITICAL_EXIT();
}
@ -549,14 +566,14 @@ static void furi_hal_infrared_tx_dma_set_buffer(uint8_t buf_num) {
/* non-circular mode requires disabled channel before setup */
FURI_CRITICAL_ENTER();
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH2_DEF);
bool channel_enabled = LL_DMA_IsEnabledChannel(INFRARED_DMA_CH2_DEF);
if(channel_enabled) {
LL_DMA_DisableChannel(IR_DMA_CH2_DEF);
LL_DMA_DisableChannel(INFRARED_DMA_CH2_DEF);
}
LL_DMA_SetMemoryAddress(IR_DMA_CH2_DEF, (uint32_t)buffer->data);
LL_DMA_SetDataLength(IR_DMA_CH2_DEF, buffer->size);
LL_DMA_SetMemoryAddress(INFRARED_DMA_CH2_DEF, (uint32_t)buffer->data);
LL_DMA_SetDataLength(INFRARED_DMA_CH2_DEF, buffer->size);
if(channel_enabled) {
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
LL_DMA_EnableChannel(INFRARED_DMA_CH2_DEF);
}
FURI_CRITICAL_EXIT();
}
@ -571,9 +588,10 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
} else {
furi_hal_gpio_init(&gpio_infrared_tx, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
}
furi_hal_interrupt_set_isr(IR_DMA_CH1_IRQ, NULL, NULL);
furi_hal_interrupt_set_isr(IR_DMA_CH2_IRQ, NULL, NULL);
LL_TIM_DeInit(TIM1);
furi_hal_interrupt_set_isr(INFRARED_DMA_CH1_IRQ, NULL, NULL);
furi_hal_interrupt_set_isr(INFRARED_DMA_CH2_IRQ, NULL, NULL);
furi_hal_bus_disable(INFRARED_DMA_TIMER_BUS);
furi_semaphore_free(infrared_tim_tx.stop_semaphore);
free(infrared_tim_tx.buffer[0].data);
@ -614,6 +632,8 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
furi_hal_infrared_tx_fill_buffer(0, INFRARED_POLARITY_SHIFT);
furi_hal_bus_enable(INFRARED_DMA_TIMER_BUS);
furi_hal_infrared_configure_tim_pwm_tx(freq, duty_cycle);
furi_hal_infrared_configure_tim_cmgr2_dma_tx();
furi_hal_infrared_configure_tim_rcr_dma_tx();
@ -622,11 +642,11 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
furi_hal_infrared_state = InfraredStateAsyncTx;
LL_TIM_ClearFlag_UPDATE(TIM1);
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
LL_TIM_ClearFlag_UPDATE(INFRARED_DMA_TIMER);
LL_DMA_EnableChannel(INFRARED_DMA_CH1_DEF);
LL_DMA_EnableChannel(INFRARED_DMA_CH2_DEF);
furi_delay_us(5);
LL_TIM_GenerateEvent_UPDATE(TIM1); /* DMA -> TIMx_RCR */
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* DMA -> TIMx_RCR */
furi_delay_us(5);
if(infrared_external_output) {
LL_GPIO_ResetOutputPin(
@ -646,8 +666,8 @@ void furi_hal_infrared_async_tx_start(uint32_t freq, float duty_cycle) {
}
FURI_CRITICAL_ENTER();
LL_TIM_GenerateEvent_UPDATE(TIM1); /* TIMx_RCR -> Repetition counter */
LL_TIM_EnableCounter(TIM1);
LL_TIM_GenerateEvent_UPDATE(INFRARED_DMA_TIMER); /* TIMx_RCR -> Repetition counter */
LL_TIM_EnableCounter(INFRARED_DMA_TIMER);
FURI_CRITICAL_EXIT();
}

View File

@ -1,8 +1,7 @@
#include <furi_hal_pwm.h>
#include <core/check.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <stdint.h>
#include <stm32wbxx_ll_tim.h>
#include <stm32wbxx_ll_lptim.h>
#include <stm32wbxx_ll_rcc.h>
@ -29,9 +28,7 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
GpioSpeedVeryHigh,
GpioAltFn1TIM1);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM1);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusTIM1);
LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetRepetitionCounter(TIM1, 0);
@ -58,9 +55,7 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
GpioSpeedVeryHigh,
GpioAltFn14LPTIM2);
FURI_CRITICAL_ENTER();
LL_LPTIM_DeInit(LPTIM2);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusLPTIM2);
LL_LPTIM_SetUpdateMode(LPTIM2, LL_LPTIM_UPDATE_MODE_ENDOFPERIOD);
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK1);
@ -80,14 +75,10 @@ void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty)
void furi_hal_pwm_stop(FuriHalPwmOutputId channel) {
if(channel == FuriHalPwmOutputIdTim1PA7) {
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM1);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusTIM1);
} else if(channel == FuriHalPwmOutputIdLptim2PA4) {
furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeAnalog);
FURI_CRITICAL_ENTER();
LL_LPTIM_DeInit(LPTIM2);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusLPTIM2);
}
}

View File

@ -1,8 +1,9 @@
#include <furi_hal_random.h>
#include <furi_hal_bus.h>
#include <furi.h>
#include <furi_hal.h>
#include <stm32wbxx_ll_rng.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_hsem.h>
#include <hw_conf.h>
@ -32,6 +33,11 @@ static uint32_t furi_hal_random_read_rng() {
return LL_RNG_ReadRandData32(RNG);
}
void furi_hal_random_init() {
furi_hal_bus_enable(FuriHalBusRNG);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_CLK48);
}
uint32_t furi_hal_random_get() {
while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID))
;
@ -40,6 +46,7 @@ uint32_t furi_hal_random_get() {
const uint32_t random_val = furi_hal_random_read_rng();
LL_RNG_Disable(RNG);
;
LL_HSEM_ReleaseLock(HSEM, CFG_HW_RNG_SEMID, 0);
return random_val;

View File

@ -1,4 +1,5 @@
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <furi.h>
#include <stm32wbxx_ll_rcc.h>
@ -111,6 +112,13 @@ static void furi_hal_resources_init_input_pins(GpioMode mode) {
}
void furi_hal_resources_init_early() {
furi_hal_bus_enable(FuriHalBusGPIOA);
furi_hal_bus_enable(FuriHalBusGPIOB);
furi_hal_bus_enable(FuriHalBusGPIOC);
furi_hal_bus_enable(FuriHalBusGPIOD);
furi_hal_bus_enable(FuriHalBusGPIOE);
furi_hal_bus_enable(FuriHalBusGPIOH);
furi_hal_resources_init_input_pins(GpioModeInput);
// SD Card stepdown control
@ -155,6 +163,12 @@ void furi_hal_resources_init_early() {
void furi_hal_resources_deinit_early() {
furi_hal_resources_init_input_pins(GpioModeAnalog);
furi_hal_bus_disable(FuriHalBusGPIOA);
furi_hal_bus_disable(FuriHalBusGPIOB);
furi_hal_bus_disable(FuriHalBusGPIOC);
furi_hal_bus_disable(FuriHalBusGPIOD);
furi_hal_bus_disable(FuriHalBusGPIOE);
furi_hal_bus_disable(FuriHalBusGPIOH);
}
void furi_hal_resources_init() {

View File

@ -2,6 +2,7 @@
#include <furi_hal_ibutton.h>
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <furi.h>
#include <stm32wbxx_ll_tim.h>
@ -9,15 +10,18 @@
#include <stm32wbxx_ll_dma.h>
#define FURI_HAL_RFID_READ_TIMER TIM1
#define FURI_HAL_RFID_READ_TIMER_BUS FuriHalBusTIM1
#define FURI_HAL_RFID_READ_TIMER_CHANNEL LL_TIM_CHANNEL_CH1N
// We can't use N channel for LL_TIM_OC_Init, so...
#define FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG LL_TIM_CHANNEL_CH1
#define FURI_HAL_RFID_EMULATE_TIMER TIM2
#define FURI_HAL_RFID_EMULATE_TIMER_BUS FuriHalBusTIM2
#define FURI_HAL_RFID_EMULATE_TIMER_IRQ FuriHalInterruptIdTIM2
#define FURI_HAL_RFID_EMULATE_TIMER_CHANNEL LL_TIM_CHANNEL_CH3
#define RFID_CAPTURE_TIM TIM2
#define RFID_CAPTURE_TIM_BUS FuriHalBusTIM2
#define RFID_CAPTURE_IND_CH LL_TIM_CHANNEL_CH3
#define RFID_CAPTURE_DIR_CH LL_TIM_CHANNEL_CH4
@ -30,7 +34,6 @@
#define RFID_DMA_CH2_DEF RFID_DMA, RFID_DMA_CH2_CHANNEL
typedef struct {
FuriHalRfidEmulateCallback callback;
FuriHalRfidDMACallback dma_callback;
FuriHalRfidReadCaptureCallback read_capture_callback;
void* context;
@ -56,11 +59,7 @@ void furi_hal_rfid_init() {
COMP_InitStruct.InputPlus = LL_COMP_INPUT_PLUS_IO1;
COMP_InitStruct.InputMinus = LL_COMP_INPUT_MINUS_1_2VREFINT;
COMP_InitStruct.InputHysteresis = LL_COMP_HYSTERESIS_HIGH;
#ifdef INVERT_RFID_IN
COMP_InitStruct.OutputPolarity = LL_COMP_OUTPUTPOL_INVERTED;
#else
COMP_InitStruct.OutputPolarity = LL_COMP_OUTPUTPOL_NONINVERTED;
#endif
COMP_InitStruct.OutputBlankingSource = LL_COMP_BLANKINGSRC_NONE;
LL_COMP_Init(COMP1, &COMP_InitStruct);
LL_COMP_SetCommonWindowMode(__LL_COMP_COMMON_INSTANCE(COMP1), LL_COMP_WINDOWMODE_DISABLE);
@ -92,7 +91,7 @@ void furi_hal_rfid_pins_reset() {
furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
}
void furi_hal_rfid_pins_emulate() {
static void furi_hal_rfid_pins_emulate() {
// ibutton low
furi_hal_ibutton_pin_configure();
furi_hal_ibutton_pin_write(false);
@ -113,7 +112,7 @@ void furi_hal_rfid_pins_emulate() {
&gpio_rfid_carrier, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn2TIM2);
}
void furi_hal_rfid_pins_read() {
static void furi_hal_rfid_pins_read() {
// ibutton low
furi_hal_ibutton_pin_configure();
furi_hal_ibutton_pin_write(false);
@ -142,10 +141,10 @@ void furi_hal_rfid_pin_pull_pulldown() {
furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false);
}
void furi_hal_rfid_tim_read(float freq, float duty_cycle) {
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER);
FURI_CRITICAL_EXIT();
void furi_hal_rfid_tim_read_start(float freq, float duty_cycle) {
furi_hal_bus_enable(FURI_HAL_RFID_READ_TIMER_BUS);
furi_hal_rfid_pins_read();
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Autoreload = (SystemCoreClock / freq) - 1;
@ -160,23 +159,23 @@ void furi_hal_rfid_tim_read(float freq, float duty_cycle) {
FURI_HAL_RFID_READ_TIMER, FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG, &TIM_OC_InitStruct);
LL_TIM_EnableCounter(FURI_HAL_RFID_READ_TIMER);
furi_hal_rfid_tim_read_continue();
}
void furi_hal_rfid_tim_read_start() {
void furi_hal_rfid_tim_read_continue() {
LL_TIM_EnableAllOutputs(FURI_HAL_RFID_READ_TIMER);
}
void furi_hal_rfid_tim_read_stop() {
void furi_hal_rfid_tim_read_pause() {
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_READ_TIMER);
}
void furi_hal_rfid_tim_emulate(float freq) {
UNUSED(freq); // FIXME
// basic PWM setup with needed freq and internal clock
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
FURI_CRITICAL_EXIT();
void furi_hal_rfid_tim_read_stop() {
furi_hal_bus_disable(FURI_HAL_RFID_READ_TIMER_BUS);
}
static void furi_hal_rfid_tim_emulate() {
LL_TIM_SetPrescaler(FURI_HAL_RFID_EMULATE_TIMER, 0);
LL_TIM_SetCounterMode(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, 1);
@ -201,32 +200,6 @@ void furi_hal_rfid_tim_emulate(float freq) {
LL_TIM_GenerateEvent_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
}
static void furi_hal_rfid_emulate_isr() {
if(LL_TIM_IsActiveFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER)) {
LL_TIM_ClearFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
furi_hal_rfid->callback(furi_hal_rfid->context);
}
}
void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context) {
furi_assert(furi_hal_rfid);
furi_hal_rfid->callback = callback;
furi_hal_rfid->context = context;
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, furi_hal_rfid_emulate_isr, NULL);
LL_TIM_EnableIT_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
LL_TIM_EnableCounter(FURI_HAL_RFID_EMULATE_TIMER);
}
void furi_hal_rfid_tim_emulate_stop() {
LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER);
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, NULL, NULL);
}
static void furi_hal_capture_dma_isr(void* context) {
UNUSED(context);
@ -247,15 +220,13 @@ static void furi_hal_capture_dma_isr(void* context) {
}
void furi_hal_rfid_tim_read_capture_start(FuriHalRfidReadCaptureCallback callback, void* context) {
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(RFID_CAPTURE_TIM);
FURI_CRITICAL_EXIT();
furi_assert(furi_hal_rfid);
furi_hal_rfid->read_capture_callback = callback;
furi_hal_rfid->context = context;
furi_hal_bus_enable(RFID_CAPTURE_TIM_BUS);
// Timer: base
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64 - 1;
@ -303,10 +274,7 @@ void furi_hal_rfid_tim_read_capture_stop() {
furi_hal_rfid_comp_stop();
furi_hal_interrupt_set_isr(FURI_HAL_RFID_EMULATE_TIMER_IRQ, NULL, NULL);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(RFID_CAPTURE_TIM);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(RFID_CAPTURE_TIM_BUS);
}
static void furi_hal_rfid_dma_isr() {
@ -341,7 +309,8 @@ void furi_hal_rfid_tim_emulate_dma_start(
furi_hal_rfid_pins_emulate();
// configure timer
furi_hal_rfid_tim_emulate(125000);
furi_hal_bus_enable(FURI_HAL_RFID_EMULATE_TIMER_BUS);
furi_hal_rfid_tim_emulate();
LL_TIM_OC_SetPolarity(
FURI_HAL_RFID_EMULATE_TIMER, FURI_HAL_RFID_EMULATE_TIMER_CHANNEL, LL_TIM_OCPOLARITY_HIGH);
LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_RFID_EMULATE_TIMER);
@ -405,32 +374,12 @@ void furi_hal_rfid_tim_emulate_dma_stop() {
LL_DMA_DeInit(RFID_DMA_CH1_DEF);
LL_DMA_DeInit(RFID_DMA_CH2_DEF);
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
furi_hal_bus_disable(FURI_HAL_RFID_EMULATE_TIMER_BUS);
FURI_CRITICAL_EXIT();
}
void furi_hal_rfid_tim_reset() {
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER);
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
FURI_CRITICAL_EXIT();
}
void furi_hal_rfid_set_emulate_period(uint32_t period) {
LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, period);
}
void furi_hal_rfid_set_emulate_pulse(uint32_t pulse) {
#if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3
LL_TIM_OC_SetCompareCH3(FURI_HAL_RFID_EMULATE_TIMER, pulse);
#else
#error Update this code. Would you kindly?
#endif
}
void furi_hal_rfid_set_read_period(uint32_t period) {
LL_TIM_SetAutoReload(FURI_HAL_RFID_READ_TIMER, period);
}
@ -443,12 +392,6 @@ void furi_hal_rfid_set_read_pulse(uint32_t pulse) {
#endif
}
void furi_hal_rfid_change_read_config(float freq, float duty_cycle) {
uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1;
furi_hal_rfid_set_read_period(period);
furi_hal_rfid_set_read_pulse(period * duty_cycle);
}
void furi_hal_rfid_comp_start() {
LL_COMP_Enable(COMP1);
// Magic
@ -483,4 +426,4 @@ void COMP_IRQHandler() {
(LL_COMP_ReadOutputLevel(COMP1) == LL_COMP_OUTPUT_LEVEL_LOW),
furi_hal_rfid_comp_callback_context);
}
}
}

View File

@ -21,14 +21,6 @@ void furi_hal_rfid_init();
*/
void furi_hal_rfid_pins_reset();
/** Config rfid pins to emulate state
*/
void furi_hal_rfid_pins_emulate();
/** Config rfid pins to read state
*/
void furi_hal_rfid_pins_read();
/** Release rfid pull pin
*/
void furi_hal_rfid_pin_pull_release();
@ -37,33 +29,24 @@ void furi_hal_rfid_pin_pull_release();
*/
void furi_hal_rfid_pin_pull_pulldown();
/** Config rfid timer to read state
*
/** Start read timer
* @param freq timer frequency
* @param duty_cycle timer duty cycle, 0.0-1.0
*/
void furi_hal_rfid_tim_read(float freq, float duty_cycle);
void furi_hal_rfid_tim_read_start(float freq, float duty_cycle);
/** Start read timer
/** Pause read timer, to be able to continue later
*/
void furi_hal_rfid_tim_read_start();
void furi_hal_rfid_tim_read_pause();
/** Continue read timer
*/
void furi_hal_rfid_tim_read_continue();
/** Stop read timer
*/
void furi_hal_rfid_tim_read_stop();
/** Config rfid timer to emulate state
*
* @param freq timer frequency
*/
void furi_hal_rfid_tim_emulate(float freq);
typedef void (*FuriHalRfidEmulateCallback)(void* context);
/** Start emulation timer
*/
void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context);
typedef void (*FuriHalRfidReadCaptureCallback)(bool level, uint32_t duration, void* context);
void furi_hal_rfid_tim_read_capture_start(FuriHalRfidReadCaptureCallback callback, void* context);
@ -81,26 +64,6 @@ void furi_hal_rfid_tim_emulate_dma_start(
void furi_hal_rfid_tim_emulate_dma_stop();
/** Stop emulation timer
*/
void furi_hal_rfid_tim_emulate_stop();
/** Config rfid timers to reset state
*/
void furi_hal_rfid_tim_reset();
/** Set emulation timer period
*
* @param period overall duration
*/
void furi_hal_rfid_set_emulate_period(uint32_t period);
/** Set emulation timer pulse
*
* @param pulse duration of high level
*/
void furi_hal_rfid_set_emulate_pulse(uint32_t pulse);
/** Set read timer period
*
* @param period overall duration
@ -113,13 +76,6 @@ void furi_hal_rfid_set_read_period(uint32_t period);
*/
void furi_hal_rfid_set_read_pulse(uint32_t pulse);
/** Сhanges the configuration of the RFID timer "on a fly"
*
* @param freq new frequency
* @param duty_cycle new duty cycle
*/
void furi_hal_rfid_change_read_config(float freq, float duty_cycle);
/** Start/Enable comparator */
void furi_hal_rfid_comp_start();

View File

@ -2,8 +2,8 @@
#include <furi_hal_light.h>
#include <furi_hal_debug.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_pwr.h>
#include <stm32wbxx_ll_bus.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_rtc.h>
#include <stm32wbxx_ll_utils.h>
@ -44,10 +44,8 @@ _Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24)
#define FURI_HAL_RTC_MONTHS_COUNT 12
#define FURI_HAL_RTC_EPOCH_START_YEAR 1970
#define FURI_HAL_RTC_IS_LEAP_YEAR(year) \
((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
static const uint8_t furi_hal_rtc_days_per_month[][FURI_HAL_RTC_MONTHS_COUNT] = {
static const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
@ -395,7 +393,7 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
uint8_t leap_years = 0;
for(uint16_t y = FURI_HAL_RTC_EPOCH_START_YEAR; y < datetime->year; y++) {
if(FURI_HAL_RTC_IS_LEAP_YEAR(y)) {
if(furi_hal_rtc_is_leap_year(y)) {
leap_years++;
} else {
years++;
@ -406,10 +404,10 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
((years * furi_hal_rtc_days_per_year[0]) + (leap_years * furi_hal_rtc_days_per_year[1])) *
FURI_HAL_RTC_SECONDS_PER_DAY;
uint8_t year_index = (FURI_HAL_RTC_IS_LEAP_YEAR(datetime->year)) ? 1 : 0;
bool leap_year = furi_hal_rtc_is_leap_year(datetime->year);
for(uint8_t m = 0; m < (datetime->month - 1); m++) {
timestamp += furi_hal_rtc_days_per_month[year_index][m] * FURI_HAL_RTC_SECONDS_PER_DAY;
for(uint8_t m = 1; m < datetime->month; m++) {
timestamp += furi_hal_rtc_get_days_per_month(leap_year, m) * FURI_HAL_RTC_SECONDS_PER_DAY;
}
timestamp += (datetime->day - 1) * FURI_HAL_RTC_SECONDS_PER_DAY;
@ -419,3 +417,15 @@ uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime) {
return timestamp;
}
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];
}
bool furi_hal_rtc_is_leap_year(uint16_t year) {
return (((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0);
}
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month) {
return furi_hal_rtc_days_per_month[leap_year ? 1 : 0][month - 1];
}

View File

@ -2,6 +2,7 @@
#include <furi_hal_gpio.h>
#include <furi_hal_resources.h>
#include <furi_hal_power.h>
#include <furi_hal_bus.h>
#include <stm32wbxx_ll_tim.h>
#include <furi_hal_cortex.h>
@ -20,16 +21,11 @@ static FuriMutex* furi_hal_speaker_mutex = NULL;
void furi_hal_speaker_init() {
furi_assert(furi_hal_speaker_mutex == NULL);
furi_hal_speaker_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
FURI_CRITICAL_EXIT();
FURI_LOG_I(TAG, "Init OK");
}
void furi_hal_speaker_deinit() {
furi_check(furi_hal_speaker_mutex != NULL);
LL_TIM_DeInit(FURI_HAL_SPEAKER_TIMER);
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
furi_mutex_free(furi_hal_speaker_mutex);
furi_hal_speaker_mutex = NULL;
}
@ -39,6 +35,7 @@ bool furi_hal_speaker_acquire(uint32_t timeout) {
if(furi_mutex_acquire(furi_hal_speaker_mutex, timeout) == FuriStatusOk) {
furi_hal_power_insomnia_enter();
furi_hal_bus_enable(FuriHalBusTIM16);
furi_hal_gpio_init_ex(
&gpio_speaker, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn14TIM16);
return true;
@ -53,6 +50,8 @@ void furi_hal_speaker_release() {
furi_hal_speaker_stop();
furi_hal_gpio_init(&gpio_speaker, GpioModeAnalog, GpioPullDown, GpioSpeedLow);
furi_hal_bus_disable(FuriHalBusTIM16);
furi_hal_power_insomnia_exit();
furi_check(furi_mutex_release(furi_hal_speaker_mutex) == FuriStatusOk);

View File

@ -1,6 +1,7 @@
#include <furi_hal_spi_config.h>
#include <furi_hal_resources.h>
#include <furi_hal_spi.h>
#include <furi_hal_bus.h>
#include <furi.h>
#include <furi_hal_subghz.h>
@ -101,28 +102,17 @@ void furi_hal_spi_config_init() {
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_r_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
furi_mutex_free(furi_hal_spi_bus_r_mutex);
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalSpiBusEventLock) {
furi_check(furi_mutex_acquire(furi_hal_spi_bus_r_mutex, FuriWaitForever) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventUnlock) {
furi_check(furi_mutex_release(furi_hal_spi_bus_r_mutex) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventActivate) {
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusSPI1);
} else if(event == FuriHalSpiBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusSPI1);
}
}
@ -136,28 +126,17 @@ FuriMutex* furi_hal_spi_bus_d_mutex = NULL;
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if(event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_d_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
bus->current_handle = NULL;
} else if(event == FuriHalSpiBusEventDeinit) {
furi_mutex_free(furi_hal_spi_bus_d_mutex);
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
} else if(event == FuriHalSpiBusEventLock) {
furi_check(furi_mutex_acquire(furi_hal_spi_bus_d_mutex, FuriWaitForever) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventUnlock) {
furi_check(furi_mutex_release(furi_hal_spi_bus_d_mutex) == FuriStatusOk);
} else if(event == FuriHalSpiBusEventActivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
furi_hal_bus_enable(FuriHalBusSPI2);
} else if(event == FuriHalSpiBusEventDeactivate) {
FURI_CRITICAL_ENTER();
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
FURI_CRITICAL_EXIT();
furi_hal_bus_disable(FuriHalBusSPI2);
}
}

View File

@ -6,8 +6,6 @@
#include <furi_hal_gpio.h>
#include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_rcc.h>
#include <stm32wbxx_ll_bus.h>
#ifdef __cplusplus
extern "C" {

View File

@ -7,6 +7,7 @@
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>
#include <furi_hal_power.h>
#include <furi_hal_bus.h>
#include <stm32wbxx_ll_dma.h>
@ -596,6 +597,8 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
furi_hal_subghz_capture_callback = callback;
furi_hal_subghz_capture_callback_context = context;
furi_hal_bus_enable(FuriHalBusTIM2);
// Timer: base
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64 - 1;
@ -680,7 +683,7 @@ void furi_hal_subghz_stop_async_rx() {
furi_hal_subghz_idle();
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM2);
furi_hal_bus_disable(FuriHalBusTIM2);
// Stop debug
furi_hal_subghz_stop_debug();
@ -859,6 +862,8 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
LL_DMA_EnableIT_HT(SUBGHZ_DMA_CH1_DEF);
LL_DMA_EnableChannel(SUBGHZ_DMA_CH1_DEF);
furi_hal_bus_enable(FuriHalBusTIM2);
// Configure TIM2
LL_TIM_InitTypeDef TIM_InitStruct = {0};
TIM_InitStruct.Prescaler = 64 - 1;
@ -958,7 +963,7 @@ void furi_hal_subghz_stop_async_tx() {
// Deinitialize Timer
FURI_CRITICAL_ENTER();
LL_TIM_DeInit(TIM2);
furi_hal_bus_disable(FuriHalBusTIM2);
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
// Deinitialize DMA

View File

@ -4,6 +4,7 @@
#include <stm32wbxx_ll_usart.h>
#include <stm32wbxx_ll_rcc.h>
#include <furi_hal_resources.h>
#include <furi_hal_bus.h>
#include <furi.h>
@ -13,6 +14,9 @@ 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,
@ -50,6 +54,9 @@ static void furi_hal_usart_init(uint32_t baud) {
}
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,
@ -86,10 +93,11 @@ static void furi_hal_lpuart_init(uint32_t baud) {
}
void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud) {
if(ch == FuriHalUartIdLPUART1)
if(ch == FuriHalUartIdLPUART1) {
furi_hal_lpuart_init(baud);
else if(ch == FuriHalUartIdUSART1)
} else if(ch == FuriHalUartIdUSART1) {
furi_hal_usart_init(baud);
}
}
void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
@ -126,11 +134,15 @@ void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
void furi_hal_uart_deinit(FuriHalUartId ch) {
furi_hal_uart_set_irq_cb(ch, NULL, NULL);
if(ch == FuriHalUartIdUSART1) {
LL_USART_Disable(USART1);
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) {
LL_LPUART_Disable(LPUART1);
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);
}

View File

@ -2,7 +2,9 @@
#include <furi_hal_usb_i.h>
#include <furi_hal_usb.h>
#include <furi_hal_power.h>
#include <stm32wbxx_ll_pwr.h>
#include <stm32wbxx_ll_rcc.h>
#include <furi.h>
#include <toolbox/api_lock.h>
@ -86,6 +88,8 @@ static void wkup_evt(usbd_device* dev, uint8_t event, uint8_t ep);
/* Low-level init */
void furi_hal_usb_init(void) {
LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLLSAI1);
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_PWR_EnableVddUSB();
@ -98,7 +102,10 @@ void furi_hal_usb_init(void) {
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
usbd_init(&udev, &usbd_hw, USB_EP0_SIZE, ubuf, sizeof(ubuf));
FURI_CRITICAL_ENTER();
usbd_enable(&udev, true);
FURI_CRITICAL_EXIT();
usbd_reg_descr(&udev, usb_descriptor_get);
usbd_reg_event(&udev, usbd_evt_susp, susp_evt);
@ -359,8 +366,10 @@ static void usb_process_mode_reinit() {
usbd_connect(&udev, false);
usb.enabled = false;
FURI_CRITICAL_ENTER();
usbd_enable(&udev, false);
usbd_enable(&udev, true);
FURI_CRITICAL_EXIT();
furi_delay_ms(USB_RECONNECT_DELAY);
usb_process_mode_start(usb.interface, usb.interface_context);

View File

@ -38,6 +38,12 @@ static bool flipper_update_mount_sd() {
}
static bool flipper_update_init() {
// TODO: Configure missing peripherals properly
furi_hal_bus_enable(FuriHalBusHSEM);
furi_hal_bus_enable(FuriHalBusIPCC);
furi_hal_bus_enable(FuriHalBusRNG);
furi_hal_bus_enable(FuriHalBusUSART1);
furi_hal_clock_init();
furi_hal_rtc_init();
furi_hal_interrupt_init();

View File

@ -12,9 +12,11 @@ struct STOP_EXTERNING_ME {};
#include <furi_hal_cortex.h>
#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>
#include <furi_hal_sd.h>
#include <furi_hal_i2c.h>

View File

@ -6,6 +6,9 @@
extern "C" {
#endif
/** Initialize random subsystem */
void furi_hal_random_init();
/** Get random value
*
* @return random value

View File

@ -255,6 +255,30 @@ uint32_t furi_hal_rtc_get_timestamp();
*/
uint32_t furi_hal_rtc_datetime_to_timestamp(FuriHalRtcDateTime* datetime);
/** Gets the number of days in the year according to the Gregorian calendar.
*
* @param year Input year.
*
* @return number of days in `year`.
*/
uint16_t furi_hal_rtc_get_days_per_year(uint16_t year);
/** Check if a year a leap year in the Gregorian calendar.
*
* @param year Input year.
*
* @return true if `year` is a leap year.
*/
bool furi_hal_rtc_is_leap_year(uint16_t year);
/** Get the number of days in the month.
*
* @param leap_year true to calculate based on leap years
* @param month month to check, where 1 = January
* @return the number of days in the month
*/
uint8_t furi_hal_rtc_get_days_per_month(bool leap_year, uint8_t month);
#ifdef __cplusplus
}
#endif

View File

@ -78,6 +78,11 @@ extern "C" {
#define TOSTRING(x) STRINGIFY(x)
#endif
#ifndef CONCATENATE
#define CONCATENATE(a, b) CONCATENATE_(a, b)
#define CONCATENATE_(a, b) a##b
#endif
#ifndef REVERSE_BYTES_U32
#define REVERSE_BYTES_U32(x) \
((((x)&0x000000FF) << 24) | (((x)&0x0000FF00) << 8) | (((x)&0x00FF0000) >> 8) | \

View File

@ -243,10 +243,12 @@ static void digital_signal_stop_timer() {
LL_TIM_DisableCounter(TIM2);
LL_TIM_DisableUpdateEvent(TIM2);
LL_TIM_DisableDMAReq_UPDATE(TIM2);
furi_hal_bus_disable(FuriHalBusTIM2);
}
static void digital_signal_setup_timer() {
digital_signal_stop_timer();
furi_hal_bus_enable(FuriHalBusTIM2);
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);

View File

@ -151,9 +151,7 @@ static int32_t lfrfid_raw_read_worker_thread(void* thread_context) {
if(file_valid) {
// setup carrier
furi_hal_rfid_pins_read();
furi_hal_rfid_tim_read(worker->frequency, worker->duty_cycle);
furi_hal_rfid_tim_read_start();
furi_hal_rfid_tim_read_start(worker->frequency, worker->duty_cycle);
// stabilize detector
furi_delay_ms(1500);

View File

@ -100,24 +100,21 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
uint32_t timeout,
ProtocolId* result_protocol) {
LFRFIDWorkerReadState state = LFRFIDWorkerReadTimeout;
furi_hal_rfid_pins_read();
if(feature & LFRFIDFeatureASK) {
furi_hal_rfid_tim_read(125000, 0.5);
furi_hal_rfid_tim_read_start(125000, 0.5);
FURI_LOG_D(TAG, "Start ASK");
if(worker->read_cb) {
worker->read_cb(LFRFIDWorkerReadStartASK, PROTOCOL_NO, worker->cb_ctx);
}
} else {
furi_hal_rfid_tim_read(62500, 0.25);
furi_hal_rfid_tim_read_start(62500, 0.25);
FURI_LOG_D(TAG, "Start PSK");
if(worker->read_cb) {
worker->read_cb(LFRFIDWorkerReadStartPSK, PROTOCOL_NO, worker->cb_ctx);
}
}
furi_hal_rfid_tim_read_start();
// stabilize detector
lfrfid_worker_delay(worker, LFRFID_WORKER_READ_STABILIZE_TIME_MS);
@ -205,7 +202,7 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
average_index = 0;
if(worker->read_cb) {
if(average > 0.2 && average < 0.8) {
if(average > 0.2f && average < 0.8f) {
if(!card_detected) {
card_detected = true;
worker->read_cb(

View File

@ -14,9 +14,7 @@
#define T5577_OPCODE_RESET 0b00
static void t5577_start() {
furi_hal_rfid_tim_read(125000, 0.5);
furi_hal_rfid_pins_read();
furi_hal_rfid_tim_read_start();
furi_hal_rfid_tim_read_start(125000, 0.5);
// do not ground the antenna
furi_hal_rfid_pin_pull_release();
@ -24,14 +22,13 @@ static void t5577_start() {
static void t5577_stop() {
furi_hal_rfid_tim_read_stop();
furi_hal_rfid_tim_reset();
furi_hal_rfid_pins_reset();
}
static void t5577_write_gap(uint32_t gap_time) {
furi_hal_rfid_tim_read_stop();
furi_hal_rfid_tim_read_pause();
furi_delay_us(gap_time * 8);
furi_hal_rfid_tim_read_start();
furi_hal_rfid_tim_read_continue();
}
static void t5577_write_bit(bool value) {

View File

@ -464,6 +464,19 @@ static bool nfc_worker_read_mf_desfire(NfcWorker* nfc_worker, FuriHalNfcTxRxCont
do {
if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break;
if(!mf_df_read_card(tx_rx, data)) break;
FURI_LOG_I(TAG, "Trying to parse a supported card ...");
// The model for parsing DESFire is a little different to other cards;
// we don't have parsers to provide encryption keys, so we can read the
// data normally, and then pass the read data to a parser.
//
// There are fully-protected DESFire cards, but providing keys for them
// is difficult (and unnessesary for many transit cards).
for(size_t i = 0; i < NfcSupportedCardTypeEnd; i++) {
if(nfc_supported_card[i].protocol == NfcDeviceProtocolMifareDesfire) {
if(nfc_supported_card[i].parse(nfc_worker->dev_data)) break;
}
}
read_success = true;
} while(false);

View File

@ -6,6 +6,7 @@
#include "troika_4k_parser.h"
#include "two_cities.h"
#include "all_in_one.h"
#include "opal.h"
NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = {
[NfcSupportedCardTypePlantain] =
@ -50,6 +51,14 @@ NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = {
.read = all_in_one_parser_read,
.parse = all_in_one_parser_parse,
},
[NfcSupportedCardTypeOpal] =
{
.protocol = NfcDeviceProtocolMifareDesfire,
.verify = stub_parser_verify_read,
.read = stub_parser_verify_read,
.parse = opal_parser_parse,
},
};
bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data) {
@ -65,3 +74,9 @@ bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data) {
return card_parsed;
}
bool stub_parser_verify_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
UNUSED(nfc_worker);
UNUSED(tx_rx);
return false;
}

View File

@ -11,6 +11,7 @@ typedef enum {
NfcSupportedCardTypeTroika4K,
NfcSupportedCardTypeTwoCities,
NfcSupportedCardTypeAllInOne,
NfcSupportedCardTypeOpal,
NfcSupportedCardTypeEnd,
} NfcSupportedCardType;
@ -31,3 +32,8 @@ typedef struct {
extern NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd];
bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data);
// stub_parser_verify_read does nothing, and always reports that it does not
// support the card. This is needed for DESFire card parsers which can't
// provide keys, and only use NfcSupportedCard->parse.
bool stub_parser_verify_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);

204
lib/nfc/parsers/opal.c Normal file
View File

@ -0,0 +1,204 @@
/*
* opal.c - Parser for Opal card (Sydney, Australia).
*
* Copyright 2023 Michael Farrell <micolous+git@gmail.com>
*
* This will only read "standard" MIFARE DESFire-based Opal cards. Free travel
* cards (including School Opal cards, veteran, vision-impaired persons and
* TfNSW employees' cards) and single-trip tickets are MIFARE Ultralight C
* cards and not supported.
*
* Reference: https://github.com/metrodroid/metrodroid/wiki/Opal
*
* Note: The card values are all little-endian (like Flipper), but the above
* reference was originally written based on Java APIs, which are big-endian.
* This implementation presumes a little-endian system.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "nfc_supported_card.h"
#include "opal.h"
#include <applications/services/locale/locale.h>
#include <gui/modules/widget.h>
#include <nfc_worker_i.h>
#include <furi_hal.h>
static const uint8_t opal_aid[3] = {0x31, 0x45, 0x53};
static const char* opal_modes[5] =
{"Rail / Metro", "Ferry / Light Rail", "Bus", "Unknown mode", "Manly Ferry"};
static const char* opal_usages[14] = {
"New / Unused",
"Tap on: new journey",
"Tap on: transfer from same mode",
"Tap on: transfer from other mode",
"", // Manly Ferry: new journey
"", // Manly Ferry: transfer from ferry
"", // Manly Ferry: transfer from other
"Tap off: distance fare",
"Tap off: flat fare",
"Automated tap off: failed to tap off",
"Tap off: end of trip without start",
"Tap off: reversal",
"Tap on: rejected",
"Unknown usage",
};
// Opal file 0x7 structure. Assumes a little-endian CPU.
typedef struct __attribute__((__packed__)) {
uint32_t serial : 32;
uint8_t check_digit : 4;
bool blocked : 1;
uint16_t txn_number : 16;
int32_t balance : 21;
uint16_t days : 15;
uint16_t minutes : 11;
uint8_t mode : 3;
uint16_t usage : 4;
bool auto_topup : 1;
uint8_t weekly_journeys : 4;
uint16_t checksum : 16;
} OpalFile;
static_assert(sizeof(OpalFile) == 16);
// Converts an Opal timestamp to FuriHalRtcDateTime.
//
// Opal measures days since 1980-01-01 and minutes since midnight, and presumes
// all days are 1440 minutes.
void opal_date_time_to_furi(uint16_t days, uint16_t minutes, FuriHalRtcDateTime* out) {
if(!out) return;
uint16_t diy;
out->year = 1980;
out->month = 1;
// 1980-01-01 is a Tuesday
out->weekday = ((days + 1) % 7) + 1;
out->hour = minutes / 60;
out->minute = minutes % 60;
out->second = 0;
// What year is it?
for(;;) {
diy = furi_hal_rtc_get_days_per_year(out->year);
if(days < diy) break;
days -= diy;
out->year++;
}
// 1-index the day of the year
days++;
// What month is it?
bool is_leap = furi_hal_rtc_is_leap_year(out->year);
for(;;) {
uint8_t dim = furi_hal_rtc_get_days_per_month(is_leap, out->month);
if(days <= dim) break;
days -= dim;
out->month++;
}
out->day = days;
}
bool opal_parser_parse(NfcDeviceData* dev_data) {
if(dev_data->protocol != NfcDeviceProtocolMifareDesfire) {
return false;
}
MifareDesfireApplication* app = mf_df_get_application(&dev_data->mf_df_data, &opal_aid);
if(app == NULL) {
return false;
}
MifareDesfireFile* f = mf_df_get_file(app, 0x07);
if(f == NULL || f->type != MifareDesfireFileTypeStandard || f->settings.data.size != 16 ||
!f->contents) {
return false;
}
OpalFile* o = (OpalFile*)f->contents;
uint8_t serial2 = o->serial / 10000000;
uint16_t serial3 = (o->serial / 1000) % 10000;
uint16_t serial4 = (o->serial % 1000);
if(o->check_digit > 9) {
return false;
}
char* sign = "";
if(o->balance < 0) {
// Negative balance. Make this a positive value again and record the
// sign separately, because then we can handle balances of -99..-1
// cents, as the "dollars" division below would result in a positive
// zero value.
o->balance = abs(o->balance); //-V1081
sign = "-";
}
uint8_t cents = o->balance % 100;
int32_t dollars = o->balance / 100;
FuriHalRtcDateTime timestamp;
opal_date_time_to_furi(o->days, o->minutes, &timestamp);
if(o->mode >= 3) {
// 3..7 are "reserved", but we use 4 to indicate the Manly Ferry.
o->mode = 3;
}
if(o->usage >= 4 && o->usage <= 6) {
// Usages 4..6 associated with the Manly Ferry, which correspond to
// usages 1..3 for other modes.
o->usage -= 3;
o->mode = 4;
}
const char* mode_str = (o->mode <= 4 ? opal_modes[o->mode] : opal_modes[3]); //-V547
const char* usage_str = (o->usage <= 12 ? opal_usages[o->usage] : opal_usages[13]);
furi_string_printf(
dev_data->parsed_data,
"\e#Opal: $%s%ld.%02hu\n3085 22%02hhu %04hu %03hu%01hhu\n%s, %s\n",
sign,
dollars,
cents,
serial2,
serial3,
serial4,
o->check_digit,
mode_str,
usage_str);
FuriString* timestamp_str = furi_string_alloc();
locale_format_date(timestamp_str, &timestamp, locale_get_date_format(), "-");
furi_string_cat(dev_data->parsed_data, timestamp_str);
furi_string_cat_str(dev_data->parsed_data, " at ");
locale_format_time(timestamp_str, &timestamp, locale_get_time_format(), false);
furi_string_cat(dev_data->parsed_data, timestamp_str);
furi_string_free(timestamp_str);
furi_string_cat_printf(
dev_data->parsed_data,
"\nWeekly journeys: %hhu, Txn #%hu\n",
o->weekly_journeys,
o->txn_number);
if(o->auto_topup) {
furi_string_cat_str(dev_data->parsed_data, "Auto-topup enabled\n");
}
if(o->blocked) {
furi_string_cat_str(dev_data->parsed_data, "Card blocked\n");
}
return true;
}

5
lib/nfc/parsers/opal.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "nfc_supported_card.h"
bool opal_parser_parse(NfcDeviceData* dev_data);

View File

@ -42,6 +42,30 @@ void mf_df_clear(MifareDesfireData* data) {
data->app_head = NULL;
}
MifareDesfireApplication* mf_df_get_application(MifareDesfireData* data, const uint8_t (*aid)[3]) {
if(!data) {
return NULL;
}
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
if(memcmp(aid, app->id, 3) == 0) {
return app;
}
}
return NULL;
}
MifareDesfireFile* mf_df_get_file(MifareDesfireApplication* app, uint8_t id) {
if(!app) {
return NULL;
}
for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
if(file->id == id) {
return file;
}
}
return NULL;
}
void mf_df_cat_data(MifareDesfireData* data, FuriString* out) {
mf_df_cat_card_info(data, out);
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {

View File

@ -130,6 +130,9 @@ void mf_df_cat_file(MifareDesfireFile* file, FuriString* out);
bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK);
MifareDesfireApplication* mf_df_get_application(MifareDesfireData* data, const uint8_t (*aid)[3]);
MifareDesfireFile* mf_df_get_file(MifareDesfireApplication* app, uint8_t id);
uint16_t mf_df_prepare_get_version(uint8_t* dest);
bool mf_df_parse_get_version_response(uint8_t* buf, uint16_t len, MifareDesfireVersion* out);

View File

@ -135,6 +135,7 @@ void pulse_reader_stop(PulseReader* signal) {
LL_DMA_DisableChannel(DMA1, signal->dma_channel + 1);
LL_DMAMUX_DisableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0);
LL_TIM_DisableCounter(TIM2);
furi_hal_bus_disable(FuriHalBusTIM2);
furi_hal_gpio_init_simple(signal->gpio, GpioModeAnalog);
}
@ -146,6 +147,8 @@ void pulse_reader_start(PulseReader* signal) {
signal->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)signal->gpio_buffer;
signal->dma_config_gpio.NbData = signal->size;
furi_hal_bus_enable(FuriHalBusTIM2);
/* start counter */
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);

View File

@ -5,7 +5,7 @@
#define VERSION_MAGIC (0xBE40u)
#define VERSION_MAJOR (0x1u)
#define VERSION_MINOR (0x0u)
#define VERSION_MINOR (0x1u)
struct Version {
// Header
@ -20,6 +20,9 @@ struct Version {
// Payload bits and pieces
const uint8_t target;
const bool build_is_dirty;
// v 1.1
const char* firmware_origin;
const char* git_origin;
const char* custom_flipper_name;
};
@ -38,6 +41,8 @@ static Version version = {
,
.target = TARGET,
.build_is_dirty = BUILD_DIRTY,
.firmware_origin = FIRMWARE_ORIGIN,
.git_origin = GIT_ORIGIN,
.custom_flipper_name = NULL,
};
@ -83,3 +88,11 @@ uint8_t version_get_target(const Version* v) {
bool version_get_dirty_flag(const Version* v) {
return v ? v->build_is_dirty : version.build_is_dirty;
}
const char* version_get_firmware_origin(const Version* v) {
return v ? v->firmware_origin : version.firmware_origin;
}
const char* version_get_git_origin(const Version* v) {
return v ? v->git_origin : version.git_origin;
}

View File

@ -100,6 +100,17 @@ uint8_t version_get_target(const Version* v);
*/
bool version_get_dirty_flag(const Version* v);
/**
* Get firmware origin. "Official" for mainline firmware, fork name for forks.
* Set by FIRMWARE_ORIGIN fbt argument.
*/
const char* version_get_firmware_origin(const Version* v);
/**
* Get git repo origin
*/
const char* version_get_git_origin(const Version* v);
#ifdef __cplusplus
}
#endif

View File

@ -23,6 +23,10 @@ class VersionData:
version: str
target: int
build_is_dirty: bool
# Since version 1.1
firmware_origin: str = ""
git_origin: str = ""
# More fields may be added in the future
extra: Optional[Dict[str, str]] = field(default_factory=dict)
@ -52,7 +56,7 @@ class VersionLoader:
# Struct version 1.0
extra_data = int(self.version_ptr[5].cast(self._uint_type))
return VersionData(
version_data = VersionData(
git_hash=self.version_ptr[1].cast(self._cstr_type).string(),
git_branch=self.version_ptr[2].cast(self._cstr_type).string(),
build_date=self.version_ptr[3].cast(self._cstr_type).string(),
@ -60,6 +64,12 @@ class VersionLoader:
target=extra_data & 0xF,
build_is_dirty=bool((extra_data >> 8) & 0xF),
)
if minor >= 1:
version_data.firmware_origin = (
self.version_ptr[6].cast(self._cstr_type).string()
)
version_data.git_origin = self.version_ptr[7].cast(self._cstr_type).string()
return version_data
def load_unversioned(self):
"""Parse an early version of the version struct."""
@ -104,6 +114,10 @@ class FlipperFwVersion(gdb.Command):
print(f"\tGit commit: {v.version.git_hash}")
print(f"\tDirty: {v.version.build_is_dirty}")
print(f"\tHW Target: {v.version.target}")
if v.version.firmware_origin:
print(f"\tOrigin: {v.version.firmware_origin}")
if v.version.git_origin:
print(f"\tGit origin: {v.version.git_origin}")
FlipperFwVersion()

View File

@ -0,0 +1,67 @@
"""
To introduce changes to firmware build environment that are specific to your fork:
create a file "scripts/fbt/fbt_hooks.py"
With it, you can define functions that will be called at specific points of
firmware build configuration, with environment as an argument.
For example, you can define a function `PreConfigureFwEnvionment(env)` that
defines that will be a part of SDK build, so applications can
use them for conditional compilation.
Here is a list of all available hooks:
PreConfigureFwEnvionment(env):
This function is called on firmware environment (incl. updater)
before any major configuration is done.
PostConfigureFwEnvionment(env):
This function is called on firmware environment (incl. updater)
after all configuration is done.
PreConfigureUfbtEnvionment(env):
This function is called on ufbt environment at the beginning of
its configuration, before dist environment is created.
PostConfigureUfbtEnvionment(env):
This function is called on ufbt dist_env environment after all
configuration and target creation is done.
"""
class DefaultFbtHooks:
pass
try:
from fbt import fbt_hooks
except ImportError:
fbt_hooks = DefaultFbtHooks()
def generate(env):
stub_hook = lambda env: None
control_hooks = [
"PreConfigureFwEnvionment",
"PostConfigureFwEnvionment",
"PreConfigureUfbtEnvionment",
"PostConfigureUfbtEnvionment",
]
if (
isinstance(fbt_hooks, DefaultFbtHooks)
and env.subst("${FIRMWARE_ORIGIN}") != "Official"
):
# If fbt_hooks.py is not present, but we are not building official firmware,
# create "scripts/fbt/fbt_hooks.py" to implement changes to firmware build environment.
pass
for hook_name in control_hooks:
hook_fn = getattr(fbt_hooks, hook_name, stub_hook)
env.AddMethod(hook_fn, hook_name)
def exists():
return True

View File

@ -19,7 +19,9 @@ def generate(env):
BUILDERS={
"VersionBuilder": Builder(
action=Action(
'${PYTHON3} "${VERSION_SCRIPT}" generate -t ${TARGET_HW} -o ${TARGET.dir.posix} --dir "${ROOT_DIR}"',
'${PYTHON3} "${VERSION_SCRIPT}" generate '
"-t ${TARGET_HW} -fw-origin ${FIRMWARE_ORIGIN} "
'-o ${TARGET.dir.posix} --dir "${ROOT_DIR}"',
"${VERSIONCOMSTR}",
),
emitter=version_emitter,

Some files were not shown because too many files have changed in this diff Show More