mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-25 01:38:11 -07:00
Merge branch 'dev' into nfcf
This commit is contained in:
+4
-13
@@ -2,15 +2,6 @@ Import("env")
|
||||
|
||||
env.Append(
|
||||
LINT_SOURCES=[Dir(".")],
|
||||
SDK_HEADERS=[
|
||||
*env.GlobRecursive("*.h", "targets/furi_hal_include", "*_i.h"),
|
||||
*env.GlobRecursive("*.h", "targets/f${TARGET_HW}/furi_hal", "*_i.h"),
|
||||
File("targets/f7/platform_specific/intrinsic_export.h"),
|
||||
],
|
||||
)
|
||||
|
||||
env.SetDefault(
|
||||
SDK_DEFINITION=env.File("./targets/f${TARGET_HW}/api_symbols.csv").srcnode()
|
||||
)
|
||||
|
||||
libenv = env.Clone(FW_LIB_NAME="flipper${TARGET_HW}")
|
||||
@@ -22,9 +13,9 @@ libenv.Append(
|
||||
libenv.ApplyLibFlags()
|
||||
|
||||
|
||||
sources = ["targets/f${TARGET_HW}/startup_stm32wb55xx_cm4.s"]
|
||||
sources += libenv.GlobRecursive("*.c")
|
||||
|
||||
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
|
||||
lib = libenv.StaticLibrary(
|
||||
"${FW_LIB_NAME}",
|
||||
env.get("TARGET_CFG").gatherSources(),
|
||||
)
|
||||
libenv.Install("${LIB_DIST_DIR}", lib)
|
||||
Return("lib")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi_hal_mpu.h>
|
||||
#include <furi_hal_memory.h>
|
||||
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
|
||||
#define TAG "FuriHal"
|
||||
|
||||
void furi_hal_init_early() {
|
||||
furi_hal_cortex_init_early();
|
||||
furi_hal_clock_init_early();
|
||||
furi_hal_resources_init_early();
|
||||
furi_hal_os_init();
|
||||
furi_hal_spi_config_init_early();
|
||||
furi_hal_i2c_init_early();
|
||||
furi_hal_light_init();
|
||||
furi_hal_rtc_init_early();
|
||||
}
|
||||
|
||||
void furi_hal_deinit_early() {
|
||||
furi_hal_rtc_deinit_early();
|
||||
furi_hal_i2c_deinit_early();
|
||||
furi_hal_spi_config_deinit_early();
|
||||
furi_hal_resources_deinit_early();
|
||||
furi_hal_clock_deinit_early();
|
||||
}
|
||||
|
||||
void furi_hal_init() {
|
||||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
furi_hal_flash_init();
|
||||
furi_hal_resources_init();
|
||||
furi_hal_version_init();
|
||||
furi_hal_spi_config_init();
|
||||
furi_hal_spi_dma_init();
|
||||
furi_hal_speaker_init();
|
||||
furi_hal_crypto_init();
|
||||
furi_hal_i2c_init();
|
||||
furi_hal_power_init();
|
||||
furi_hal_light_init();
|
||||
furi_hal_bt_init();
|
||||
furi_hal_memory_init();
|
||||
|
||||
#ifndef FURI_RAM_EXEC
|
||||
furi_hal_usb_init();
|
||||
furi_hal_vibro_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void furi_hal_switch(void* address) {
|
||||
__set_BASEPRI(0);
|
||||
asm volatile("ldr r3, [%0] \n"
|
||||
"msr msp, r3 \n"
|
||||
"ldr r3, [%1] \n"
|
||||
"mov pc, r3 \n"
|
||||
:
|
||||
: "r"(address), "r"(address + 0x4)
|
||||
: "r3");
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
|
||||
#define TAG "FuriHalResources"
|
||||
|
||||
const GpioPin vibro_gpio = {.port = GPIOA, .pin = LL_GPIO_PIN_8};
|
||||
const GpioPin ibutton_gpio = {.port = GPIOB, .pin = LL_GPIO_PIN_14};
|
||||
|
||||
const GpioPin gpio_display_cs = {.port = GPIOC, .pin = LL_GPIO_PIN_11};
|
||||
const GpioPin gpio_display_rst_n = {.port = GPIOB, .pin = LL_GPIO_PIN_0};
|
||||
const GpioPin gpio_display_di = {.port = GPIOB, .pin = LL_GPIO_PIN_1};
|
||||
const GpioPin gpio_sdcard_cs = {.port = GPIOC, .pin = LL_GPIO_PIN_12};
|
||||
const GpioPin gpio_sdcard_cd = {.port = GPIOC, .pin = LL_GPIO_PIN_10};
|
||||
|
||||
const GpioPin gpio_button_up = {.port = GPIOB, .pin = LL_GPIO_PIN_10};
|
||||
const GpioPin gpio_button_down = {.port = GPIOC, .pin = LL_GPIO_PIN_6};
|
||||
const GpioPin gpio_button_right = {.port = GPIOB, .pin = LL_GPIO_PIN_12};
|
||||
const GpioPin gpio_button_left = {.port = GPIOB, .pin = LL_GPIO_PIN_11};
|
||||
const GpioPin gpio_button_ok = {.port = GPIOH, .pin = LL_GPIO_PIN_3};
|
||||
const GpioPin gpio_button_back = {.port = GPIOC, .pin = LL_GPIO_PIN_13};
|
||||
|
||||
const GpioPin gpio_spi_d_miso = {.port = GPIOC, .pin = LL_GPIO_PIN_2};
|
||||
const GpioPin gpio_spi_d_mosi = {.port = GPIOB, .pin = LL_GPIO_PIN_15};
|
||||
const GpioPin gpio_spi_d_sck = {.port = GPIOD, .pin = LL_GPIO_PIN_1};
|
||||
|
||||
const GpioPin gpio_ext_pc0 = {.port = GPIOC, .pin = LL_GPIO_PIN_0};
|
||||
const GpioPin gpio_ext_pc1 = {.port = GPIOC, .pin = LL_GPIO_PIN_1};
|
||||
const GpioPin gpio_ext_pc3 = {.port = GPIOC, .pin = LL_GPIO_PIN_3};
|
||||
const GpioPin gpio_ext_pb2 = {.port = GPIOB, .pin = LL_GPIO_PIN_2};
|
||||
const GpioPin gpio_ext_pb3 = {.port = GPIOB, .pin = LL_GPIO_PIN_3};
|
||||
const GpioPin gpio_ext_pa4 = {.port = GPIOA, .pin = LL_GPIO_PIN_4};
|
||||
const GpioPin gpio_ext_pa6 = {.port = GPIOA, .pin = LL_GPIO_PIN_6};
|
||||
const GpioPin gpio_ext_pa7 = {.port = GPIOA, .pin = LL_GPIO_PIN_7};
|
||||
|
||||
const GpioPin gpio_ext_pc5 = {.port = GPIOC, .pin = LL_GPIO_PIN_5};
|
||||
const GpioPin gpio_ext_pc4 = {.port = GPIOC, .pin = LL_GPIO_PIN_4};
|
||||
const GpioPin gpio_ext_pa5 = {.port = GPIOA, .pin = LL_GPIO_PIN_5};
|
||||
const GpioPin gpio_ext_pb9 = {.port = GPIOB, .pin = LL_GPIO_PIN_9};
|
||||
const GpioPin gpio_ext_pa0 = {.port = GPIOA, .pin = LL_GPIO_PIN_0};
|
||||
const GpioPin gpio_ext_pa1 = {.port = GPIOA, .pin = LL_GPIO_PIN_1};
|
||||
const GpioPin gpio_ext_pa15 = {.port = GPIOA, .pin = LL_GPIO_PIN_15};
|
||||
const GpioPin gpio_ext_pe4 = {.port = GPIOE, .pin = LL_GPIO_PIN_4};
|
||||
const GpioPin gpio_ext_pa2 = {.port = GPIOA, .pin = LL_GPIO_PIN_2};
|
||||
const GpioPin gpio_ext_pb4 = {.port = GPIOB, .pin = LL_GPIO_PIN_4};
|
||||
const GpioPin gpio_ext_pb5 = {.port = GPIOB, .pin = LL_GPIO_PIN_5};
|
||||
const GpioPin gpio_ext_pd0 = {.port = GPIOD, .pin = LL_GPIO_PIN_0};
|
||||
const GpioPin gpio_ext_pb13 = {.port = GPIOB, .pin = LL_GPIO_PIN_13};
|
||||
|
||||
const GpioPin gpio_usart_tx = {.port = GPIOB, .pin = LL_GPIO_PIN_6};
|
||||
const GpioPin gpio_usart_rx = {.port = GPIOB, .pin = LL_GPIO_PIN_7};
|
||||
|
||||
const GpioPin gpio_i2c_power_sda = {.port = GPIOA, .pin = LL_GPIO_PIN_10};
|
||||
const GpioPin gpio_i2c_power_scl = {.port = GPIOA, .pin = LL_GPIO_PIN_9};
|
||||
|
||||
const GpioPin gpio_speaker = {.port = GPIOB, .pin = LL_GPIO_PIN_8};
|
||||
|
||||
const GpioPin periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3};
|
||||
|
||||
const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11};
|
||||
const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12};
|
||||
|
||||
const GpioPinRecord gpio_pins[] = {
|
||||
{.pin = &gpio_ext_pa7, .name = "PA7", .debug = false},
|
||||
{.pin = &gpio_ext_pa6, .name = "PA6", .debug = false},
|
||||
{.pin = &gpio_ext_pa4, .name = "PA4", .debug = false},
|
||||
{.pin = &gpio_ext_pb3, .name = "PB3", .debug = false},
|
||||
{.pin = &gpio_ext_pb2, .name = "PB2", .debug = false},
|
||||
{.pin = &gpio_ext_pc3, .name = "PC3", .debug = false},
|
||||
{.pin = &gpio_ext_pc1, .name = "PC1", .debug = false},
|
||||
{.pin = &gpio_ext_pc0, .name = "PC0", .debug = false},
|
||||
|
||||
{.pin = &gpio_ext_pc5, .name = "PC5", .debug = false},
|
||||
{.pin = &gpio_ext_pc4, .name = "PC4", .debug = false},
|
||||
{.pin = &gpio_ext_pa5, .name = "PA5", .debug = false},
|
||||
{.pin = &gpio_ext_pb9, .name = "PB9", .debug = false},
|
||||
{.pin = &gpio_ext_pa0, .name = "PA0", .debug = false},
|
||||
{.pin = &gpio_ext_pa1, .name = "PA1", .debug = false},
|
||||
{.pin = &gpio_ext_pa15, .name = "PA15", .debug = false},
|
||||
{.pin = &gpio_ext_pe4, .name = "PE4", .debug = false},
|
||||
{.pin = &gpio_ext_pa2, .name = "PA2", .debug = false},
|
||||
{.pin = &gpio_ext_pb4, .name = "PB4", .debug = false},
|
||||
{.pin = &gpio_ext_pb5, .name = "PB5", .debug = false},
|
||||
{.pin = &gpio_ext_pd0, .name = "PD0", .debug = false},
|
||||
{.pin = &gpio_ext_pb13, .name = "PB13", .debug = false},
|
||||
|
||||
/* Dangerous pins, may damage hardware */
|
||||
{.pin = &gpio_usart_rx, .name = "PB7", .debug = true},
|
||||
{.pin = &gpio_speaker, .name = "PB8", .debug = true},
|
||||
};
|
||||
|
||||
const size_t gpio_pins_count = sizeof(gpio_pins) / sizeof(GpioPinRecord);
|
||||
|
||||
const InputPin input_pins[] = {
|
||||
{.gpio = &gpio_button_up, .key = InputKeyUp, .inverted = true, .name = "Up"},
|
||||
{.gpio = &gpio_button_down, .key = InputKeyDown, .inverted = true, .name = "Down"},
|
||||
{.gpio = &gpio_button_right, .key = InputKeyRight, .inverted = true, .name = "Right"},
|
||||
{.gpio = &gpio_button_left, .key = InputKeyLeft, .inverted = true, .name = "Left"},
|
||||
{.gpio = &gpio_button_ok, .key = InputKeyOk, .inverted = false, .name = "OK"},
|
||||
{.gpio = &gpio_button_back, .key = InputKeyBack, .inverted = true, .name = "Back"},
|
||||
};
|
||||
|
||||
const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
||||
|
||||
static void furi_hal_resources_init_input_pins(GpioMode mode) {
|
||||
for(size_t i = 0; i < input_pins_count; i++) {
|
||||
furi_hal_gpio_init(
|
||||
input_pins[i].gpio,
|
||||
mode,
|
||||
(input_pins[i].inverted) ? GpioPullUp : GpioPullDown,
|
||||
GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_resources_init_early() {
|
||||
furi_hal_resources_init_input_pins(GpioModeInput);
|
||||
|
||||
// SD Card stepdown control
|
||||
furi_hal_gpio_write(&periph_power, 1);
|
||||
furi_hal_gpio_init(&periph_power, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
// Display pins
|
||||
furi_hal_gpio_write(&gpio_display_rst_n, 1);
|
||||
furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull);
|
||||
furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
// Pullup display reset pin for shutdown
|
||||
SET_BIT(PWR->PUCRB, gpio_display_rst_n.pin);
|
||||
CLEAR_BIT(PWR->PDCRB, gpio_display_rst_n.pin);
|
||||
SET_BIT(PWR->CR3, PWR_CR3_APC);
|
||||
|
||||
// Hard reset USB
|
||||
furi_hal_gpio_write(&gpio_usb_dm, 1);
|
||||
furi_hal_gpio_write(&gpio_usb_dp, 1);
|
||||
furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain);
|
||||
furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain);
|
||||
furi_hal_gpio_write(&gpio_usb_dm, 0);
|
||||
furi_hal_gpio_write(&gpio_usb_dp, 0);
|
||||
furi_delay_us(5); // Device Driven disconnect: 2.5us + extra to compensate cables
|
||||
furi_hal_gpio_write(&gpio_usb_dm, 1);
|
||||
furi_hal_gpio_write(&gpio_usb_dp, 1);
|
||||
furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeAnalog);
|
||||
furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeAnalog);
|
||||
furi_hal_gpio_write(&gpio_usb_dm, 0);
|
||||
furi_hal_gpio_write(&gpio_usb_dp, 0);
|
||||
|
||||
// External header pins
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void furi_hal_resources_deinit_early() {
|
||||
furi_hal_resources_init_input_pins(GpioModeAnalog);
|
||||
}
|
||||
|
||||
void furi_hal_resources_init() {
|
||||
// Button pins
|
||||
furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall);
|
||||
|
||||
// Display pins
|
||||
furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_display_rst_n, 0);
|
||||
|
||||
furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_display_di, 0);
|
||||
|
||||
// SD pins
|
||||
furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_write(&gpio_sdcard_cd, 0);
|
||||
|
||||
furi_hal_gpio_init(&vibro_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
NVIC_SetPriority(EXTI0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI0_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI2_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI3_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI9_5_IRQn);
|
||||
|
||||
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) {
|
||||
// TODO: describe second ROW
|
||||
if(gpio == &gpio_ext_pa7)
|
||||
return 2;
|
||||
else if(gpio == &gpio_ext_pa6)
|
||||
return 3;
|
||||
else if(gpio == &gpio_ext_pa4)
|
||||
return 4;
|
||||
else if(gpio == &gpio_ext_pb3)
|
||||
return 5;
|
||||
else if(gpio == &gpio_ext_pb2)
|
||||
return 6;
|
||||
else if(gpio == &gpio_ext_pc3)
|
||||
return 7;
|
||||
else if(gpio == &gpio_ext_pc1)
|
||||
return 15;
|
||||
else if(gpio == &gpio_ext_pc0)
|
||||
return 16;
|
||||
else if(gpio == &ibutton_gpio)
|
||||
return 17;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Input Related Constants */
|
||||
#define INPUT_DEBOUNCE_TICKS 4
|
||||
|
||||
/* Input Keys */
|
||||
typedef enum {
|
||||
InputKeyUp,
|
||||
InputKeyDown,
|
||||
InputKeyRight,
|
||||
InputKeyLeft,
|
||||
InputKeyOk,
|
||||
InputKeyBack,
|
||||
InputKeyMAX, /**< Special value */
|
||||
} InputKey;
|
||||
|
||||
/* Light */
|
||||
typedef enum {
|
||||
LightRed = (1 << 0),
|
||||
LightGreen = (1 << 1),
|
||||
LightBlue = (1 << 2),
|
||||
LightBacklight = (1 << 3),
|
||||
} Light;
|
||||
|
||||
typedef struct {
|
||||
const GpioPin* gpio;
|
||||
const InputKey key;
|
||||
const bool inverted;
|
||||
const char* name;
|
||||
} InputPin;
|
||||
|
||||
typedef struct {
|
||||
const GpioPin* pin;
|
||||
const char* name;
|
||||
const bool debug;
|
||||
} GpioPinRecord;
|
||||
|
||||
extern const InputPin input_pins[];
|
||||
extern const size_t input_pins_count;
|
||||
|
||||
extern const GpioPinRecord gpio_pins[];
|
||||
extern const size_t gpio_pins_count;
|
||||
|
||||
extern const GpioPin vibro_gpio;
|
||||
extern const GpioPin ibutton_gpio;
|
||||
|
||||
extern const GpioPin gpio_display_cs;
|
||||
extern const GpioPin gpio_display_rst_n;
|
||||
extern const GpioPin gpio_display_di;
|
||||
extern const GpioPin gpio_sdcard_cs;
|
||||
extern const GpioPin gpio_sdcard_cd;
|
||||
|
||||
extern const GpioPin gpio_button_up;
|
||||
extern const GpioPin gpio_button_down;
|
||||
extern const GpioPin gpio_button_right;
|
||||
extern const GpioPin gpio_button_left;
|
||||
extern const GpioPin gpio_button_ok;
|
||||
extern const GpioPin gpio_button_back;
|
||||
|
||||
extern const GpioPin gpio_spi_d_miso;
|
||||
extern const GpioPin gpio_spi_d_mosi;
|
||||
extern const GpioPin gpio_spi_d_sck;
|
||||
|
||||
extern const GpioPin gpio_ext_pc0;
|
||||
extern const GpioPin gpio_ext_pc1;
|
||||
extern const GpioPin gpio_ext_pc3;
|
||||
extern const GpioPin gpio_ext_pb2;
|
||||
extern const GpioPin gpio_ext_pb3;
|
||||
extern const GpioPin gpio_ext_pa4;
|
||||
extern const GpioPin gpio_ext_pa6;
|
||||
extern const GpioPin gpio_ext_pa7;
|
||||
|
||||
extern const GpioPin gpio_ext_pc5;
|
||||
extern const GpioPin gpio_ext_pc4;
|
||||
extern const GpioPin gpio_ext_pa5;
|
||||
extern const GpioPin gpio_ext_pb9;
|
||||
extern const GpioPin gpio_ext_pa0;
|
||||
extern const GpioPin gpio_ext_pa1;
|
||||
extern const GpioPin gpio_ext_pa15;
|
||||
extern const GpioPin gpio_ext_pe4;
|
||||
extern const GpioPin gpio_ext_pa2;
|
||||
extern const GpioPin gpio_ext_pb4;
|
||||
extern const GpioPin gpio_ext_pb5;
|
||||
extern const GpioPin gpio_ext_pd0;
|
||||
extern const GpioPin gpio_ext_pb13;
|
||||
|
||||
extern const GpioPin gpio_usart_tx;
|
||||
extern const GpioPin gpio_usart_rx;
|
||||
extern const GpioPin gpio_i2c_power_sda;
|
||||
extern const GpioPin gpio_i2c_power_scl;
|
||||
|
||||
extern const GpioPin gpio_speaker;
|
||||
|
||||
extern const GpioPin periph_power;
|
||||
|
||||
extern const GpioPin gpio_usb_dm;
|
||||
extern const GpioPin gpio_usb_dp;
|
||||
|
||||
void furi_hal_resources_init_early();
|
||||
|
||||
void furi_hal_resources_deinit_early();
|
||||
|
||||
void furi_hal_resources_init();
|
||||
|
||||
/**
|
||||
* Get a corresponding external connector pin number for a gpio
|
||||
* @param gpio GpioPin
|
||||
* @return pin number or -1 if gpio is not on the external connector
|
||||
*/
|
||||
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,377 @@
|
||||
#include <furi_hal_spi_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalSpiConfig"
|
||||
|
||||
/* SPI Presets */
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = {
|
||||
.Mode = LL_SPI_MODE_MASTER,
|
||||
.TransferDirection = LL_SPI_FULL_DUPLEX,
|
||||
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
|
||||
.ClockPolarity = LL_SPI_POLARITY_LOW,
|
||||
.ClockPhase = LL_SPI_PHASE_2EDGE,
|
||||
.NSS = LL_SPI_NSS_SOFT,
|
||||
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
|
||||
.BitOrder = LL_SPI_MSB_FIRST,
|
||||
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = {
|
||||
.Mode = LL_SPI_MODE_MASTER,
|
||||
.TransferDirection = LL_SPI_FULL_DUPLEX,
|
||||
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
|
||||
.ClockPolarity = LL_SPI_POLARITY_LOW,
|
||||
.ClockPhase = LL_SPI_PHASE_1EDGE,
|
||||
.NSS = LL_SPI_NSS_SOFT,
|
||||
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8,
|
||||
.BitOrder = LL_SPI_MSB_FIRST,
|
||||
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = {
|
||||
.Mode = LL_SPI_MODE_MASTER,
|
||||
.TransferDirection = LL_SPI_FULL_DUPLEX,
|
||||
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
|
||||
.ClockPolarity = LL_SPI_POLARITY_LOW,
|
||||
.ClockPhase = LL_SPI_PHASE_1EDGE,
|
||||
.NSS = LL_SPI_NSS_SOFT,
|
||||
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV16,
|
||||
.BitOrder = LL_SPI_MSB_FIRST,
|
||||
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
|
||||
.Mode = LL_SPI_MODE_MASTER,
|
||||
.TransferDirection = LL_SPI_FULL_DUPLEX,
|
||||
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
|
||||
.ClockPolarity = LL_SPI_POLARITY_LOW,
|
||||
.ClockPhase = LL_SPI_PHASE_1EDGE,
|
||||
.NSS = LL_SPI_NSS_SOFT,
|
||||
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2,
|
||||
.BitOrder = LL_SPI_MSB_FIRST,
|
||||
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
|
||||
.Mode = LL_SPI_MODE_MASTER,
|
||||
.TransferDirection = LL_SPI_FULL_DUPLEX,
|
||||
.DataWidth = LL_SPI_DATAWIDTH_8BIT,
|
||||
.ClockPolarity = LL_SPI_POLARITY_LOW,
|
||||
.ClockPhase = LL_SPI_PHASE_1EDGE,
|
||||
.NSS = LL_SPI_NSS_SOFT,
|
||||
.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV32,
|
||||
.BitOrder = LL_SPI_MSB_FIRST,
|
||||
.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
/* SPI Buses */
|
||||
|
||||
FuriMutex* furi_hal_spi_bus_r_mutex = NULL;
|
||||
|
||||
void furi_hal_spi_config_init_early() {
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
|
||||
}
|
||||
|
||||
void furi_hal_spi_config_deinit_early() {
|
||||
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_display);
|
||||
furi_hal_spi_bus_deinit(&furi_hal_spi_bus_d);
|
||||
}
|
||||
|
||||
void furi_hal_spi_config_init() {
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
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();
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
}
|
||||
|
||||
FuriHalSpiBus furi_hal_spi_bus_r = {
|
||||
.spi = SPI1,
|
||||
.callback = furi_hal_spi_bus_r_event_callback,
|
||||
};
|
||||
|
||||
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();
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
}
|
||||
|
||||
FuriHalSpiBus furi_hal_spi_bus_d = {
|
||||
.spi = SPI2,
|
||||
.callback = furi_hal_spi_bus_d_event_callback,
|
||||
};
|
||||
|
||||
/* SPI Bus Handles */
|
||||
|
||||
inline static void furi_hal_spi_bus_r_handle_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event,
|
||||
const LL_SPI_InitTypeDef* preset) {
|
||||
if(event == FuriHalSpiBusHandleEventInit) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeinit) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(event == FuriHalSpiBusHandleEventActivate) {
|
||||
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
|
||||
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(handle->bus->spi);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
|
||||
furi_hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
LL_SPI_Disable(handle->bus->spi);
|
||||
}
|
||||
}
|
||||
|
||||
inline static void furi_hal_spi_bus_nfc_handle_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event,
|
||||
const LL_SPI_InitTypeDef* preset) {
|
||||
if(event == FuriHalSpiBusHandleEventInit) {
|
||||
// Configure GPIOs in normal SPI mode
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeinit) {
|
||||
// Configure GPIOs for st25r3916 Transparent mode
|
||||
furi_hal_gpio_init(handle->sck, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->miso, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
furi_hal_gpio_write(handle->mosi, false);
|
||||
furi_hal_gpio_init(handle->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
} else if(event == FuriHalSpiBusHandleEventActivate) {
|
||||
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
|
||||
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(handle->bus->spi);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
|
||||
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
|
||||
furi_hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
LL_SPI_Disable(handle->bus->spi);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_spi_bus_handle_external_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = {
|
||||
.bus = &furi_hal_spi_bus_r,
|
||||
.callback = furi_hal_spi_bus_handle_external_event_callback,
|
||||
.miso = &gpio_ext_pa6,
|
||||
.mosi = &gpio_ext_pa7,
|
||||
.sck = &gpio_ext_pb3,
|
||||
.cs = &gpio_ext_pa4,
|
||||
};
|
||||
|
||||
inline static void furi_hal_spi_bus_d_handle_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event,
|
||||
const LL_SPI_InitTypeDef* preset) {
|
||||
if(event == FuriHalSpiBusHandleEventInit) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
furi_hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
|
||||
} else if(event == FuriHalSpiBusHandleEventDeinit) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
furi_hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow);
|
||||
} else if(event == FuriHalSpiBusHandleEventActivate) {
|
||||
LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset);
|
||||
LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable(handle->bus->spi);
|
||||
furi_hal_gpio_write(handle->cs, false);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
|
||||
furi_hal_gpio_write(handle->cs, true);
|
||||
LL_SPI_Disable(handle->bus->spi);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_spi_bus_handle_display_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = {
|
||||
.bus = &furi_hal_spi_bus_d,
|
||||
.callback = furi_hal_spi_bus_handle_display_event_callback,
|
||||
.miso = &gpio_spi_d_miso,
|
||||
.mosi = &gpio_spi_d_mosi,
|
||||
.sck = &gpio_spi_d_sck,
|
||||
.cs = &gpio_display_cs,
|
||||
};
|
||||
|
||||
static void furi_hal_spi_bus_handle_sd_fast_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
|
||||
.bus = &furi_hal_spi_bus_d,
|
||||
.callback = furi_hal_spi_bus_handle_sd_fast_event_callback,
|
||||
.miso = &gpio_spi_d_miso,
|
||||
.mosi = &gpio_spi_d_mosi,
|
||||
.sck = &gpio_spi_d_sck,
|
||||
.cs = &gpio_sdcard_cs,
|
||||
};
|
||||
|
||||
static void furi_hal_spi_bus_handle_sd_slow_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = {
|
||||
.bus = &furi_hal_spi_bus_d,
|
||||
.callback = furi_hal_spi_bus_handle_sd_slow_event_callback,
|
||||
.miso = &gpio_spi_d_miso,
|
||||
.mosi = &gpio_spi_d_mosi,
|
||||
.sck = &gpio_spi_d_sck,
|
||||
.cs = &gpio_sdcard_cs,
|
||||
};
|
||||
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_spi_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Preset for ST25R916 */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
|
||||
|
||||
/** Preset for CC1101 */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m;
|
||||
|
||||
/** Preset for ST7567 (Display) */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m;
|
||||
|
||||
/** Preset for SdCard in fast mode */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m;
|
||||
|
||||
/** Preset for SdCard in slow mode */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m;
|
||||
|
||||
/** Furi Hal Spi Bus R (External) */
|
||||
extern FuriHalSpiBus furi_hal_spi_bus_r;
|
||||
|
||||
/** Furi Hal Spi Bus D (Display, SdCard) */
|
||||
extern FuriHalSpiBus furi_hal_spi_bus_d;
|
||||
|
||||
/** External on `furi_hal_spi_bus_r`
|
||||
* Preset: `furi_hal_spi_preset_1edge_low_2m`
|
||||
*
|
||||
* miso: pa6
|
||||
* mosi: pa7
|
||||
* sck: pb3
|
||||
* cs: pa4 (software controlled)
|
||||
*
|
||||
* @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize
|
||||
* Bus pins are floating on inactive state, CS high after initialization
|
||||
*
|
||||
*/
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
|
||||
|
||||
/** ST7567(Display) on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
|
||||
|
||||
/** SdCard in fast mode on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
/** SdCard in slow mode on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <furi_hal_version.h>
|
||||
|
||||
bool furi_hal_version_do_i_belong_here() {
|
||||
return (furi_hal_version_get_hw_target() == 18) || (furi_hal_version_get_hw_target() == 0);
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_model_name() {
|
||||
return "Komi";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_model_code() {
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_fcc_id() {
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_ic_id() {
|
||||
return "N/A";
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"inherit": "7",
|
||||
"include_paths": [
|
||||
"furi_hal"
|
||||
],
|
||||
"sdk_header_paths": [
|
||||
"../furi_hal_include",
|
||||
"furi_hal",
|
||||
"platform_specific"
|
||||
],
|
||||
"sdk_symbols": "api_symbols.csv",
|
||||
"linker_dependencies": [
|
||||
"print",
|
||||
"flipper18",
|
||||
"furi",
|
||||
"freertos",
|
||||
"stm32cubewb",
|
||||
"hwdrivers",
|
||||
"fatfs",
|
||||
"littlefs",
|
||||
"flipperformat",
|
||||
"toolbox",
|
||||
"microtar",
|
||||
"usb_stm32",
|
||||
"appframe",
|
||||
"assets",
|
||||
"one_wire",
|
||||
"misc",
|
||||
"flipper_application",
|
||||
"flipperformat",
|
||||
"toolbox",
|
||||
"flipper18"
|
||||
],
|
||||
"excluded_sources": [
|
||||
"furi_hal_infrared.c",
|
||||
"furi_hal_nfc.c",
|
||||
"furi_hal_rfid.c",
|
||||
"furi_hal_subghz.c"
|
||||
],
|
||||
"excluded_headers": [
|
||||
"furi_hal_infrared.h",
|
||||
"furi_hal_nfc.h",
|
||||
"furi_hal_rfid.h",
|
||||
"furi_hal_subghz.h",
|
||||
"furi_hal_ibutton.h",
|
||||
"furi_hal_subghz_configs.h"
|
||||
],
|
||||
"excluded_modules": [
|
||||
"nfc",
|
||||
"lfrfid",
|
||||
"subghz",
|
||||
"ibutton",
|
||||
"infrared",
|
||||
"st25rfal002"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,11.10,,
|
||||
Version,+,20.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
@@ -28,6 +28,7 @@ Header,+,applications/services/gui/modules/widget_elements/widget_element.h,,
|
||||
Header,+,applications/services/gui/view_dispatcher.h,,
|
||||
Header,+,applications/services/gui/view_stack.h,,
|
||||
Header,+,applications/services/input/input.h,,
|
||||
Header,+,applications/services/loader/firmware_api/firmware_api.h,,
|
||||
Header,+,applications/services/loader/loader.h,,
|
||||
Header,+,applications/services/locale/locale.h,,
|
||||
Header,+,applications/services/notification/notification.h,,
|
||||
@@ -41,14 +42,19 @@ 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,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_i2c_types.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_ibutton.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_idle_timer.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_interrupt.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_nfc.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_os.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_pwm.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_resources.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_rfid.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_config.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_spi_types.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_subghz_configs.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_uart.h,,
|
||||
Header,+,firmware/targets/f7/furi_hal/furi_hal_usb_cdc.h,,
|
||||
Header,+,firmware/targets/f7/platform_specific/intrinsic_export.h,,
|
||||
@@ -56,27 +62,22 @@ Header,+,firmware/targets/furi_hal_include/furi_hal.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_bt.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_bt_hid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_bt_serial.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_compress.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_cortex.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_crypto.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_debug.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_i2c.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_ibutton.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_info.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_infrared.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_light.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_memory.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_mpu.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_nfc.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_power.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_random.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_region.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_rfid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_rtc.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_spi.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_subghz.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid.h,,
|
||||
Header,+,firmware/targets/furi_hal_include/furi_hal_usb_hid_u2f.h,,
|
||||
@@ -109,9 +110,16 @@ Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_tim.h,,
|
||||
Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_usart.h,,
|
||||
Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_utils.h,,
|
||||
Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,,
|
||||
Header,+,lib/flipper_application/api_hashtable/api_hashtable.h,,
|
||||
Header,+,lib/flipper_application/api_hashtable/compilesort.hpp,,
|
||||
Header,+,lib/flipper_application/flipper_application.h,,
|
||||
Header,+,lib/flipper_application/plugins/composite_resolver.h,,
|
||||
Header,+,lib/flipper_application/plugins/plugin_manager.h,,
|
||||
Header,+,lib/flipper_format/flipper_format.h,,
|
||||
Header,+,lib/flipper_format/flipper_format_i.h,,
|
||||
Header,+,lib/ibutton/ibutton_key.h,,
|
||||
Header,+,lib/ibutton/ibutton_protocols.h,,
|
||||
Header,+,lib/ibutton/ibutton_worker.h,,
|
||||
Header,+,lib/infrared/encoder_decoder/infrared.h,,
|
||||
Header,+,lib/infrared/worker/infrared_transmit.h,,
|
||||
Header,+,lib/infrared/worker/infrared_worker.h,,
|
||||
@@ -150,12 +158,19 @@ Header,+,lib/libusb_stm32/inc/usbd_core.h,,
|
||||
Header,+,lib/mbedtls/include/mbedtls/des.h,,
|
||||
Header,+,lib/mbedtls/include/mbedtls/sha1.h,,
|
||||
Header,+,lib/micro-ecc/uECC.h,,
|
||||
Header,+,lib/mlib/m-algo.h,,
|
||||
Header,+,lib/mlib/m-array.h,,
|
||||
Header,+,lib/mlib/m-bptree.h,,
|
||||
Header,+,lib/mlib/m-core.h,,
|
||||
Header,+,lib/mlib/m-deque.h,,
|
||||
Header,+,lib/mlib/m-dict.h,,
|
||||
Header,+,lib/mlib/m-list.h,,
|
||||
Header,+,lib/mlib/m-rbtree.h,,
|
||||
Header,+,lib/mlib/m-tuple.h,,
|
||||
Header,+,lib/mlib/m-variant.h,,
|
||||
Header,+,lib/nfc/nfc_device.h,,
|
||||
Header,+,lib/one_wire/ibutton/ibutton_worker.h,,
|
||||
Header,+,lib/one_wire/maxim_crc.h,,
|
||||
Header,+,lib/one_wire/one_wire_device.h,,
|
||||
Header,+,lib/one_wire/one_wire_host.h,,
|
||||
Header,+,lib/one_wire/one_wire_host_timing.h,,
|
||||
Header,+,lib/one_wire/one_wire_slave.h,,
|
||||
Header,+,lib/print/wrappers.h,,
|
||||
Header,+,lib/subghz/blocks/const.h,,
|
||||
@@ -175,14 +190,15 @@ Header,+,lib/toolbox/args.h,,
|
||||
Header,+,lib/toolbox/crc32_calc.h,,
|
||||
Header,+,lib/toolbox/dir_walk.h,,
|
||||
Header,+,lib/toolbox/float_tools.h,,
|
||||
Header,+,lib/toolbox/hmac_sha256.h,,
|
||||
Header,+,lib/toolbox/manchester_decoder.h,,
|
||||
Header,+,lib/toolbox/manchester_encoder.h,,
|
||||
Header,+,lib/toolbox/md5.h,,
|
||||
Header,+,lib/toolbox/path.h,,
|
||||
Header,+,lib/toolbox/pretty_format.h,,
|
||||
Header,+,lib/toolbox/protocols/protocol_dict.h,,
|
||||
Header,+,lib/toolbox/random_name.h,,
|
||||
Header,+,lib/toolbox/saved_struct.h,,
|
||||
Header,+,lib/toolbox/sha256.h,,
|
||||
Header,+,lib/toolbox/stream/buffered_file_stream.h,,
|
||||
Header,+,lib/toolbox/stream/file_stream.h,,
|
||||
Header,+,lib/toolbox/stream/stream.h,,
|
||||
@@ -478,7 +494,6 @@ Function,-,acosh,double,double
|
||||
Function,-,acoshf,float,float
|
||||
Function,-,acoshl,long double,long double
|
||||
Function,-,acosl,long double,long double
|
||||
Function,+,acquire_mutex,void*,"ValueMutex*, uint32_t"
|
||||
Function,-,aligned_alloc,void*,"size_t, size_t"
|
||||
Function,+,aligned_free,void,void*
|
||||
Function,+,aligned_malloc,void*,"size_t, size_t"
|
||||
@@ -596,7 +611,7 @@ Function,-,bzero,void,"void*, size_t"
|
||||
Function,-,calloc,void*,"size_t, size_t"
|
||||
Function,+,canvas_clear,void,Canvas*
|
||||
Function,+,canvas_commit,void,Canvas*
|
||||
Function,+,canvas_current_font_height,uint8_t,Canvas*
|
||||
Function,+,canvas_current_font_height,uint8_t,const Canvas*
|
||||
Function,+,canvas_draw_bitmap,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*"
|
||||
Function,+,canvas_draw_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
|
||||
Function,+,canvas_draw_circle,void,"Canvas*, uint8_t, uint8_t, uint8_t"
|
||||
@@ -613,17 +628,18 @@ Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*"
|
||||
Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*"
|
||||
Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection"
|
||||
Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*"
|
||||
Function,+,canvas_get_font_params,CanvasFontParameters*,"Canvas*, Font"
|
||||
Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font"
|
||||
Function,+,canvas_glyph_width,uint8_t,"Canvas*, char"
|
||||
Function,+,canvas_height,uint8_t,Canvas*
|
||||
Function,+,canvas_height,uint8_t,const Canvas*
|
||||
Function,+,canvas_invert_color,void,Canvas*
|
||||
Function,+,canvas_reset,void,Canvas*
|
||||
Function,+,canvas_set_bitmap_mode,void,"Canvas*, _Bool"
|
||||
Function,+,canvas_set_color,void,"Canvas*, Color"
|
||||
Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*"
|
||||
Function,+,canvas_set_font,void,"Canvas*, Font"
|
||||
Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection"
|
||||
Function,+,canvas_string_width,uint16_t,"Canvas*, const char*"
|
||||
Function,+,canvas_width,uint8_t,Canvas*
|
||||
Function,+,canvas_width,uint8_t,const Canvas*
|
||||
Function,-,cbrt,double,double
|
||||
Function,-,cbrtf,float,float
|
||||
Function,-,cbrtl,long double,long double
|
||||
@@ -666,6 +682,10 @@ Function,+,cli_session_close,void,Cli*
|
||||
Function,+,cli_session_open,void,"Cli*, void*"
|
||||
Function,+,cli_write,void,"Cli*, const uint8_t*, size_t"
|
||||
Function,-,clock,clock_t,
|
||||
Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiInterface*"
|
||||
Function,+,composite_api_resolver_alloc,CompositeApiResolver*,
|
||||
Function,+,composite_api_resolver_free,void,CompositeApiResolver*
|
||||
Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver*
|
||||
Function,-,copysign,double,"double, double"
|
||||
Function,-,copysignf,float,"float, float"
|
||||
Function,-,copysignl,long double,"long double, long double"
|
||||
@@ -689,7 +709,6 @@ Function,-,ctermid,char*,char*
|
||||
Function,-,ctime,char*,const time_t*
|
||||
Function,-,ctime_r,char*,"const time_t*, char*"
|
||||
Function,-,cuserid,char*,char*
|
||||
Function,+,delete_mutex,_Bool,ValueMutex*
|
||||
Function,+,dialog_ex_alloc,DialogEx*,
|
||||
Function,+,dialog_ex_disable_extended_events,void,DialogEx*
|
||||
Function,+,dialog_ex_enable_extended_events,void,DialogEx*
|
||||
@@ -766,6 +785,7 @@ Function,+,elements_slightly_rounded_box,void,"Canvas*, uint8_t, uint8_t, uint8_
|
||||
Function,+,elements_slightly_rounded_frame,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t"
|
||||
Function,+,elements_string_fit_width,void,"Canvas*, FuriString*, uint8_t"
|
||||
Function,+,elements_text_box,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Align, Align, const char*, _Bool"
|
||||
Function,+,elf_resolve_from_hashtable,_Bool,"const ElfApiInterface*, const char*, Elf32_Addr*"
|
||||
Function,+,empty_screen_alloc,EmptyScreen*,
|
||||
Function,+,empty_screen_free,void,EmptyScreen*
|
||||
Function,+,empty_screen_get_view,View*,EmptyScreen*
|
||||
@@ -850,6 +870,7 @@ Function,+,file_browser_worker_set_folder_callback,void,"BrowserWorker*, Browser
|
||||
Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback"
|
||||
Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback"
|
||||
Function,+,file_browser_worker_set_long_load_callback,void,"BrowserWorker*, BrowserWorkerLongLoadCallback"
|
||||
Function,+,file_info_is_dir,_Bool,const FileInfo*
|
||||
Function,+,file_stream_alloc,Stream*,Storage*
|
||||
Function,+,file_stream_close,_Bool,Stream*
|
||||
Function,+,file_stream_get_error,FS_Error,Stream*
|
||||
@@ -865,16 +886,20 @@ Function,-,fiscanf,int,"FILE*, const char*, ..."
|
||||
Function,+,flipper_application_alloc,FlipperApplication*,"Storage*, const ElfApiInterface*"
|
||||
Function,+,flipper_application_free,void,FlipperApplication*
|
||||
Function,+,flipper_application_get_manifest,const FlipperApplicationManifest*,FlipperApplication*
|
||||
Function,+,flipper_application_is_plugin,_Bool,FlipperApplication*
|
||||
Function,+,flipper_application_load_status_to_string,const char*,FlipperApplicationLoadStatus
|
||||
Function,+,flipper_application_manifest_is_compatible,_Bool,"const FlipperApplicationManifest*, const ElfApiInterface*"
|
||||
Function,+,flipper_application_manifest_is_target_compatible,_Bool,const FlipperApplicationManifest*
|
||||
Function,+,flipper_application_manifest_is_valid,_Bool,const FlipperApplicationManifest*
|
||||
Function,+,flipper_application_map_to_memory,FlipperApplicationLoadStatus,FlipperApplication*
|
||||
Function,+,flipper_application_plugin_get_descriptor,const FlipperAppPluginDescriptor*,FlipperApplication*
|
||||
Function,+,flipper_application_preload,FlipperApplicationPreloadStatus,"FlipperApplication*, const char*"
|
||||
Function,+,flipper_application_preload_manifest,FlipperApplicationPreloadStatus,"FlipperApplication*, const char*"
|
||||
Function,-,flipper_application_preload_status_to_string,const char*,FlipperApplicationPreloadStatus
|
||||
Function,+,flipper_application_preload_status_to_string,const char*,FlipperApplicationPreloadStatus
|
||||
Function,+,flipper_application_spawn,FuriThread*,"FlipperApplication*, void*"
|
||||
Function,+,flipper_format_buffered_file_alloc,FlipperFormat*,Storage*
|
||||
Function,+,flipper_format_buffered_file_close,_Bool,FlipperFormat*
|
||||
Function,+,flipper_format_buffered_file_open_always,_Bool,"FlipperFormat*, const char*"
|
||||
Function,+,flipper_format_buffered_file_open_existing,_Bool,"FlipperFormat*, const char*"
|
||||
Function,+,flipper_format_delete_key,_Bool,"FlipperFormat*, const char*"
|
||||
Function,+,flipper_format_file_alloc,FlipperFormat*,Storage*
|
||||
@@ -1037,7 +1062,7 @@ 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"
|
||||
Function,+,furi_hal_cdc_send,void,"uint8_t, uint8_t*, uint16_t"
|
||||
Function,+,furi_hal_cdc_set_callbacks,void,"uint8_t, CdcCallbacks*, void*"
|
||||
Function,+,furi_hal_clock_deinit_early,void,
|
||||
Function,-,furi_hal_clock_deinit_early,void,
|
||||
Function,-,furi_hal_clock_init,void,
|
||||
Function,-,furi_hal_clock_init_early,void,
|
||||
Function,+,furi_hal_clock_mco_disable,void,
|
||||
@@ -1046,12 +1071,6 @@ Function,-,furi_hal_clock_resume_tick,void,
|
||||
Function,-,furi_hal_clock_suspend_tick,void,
|
||||
Function,-,furi_hal_clock_switch_to_hsi,void,
|
||||
Function,-,furi_hal_clock_switch_to_pll,void,
|
||||
Function,-,furi_hal_compress_alloc,FuriHalCompress*,uint16_t
|
||||
Function,-,furi_hal_compress_decode,_Bool,"FuriHalCompress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
|
||||
Function,-,furi_hal_compress_encode,_Bool,"FuriHalCompress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
|
||||
Function,-,furi_hal_compress_free,void,FuriHalCompress*
|
||||
Function,-,furi_hal_compress_icon_decode,void,"const uint8_t*, uint8_t**"
|
||||
Function,-,furi_hal_compress_icon_init,void,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
@@ -1118,7 +1137,7 @@ Function,+,furi_hal_hid_u2f_is_connected,_Bool,
|
||||
Function,+,furi_hal_hid_u2f_send_response,void,"uint8_t*, uint8_t"
|
||||
Function,+,furi_hal_hid_u2f_set_callback,void,"HidU2fCallback, void*"
|
||||
Function,+,furi_hal_i2c_acquire,void,FuriHalI2cBusHandle*
|
||||
Function,+,furi_hal_i2c_deinit_early,void,
|
||||
Function,-,furi_hal_i2c_deinit_early,void,
|
||||
Function,-,furi_hal_i2c_init,void,
|
||||
Function,-,furi_hal_i2c_init_early,void,
|
||||
Function,+,furi_hal_i2c_is_device_ready,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint32_t"
|
||||
@@ -1132,20 +1151,13 @@ Function,+,furi_hal_i2c_tx,_Bool,"FuriHalI2cBusHandle*, const uint8_t, const uin
|
||||
Function,+,furi_hal_i2c_write_mem,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t*, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_16,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint16_t, uint32_t"
|
||||
Function,+,furi_hal_i2c_write_reg_8,_Bool,"FuriHalI2cBusHandle*, uint8_t, uint8_t, uint8_t, uint32_t"
|
||||
Function,+,furi_hal_ibutton_add_interrupt,void,"GpioExtiCallback, void*"
|
||||
Function,+,furi_hal_ibutton_emulate_set_next,void,uint32_t
|
||||
Function,+,furi_hal_ibutton_emulate_start,void,"uint32_t, FuriHalIbuttonEmulateCallback, void*"
|
||||
Function,+,furi_hal_ibutton_emulate_stop,void,
|
||||
Function,-,furi_hal_ibutton_init,void,
|
||||
Function,+,furi_hal_ibutton_pin_get_level,_Bool,
|
||||
Function,+,furi_hal_ibutton_pin_high,void,
|
||||
Function,+,furi_hal_ibutton_pin_low,void,
|
||||
Function,+,furi_hal_ibutton_remove_interrupt,void,
|
||||
Function,+,furi_hal_ibutton_start_drive,void,
|
||||
Function,+,furi_hal_ibutton_start_drive_in_isr,void,
|
||||
Function,+,furi_hal_ibutton_start_interrupt,void,
|
||||
Function,+,furi_hal_ibutton_start_interrupt_in_isr,void,
|
||||
Function,+,furi_hal_ibutton_stop,void,
|
||||
Function,+,furi_hal_ibutton_pin_configure,void,
|
||||
Function,+,furi_hal_ibutton_pin_reset,void,
|
||||
Function,+,furi_hal_ibutton_pin_write,void,const _Bool
|
||||
Function,+,furi_hal_info_get,void,"PropertyValueCallback, char, void*"
|
||||
Function,+,furi_hal_infrared_async_rx_set_capture_isr_callback,void,"FuriHalInfraredRxCaptureCallback, void*"
|
||||
Function,+,furi_hal_infrared_async_rx_set_timeout,void,uint32_t
|
||||
@@ -1180,6 +1192,7 @@ Function,+,furi_hal_mpu_protect_disable,void,FuriHalMpuRegion
|
||||
Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize"
|
||||
Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize"
|
||||
Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*"
|
||||
Function,-,furi_hal_nfc_deinit,void,
|
||||
Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t"
|
||||
Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t"
|
||||
Function,+,furi_hal_nfc_exit_sleep,void,
|
||||
@@ -1219,7 +1232,7 @@ Function,+,furi_hal_power_enable_external_3_3v,void,
|
||||
Function,+,furi_hal_power_enable_otg,void,
|
||||
Function,+,furi_hal_power_gauge_is_ok,_Bool,
|
||||
Function,+,furi_hal_power_get_bat_health_pct,uint8_t,
|
||||
Function,+,furi_hal_power_get_battery_charging_voltage,float,
|
||||
Function,+,furi_hal_power_get_battery_charge_voltage_limit,float,
|
||||
Function,+,furi_hal_power_get_battery_current,float,FuriHalPowerIC
|
||||
Function,+,furi_hal_power_get_battery_design_capacity,uint32_t,
|
||||
Function,+,furi_hal_power_get_battery_full_capacity,uint32_t,
|
||||
@@ -1238,7 +1251,7 @@ Function,+,furi_hal_power_is_charging_done,_Bool,
|
||||
Function,+,furi_hal_power_is_otg_enabled,_Bool,
|
||||
Function,+,furi_hal_power_off,void,
|
||||
Function,+,furi_hal_power_reset,void,
|
||||
Function,+,furi_hal_power_set_battery_charging_voltage,void,float
|
||||
Function,+,furi_hal_power_set_battery_charge_voltage_limit,void,float
|
||||
Function,+,furi_hal_power_shutdown,void,
|
||||
Function,+,furi_hal_power_sleep,void,
|
||||
Function,+,furi_hal_power_sleep_available,_Bool,
|
||||
@@ -1256,7 +1269,8 @@ Function,-,furi_hal_region_init,void,
|
||||
Function,+,furi_hal_region_is_frequency_allowed,_Bool,uint32_t
|
||||
Function,+,furi_hal_region_is_provisioned,_Bool,
|
||||
Function,+,furi_hal_region_set,void,FuriHalRegion*
|
||||
Function,+,furi_hal_resources_deinit_early,void,
|
||||
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"
|
||||
@@ -1285,7 +1299,7 @@ Function,+,furi_hal_rfid_tim_read_start,void,
|
||||
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_deinit_early,void,
|
||||
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
|
||||
Function,+,furi_hal_rtc_get_datetime,void,FuriHalRtcDateTime*
|
||||
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
|
||||
@@ -1327,11 +1341,13 @@ Function,+,furi_hal_spi_bus_handle_deinit,void,FuriHalSpiBusHandle*
|
||||
Function,+,furi_hal_spi_bus_handle_init,void,FuriHalSpiBusHandle*
|
||||
Function,+,furi_hal_spi_bus_init,void,FuriHalSpiBus*
|
||||
Function,+,furi_hal_spi_bus_rx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_spi_deinit_early,void,
|
||||
Function,-,furi_hal_spi_init,void,
|
||||
Function,+,furi_hal_spi_init_early,void,
|
||||
Function,+,furi_hal_spi_bus_trx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_spi_bus_trx_dma,_Bool,"FuriHalSpiBusHandle*, uint8_t*, uint8_t*, size_t, uint32_t"
|
||||
Function,+,furi_hal_spi_bus_tx,_Bool,"FuriHalSpiBusHandle*, const uint8_t*, size_t, uint32_t"
|
||||
Function,-,furi_hal_spi_config_deinit_early,void,
|
||||
Function,-,furi_hal_spi_config_init,void,
|
||||
Function,-,furi_hal_spi_config_init_early,void,
|
||||
Function,-,furi_hal_spi_dma_init,void,
|
||||
Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle*
|
||||
Function,-,furi_hal_subghz_dump_state,void,
|
||||
Function,+,furi_hal_subghz_flush_rx,void,
|
||||
@@ -1385,6 +1401,7 @@ Function,+,furi_hal_version_do_i_belong_here,_Bool,
|
||||
Function,+,furi_hal_version_get_ble_local_device_name_ptr,const char*,
|
||||
Function,+,furi_hal_version_get_ble_mac,const uint8_t*,
|
||||
Function,+,furi_hal_version_get_device_name_ptr,const char*,
|
||||
Function,+,furi_hal_version_get_fcc_id,const char*,
|
||||
Function,+,furi_hal_version_get_firmware_version,const Version*,
|
||||
Function,+,furi_hal_version_get_hw_body,uint8_t,
|
||||
Function,+,furi_hal_version_get_hw_color,FuriHalVersionColor,
|
||||
@@ -1395,6 +1412,8 @@ Function,+,furi_hal_version_get_hw_region_name,const char*,
|
||||
Function,+,furi_hal_version_get_hw_target,uint8_t,
|
||||
Function,+,furi_hal_version_get_hw_timestamp,uint32_t,
|
||||
Function,+,furi_hal_version_get_hw_version,uint8_t,
|
||||
Function,+,furi_hal_version_get_ic_id,const char*,
|
||||
Function,+,furi_hal_version_get_model_code,const char*,
|
||||
Function,+,furi_hal_version_get_model_name,const char*,
|
||||
Function,+,furi_hal_version_get_name_ptr,const char*,
|
||||
Function,+,furi_hal_version_get_otp_version,FuriHalVersionOtpVersion,
|
||||
@@ -1412,6 +1431,7 @@ Function,+,furi_kernel_unlock,int32_t,
|
||||
Function,+,furi_log_get_level,FuriLogLevel,
|
||||
Function,-,furi_log_init,void,
|
||||
Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..."
|
||||
Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..."
|
||||
Function,+,furi_log_set_level,void,FuriLogLevel
|
||||
Function,-,furi_log_set_puts,void,FuriLogPuts
|
||||
Function,-,furi_log_set_timestamp,void,FuriLogTimestamp
|
||||
@@ -1522,8 +1542,10 @@ Function,+,furi_thread_flags_get,uint32_t,
|
||||
Function,+,furi_thread_flags_set,uint32_t,"FuriThreadId, uint32_t"
|
||||
Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t"
|
||||
Function,+,furi_thread_free,void,FuriThread*
|
||||
Function,+,furi_thread_get_appid,const char*,FuriThreadId
|
||||
Function,+,furi_thread_get_current,FuriThread*,
|
||||
Function,+,furi_thread_get_current_id,FuriThreadId,
|
||||
Function,+,furi_thread_get_current_priority,FuriThreadPriority,
|
||||
Function,+,furi_thread_get_heap_size,size_t,FuriThread*
|
||||
Function,+,furi_thread_get_id,FuriThreadId,FuriThread*
|
||||
Function,+,furi_thread_get_name,const char*,FuriThreadId
|
||||
@@ -1535,8 +1557,10 @@ Function,+,furi_thread_is_suspended,_Bool,FuriThreadId
|
||||
Function,+,furi_thread_join,_Bool,FuriThread*
|
||||
Function,+,furi_thread_mark_as_service,void,FuriThread*
|
||||
Function,+,furi_thread_resume,void,FuriThreadId
|
||||
Function,+,furi_thread_set_appid,void,"FuriThread*, const char*"
|
||||
Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback"
|
||||
Function,+,furi_thread_set_context,void,"FuriThread*, void*"
|
||||
Function,+,furi_thread_set_current_priority,void,FuriThreadPriority
|
||||
Function,+,furi_thread_set_name,void,"FuriThread*, const char*"
|
||||
Function,+,furi_thread_set_priority,void,"FuriThread*, FuriThreadPriority"
|
||||
Function,+,furi_thread_set_stack_size,void,"FuriThread*, size_t"
|
||||
@@ -1578,7 +1602,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi
|
||||
Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer"
|
||||
Function,+,gui_direct_draw_acquire,Canvas*,Gui*
|
||||
Function,+,gui_direct_draw_release,void,Gui*
|
||||
Function,+,gui_get_framebuffer_size,size_t,Gui*
|
||||
Function,+,gui_get_framebuffer_size,size_t,const Gui*
|
||||
Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*"
|
||||
Function,+,gui_remove_view_port,void,"Gui*, ViewPort*"
|
||||
Function,+,gui_set_lockdown,void,"Gui*, _Bool"
|
||||
@@ -1587,28 +1611,36 @@ Function,+,gui_view_port_send_to_front,void,"Gui*, ViewPort*"
|
||||
Function,+,hal_sd_detect,_Bool,
|
||||
Function,+,hal_sd_detect_init,void,
|
||||
Function,+,hal_sd_detect_set_low,void,
|
||||
Function,+,hmac_sha256_finish,void,"const hmac_sha256_context*, const uint8_t*, uint8_t*"
|
||||
Function,+,hmac_sha256_init,void,"hmac_sha256_context*, const uint8_t*"
|
||||
Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, unsigned"
|
||||
Function,-,hypot,double,"double, double"
|
||||
Function,-,hypotf,float,"float, float"
|
||||
Function,-,hypotl,long double,"long double, long double"
|
||||
Function,+,ibutton_key_alloc,iButtonKey*,
|
||||
Function,+,ibutton_key_clear_data,void,iButtonKey*
|
||||
Function,+,ibutton_key_dallas_crc_is_valid,_Bool,iButtonKey*
|
||||
Function,+,ibutton_key_dallas_is_1990_key,_Bool,iButtonKey*
|
||||
Function,+,ibutton_key_alloc,iButtonKey*,size_t
|
||||
Function,+,ibutton_key_free,void,iButtonKey*
|
||||
Function,+,ibutton_key_get_data_p,const uint8_t*,iButtonKey*
|
||||
Function,+,ibutton_key_get_data_size,uint8_t,iButtonKey*
|
||||
Function,+,ibutton_key_get_max_size,uint8_t,
|
||||
Function,+,ibutton_key_get_size_by_type,uint8_t,iButtonKeyType
|
||||
Function,+,ibutton_key_get_string_by_type,const char*,iButtonKeyType
|
||||
Function,+,ibutton_key_get_type,iButtonKeyType,iButtonKey*
|
||||
Function,+,ibutton_key_get_type_by_string,_Bool,"const char*, iButtonKeyType*"
|
||||
Function,+,ibutton_key_set,void,"iButtonKey*, const iButtonKey*"
|
||||
Function,+,ibutton_key_set_data,void,"iButtonKey*, uint8_t*, uint8_t"
|
||||
Function,+,ibutton_key_set_type,void,"iButtonKey*, iButtonKeyType"
|
||||
Function,+,ibutton_worker_alloc,iButtonWorker*,
|
||||
Function,+,ibutton_key_get_protocol_id,iButtonProtocolId,const iButtonKey*
|
||||
Function,+,ibutton_key_reset,void,iButtonKey*
|
||||
Function,+,ibutton_key_set_protocol_id,void,"iButtonKey*, iButtonProtocolId"
|
||||
Function,+,ibutton_protocols_alloc,iButtonProtocols*,
|
||||
Function,+,ibutton_protocols_apply_edits,void,"iButtonProtocols*, const iButtonKey*"
|
||||
Function,+,ibutton_protocols_emulate_start,void,"iButtonProtocols*, iButtonKey*"
|
||||
Function,+,ibutton_protocols_emulate_stop,void,"iButtonProtocols*, iButtonKey*"
|
||||
Function,+,ibutton_protocols_free,void,iButtonProtocols*
|
||||
Function,+,ibutton_protocols_get_editable_data,void,"iButtonProtocols*, const iButtonKey*, iButtonEditableData*"
|
||||
Function,+,ibutton_protocols_get_features,uint32_t,"iButtonProtocols*, iButtonProtocolId"
|
||||
Function,+,ibutton_protocols_get_id_by_name,iButtonProtocolId,"iButtonProtocols*, const char*"
|
||||
Function,+,ibutton_protocols_get_manufacturer,const char*,"iButtonProtocols*, iButtonProtocolId"
|
||||
Function,+,ibutton_protocols_get_max_data_size,size_t,iButtonProtocols*
|
||||
Function,+,ibutton_protocols_get_name,const char*,"iButtonProtocols*, iButtonProtocolId"
|
||||
Function,+,ibutton_protocols_get_protocol_count,uint32_t,
|
||||
Function,+,ibutton_protocols_is_valid,_Bool,"iButtonProtocols*, const iButtonKey*"
|
||||
Function,+,ibutton_protocols_load,_Bool,"iButtonProtocols*, iButtonKey*, const char*"
|
||||
Function,+,ibutton_protocols_read,_Bool,"iButtonProtocols*, iButtonKey*"
|
||||
Function,+,ibutton_protocols_render_brief_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||
Function,+,ibutton_protocols_render_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||
Function,+,ibutton_protocols_render_error,void,"iButtonProtocols*, const iButtonKey*, FuriString*"
|
||||
Function,+,ibutton_protocols_save,_Bool,"iButtonProtocols*, const iButtonKey*, const char*"
|
||||
Function,+,ibutton_protocols_write_blank,_Bool,"iButtonProtocols*, iButtonKey*"
|
||||
Function,+,ibutton_protocols_write_copy,_Bool,"iButtonProtocols*, iButtonKey*"
|
||||
Function,+,ibutton_worker_alloc,iButtonWorker*,iButtonProtocols*
|
||||
Function,+,ibutton_worker_emulate_set_callback,void,"iButtonWorker*, iButtonWorkerEmulateCallback, void*"
|
||||
Function,+,ibutton_worker_emulate_start,void,"iButtonWorker*, iButtonKey*"
|
||||
Function,+,ibutton_worker_free,void,iButtonWorker*
|
||||
@@ -1617,13 +1649,14 @@ Function,+,ibutton_worker_read_start,void,"iButtonWorker*, iButtonKey*"
|
||||
Function,+,ibutton_worker_start_thread,void,iButtonWorker*
|
||||
Function,+,ibutton_worker_stop,void,iButtonWorker*
|
||||
Function,+,ibutton_worker_stop_thread,void,iButtonWorker*
|
||||
Function,+,ibutton_worker_write_blank_start,void,"iButtonWorker*, iButtonKey*"
|
||||
Function,+,ibutton_worker_write_copy_start,void,"iButtonWorker*, iButtonKey*"
|
||||
Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorkerWriteCallback, void*"
|
||||
Function,+,ibutton_worker_write_start,void,"iButtonWorker*, iButtonKey*"
|
||||
Function,+,icon_animation_alloc,IconAnimation*,const Icon*
|
||||
Function,+,icon_animation_free,void,IconAnimation*
|
||||
Function,+,icon_animation_get_height,uint8_t,IconAnimation*
|
||||
Function,+,icon_animation_get_width,uint8_t,IconAnimation*
|
||||
Function,+,icon_animation_is_last_frame,_Bool,IconAnimation*
|
||||
Function,+,icon_animation_get_height,uint8_t,const IconAnimation*
|
||||
Function,+,icon_animation_get_width,uint8_t,const IconAnimation*
|
||||
Function,+,icon_animation_is_last_frame,_Bool,const IconAnimation*
|
||||
Function,+,icon_animation_set_update_callback,void,"IconAnimation*, IconAnimationCallback, void*"
|
||||
Function,+,icon_animation_start,void,IconAnimation*
|
||||
Function,+,icon_animation_stop,void,IconAnimation*
|
||||
@@ -1673,7 +1706,6 @@ Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, Inf
|
||||
Function,+,infrared_worker_tx_set_signal_sent_callback,void,"InfraredWorker*, InfraredWorkerMessageSentCallback, void*"
|
||||
Function,+,infrared_worker_tx_start,void,InfraredWorker*
|
||||
Function,+,infrared_worker_tx_stop,void,InfraredWorker*
|
||||
Function,+,init_mutex,_Bool,"ValueMutex*, void*, size_t"
|
||||
Function,-,initstate,char*,"unsigned, char*, size_t"
|
||||
Function,+,input_get_key_name,const char*,InputKey
|
||||
Function,+,input_get_type_name,const char*,InputType
|
||||
@@ -1763,7 +1795,7 @@ Function,-,llround,long long int,double
|
||||
Function,-,llroundf,long long int,float
|
||||
Function,-,llroundl,long long int,long double
|
||||
Function,+,loader_get_pubsub,FuriPubSub*,Loader*
|
||||
Function,+,loader_is_locked,_Bool,Loader*
|
||||
Function,+,loader_is_locked,_Bool,const Loader*
|
||||
Function,+,loader_lock,_Bool,Loader*
|
||||
Function,+,loader_show_menu,void,
|
||||
Function,+,loader_start,LoaderStatus,"Loader*, const char*, const char*"
|
||||
@@ -1876,10 +1908,12 @@ Function,+,menu_free,void,Menu*
|
||||
Function,+,menu_get_view,View*,Menu*
|
||||
Function,+,menu_reset,void,Menu*
|
||||
Function,+,menu_set_selected_item,void,"Menu*, uint32_t"
|
||||
Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, MfClassicAuthContext*, uint64_t"
|
||||
Function,-,mf_classic_auth_attempt,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, MfClassicAuthContext*, uint64_t"
|
||||
Function,-,mf_classic_auth_init_context,void,"MfClassicAuthContext*, uint8_t"
|
||||
Function,-,mf_classic_auth_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t"
|
||||
Function,-,mf_classic_authenticate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey"
|
||||
Function,-,mf_classic_authenticate_skip_activate,_Bool,"FuriHalNfcTxRxContext*, uint8_t, uint64_t, MfClassicKey, _Bool, uint32_t"
|
||||
Function,-,mf_classic_block_to_value,_Bool,"const uint8_t*, int32_t*, uint8_t*"
|
||||
Function,-,mf_classic_check_card_type,_Bool,FuriHalNfcADevData*
|
||||
Function,-,mf_classic_dict_add_key,_Bool,"MfClassicDict*, uint8_t*"
|
||||
Function,-,mf_classic_dict_add_key_str,_Bool,"MfClassicDict*, FuriString*"
|
||||
@@ -1906,6 +1940,7 @@ Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfCl
|
||||
Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType
|
||||
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
|
||||
Function,-,mf_classic_get_type_str,const char*,MfClassicType
|
||||
Function,-,mf_classic_halt,void,"FuriHalNfcTxRxContext*, Crypto1*"
|
||||
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
|
||||
Function,-,mf_classic_is_allowed_access_sector_trailer,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
|
||||
Function,-,mf_classic_is_block_read,_Bool,"MfClassicData*, uint8_t"
|
||||
@@ -1914,6 +1949,8 @@ Function,-,mf_classic_is_key_found,_Bool,"MfClassicData*, uint8_t, MfClassicKey"
|
||||
Function,-,mf_classic_is_sector_data_read,_Bool,"MfClassicData*, uint8_t"
|
||||
Function,-,mf_classic_is_sector_read,_Bool,"MfClassicData*, uint8_t"
|
||||
Function,-,mf_classic_is_sector_trailer,_Bool,uint8_t
|
||||
Function,-,mf_classic_is_value_block,_Bool,"MfClassicData*, uint8_t"
|
||||
Function,-,mf_classic_read_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*"
|
||||
Function,-,mf_classic_read_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicReader*, MfClassicData*"
|
||||
Function,-,mf_classic_read_sector,void,"FuriHalNfcTxRxContext*, MfClassicData*, uint8_t"
|
||||
Function,-,mf_classic_reader_add_sector,void,"MfClassicReader*, uint8_t, uint64_t, uint64_t"
|
||||
@@ -1921,8 +1958,12 @@ Function,-,mf_classic_set_block_read,void,"MfClassicData*, uint8_t, MfClassicBlo
|
||||
Function,-,mf_classic_set_key_found,void,"MfClassicData*, uint8_t, MfClassicKey, uint64_t"
|
||||
Function,-,mf_classic_set_key_not_found,void,"MfClassicData*, uint8_t, MfClassicKey"
|
||||
Function,-,mf_classic_set_sector_data_not_read,void,MfClassicData*
|
||||
Function,-,mf_classic_transfer,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t"
|
||||
Function,-,mf_classic_update_card,uint8_t,"FuriHalNfcTxRxContext*, MfClassicData*"
|
||||
Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t"
|
||||
Function,-,mf_classic_value_cmd,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, uint8_t, int32_t"
|
||||
Function,-,mf_classic_value_cmd_full,_Bool,"FuriHalNfcTxRxContext*, MfClassicBlock*, uint8_t, MfClassicKey, uint64_t, int32_t"
|
||||
Function,-,mf_classic_value_to_block,void,"int32_t, uint8_t, uint8_t*"
|
||||
Function,-,mf_classic_write_block,_Bool,"FuriHalNfcTxRxContext*, Crypto1*, uint8_t, MfClassicBlock*"
|
||||
Function,-,mf_classic_write_sector,_Bool,"FuriHalNfcTxRxContext*, MfClassicData*, MfClassicData*, uint8_t"
|
||||
Function,-,mf_df_cat_application,void,"MifareDesfireApplication*, FuriString*"
|
||||
Function,-,mf_df_cat_application_info,void,"MifareDesfireApplication*, FuriString*"
|
||||
@@ -2021,30 +2062,30 @@ Function,+,notification_message,void,"NotificationApp*, const NotificationSequen
|
||||
Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*"
|
||||
Function,-,nrand48,long,unsigned short[3]
|
||||
Function,-,on_exit,int,"void (*)(int, void*), void*"
|
||||
Function,+,onewire_device_alloc,OneWireDevice*,"uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t"
|
||||
Function,+,onewire_device_attach,void,"OneWireDevice*, OneWireSlave*"
|
||||
Function,+,onewire_device_detach,void,OneWireDevice*
|
||||
Function,+,onewire_device_free,void,OneWireDevice*
|
||||
Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice*
|
||||
Function,+,onewire_device_send_id,void,OneWireDevice*
|
||||
Function,+,onewire_host_alloc,OneWireHost*,
|
||||
Function,+,onewire_host_alloc,OneWireHost*,const GpioPin*
|
||||
Function,+,onewire_host_free,void,OneWireHost*
|
||||
Function,+,onewire_host_read,uint8_t,OneWireHost*
|
||||
Function,+,onewire_host_read_bit,_Bool,OneWireHost*
|
||||
Function,+,onewire_host_read_bytes,void,"OneWireHost*, uint8_t*, uint16_t"
|
||||
Function,+,onewire_host_reset,_Bool,OneWireHost*
|
||||
Function,+,onewire_host_reset_search,void,OneWireHost*
|
||||
Function,+,onewire_host_search,uint8_t,"OneWireHost*, uint8_t*, OneWireHostSearchMode"
|
||||
Function,+,onewire_host_skip,void,OneWireHost*
|
||||
Function,+,onewire_host_search,_Bool,"OneWireHost*, uint8_t*, OneWireHostSearchMode"
|
||||
Function,+,onewire_host_set_overdrive,void,"OneWireHost*, _Bool"
|
||||
Function,+,onewire_host_start,void,OneWireHost*
|
||||
Function,+,onewire_host_stop,void,OneWireHost*
|
||||
Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t"
|
||||
Function,+,onewire_host_write,void,"OneWireHost*, uint8_t"
|
||||
Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool"
|
||||
Function,+,onewire_slave_alloc,OneWireSlave*,
|
||||
Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*"
|
||||
Function,+,onewire_slave_detach,void,OneWireSlave*
|
||||
Function,+,onewire_host_write_bytes,void,"OneWireHost*, const uint8_t*, uint16_t"
|
||||
Function,+,onewire_slave_alloc,OneWireSlave*,const GpioPin*
|
||||
Function,+,onewire_slave_free,void,OneWireSlave*
|
||||
Function,+,onewire_slave_receive,_Bool,"OneWireSlave*, uint8_t*, size_t"
|
||||
Function,+,onewire_slave_receive_bit,_Bool,OneWireSlave*
|
||||
Function,+,onewire_slave_send,_Bool,"OneWireSlave*, const uint8_t*, size_t"
|
||||
Function,+,onewire_slave_send_bit,_Bool,"OneWireSlave*, _Bool"
|
||||
Function,+,onewire_slave_set_command_callback,void,"OneWireSlave*, OneWireSlaveCommandCallback, void*"
|
||||
Function,+,onewire_slave_set_overdrive,void,"OneWireSlave*, _Bool"
|
||||
Function,+,onewire_slave_set_reset_callback,void,"OneWireSlave*, OneWireSlaveResetCallback, void*"
|
||||
Function,+,onewire_slave_set_result_callback,void,"OneWireSlave*, OneWireSlaveResultCallback, void*"
|
||||
Function,+,onewire_slave_start,void,OneWireSlave*
|
||||
Function,+,onewire_slave_stop,void,OneWireSlave*
|
||||
@@ -2067,6 +2108,13 @@ Function,-,platformProtectST25RComm,void,
|
||||
Function,-,platformSetIrqCallback,void,PlatformIrqCallback
|
||||
Function,-,platformSpiTxRx,_Bool,"const uint8_t*, uint8_t*, uint16_t"
|
||||
Function,-,platformUnprotectST25RComm,void,
|
||||
Function,+,plugin_manager_alloc,PluginManager*,"const char*, uint32_t, const ElfApiInterface*"
|
||||
Function,+,plugin_manager_free,void,PluginManager*
|
||||
Function,+,plugin_manager_get,const FlipperAppPluginDescriptor*,"PluginManager*, uint32_t"
|
||||
Function,+,plugin_manager_get_count,uint32_t,PluginManager*
|
||||
Function,+,plugin_manager_get_ep,const void*,"PluginManager*, uint32_t"
|
||||
Function,+,plugin_manager_load_all,PluginManagerError,"PluginManager*, const char*"
|
||||
Function,+,plugin_manager_load_single,PluginManagerError,"PluginManager*, const char*"
|
||||
Function,-,popen,FILE*,"const char*, const char*"
|
||||
Function,+,popup_alloc,Popup*,
|
||||
Function,+,popup_disable_timeout,void,Popup*
|
||||
@@ -2092,6 +2140,7 @@ Function,+,power_off,void,Power*
|
||||
Function,+,power_reboot,void,PowerBootMode
|
||||
Function,+,powf,float,"float, float"
|
||||
Function,-,powl,long double,"long double, long double"
|
||||
Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t"
|
||||
Function,-,printf,int,"const char*, ..."
|
||||
Function,-,prng_successor,uint32_t,"uint32_t, uint32_t"
|
||||
Function,+,property_value_out,void,"PropertyValueContext*, const char*, unsigned int, ..."
|
||||
@@ -2136,12 +2185,10 @@ Function,+,rand,int,
|
||||
Function,-,rand_r,int,unsigned*
|
||||
Function,+,random,long,
|
||||
Function,-,rawmemchr,void*,"const void*, int"
|
||||
Function,-,read_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
|
||||
Function,+,realloc,void*,"void*, size_t"
|
||||
Function,-,reallocarray,void*,"void*, size_t, size_t"
|
||||
Function,-,reallocf,void*,"void*, size_t"
|
||||
Function,-,realpath,char*,"const char*, char*"
|
||||
Function,+,release_mutex,_Bool,"ValueMutex*, const void*"
|
||||
Function,-,remainder,double,"double, double"
|
||||
Function,-,remainderf,float,"float, float"
|
||||
Function,-,remainderl,long double,"long double, long double"
|
||||
@@ -2363,11 +2410,11 @@ Function,-,scalbnl,long double,"long double, int"
|
||||
Function,-,scanf,int,"const char*, ..."
|
||||
Function,+,scene_manager_alloc,SceneManager*,"const SceneManagerHandlers*, void*"
|
||||
Function,+,scene_manager_free,void,SceneManager*
|
||||
Function,+,scene_manager_get_scene_state,uint32_t,"SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_get_scene_state,uint32_t,"const SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_handle_back_event,_Bool,SceneManager*
|
||||
Function,+,scene_manager_handle_custom_event,_Bool,"SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_handle_tick_event,void,SceneManager*
|
||||
Function,+,scene_manager_has_previous_scene,_Bool,"SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_has_previous_scene,_Bool,"const SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_next_scene,void,"SceneManager*, uint32_t"
|
||||
Function,+,scene_manager_previous_scene,_Bool,SceneManager*
|
||||
Function,+,scene_manager_search_and_switch_to_another_scene,_Bool,"SceneManager*, uint32_t"
|
||||
@@ -2420,20 +2467,25 @@ Function,-,srand48,void,long
|
||||
Function,-,srandom,void,unsigned
|
||||
Function,+,sscanf,int,"const char*, const char*, ..."
|
||||
Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*"
|
||||
Function,+,storage_common_exists,_Bool,"Storage*, const char*"
|
||||
Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*"
|
||||
Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*"
|
||||
Function,+,storage_common_migrate,FS_Error,"Storage*, const char*, const char*"
|
||||
Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*"
|
||||
Function,+,storage_common_remove,FS_Error,"Storage*, const char*"
|
||||
Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*"
|
||||
Function,+,storage_common_resolve_path_and_ensure_app_directory,void,"Storage*, FuriString*"
|
||||
Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*"
|
||||
Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*"
|
||||
Function,+,storage_dir_close,_Bool,File*
|
||||
Function,+,storage_dir_exists,_Bool,"Storage*, const char*"
|
||||
Function,+,storage_dir_open,_Bool,"File*, const char*"
|
||||
Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t"
|
||||
Function,-,storage_dir_rewind,_Bool,File*
|
||||
Function,+,storage_error_get_desc,const char*,FS_Error
|
||||
Function,+,storage_file_alloc,File*,Storage*
|
||||
Function,+,storage_file_close,_Bool,File*
|
||||
Function,+,storage_file_copy_to_file,_Bool,"File*, File*, uint32_t"
|
||||
Function,+,storage_file_eof,_Bool,File*
|
||||
Function,+,storage_file_exists,_Bool,"Storage*, const char*"
|
||||
Function,+,storage_file_free,void,File*
|
||||
@@ -2556,17 +2608,20 @@ Function,-,strupr,char*,char*
|
||||
Function,-,strverscmp,int,"const char*, const char*"
|
||||
Function,-,strxfrm,size_t,"char*, const char*, size_t"
|
||||
Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t"
|
||||
Function,+,subghz_block_generic_deserialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*"
|
||||
Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*"
|
||||
Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t"
|
||||
Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*"
|
||||
Function,+,subghz_block_generic_serialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*"
|
||||
Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*"
|
||||
Function,+,subghz_environment_alloc,SubGhzEnvironment*,
|
||||
Function,+,subghz_environment_free,void,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_came_atomo_rainbow_table_file_name,const char*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_keystore,SubGhzKeystore*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_nice_flor_s_rainbow_table_file_name,const char*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_get_protocol_name_registry,const char*,"SubGhzEnvironment*, size_t"
|
||||
Function,+,subghz_environment_get_protocol_registry,void*,SubGhzEnvironment*
|
||||
Function,+,subghz_environment_load_keystore,_Bool,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_alutech_at_4n_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_came_atomo_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_nice_flor_s_rainbow_table_file_name,void,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_environment_set_protocol_registry,void,"SubGhzEnvironment*, void*"
|
||||
@@ -2589,7 +2644,7 @@ Function,+,subghz_protocol_blocks_crc8le,uint8_t,"const uint8_t[], size_t, uint8
|
||||
Function,+,subghz_protocol_blocks_get_bit_array,_Bool,"uint8_t[], size_t"
|
||||
Function,+,subghz_protocol_blocks_get_hash_data,uint8_t,"SubGhzBlockDecoder*, size_t"
|
||||
Function,+,subghz_protocol_blocks_get_parity,uint8_t,"uint64_t, uint8_t"
|
||||
Function,+,subghz_protocol_blocks_get_upload,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t"
|
||||
Function,+,subghz_protocol_blocks_get_upload_from_bit_array,size_t,"uint8_t[], size_t, LevelDuration*, size_t, uint32_t, SubGhzProtocolBlockAlignBit"
|
||||
Function,+,subghz_protocol_blocks_lfsr_digest16,uint16_t,"const uint8_t[], size_t, uint16_t, uint16_t"
|
||||
Function,+,subghz_protocol_blocks_lfsr_digest8,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t"
|
||||
Function,+,subghz_protocol_blocks_lfsr_digest8_reflect,uint8_t,"const uint8_t[], size_t, uint8_t, uint8_t"
|
||||
@@ -2598,19 +2653,19 @@ Function,+,subghz_protocol_blocks_parity_bytes,uint8_t,"const uint8_t[], size_t"
|
||||
Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t"
|
||||
Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t"
|
||||
Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t"
|
||||
Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_decoder_base_deserialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase*
|
||||
Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*"
|
||||
Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*"
|
||||
Function,+,subghz_protocol_decoder_base_serialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*"
|
||||
Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*"
|
||||
Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment*
|
||||
Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_decoder_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t"
|
||||
Function,+,subghz_protocol_decoder_raw_free,void,void*
|
||||
Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, FuriString*"
|
||||
Function,+,subghz_protocol_decoder_raw_reset,void,void*
|
||||
Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment*
|
||||
Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_encoder_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*"
|
||||
Function,+,subghz_protocol_encoder_raw_free,void,void*
|
||||
Function,+,subghz_protocol_encoder_raw_stop,void,void*
|
||||
Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void*
|
||||
@@ -2648,7 +2703,7 @@ Function,+,subghz_setting_get_preset_name,const char*,"SubGhzSetting*, size_t"
|
||||
Function,+,subghz_setting_load,void,"SubGhzSetting*, const char*"
|
||||
Function,+,subghz_setting_load_custom_preset,_Bool,"SubGhzSetting*, const char*, FlipperFormat*"
|
||||
Function,+,subghz_transmitter_alloc_init,SubGhzTransmitter*,"SubGhzEnvironment*, const char*"
|
||||
Function,+,subghz_transmitter_deserialize,_Bool,"SubGhzTransmitter*, FlipperFormat*"
|
||||
Function,+,subghz_transmitter_deserialize,SubGhzProtocolStatus,"SubGhzTransmitter*, FlipperFormat*"
|
||||
Function,+,subghz_transmitter_free,void,SubGhzTransmitter*
|
||||
Function,+,subghz_transmitter_get_protocol_instance,SubGhzProtocolEncoderBase*,SubGhzTransmitter*
|
||||
Function,+,subghz_transmitter_stop,_Bool,SubGhzTransmitter*
|
||||
@@ -2667,6 +2722,7 @@ Function,+,subghz_worker_free,void,SubGhzWorker*
|
||||
Function,+,subghz_worker_is_running,_Bool,SubGhzWorker*
|
||||
Function,+,subghz_worker_rx_callback,void,"_Bool, uint32_t, void*"
|
||||
Function,+,subghz_worker_set_context,void,"SubGhzWorker*, void*"
|
||||
Function,+,subghz_worker_set_filter,void,"SubGhzWorker*, uint16_t"
|
||||
Function,+,subghz_worker_set_overrun_callback,void,"SubGhzWorker*, SubGhzWorkerOverrunCallback"
|
||||
Function,+,subghz_worker_set_pair_callback,void,"SubGhzWorker*, SubGhzWorkerPairCallback"
|
||||
Function,+,subghz_worker_start,void,SubGhzWorker*
|
||||
@@ -2883,11 +2939,11 @@ Function,+,view_port_alloc,ViewPort*,
|
||||
Function,+,view_port_draw_callback_set,void,"ViewPort*, ViewPortDrawCallback, void*"
|
||||
Function,+,view_port_enabled_set,void,"ViewPort*, _Bool"
|
||||
Function,+,view_port_free,void,ViewPort*
|
||||
Function,+,view_port_get_height,uint8_t,ViewPort*
|
||||
Function,+,view_port_get_height,uint8_t,const ViewPort*
|
||||
Function,+,view_port_get_orientation,ViewPortOrientation,const ViewPort*
|
||||
Function,+,view_port_get_width,uint8_t,ViewPort*
|
||||
Function,+,view_port_get_width,uint8_t,const ViewPort*
|
||||
Function,+,view_port_input_callback_set,void,"ViewPort*, ViewPortInputCallback, void*"
|
||||
Function,+,view_port_is_enabled,_Bool,ViewPort*
|
||||
Function,+,view_port_is_enabled,_Bool,const ViewPort*
|
||||
Function,+,view_port_set_height,void,"ViewPort*, uint8_t"
|
||||
Function,+,view_port_set_orientation,void,"ViewPort*, ViewPortOrientation"
|
||||
Function,+,view_port_set_width,void,"ViewPort*, uint8_t"
|
||||
@@ -2931,7 +2987,6 @@ Function,+,widget_alloc,Widget*,
|
||||
Function,+,widget_free,void,Widget*
|
||||
Function,+,widget_get_view,View*,Widget*
|
||||
Function,+,widget_reset,void,Widget*
|
||||
Function,-,write_mutex,_Bool,"ValueMutex*, void*, size_t, uint32_t"
|
||||
Function,-,xPortGetFreeHeapSize,size_t,
|
||||
Function,-,xPortGetMinimumEverFreeHeapSize,size_t,
|
||||
Function,-,xPortStartScheduler,BaseType_t,
|
||||
@@ -2990,6 +3045,7 @@ Variable,-,_sys_nerr,int,
|
||||
Variable,-,_timezone,long,
|
||||
Variable,-,_tzname,char*[2],
|
||||
Variable,+,cli_vcp,CliSession,
|
||||
Variable,+,firmware_api_interface,const ElfApiInterface*,
|
||||
Variable,+,furi_hal_i2c_bus_external,FuriHalI2cBus,
|
||||
Variable,+,furi_hal_i2c_bus_power,FuriHalI2cBus,
|
||||
Variable,+,furi_hal_i2c_handle_external,FuriHalI2cBusHandle,
|
||||
@@ -3032,6 +3088,8 @@ Variable,+,gpio_infrared_rx,const GpioPin,
|
||||
Variable,+,gpio_infrared_tx,const GpioPin,
|
||||
Variable,+,gpio_nfc_cs,const GpioPin,
|
||||
Variable,+,gpio_nfc_irq_rfid_pull,const GpioPin,
|
||||
Variable,+,gpio_pins,const GpioPinRecord[],
|
||||
Variable,+,gpio_pins_count,const size_t,
|
||||
Variable,+,gpio_rf_sw_0,const GpioPin,
|
||||
Variable,+,gpio_rfid_carrier,const GpioPin,
|
||||
Variable,+,gpio_rfid_carrier_out,const GpioPin,
|
||||
|
||||
|
@@ -1,39 +1,12 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file fatfs.c
|
||||
* @brief Code for fatfs applications
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "fatfs.h"
|
||||
|
||||
uint8_t retUSER; /* Return value for USER */
|
||||
char USERPath[4]; /* USER logical drive path */
|
||||
FATFS USERFatFS; /* File system object for USER logical drive */
|
||||
FIL USERFile; /* File object for USER */
|
||||
/** logical drive path */
|
||||
char fatfs_path[4];
|
||||
/** File system object */
|
||||
FATFS fatfs_object;
|
||||
|
||||
/* USER CODE BEGIN Variables */
|
||||
|
||||
/* USER CODE END Variables */
|
||||
|
||||
void MX_FATFS_Init(void) {
|
||||
/*## FatFS: Link the USER driver ###########################*/
|
||||
retUSER = FATFS_LinkDriver(&USER_Driver, USERPath);
|
||||
|
||||
/* USER CODE BEGIN Init */
|
||||
/* additional user code for init */
|
||||
/* USER CODE END Init */
|
||||
void fatfs_init(void) {
|
||||
FATFS_LinkDriver(&sd_fatfs_driver, fatfs_path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,13 +15,5 @@ void MX_FATFS_Init(void) {
|
||||
* @retval Time in DWORD
|
||||
*/
|
||||
DWORD get_fattime(void) {
|
||||
/* USER CODE BEGIN get_fattime */
|
||||
return 0;
|
||||
/* USER CODE END get_fattime */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN Application */
|
||||
|
||||
/* USER CODE END Application */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@@ -1,49 +1,19 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file fatfs.h
|
||||
* @brief Header for fatfs applications
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "fatfs/ff.h"
|
||||
#include "fatfs/ff_gen_drv.h"
|
||||
#include "user_diskio.h"
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __fatfs_H
|
||||
#define __fatfs_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "fatfs/ff.h"
|
||||
#include "fatfs/ff_gen_drv.h"
|
||||
#include "user_diskio.h" /* defines USER_Driver as external */
|
||||
/** File system object */
|
||||
extern FATFS fatfs_object;
|
||||
|
||||
/* USER CODE BEGIN Includes */
|
||||
/** Init file system driver */
|
||||
void fatfs_init(void);
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
extern uint8_t retUSER; /* Return value for USER */
|
||||
extern char USERPath[4]; /* USER logical drive path */
|
||||
extern FATFS USERFatFS; /* File system object for USER logical drive */
|
||||
extern FIL USERFile; /* File object for USER */
|
||||
|
||||
void MX_FATFS_Init(void);
|
||||
|
||||
/* USER CODE BEGIN Prototypes */
|
||||
|
||||
/* USER CODE END Prototypes */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*__fatfs_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
#endif
|
||||
@@ -164,7 +164,7 @@
|
||||
|
||||
/* USER CODE BEGIN Volumes */
|
||||
#define _STR_VOLUME_ID 0 /* 0:Use only 0-9 for drive ID, 1:Use strings for drive ID */
|
||||
#define _VOLUME_STRS "RAM", "NAND", "CF", "SD1", "SD2", "USB1", "USB2", "USB3"
|
||||
#define _VOLUME_STRS "SD"
|
||||
/* _STR_VOLUME_ID switches string support of volume ID.
|
||||
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||
|
||||
@@ -0,0 +1,843 @@
|
||||
#include "sd_spi_io.h"
|
||||
#include "sector_cache.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <furi/core/core_defines.h>
|
||||
|
||||
// #define SD_SPI_DEBUG 1
|
||||
#define TAG "SdSpi"
|
||||
|
||||
#ifdef SD_SPI_DEBUG
|
||||
#define sd_spi_debug(...) FURI_LOG_I(TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define sd_spi_debug(...)
|
||||
#endif
|
||||
|
||||
#define SD_CMD_LENGTH 6
|
||||
#define SD_DUMMY_BYTE 0xFF
|
||||
#define SD_ANSWER_RETRY_COUNT 8
|
||||
#define SD_IDLE_RETRY_COUNT 100
|
||||
|
||||
#define FLAG_SET(x, y) (((x) & (y)) == (y))
|
||||
|
||||
static bool sd_high_capacity = false;
|
||||
|
||||
typedef enum {
|
||||
SdSpiDataResponceOK = 0x05,
|
||||
SdSpiDataResponceCRCError = 0x0B,
|
||||
SdSpiDataResponceWriteError = 0x0D,
|
||||
SdSpiDataResponceOtherError = 0xFF,
|
||||
} SdSpiDataResponce;
|
||||
|
||||
typedef struct {
|
||||
uint8_t r1;
|
||||
uint8_t r2;
|
||||
uint8_t r3;
|
||||
uint8_t r4;
|
||||
uint8_t r5;
|
||||
} SdSpiCmdAnswer;
|
||||
|
||||
typedef enum {
|
||||
SdSpiCmdAnswerTypeR1,
|
||||
SdSpiCmdAnswerTypeR1B,
|
||||
SdSpiCmdAnswerTypeR2,
|
||||
SdSpiCmdAnswerTypeR3,
|
||||
SdSpiCmdAnswerTypeR4R5,
|
||||
SdSpiCmdAnswerTypeR7,
|
||||
} SdSpiCmdAnswerType;
|
||||
|
||||
/*
|
||||
SdSpiCmd and SdSpiToken use non-standard enum value names convention,
|
||||
because it is more convenient to look for documentation on a specific command.
|
||||
For example, to find out what the SD_CMD23_SET_BLOCK_COUNT command does, you need to look for
|
||||
SET_BLOCK_COUNT or CMD23 in the "Part 1 Physical Layer Simplified Specification".
|
||||
|
||||
Do not use that naming convention in other places.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SD_CMD0_GO_IDLE_STATE = 0,
|
||||
SD_CMD1_SEND_OP_COND = 1,
|
||||
SD_CMD8_SEND_IF_COND = 8,
|
||||
SD_CMD9_SEND_CSD = 9,
|
||||
SD_CMD10_SEND_CID = 10,
|
||||
SD_CMD12_STOP_TRANSMISSION = 12,
|
||||
SD_CMD13_SEND_STATUS = 13,
|
||||
SD_CMD16_SET_BLOCKLEN = 16,
|
||||
SD_CMD17_READ_SINGLE_BLOCK = 17,
|
||||
SD_CMD18_READ_MULT_BLOCK = 18,
|
||||
SD_CMD23_SET_BLOCK_COUNT = 23,
|
||||
SD_CMD24_WRITE_SINGLE_BLOCK = 24,
|
||||
SD_CMD25_WRITE_MULT_BLOCK = 25,
|
||||
SD_CMD27_PROG_CSD = 27,
|
||||
SD_CMD28_SET_WRITE_PROT = 28,
|
||||
SD_CMD29_CLR_WRITE_PROT = 29,
|
||||
SD_CMD30_SEND_WRITE_PROT = 30,
|
||||
SD_CMD32_SD_ERASE_GRP_START = 32,
|
||||
SD_CMD33_SD_ERASE_GRP_END = 33,
|
||||
SD_CMD34_UNTAG_SECTOR = 34,
|
||||
SD_CMD35_ERASE_GRP_START = 35,
|
||||
SD_CMD36_ERASE_GRP_END = 36,
|
||||
SD_CMD37_UNTAG_ERASE_GROUP = 37,
|
||||
SD_CMD38_ERASE = 38,
|
||||
SD_CMD41_SD_APP_OP_COND = 41,
|
||||
SD_CMD55_APP_CMD = 55,
|
||||
SD_CMD58_READ_OCR = 58,
|
||||
} SdSpiCmd;
|
||||
|
||||
/** Data tokens */
|
||||
typedef enum {
|
||||
SD_TOKEN_START_DATA_SINGLE_BLOCK_READ = 0xFE,
|
||||
SD_TOKEN_START_DATA_MULTIPLE_BLOCK_READ = 0xFE,
|
||||
SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE = 0xFE,
|
||||
SD_TOKEN_START_DATA_MULTIPLE_BLOCK_WRITE = 0xFC,
|
||||
SD_TOKEN_STOP_DATA_MULTIPLE_BLOCK_WRITE = 0xFD,
|
||||
} SdSpiToken;
|
||||
|
||||
/** R1 answer value */
|
||||
typedef enum {
|
||||
SdSpi_R1_NO_ERROR = 0x00,
|
||||
SdSpi_R1_IN_IDLE_STATE = 0x01,
|
||||
SdSpi_R1_ERASE_RESET = 0x02,
|
||||
SdSpi_R1_ILLEGAL_COMMAND = 0x04,
|
||||
SdSpi_R1_COM_CRC_ERROR = 0x08,
|
||||
SdSpi_R1_ERASE_SEQUENCE_ERROR = 0x10,
|
||||
SdSpi_R1_ADDRESS_ERROR = 0x20,
|
||||
SdSpi_R1_PARAMETER_ERROR = 0x40,
|
||||
} SdSpiR1;
|
||||
|
||||
/** R2 answer value */
|
||||
typedef enum {
|
||||
/* R2 answer value */
|
||||
SdSpi_R2_NO_ERROR = 0x00,
|
||||
SdSpi_R2_CARD_LOCKED = 0x01,
|
||||
SdSpi_R2_LOCKUNLOCK_ERROR = 0x02,
|
||||
SdSpi_R2_ERROR = 0x04,
|
||||
SdSpi_R2_CC_ERROR = 0x08,
|
||||
SdSpi_R2_CARD_ECC_FAILED = 0x10,
|
||||
SdSpi_R2_WP_VIOLATION = 0x20,
|
||||
SdSpi_R2_ERASE_PARAM = 0x40,
|
||||
SdSpi_R2_OUTOFRANGE = 0x80,
|
||||
} SdSpiR2;
|
||||
|
||||
static inline void sd_spi_select_card() {
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
|
||||
furi_delay_us(10); // Entry guard time for some SD cards
|
||||
}
|
||||
|
||||
static inline void sd_spi_deselect_card() {
|
||||
furi_delay_us(10); // Exit guard time for some SD cards
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
|
||||
}
|
||||
|
||||
static void sd_spi_bus_to_ground() {
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->miso,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFnUnused);
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->mosi,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFnUnused);
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->sck,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFnUnused);
|
||||
|
||||
sd_spi_select_card();
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->miso, false);
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->mosi, false);
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->sck, false);
|
||||
}
|
||||
|
||||
static void sd_spi_bus_rise_up() {
|
||||
sd_spi_deselect_card();
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
furi_hal_gpio_init_ex(
|
||||
furi_hal_sd_spi_handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
}
|
||||
|
||||
static inline uint8_t sd_spi_read_byte(void) {
|
||||
uint8_t responce;
|
||||
furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, &responce, 1, SD_TIMEOUT_MS));
|
||||
return responce;
|
||||
}
|
||||
|
||||
static inline void sd_spi_write_byte(uint8_t data) {
|
||||
furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, NULL, 1, SD_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
static inline uint8_t sd_spi_write_and_read_byte(uint8_t data) {
|
||||
uint8_t responce;
|
||||
furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, &data, &responce, 1, SD_TIMEOUT_MS));
|
||||
return responce;
|
||||
}
|
||||
|
||||
static inline void sd_spi_write_bytes(uint8_t* data, uint32_t size) {
|
||||
furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
static inline void sd_spi_read_bytes(uint8_t* data, uint32_t size) {
|
||||
furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
static inline void sd_spi_write_bytes_dma(uint8_t* data, uint32_t size) {
|
||||
uint32_t timeout_mul = (size / 512) + 1;
|
||||
furi_check(furi_hal_spi_bus_trx_dma(
|
||||
furi_hal_sd_spi_handle, data, NULL, size, SD_TIMEOUT_MS * timeout_mul));
|
||||
}
|
||||
|
||||
static inline void sd_spi_read_bytes_dma(uint8_t* data, uint32_t size) {
|
||||
uint32_t timeout_mul = (size / 512) + 1;
|
||||
furi_check(furi_hal_spi_bus_trx_dma(
|
||||
furi_hal_sd_spi_handle, NULL, data, size, SD_TIMEOUT_MS * timeout_mul));
|
||||
}
|
||||
|
||||
static uint8_t sd_spi_wait_for_data_and_read(void) {
|
||||
uint8_t retry_count = SD_ANSWER_RETRY_COUNT;
|
||||
uint8_t responce;
|
||||
|
||||
// Wait until we get a valid data
|
||||
do {
|
||||
responce = sd_spi_read_byte();
|
||||
retry_count--;
|
||||
|
||||
} while((responce == SD_DUMMY_BYTE) && retry_count);
|
||||
|
||||
return responce;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_wait_for_data(uint8_t data, uint32_t timeout_ms) {
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_ms * 1000);
|
||||
uint8_t byte;
|
||||
|
||||
do {
|
||||
byte = sd_spi_read_byte();
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
return SdSpiStatusTimeout;
|
||||
}
|
||||
} while((byte != data));
|
||||
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
static inline void sd_spi_deselect_card_and_purge() {
|
||||
sd_spi_deselect_card();
|
||||
sd_spi_read_byte();
|
||||
}
|
||||
|
||||
static inline void sd_spi_purge_crc() {
|
||||
sd_spi_read_byte();
|
||||
sd_spi_read_byte();
|
||||
}
|
||||
|
||||
static SdSpiCmdAnswer
|
||||
sd_spi_send_cmd(SdSpiCmd cmd, uint32_t arg, uint8_t crc, SdSpiCmdAnswerType answer_type) {
|
||||
uint8_t frame[SD_CMD_LENGTH];
|
||||
SdSpiCmdAnswer cmd_answer = {
|
||||
.r1 = SD_DUMMY_BYTE,
|
||||
.r2 = SD_DUMMY_BYTE,
|
||||
.r3 = SD_DUMMY_BYTE,
|
||||
.r4 = SD_DUMMY_BYTE,
|
||||
.r5 = SD_DUMMY_BYTE,
|
||||
};
|
||||
|
||||
// R1 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 1 Bytes answer + NEC(0) = 15bytes
|
||||
// R1b identical to R1 + Busy information
|
||||
// R2 Length = NCS(0)+ 6 Bytes command + NCR(min1 max8) + 2 Bytes answer + NEC(0) = 16bytes
|
||||
|
||||
frame[0] = ((uint8_t)cmd | 0x40);
|
||||
frame[1] = (uint8_t)(arg >> 24);
|
||||
frame[2] = (uint8_t)(arg >> 16);
|
||||
frame[3] = (uint8_t)(arg >> 8);
|
||||
frame[4] = (uint8_t)(arg);
|
||||
frame[5] = (crc | 0x01);
|
||||
|
||||
sd_spi_select_card();
|
||||
sd_spi_write_bytes(frame, sizeof(frame));
|
||||
|
||||
switch(answer_type) {
|
||||
case SdSpiCmdAnswerTypeR1:
|
||||
cmd_answer.r1 = sd_spi_wait_for_data_and_read();
|
||||
break;
|
||||
case SdSpiCmdAnswerTypeR1B:
|
||||
// TODO: can be wrong, at least for SD_CMD12_STOP_TRANSMISSION you need to purge one byte before reading R1
|
||||
cmd_answer.r1 = sd_spi_wait_for_data_and_read();
|
||||
|
||||
// In general this shenenigans seems suspicious, please double check SD specs if you are using SdSpiCmdAnswerTypeR1B
|
||||
// reassert card
|
||||
sd_spi_deselect_card();
|
||||
furi_delay_us(1000);
|
||||
sd_spi_deselect_card();
|
||||
|
||||
// and wait for it to be ready
|
||||
while(sd_spi_read_byte() != 0xFF) {
|
||||
};
|
||||
|
||||
break;
|
||||
case SdSpiCmdAnswerTypeR2:
|
||||
cmd_answer.r1 = sd_spi_wait_for_data_and_read();
|
||||
cmd_answer.r2 = sd_spi_read_byte();
|
||||
break;
|
||||
case SdSpiCmdAnswerTypeR3:
|
||||
case SdSpiCmdAnswerTypeR7:
|
||||
cmd_answer.r1 = sd_spi_wait_for_data_and_read();
|
||||
cmd_answer.r2 = sd_spi_read_byte();
|
||||
cmd_answer.r3 = sd_spi_read_byte();
|
||||
cmd_answer.r4 = sd_spi_read_byte();
|
||||
cmd_answer.r5 = sd_spi_read_byte();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return cmd_answer;
|
||||
}
|
||||
|
||||
static SdSpiDataResponce sd_spi_get_data_response(uint32_t timeout_ms) {
|
||||
SdSpiDataResponce responce = sd_spi_read_byte();
|
||||
// read busy response byte
|
||||
sd_spi_read_byte();
|
||||
|
||||
switch(responce & 0x1F) {
|
||||
case SdSpiDataResponceOK:
|
||||
// TODO: check timings
|
||||
sd_spi_deselect_card();
|
||||
sd_spi_select_card();
|
||||
|
||||
// wait for 0xFF
|
||||
if(sd_spi_wait_for_data(0xFF, timeout_ms) == SdSpiStatusOK) {
|
||||
return SdSpiDataResponceOK;
|
||||
} else {
|
||||
return SdSpiDataResponceOtherError;
|
||||
}
|
||||
case SdSpiDataResponceCRCError:
|
||||
return SdSpiDataResponceCRCError;
|
||||
case SdSpiDataResponceWriteError:
|
||||
return SdSpiDataResponceWriteError;
|
||||
default:
|
||||
return SdSpiDataResponceOtherError;
|
||||
}
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_init_spi_mode_v1(void) {
|
||||
SdSpiCmdAnswer response;
|
||||
uint8_t retry_count = 0;
|
||||
|
||||
sd_spi_debug("Init SD card in SPI mode v1");
|
||||
|
||||
do {
|
||||
retry_count++;
|
||||
|
||||
// CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
|
||||
sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
// ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
|
||||
response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(retry_count >= SD_IDLE_RETRY_COUNT) {
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
} while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
|
||||
|
||||
sd_spi_debug("Init SD card in SPI mode v1 done");
|
||||
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_init_spi_mode_v2(void) {
|
||||
SdSpiCmdAnswer response;
|
||||
uint8_t retry_count = 0;
|
||||
|
||||
sd_spi_debug("Init SD card in SPI mode v2");
|
||||
|
||||
do {
|
||||
retry_count++;
|
||||
// CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
|
||||
sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
// ACMD41 (APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
|
||||
response =
|
||||
sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0x40000000, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(retry_count >= SD_IDLE_RETRY_COUNT) {
|
||||
sd_spi_debug("ACMD41 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
} while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
|
||||
|
||||
if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) {
|
||||
sd_spi_debug("ACMD41 is illegal command");
|
||||
retry_count = 0;
|
||||
do {
|
||||
retry_count++;
|
||||
// CMD55 (APP_CMD) before any ACMD command: R1 response (0x00: no errors)
|
||||
response = sd_spi_send_cmd(SD_CMD55_APP_CMD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(response.r1 != SdSpi_R1_IN_IDLE_STATE) {
|
||||
sd_spi_debug("CMD55 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
// ACMD41 (SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors)
|
||||
response = sd_spi_send_cmd(SD_CMD41_SD_APP_OP_COND, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(retry_count >= SD_IDLE_RETRY_COUNT) {
|
||||
sd_spi_debug("ACMD41 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
} while(response.r1 == SdSpi_R1_IN_IDLE_STATE);
|
||||
}
|
||||
|
||||
sd_spi_debug("Init SD card in SPI mode v2 done");
|
||||
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_init_spi_mode(void) {
|
||||
SdSpiCmdAnswer response;
|
||||
uint8_t retry_count;
|
||||
|
||||
// CMD0 (GO_IDLE_STATE) to put SD in SPI mode and
|
||||
// wait for In Idle State Response (R1 Format) equal to 0x01
|
||||
retry_count = 0;
|
||||
do {
|
||||
retry_count++;
|
||||
response = sd_spi_send_cmd(SD_CMD0_GO_IDLE_STATE, 0, 0x95, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(retry_count >= SD_IDLE_RETRY_COUNT) {
|
||||
sd_spi_debug("CMD0 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
} while(response.r1 != SdSpi_R1_IN_IDLE_STATE);
|
||||
|
||||
// CMD8 (SEND_IF_COND) to check the power supply status
|
||||
// and wait until response (R7 Format) equal to 0xAA and
|
||||
response = sd_spi_send_cmd(SD_CMD8_SEND_IF_COND, 0x1AA, 0x87, SdSpiCmdAnswerTypeR7);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(FLAG_SET(response.r1, SdSpi_R1_ILLEGAL_COMMAND)) {
|
||||
if(sd_spi_init_spi_mode_v1() != SdSpiStatusOK) {
|
||||
sd_spi_debug("Init mode v1 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
sd_high_capacity = 0;
|
||||
} else if(response.r1 == SdSpi_R1_IN_IDLE_STATE) {
|
||||
if(sd_spi_init_spi_mode_v2() != SdSpiStatusOK) {
|
||||
sd_spi_debug("Init mode v2 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
// CMD58 (READ_OCR) to initialize SDHC or SDXC cards: R3 response
|
||||
response = sd_spi_send_cmd(SD_CMD58_READ_OCR, 0, 0xFF, SdSpiCmdAnswerTypeR3);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(response.r1 != SdSpi_R1_NO_ERROR) {
|
||||
sd_spi_debug("CMD58 failed");
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
sd_high_capacity = (response.r2 & 0x40) >> 6;
|
||||
} else {
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
sd_spi_debug("SD card is %s", sd_high_capacity ? "SDHC or SDXC" : "SDSC");
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_get_csd(SD_CSD* csd) {
|
||||
uint16_t counter = 0;
|
||||
uint8_t csd_data[16];
|
||||
SdSpiStatus ret = SdSpiStatusError;
|
||||
SdSpiCmdAnswer response;
|
||||
|
||||
// CMD9 (SEND_CSD): R1 format (0x00 is no errors)
|
||||
response = sd_spi_send_cmd(SD_CMD9_SEND_CSD, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
|
||||
if(response.r1 == SdSpi_R1_NO_ERROR) {
|
||||
if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) ==
|
||||
SdSpiStatusOK) {
|
||||
// read CSD data
|
||||
for(counter = 0; counter < 16; counter++) {
|
||||
csd_data[counter] = sd_spi_read_byte();
|
||||
}
|
||||
|
||||
sd_spi_purge_crc();
|
||||
|
||||
/*************************************************************************
|
||||
CSD header decoding
|
||||
*************************************************************************/
|
||||
|
||||
csd->CSDStruct = (csd_data[0] & 0xC0) >> 6;
|
||||
csd->Reserved1 = csd_data[0] & 0x3F;
|
||||
csd->TAAC = csd_data[1];
|
||||
csd->NSAC = csd_data[2];
|
||||
csd->MaxBusClkFrec = csd_data[3];
|
||||
csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4);
|
||||
csd->RdBlockLen = csd_data[5] & 0x0F;
|
||||
csd->PartBlockRead = (csd_data[6] & 0x80) >> 7;
|
||||
csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6;
|
||||
csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5;
|
||||
csd->DSRImpl = (csd_data[6] & 0x10) >> 4;
|
||||
|
||||
/*************************************************************************
|
||||
CSD v1/v2 decoding
|
||||
*************************************************************************/
|
||||
|
||||
if(sd_high_capacity == 0) {
|
||||
csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2);
|
||||
csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) |
|
||||
((csd_data[8] & 0xC0) >> 6);
|
||||
csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3;
|
||||
csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07);
|
||||
csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5;
|
||||
csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2;
|
||||
csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) |
|
||||
((csd_data[10] & 0x80) >> 7);
|
||||
} else {
|
||||
csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) |
|
||||
((csd_data[7] & 0xC0) >> 6);
|
||||
csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) |
|
||||
csd_data[9];
|
||||
csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8);
|
||||
}
|
||||
|
||||
csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6;
|
||||
csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7);
|
||||
csd->WrProtectGrSize = (csd_data[11] & 0x7F);
|
||||
csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7;
|
||||
csd->Reserved2 = (csd_data[12] & 0x60) >> 5;
|
||||
csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2;
|
||||
csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6);
|
||||
csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5;
|
||||
csd->Reserved3 = (csd_data[13] & 0x1F);
|
||||
csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7;
|
||||
csd->CopyFlag = (csd_data[14] & 0x40) >> 6;
|
||||
csd->PermWrProtect = (csd_data[14] & 0x20) >> 5;
|
||||
csd->TempWrProtect = (csd_data[14] & 0x10) >> 4;
|
||||
csd->FileFormat = (csd_data[14] & 0x0C) >> 2;
|
||||
csd->Reserved4 = (csd_data[14] & 0x03);
|
||||
csd->crc = (csd_data[15] & 0xFE) >> 1;
|
||||
csd->Reserved5 = (csd_data[15] & 0x01);
|
||||
|
||||
ret = SdSpiStatusOK;
|
||||
}
|
||||
}
|
||||
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_get_cid(SD_CID* Cid) {
|
||||
uint16_t counter = 0;
|
||||
uint8_t cid_data[16];
|
||||
SdSpiStatus ret = SdSpiStatusError;
|
||||
SdSpiCmdAnswer response;
|
||||
|
||||
// CMD10 (SEND_CID): R1 format (0x00 is no errors)
|
||||
response = sd_spi_send_cmd(SD_CMD10_SEND_CID, 0, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
|
||||
if(response.r1 == SdSpi_R1_NO_ERROR) {
|
||||
if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, SD_TIMEOUT_MS) ==
|
||||
SdSpiStatusOK) {
|
||||
// read CID data
|
||||
for(counter = 0; counter < 16; counter++) {
|
||||
cid_data[counter] = sd_spi_read_byte();
|
||||
}
|
||||
|
||||
sd_spi_purge_crc();
|
||||
|
||||
Cid->ManufacturerID = cid_data[0];
|
||||
memcpy(Cid->OEM_AppliID, cid_data + 1, 2);
|
||||
memcpy(Cid->ProdName, cid_data + 3, 5);
|
||||
Cid->ProdRev = cid_data[8];
|
||||
Cid->ProdSN = cid_data[9] << 24;
|
||||
Cid->ProdSN |= cid_data[10] << 16;
|
||||
Cid->ProdSN |= cid_data[11] << 8;
|
||||
Cid->ProdSN |= cid_data[12];
|
||||
Cid->Reserved1 = (cid_data[13] & 0xF0) >> 4;
|
||||
Cid->ManufactYear = (cid_data[13] & 0x0F) << 4;
|
||||
Cid->ManufactYear |= (cid_data[14] & 0xF0) >> 4;
|
||||
Cid->ManufactMonth = (cid_data[14] & 0x0F);
|
||||
Cid->CID_CRC = (cid_data[15] & 0xFE) >> 1;
|
||||
Cid->Reserved2 = 1;
|
||||
|
||||
ret = SdSpiStatusOK;
|
||||
}
|
||||
}
|
||||
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SdSpiStatus
|
||||
sd_spi_cmd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
|
||||
uint32_t block_address = address;
|
||||
uint32_t offset = 0;
|
||||
|
||||
// CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors)
|
||||
SdSpiCmdAnswer response =
|
||||
sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(response.r1 != SdSpi_R1_NO_ERROR) {
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
if(!sd_high_capacity) {
|
||||
block_address = address * SD_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
while(blocks--) {
|
||||
// CMD17 (READ_SINGLE_BLOCK): R1 response (0x00: no errors)
|
||||
response =
|
||||
sd_spi_send_cmd(SD_CMD17_READ_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
if(response.r1 != SdSpi_R1_NO_ERROR) {
|
||||
sd_spi_deselect_card_and_purge();
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
// Wait for the data start token
|
||||
if(sd_spi_wait_for_data(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ, timeout_ms) ==
|
||||
SdSpiStatusOK) {
|
||||
// Read the data block
|
||||
sd_spi_read_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE);
|
||||
sd_spi_purge_crc();
|
||||
|
||||
// increase offset
|
||||
offset += SD_BLOCK_SIZE;
|
||||
|
||||
// increase block address
|
||||
if(sd_high_capacity) {
|
||||
block_address += 1;
|
||||
} else {
|
||||
block_address += SD_BLOCK_SIZE;
|
||||
}
|
||||
} else {
|
||||
sd_spi_deselect_card_and_purge();
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
sd_spi_deselect_card_and_purge();
|
||||
}
|
||||
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
static SdSpiStatus sd_spi_cmd_write_blocks(
|
||||
uint32_t* data,
|
||||
uint32_t address,
|
||||
uint32_t blocks,
|
||||
uint32_t timeout_ms) {
|
||||
uint32_t block_address = address;
|
||||
uint32_t offset = 0;
|
||||
|
||||
// CMD16 (SET_BLOCKLEN): R1 response (0x00: no errors)
|
||||
SdSpiCmdAnswer response =
|
||||
sd_spi_send_cmd(SD_CMD16_SET_BLOCKLEN, SD_BLOCK_SIZE, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(response.r1 != SdSpi_R1_NO_ERROR) {
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
if(!sd_high_capacity) {
|
||||
block_address = address * SD_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
while(blocks--) {
|
||||
// CMD24 (WRITE_SINGLE_BLOCK): R1 response (0x00: no errors)
|
||||
response = sd_spi_send_cmd(
|
||||
SD_CMD24_WRITE_SINGLE_BLOCK, block_address, 0xFF, SdSpiCmdAnswerTypeR1);
|
||||
if(response.r1 != SdSpi_R1_NO_ERROR) {
|
||||
sd_spi_deselect_card_and_purge();
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
// Send dummy byte for NWR timing : one byte between CMD_WRITE and TOKEN
|
||||
// TODO: check bytes count
|
||||
sd_spi_write_byte(SD_DUMMY_BYTE);
|
||||
sd_spi_write_byte(SD_DUMMY_BYTE);
|
||||
|
||||
// Send the data start token
|
||||
sd_spi_write_byte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE);
|
||||
sd_spi_write_bytes_dma((uint8_t*)data + offset, SD_BLOCK_SIZE);
|
||||
sd_spi_purge_crc();
|
||||
|
||||
// Read data response
|
||||
SdSpiDataResponce data_responce = sd_spi_get_data_response(timeout_ms);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
if(data_responce != SdSpiDataResponceOK) {
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
// increase offset
|
||||
offset += SD_BLOCK_SIZE;
|
||||
|
||||
// increase block address
|
||||
if(sd_high_capacity) {
|
||||
block_address += 1;
|
||||
} else {
|
||||
block_address += SD_BLOCK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
uint8_t sd_max_mount_retry_count() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
SdSpiStatus sd_init(bool power_reset) {
|
||||
// Slow speed init
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow;
|
||||
|
||||
// We reset card in spi_lock context, so it is safe to disturb spi bus
|
||||
if(power_reset) {
|
||||
sd_spi_debug("Power reset");
|
||||
|
||||
// disable power and set low on all bus pins
|
||||
furi_hal_power_disable_external_3_3v();
|
||||
sd_spi_bus_to_ground();
|
||||
hal_sd_detect_set_low();
|
||||
furi_delay_ms(250);
|
||||
|
||||
// reinit bus and enable power
|
||||
sd_spi_bus_rise_up();
|
||||
hal_sd_detect_init();
|
||||
furi_hal_power_enable_external_3_3v();
|
||||
furi_delay_ms(100);
|
||||
}
|
||||
|
||||
SdSpiStatus status = SdSpiStatusError;
|
||||
|
||||
// Send 80 dummy clocks with CS high
|
||||
sd_spi_deselect_card();
|
||||
for(uint8_t i = 0; i < 80; i++) {
|
||||
sd_spi_write_byte(SD_DUMMY_BYTE);
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 128; i++) {
|
||||
status = sd_spi_init_spi_mode();
|
||||
if(status == SdSpiStatusOK) {
|
||||
// SD initialized and init to SPI mode properly
|
||||
sd_spi_debug("SD init OK after %d retries", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow);
|
||||
|
||||
// Init sector cache
|
||||
sector_cache_init();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SdSpiStatus sd_get_card_state(void) {
|
||||
SdSpiCmdAnswer response;
|
||||
|
||||
// Send CMD13 (SEND_STATUS) to get SD status
|
||||
response = sd_spi_send_cmd(SD_CMD13_SEND_STATUS, 0, 0xFF, SdSpiCmdAnswerTypeR2);
|
||||
sd_spi_deselect_card_and_purge();
|
||||
|
||||
// Return status OK if response is valid
|
||||
if((response.r1 == SdSpi_R1_NO_ERROR) && (response.r2 == SdSpi_R2_NO_ERROR)) {
|
||||
return SdSpiStatusOK;
|
||||
}
|
||||
|
||||
return SdSpiStatusError;
|
||||
}
|
||||
|
||||
SdSpiStatus sd_get_card_info(SD_CardInfo* card_info) {
|
||||
SdSpiStatus status;
|
||||
|
||||
status = sd_spi_get_csd(&(card_info->Csd));
|
||||
|
||||
if(status != SdSpiStatusOK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = sd_spi_get_cid(&(card_info->Cid));
|
||||
|
||||
if(status != SdSpiStatusOK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if(sd_high_capacity == 1) {
|
||||
card_info->LogBlockSize = 512;
|
||||
card_info->CardBlockSize = 512;
|
||||
card_info->CardCapacity = ((uint64_t)card_info->Csd.version.v2.DeviceSize + 1UL) * 1024UL *
|
||||
(uint64_t)card_info->LogBlockSize;
|
||||
card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize);
|
||||
} else {
|
||||
card_info->CardCapacity = (card_info->Csd.version.v1.DeviceSize + 1);
|
||||
card_info->CardCapacity *= (1UL << (card_info->Csd.version.v1.DeviceSizeMul + 2));
|
||||
card_info->LogBlockSize = 512;
|
||||
card_info->CardBlockSize = 1UL << (card_info->Csd.RdBlockLen);
|
||||
card_info->CardCapacity *= card_info->CardBlockSize;
|
||||
card_info->LogBlockNbr = (card_info->CardCapacity) / (card_info->LogBlockSize);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
SdSpiStatus
|
||||
sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
|
||||
SdSpiStatus status = sd_spi_cmd_read_blocks(data, address, blocks, timeout_ms);
|
||||
return status;
|
||||
}
|
||||
|
||||
SdSpiStatus
|
||||
sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms) {
|
||||
SdSpiStatus status = sd_spi_cmd_write_blocks(data, address, blocks, timeout_ms);
|
||||
return status;
|
||||
}
|
||||
|
||||
SdSpiStatus sd_get_cid(SD_CID* cid) {
|
||||
SdSpiStatus status;
|
||||
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
memset(cid, 0, sizeof(SD_CID));
|
||||
status = sd_spi_get_cid(cid);
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
#define SD_TIMEOUT_MS (1000)
|
||||
#define SD_BLOCK_SIZE 512
|
||||
|
||||
typedef enum {
|
||||
SdSpiStatusOK,
|
||||
SdSpiStatusError,
|
||||
SdSpiStatusTimeout,
|
||||
} SdSpiStatus;
|
||||
|
||||
/**
|
||||
* @brief Card Specific Data: CSD Register
|
||||
*/
|
||||
typedef struct {
|
||||
/* Header part */
|
||||
uint8_t CSDStruct : 2; /* CSD structure */
|
||||
uint8_t Reserved1 : 6; /* Reserved */
|
||||
uint8_t TAAC : 8; /* Data read access-time 1 */
|
||||
uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */
|
||||
uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */
|
||||
uint16_t CardComdClasses : 12; /* Card command classes */
|
||||
uint8_t RdBlockLen : 4; /* Max. read data block length */
|
||||
uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */
|
||||
uint8_t WrBlockMisalign : 1; /* Write block misalignment */
|
||||
uint8_t RdBlockMisalign : 1; /* Read block misalignment */
|
||||
uint8_t DSRImpl : 1; /* DSR implemented */
|
||||
|
||||
/* v1 or v2 struct */
|
||||
union csd_version {
|
||||
struct {
|
||||
uint8_t Reserved1 : 2; /* Reserved */
|
||||
uint16_t DeviceSize : 12; /* Device Size */
|
||||
uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */
|
||||
uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */
|
||||
uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */
|
||||
uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */
|
||||
uint8_t DeviceSizeMul : 3; /* Device size multiplier */
|
||||
} v1;
|
||||
struct {
|
||||
uint8_t Reserved1 : 6; /* Reserved */
|
||||
uint32_t DeviceSize : 22; /* Device Size */
|
||||
uint8_t Reserved2 : 1; /* Reserved */
|
||||
} v2;
|
||||
} version;
|
||||
|
||||
uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */
|
||||
uint8_t EraseSectorSize : 7; /* Erase group size multiplier */
|
||||
uint8_t WrProtectGrSize : 7; /* Write protect group size */
|
||||
uint8_t WrProtectGrEnable : 1; /* Write protect group enable */
|
||||
uint8_t Reserved2 : 2; /* Reserved */
|
||||
uint8_t WrSpeedFact : 3; /* Write speed factor */
|
||||
uint8_t MaxWrBlockLen : 4; /* Max. write data block length */
|
||||
uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */
|
||||
uint8_t Reserved3 : 5; /* Reserved */
|
||||
uint8_t FileFormatGrouop : 1; /* File format group */
|
||||
uint8_t CopyFlag : 1; /* Copy flag (OTP) */
|
||||
uint8_t PermWrProtect : 1; /* Permanent write protection */
|
||||
uint8_t TempWrProtect : 1; /* Temporary write protection */
|
||||
uint8_t FileFormat : 2; /* File Format */
|
||||
uint8_t Reserved4 : 2; /* Reserved */
|
||||
uint8_t crc : 7; /* Reserved */
|
||||
uint8_t Reserved5 : 1; /* always 1*/
|
||||
|
||||
} SD_CSD;
|
||||
|
||||
/**
|
||||
* @brief Card Identification Data: CID Register
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t ManufacturerID; /* ManufacturerID */
|
||||
char OEM_AppliID[2]; /* OEM/Application ID */
|
||||
char ProdName[5]; /* Product Name */
|
||||
uint8_t ProdRev; /* Product Revision */
|
||||
uint32_t ProdSN; /* Product Serial Number */
|
||||
uint8_t Reserved1; /* Reserved1 */
|
||||
uint8_t ManufactYear; /* Manufacturing Year */
|
||||
uint8_t ManufactMonth; /* Manufacturing Month */
|
||||
uint8_t CID_CRC; /* CID CRC */
|
||||
uint8_t Reserved2; /* always 1 */
|
||||
} SD_CID;
|
||||
|
||||
/**
|
||||
* @brief SD Card information structure
|
||||
*/
|
||||
typedef struct {
|
||||
SD_CSD Csd;
|
||||
SD_CID Cid;
|
||||
uint64_t CardCapacity; /*!< Card Capacity */
|
||||
uint32_t CardBlockSize; /*!< Card Block Size */
|
||||
uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */
|
||||
uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */
|
||||
} SD_CardInfo;
|
||||
|
||||
/**
|
||||
* @brief SD card max mount retry count
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t sd_max_mount_retry_count();
|
||||
|
||||
/**
|
||||
* @brief Init sd card
|
||||
*
|
||||
* @param power_reset reset card power
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus sd_init(bool power_reset);
|
||||
|
||||
/**
|
||||
* @brief Get card state
|
||||
*
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus sd_get_card_state(void);
|
||||
|
||||
/**
|
||||
* @brief Get card info
|
||||
*
|
||||
* @param card_info
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus sd_get_card_info(SD_CardInfo* card_info);
|
||||
|
||||
/**
|
||||
* @brief Read blocks
|
||||
*
|
||||
* @param data
|
||||
* @param address
|
||||
* @param blocks
|
||||
* @param timeout_ms
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus sd_read_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Write blocks
|
||||
*
|
||||
* @param data
|
||||
* @param address
|
||||
* @param blocks
|
||||
* @param timeout_ms
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus
|
||||
sd_write_blocks(uint32_t* data, uint32_t address, uint32_t blocks, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Get card CSD register
|
||||
*
|
||||
* @param Cid
|
||||
* @return SdSpiStatus
|
||||
*/
|
||||
SdSpiStatus sd_get_cid(SD_CID* cid);
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define N_SECTORS 8
|
||||
#define TAG "SDCache"
|
||||
|
||||
typedef struct {
|
||||
uint32_t itr;
|
||||
@@ -20,15 +19,11 @@ static SectorCache* cache = NULL;
|
||||
|
||||
void sector_cache_init() {
|
||||
if(cache == NULL) {
|
||||
// TODO: tuneup allocation order, to place cache in mem pool (MEM2)
|
||||
cache = memmgr_alloc_from_pool(sizeof(SectorCache));
|
||||
}
|
||||
|
||||
if(cache != NULL) {
|
||||
FURI_LOG_I(TAG, "Init");
|
||||
memset(cache, 0, sizeof(SectorCache));
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "Init failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define SD_DUMMY_BYTE 0xFF
|
||||
|
||||
const uint32_t SpiTimeout = 1000;
|
||||
uint8_t SD_IO_WriteByte(uint8_t Data);
|
||||
|
||||
/******************************************************************************
|
||||
BUS OPERATIONS
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief SPI Write byte(s) to device
|
||||
* @param DataIn: Pointer to data buffer to write
|
||||
* @param DataOut: Pointer to data buffer for read data
|
||||
* @param DataLength: number of bytes to write
|
||||
* @retval None
|
||||
*/
|
||||
static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
|
||||
furi_check(furi_hal_spi_bus_trx(
|
||||
furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI Write a byte to device
|
||||
* @param Value: value to be written
|
||||
* @retval None
|
||||
*/
|
||||
__attribute__((unused)) static void SPIx_Write(uint8_t Value) {
|
||||
furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
LINK OPERATIONS
|
||||
*******************************************************************************/
|
||||
|
||||
/********************************* LINK SD ************************************/
|
||||
/**
|
||||
* @brief Initialize the SD Card and put it into StandBy State (Ready for
|
||||
* data transfer).
|
||||
* @retval None
|
||||
*/
|
||||
void SD_IO_Init(void) {
|
||||
uint8_t counter = 0;
|
||||
|
||||
/* SD chip select high */
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
|
||||
furi_delay_us(10);
|
||||
|
||||
/* Send dummy byte 0xFF, 10 times with CS high */
|
||||
/* Rise CS and MOSI for 80 clocks cycles */
|
||||
for(counter = 0; counter <= 200; counter++) {
|
||||
/* Send dummy byte 0xFF */
|
||||
SD_IO_WriteByte(SD_DUMMY_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SD interface Chip Select state
|
||||
* @param val: 0 (low) or 1 (high) state
|
||||
* @retval None
|
||||
*/
|
||||
void SD_IO_CSState(uint8_t val) {
|
||||
/* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */
|
||||
if(val == 1) {
|
||||
furi_delay_us(10); // Exit guard time for some SD cards
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
|
||||
} else {
|
||||
furi_hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
|
||||
furi_delay_us(10); // Entry guard time for some SD cards
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write byte(s) on the SD
|
||||
* @param DataIn: Pointer to data buffer to write
|
||||
* @param DataOut: Pointer to data buffer for read data
|
||||
* @param DataLength: number of bytes to write
|
||||
* @retval None
|
||||
*/
|
||||
void SD_IO_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
|
||||
/* Send the byte */
|
||||
SPIx_WriteReadData(DataIn, DataOut, DataLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a byte on the SD.
|
||||
* @param Data: byte to send.
|
||||
* @retval Data written
|
||||
*/
|
||||
uint8_t SD_IO_WriteByte(uint8_t Data) {
|
||||
uint8_t tmp;
|
||||
|
||||
/* Send the byte */
|
||||
SPIx_WriteReadData(&Data, &tmp, 1);
|
||||
return tmp;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +0,0 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32_adafruit_sd.h
|
||||
* @author MCD Application Team
|
||||
* @version V3.0.0
|
||||
* @date 23-December-2016
|
||||
* @brief This file contains the common defines and functions prototypes for
|
||||
* the stm32_adafruit_sd.c driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of STMicroelectronics nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __STM32_ADAFRUIT_SD_H
|
||||
#define __STM32_ADAFRUIT_SD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/** @addtogroup BSP
|
||||
* @{
|
||||
*/
|
||||
#define __IO volatile
|
||||
|
||||
/** @addtogroup STM32_ADAFRUIT
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup STM32_ADAFRUIT_SD
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup STM32_ADAFRUIT_SD_Exported_Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SD status structure definition
|
||||
*/
|
||||
enum { BSP_SD_OK = 0x00, MSD_OK = 0x00, BSP_SD_ERROR = 0x01, BSP_SD_TIMEOUT };
|
||||
|
||||
typedef struct {
|
||||
uint8_t Reserved1 : 2; /* Reserved */
|
||||
uint16_t DeviceSize : 12; /* Device Size */
|
||||
uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */
|
||||
uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */
|
||||
uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */
|
||||
uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */
|
||||
uint8_t DeviceSizeMul : 3; /* Device size multiplier */
|
||||
} struct_v1;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Reserved1 : 6; /* Reserved */
|
||||
uint32_t DeviceSize : 22; /* Device Size */
|
||||
uint8_t Reserved2 : 1; /* Reserved */
|
||||
} struct_v2;
|
||||
|
||||
/**
|
||||
* @brief Card Specific Data: CSD Register
|
||||
*/
|
||||
typedef struct {
|
||||
/* Header part */
|
||||
uint8_t CSDStruct : 2; /* CSD structure */
|
||||
uint8_t Reserved1 : 6; /* Reserved */
|
||||
uint8_t TAAC : 8; /* Data read access-time 1 */
|
||||
uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */
|
||||
uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */
|
||||
uint16_t CardComdClasses : 12; /* Card command classes */
|
||||
uint8_t RdBlockLen : 4; /* Max. read data block length */
|
||||
uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */
|
||||
uint8_t WrBlockMisalign : 1; /* Write block misalignment */
|
||||
uint8_t RdBlockMisalign : 1; /* Read block misalignment */
|
||||
uint8_t DSRImpl : 1; /* DSR implemented */
|
||||
|
||||
/* v1 or v2 struct */
|
||||
union csd_version {
|
||||
struct_v1 v1;
|
||||
struct_v2 v2;
|
||||
} version;
|
||||
|
||||
uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */
|
||||
uint8_t EraseSectorSize : 7; /* Erase group size multiplier */
|
||||
uint8_t WrProtectGrSize : 7; /* Write protect group size */
|
||||
uint8_t WrProtectGrEnable : 1; /* Write protect group enable */
|
||||
uint8_t Reserved2 : 2; /* Reserved */
|
||||
uint8_t WrSpeedFact : 3; /* Write speed factor */
|
||||
uint8_t MaxWrBlockLen : 4; /* Max. write data block length */
|
||||
uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */
|
||||
uint8_t Reserved3 : 5; /* Reserved */
|
||||
uint8_t FileFormatGrouop : 1; /* File format group */
|
||||
uint8_t CopyFlag : 1; /* Copy flag (OTP) */
|
||||
uint8_t PermWrProtect : 1; /* Permanent write protection */
|
||||
uint8_t TempWrProtect : 1; /* Temporary write protection */
|
||||
uint8_t FileFormat : 2; /* File Format */
|
||||
uint8_t Reserved4 : 2; /* Reserved */
|
||||
uint8_t crc : 7; /* Reserved */
|
||||
uint8_t Reserved5 : 1; /* always 1*/
|
||||
|
||||
} SD_CSD;
|
||||
|
||||
/**
|
||||
* @brief Card Identification Data: CID Register
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t ManufacturerID; /* ManufacturerID */
|
||||
char OEM_AppliID[2]; /* OEM/Application ID */
|
||||
char ProdName[5]; /* Product Name */
|
||||
uint8_t ProdRev; /* Product Revision */
|
||||
uint32_t ProdSN; /* Product Serial Number */
|
||||
uint8_t Reserved1; /* Reserved1 */
|
||||
uint8_t ManufactYear; /* Manufacturing Year */
|
||||
uint8_t ManufactMonth; /* Manufacturing Month */
|
||||
uint8_t CID_CRC; /* CID CRC */
|
||||
uint8_t Reserved2; /* always 1 */
|
||||
} SD_CID;
|
||||
|
||||
/**
|
||||
* @brief SD Card information
|
||||
*/
|
||||
typedef struct {
|
||||
SD_CSD Csd;
|
||||
SD_CID Cid;
|
||||
uint64_t CardCapacity; /*!< Card Capacity */
|
||||
uint32_t CardBlockSize; /*!< Card Block Size */
|
||||
uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */
|
||||
uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */
|
||||
} SD_CardInfo;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup STM32_ADAFRUIT_SPI_SD_Exported_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Block Size
|
||||
*/
|
||||
#define SD_BLOCK_SIZE 0x200
|
||||
|
||||
/**
|
||||
* @brief SD detection on its memory slot
|
||||
*/
|
||||
#define SD_PRESENT ((uint8_t)0x01)
|
||||
#define SD_NOT_PRESENT ((uint8_t)0x00)
|
||||
|
||||
#define SD_DATATIMEOUT ((uint32_t)100000000)
|
||||
|
||||
/**
|
||||
* @brief SD Card information structure
|
||||
*/
|
||||
#define BSP_SD_CardInfo SD_CardInfo
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup STM32_ADAFRUIT_SD_Exported_Macro
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup STM32_ADAFRUIT_SD_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
uint8_t BSP_SD_MaxMountRetryCount();
|
||||
uint8_t BSP_SD_Init(bool reset_card);
|
||||
uint8_t
|
||||
BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout);
|
||||
uint8_t
|
||||
BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout);
|
||||
uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr);
|
||||
uint8_t BSP_SD_GetCardState(void);
|
||||
uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo);
|
||||
uint8_t BSP_SD_GetCIDRegister(SD_CID* Cid);
|
||||
|
||||
/* Link functions for SD Card peripheral*/
|
||||
void SD_SPI_Slow_Init(void);
|
||||
void SD_SPI_Fast_Init(void);
|
||||
void SD_IO_Init(void);
|
||||
void SD_IO_CSState(uint8_t state);
|
||||
void SD_IO_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength);
|
||||
uint8_t SD_IO_WriteByte(uint8_t Data);
|
||||
|
||||
/* Link function for HAL delay */
|
||||
void HAL_Delay(__IO uint32_t Delay);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __STM32_ADAFRUIT_SD_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
@@ -1,116 +0,0 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Sample code of OS dependent controls for FatFs */
|
||||
/* (C)ChaN, 2014 */
|
||||
/* Portions COPYRIGHT 2017 STMicroelectronics */
|
||||
/* Portions Copyright (C) 2014, ChaN, all right reserved */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics. All rights reserved.
|
||||
*
|
||||
* This software component is licensed by ST under BSD 3-Clause license,
|
||||
* the "License"; You may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at:
|
||||
* opensource.org/licenses/BSD-3-Clause
|
||||
*
|
||||
******************************************************************************
|
||||
**/
|
||||
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
#if _FS_REENTRANT
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Create a Synchronization Object */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to create a new
|
||||
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
|
||||
/ the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
int ff_cre_syncobj(/* 1:Function succeeded, 0:Could not create the sync object */
|
||||
BYTE vol, /* Corresponding volume (logical drive number) */
|
||||
_SYNC_t* sobj /* Pointer to return the created sync object */
|
||||
) {
|
||||
int ret;
|
||||
|
||||
//osSemaphoreDef(SEM);
|
||||
//*sobj = osSemaphoreCreate(osSemaphore(SEM), 1);
|
||||
*sobj = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
ret = (*sobj != NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Delete a Synchronization Object */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to delete a synchronization
|
||||
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
|
||||
/ the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
int ff_del_syncobj(/* 1:Function succeeded, 0:Could not delete due to any error */
|
||||
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
|
||||
) {
|
||||
furi_mutex_free(sobj);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Request Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on entering file functions to lock the volume.
|
||||
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
|
||||
*/
|
||||
|
||||
int ff_req_grant(/* 1:Got a grant to access the volume, 0:Could not get a grant */
|
||||
_SYNC_t sobj /* Sync object to wait */
|
||||
) {
|
||||
int ret = 0;
|
||||
|
||||
if(furi_mutex_acquire(sobj, _FS_TIMEOUT) == FuriStatusOk) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Release Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on leaving file functions to unlock the volume.
|
||||
*/
|
||||
|
||||
void ff_rel_grant(_SYNC_t sobj /* Sync object to be signaled */
|
||||
) {
|
||||
furi_mutex_release(sobj);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
|
||||
*/
|
||||
|
||||
void* ff_memalloc(/* Returns pointer to the allocated memory block */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
) {
|
||||
return ff_malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Free a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree(void* mblock /* Pointer to the memory block to free */
|
||||
) {
|
||||
ff_free(mblock); /* Discard the memory block with POSIX API */
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,103 +1,121 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file user_diskio.c
|
||||
* @brief This file includes a diskio driver skeleton to be completed by the user.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
|
||||
/*
|
||||
* Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
|
||||
* To be suppressed in the future.
|
||||
* Kept to ensure backward compatibility with previous CubeMx versions when
|
||||
* migrating projects.
|
||||
* User code previously added there should be copied in the new user sections before
|
||||
* the section contents can be deleted.
|
||||
*/
|
||||
/* USER CODE BEGIN 0 */
|
||||
/* USER CODE END 0 */
|
||||
#endif
|
||||
|
||||
/* USER CODE BEGIN DECL */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "user_diskio.h"
|
||||
#include <furi_hal.h>
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#include "sector_cache.h"
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Disk status */
|
||||
static volatile DSTATUS Stat = STA_NOINIT;
|
||||
|
||||
static DSTATUS User_CheckStatus(BYTE lun) {
|
||||
static DSTATUS driver_check_status(BYTE lun) {
|
||||
UNUSED(lun);
|
||||
Stat = STA_NOINIT;
|
||||
if(BSP_SD_GetCardState() == MSD_OK) {
|
||||
if(sd_get_card_state() == SdSpiStatusOK) {
|
||||
Stat &= ~STA_NOINIT;
|
||||
}
|
||||
|
||||
return Stat;
|
||||
}
|
||||
|
||||
/* USER CODE END DECL */
|
||||
static DSTATUS driver_initialize(BYTE pdrv);
|
||||
static DSTATUS driver_status(BYTE pdrv);
|
||||
static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
||||
static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
||||
static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff);
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
DSTATUS USER_initialize(BYTE pdrv);
|
||||
DSTATUS USER_status(BYTE pdrv);
|
||||
DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
||||
#if _USE_WRITE == 1
|
||||
DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
||||
#endif /* _USE_WRITE == 1 */
|
||||
#if _USE_IOCTL == 1
|
||||
DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff);
|
||||
#endif /* _USE_IOCTL == 1 */
|
||||
|
||||
Diskio_drvTypeDef USER_Driver = {
|
||||
USER_initialize,
|
||||
USER_status,
|
||||
USER_read,
|
||||
#if _USE_WRITE
|
||||
USER_write,
|
||||
#endif /* _USE_WRITE == 1 */
|
||||
#if _USE_IOCTL == 1
|
||||
USER_ioctl,
|
||||
#endif /* _USE_IOCTL == 1 */
|
||||
Diskio_drvTypeDef sd_fatfs_driver = {
|
||||
driver_initialize,
|
||||
driver_status,
|
||||
driver_read,
|
||||
driver_write,
|
||||
driver_ioctl,
|
||||
};
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
static inline bool sd_cache_get(uint32_t address, uint32_t* data) {
|
||||
uint8_t* cached_data = sector_cache_get(address);
|
||||
if(cached_data) {
|
||||
memcpy(data, cached_data, SD_BLOCK_SIZE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void sd_cache_put(uint32_t address, uint32_t* data) {
|
||||
sector_cache_put(address, (uint8_t*)data);
|
||||
}
|
||||
|
||||
static inline void sd_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) {
|
||||
sector_cache_invalidate_range(start_sector, end_sector);
|
||||
}
|
||||
|
||||
static inline void sd_cache_invalidate_all() {
|
||||
sector_cache_init();
|
||||
}
|
||||
|
||||
static bool sd_device_read(uint32_t* buff, uint32_t sector, uint32_t count) {
|
||||
bool result = false;
|
||||
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
if(sd_read_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
|
||||
|
||||
/* wait until the read operation is finished */
|
||||
result = true;
|
||||
while(sd_get_card_state() != SdSpiStatusOK) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool sd_device_write(uint32_t* buff, uint32_t sector, uint32_t count) {
|
||||
bool result = false;
|
||||
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
if(sd_write_blocks(buff, sector, count, SD_TIMEOUT_MS) == SdSpiStatusOK) {
|
||||
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(SD_TIMEOUT_MS * 1000);
|
||||
|
||||
/* wait until the Write operation is finished */
|
||||
result = true;
|
||||
while(sd_get_card_state() != SdSpiStatusOK) {
|
||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||
sd_cache_invalidate_all();
|
||||
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes a Drive
|
||||
* @param pdrv: Physical drive number (0..)
|
||||
* @retval DSTATUS: Operation status
|
||||
*/
|
||||
DSTATUS USER_initialize(BYTE pdrv) {
|
||||
/* USER CODE BEGIN INIT */
|
||||
|
||||
static DSTATUS driver_initialize(BYTE pdrv) {
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
DSTATUS status = User_CheckStatus(pdrv);
|
||||
DSTATUS status = driver_check_status(pdrv);
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return status;
|
||||
/* USER CODE END INIT */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,11 +123,9 @@ DSTATUS USER_initialize(BYTE pdrv) {
|
||||
* @param pdrv: Physical drive number (0..)
|
||||
* @retval DSTATUS: Operation status
|
||||
*/
|
||||
DSTATUS USER_status(BYTE pdrv) {
|
||||
/* USER CODE BEGIN STATUS */
|
||||
static DSTATUS driver_status(BYTE pdrv) {
|
||||
UNUSED(pdrv);
|
||||
return Stat;
|
||||
/* USER CODE END STATUS */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,26 +136,45 @@ DSTATUS USER_status(BYTE pdrv) {
|
||||
* @param count: Number of sectors to read (1..128)
|
||||
* @retval DRESULT: Operation result
|
||||
*/
|
||||
DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
|
||||
/* USER CODE BEGIN READ */
|
||||
static DRESULT driver_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
|
||||
UNUSED(pdrv);
|
||||
DRESULT res = RES_ERROR;
|
||||
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
bool result;
|
||||
bool single_sector = count == 1;
|
||||
|
||||
if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
|
||||
/* wait until the read operation is finished */
|
||||
while(BSP_SD_GetCardState() != MSD_OK) {
|
||||
if(single_sector) {
|
||||
if(sd_cache_get(sector, (uint32_t*)buff)) {
|
||||
return RES_OK;
|
||||
}
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
|
||||
|
||||
return res;
|
||||
/* USER CODE END READ */
|
||||
if(!result) {
|
||||
uint8_t counter = sd_max_mount_retry_count();
|
||||
|
||||
while(result == false && counter > 0 && hal_sd_detect()) {
|
||||
SdSpiStatus status;
|
||||
|
||||
if((counter % 2) == 0) {
|
||||
// power reset sd card
|
||||
status = sd_init(true);
|
||||
} else {
|
||||
status = sd_init(false);
|
||||
}
|
||||
|
||||
if(status == SdSpiStatusOK) {
|
||||
result = sd_device_read((uint32_t*)buff, (uint32_t)(sector), count);
|
||||
}
|
||||
counter--;
|
||||
}
|
||||
}
|
||||
|
||||
if(single_sector && result == true) {
|
||||
sd_cache_put(sector, (uint32_t*)buff);
|
||||
}
|
||||
|
||||
return result ? RES_OK : RES_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,30 +185,36 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
|
||||
* @param count: Number of sectors to write (1..128)
|
||||
* @retval DRESULT: Operation result
|
||||
*/
|
||||
#if _USE_WRITE == 1
|
||||
DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
|
||||
/* USER CODE BEGIN WRITE */
|
||||
/* USER CODE HERE */
|
||||
static DRESULT driver_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
|
||||
UNUSED(pdrv);
|
||||
DRESULT res = RES_ERROR;
|
||||
bool result;
|
||||
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
|
||||
sd_cache_invalidate_range(sector, sector + count);
|
||||
|
||||
if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
|
||||
/* wait until the Write operation is finished */
|
||||
while(BSP_SD_GetCardState() != MSD_OK) {
|
||||
result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
|
||||
|
||||
if(!result) {
|
||||
uint8_t counter = sd_max_mount_retry_count();
|
||||
|
||||
while(result == false && counter > 0 && hal_sd_detect()) {
|
||||
SdSpiStatus status;
|
||||
|
||||
if((counter % 2) == 0) {
|
||||
// power reset sd card
|
||||
status = sd_init(true);
|
||||
} else {
|
||||
status = sd_init(false);
|
||||
}
|
||||
|
||||
if(status == SdSpiStatusOK) {
|
||||
result = sd_device_write((uint32_t*)buff, (uint32_t)(sector), count);
|
||||
}
|
||||
counter--;
|
||||
}
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
furi_hal_sd_spi_handle = NULL;
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return res;
|
||||
/* USER CODE END WRITE */
|
||||
return result ? RES_OK : RES_ERROR;
|
||||
}
|
||||
#endif /* _USE_WRITE == 1 */
|
||||
|
||||
/**
|
||||
* @brief I/O control operation
|
||||
@@ -182,12 +223,10 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
|
||||
* @param *buff: Buffer to send/receive control data
|
||||
* @retval DRESULT: Operation result
|
||||
*/
|
||||
#if _USE_IOCTL == 1
|
||||
DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
|
||||
/* USER CODE BEGIN IOCTL */
|
||||
static DRESULT driver_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
|
||||
UNUSED(pdrv);
|
||||
DRESULT res = RES_ERROR;
|
||||
BSP_SD_CardInfo CardInfo;
|
||||
SD_CardInfo CardInfo;
|
||||
|
||||
if(Stat & STA_NOINIT) return RES_NOTRDY;
|
||||
|
||||
@@ -202,21 +241,21 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
|
||||
|
||||
/* Get number of sectors on the disk (DWORD) */
|
||||
case GET_SECTOR_COUNT:
|
||||
BSP_SD_GetCardInfo(&CardInfo);
|
||||
sd_get_card_info(&CardInfo);
|
||||
*(DWORD*)buff = CardInfo.LogBlockNbr;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
/* Get R/W sector size (WORD) */
|
||||
case GET_SECTOR_SIZE:
|
||||
BSP_SD_GetCardInfo(&CardInfo);
|
||||
sd_get_card_info(&CardInfo);
|
||||
*(WORD*)buff = CardInfo.LogBlockSize;
|
||||
res = RES_OK;
|
||||
break;
|
||||
|
||||
/* Get erase block size in unit of sector (DWORD) */
|
||||
case GET_BLOCK_SIZE:
|
||||
BSP_SD_GetCardInfo(&CardInfo);
|
||||
sd_get_card_info(&CardInfo);
|
||||
*(DWORD*)buff = CardInfo.LogBlockSize;
|
||||
res = RES_OK;
|
||||
break;
|
||||
@@ -229,8 +268,4 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
|
||||
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
|
||||
|
||||
return res;
|
||||
/* USER CODE END IOCTL */
|
||||
}
|
||||
#endif /* _USE_IOCTL == 1 */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
||||
@@ -1,48 +1,14 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file user_diskio.h
|
||||
* @brief This file contains the common defines and functions prototypes for
|
||||
* the user_diskio driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USER_DISKIO_H
|
||||
#define __USER_DISKIO_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* USER CODE BEGIN 0 */
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32_adafruit_sd.h"
|
||||
#include "sd_spi_io.h"
|
||||
#include "fatfs/ff_gen_drv.h"
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
extern Diskio_drvTypeDef USER_Driver;
|
||||
|
||||
/* USER CODE END 0 */
|
||||
extern Diskio_drvTypeDef sd_fatfs_driver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USER_DISKIO_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
#endif
|
||||
@@ -4,35 +4,24 @@
|
||||
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
|
||||
#include <fatfs.h>
|
||||
|
||||
#define TAG "FuriHal"
|
||||
|
||||
void furi_hal_init_early() {
|
||||
furi_hal_cortex_init_early();
|
||||
|
||||
furi_hal_clock_init_early();
|
||||
|
||||
furi_hal_resources_init_early();
|
||||
|
||||
furi_hal_os_init();
|
||||
|
||||
furi_hal_spi_init_early();
|
||||
|
||||
furi_hal_spi_config_init_early();
|
||||
furi_hal_i2c_init_early();
|
||||
furi_hal_light_init();
|
||||
|
||||
furi_hal_rtc_init_early();
|
||||
}
|
||||
|
||||
void furi_hal_deinit_early() {
|
||||
furi_hal_rtc_deinit_early();
|
||||
|
||||
furi_hal_i2c_deinit_early();
|
||||
furi_hal_spi_deinit_early();
|
||||
|
||||
furi_hal_spi_config_deinit_early();
|
||||
furi_hal_resources_deinit_early();
|
||||
|
||||
furi_hal_clock_deinit_early();
|
||||
}
|
||||
|
||||
@@ -41,49 +30,29 @@ void furi_hal_init() {
|
||||
furi_hal_clock_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_rtc_init();
|
||||
|
||||
furi_hal_interrupt_init();
|
||||
|
||||
furi_hal_flash_init();
|
||||
|
||||
furi_hal_resources_init();
|
||||
FURI_LOG_I(TAG, "GPIO OK");
|
||||
|
||||
furi_hal_version_init();
|
||||
furi_hal_region_init();
|
||||
|
||||
furi_hal_spi_init();
|
||||
|
||||
furi_hal_spi_config_init();
|
||||
furi_hal_spi_dma_init();
|
||||
furi_hal_ibutton_init();
|
||||
FURI_LOG_I(TAG, "iButton OK");
|
||||
furi_hal_speaker_init();
|
||||
FURI_LOG_I(TAG, "Speaker OK");
|
||||
|
||||
furi_hal_crypto_init();
|
||||
|
||||
furi_hal_i2c_init();
|
||||
|
||||
// High Level
|
||||
furi_hal_power_init();
|
||||
furi_hal_light_init();
|
||||
|
||||
furi_hal_bt_init();
|
||||
furi_hal_memory_init();
|
||||
furi_hal_compress_icon_init();
|
||||
|
||||
#ifndef FURI_RAM_EXEC
|
||||
// USB
|
||||
furi_hal_usb_init();
|
||||
FURI_LOG_I(TAG, "USB OK");
|
||||
furi_hal_vibro_init();
|
||||
furi_hal_subghz_init();
|
||||
furi_hal_nfc_init();
|
||||
furi_hal_rfid_init();
|
||||
#endif
|
||||
|
||||
// FatFS driver initialization
|
||||
MX_FATFS_Init();
|
||||
FURI_LOG_I(TAG, "FATFS OK");
|
||||
}
|
||||
|
||||
void furi_hal_switch(void* address) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "furi_hal_bt_hid.h"
|
||||
#include "furi_hal_usb_hid.h"
|
||||
#include <furi_hal_bt_hid.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include "usb_hid.h"
|
||||
#include "dev_info_service.h"
|
||||
#include "battery_service.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_bt_serial.h"
|
||||
#include <furi_hal_bt_serial.h>
|
||||
#include "dev_info_service.h"
|
||||
#include "battery_service.h"
|
||||
#include "serial_service.h"
|
||||
|
||||
@@ -1,264 +0,0 @@
|
||||
#include <furi_hal_compress.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <lib/heatshrink/heatshrink_encoder.h>
|
||||
#include <lib/heatshrink/heatshrink_decoder.h>
|
||||
|
||||
#define TAG "FuriHalCompress"
|
||||
|
||||
#define FURI_HAL_COMPRESS_ICON_ENCODED_BUFF_SIZE (2 * 512)
|
||||
#define FURI_HAL_COMPRESS_ICON_DECODED_BUFF_SIZE (1024)
|
||||
|
||||
#define FURI_HAL_COMPRESS_EXP_BUFF_SIZE (1 << FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG)
|
||||
|
||||
typedef struct {
|
||||
uint8_t is_compressed;
|
||||
uint8_t reserved;
|
||||
uint16_t compressed_buff_size;
|
||||
} FuriHalCompressHeader;
|
||||
|
||||
typedef struct {
|
||||
heatshrink_decoder* decoder;
|
||||
uint8_t
|
||||
compress_buff[FURI_HAL_COMPRESS_EXP_BUFF_SIZE + FURI_HAL_COMPRESS_ICON_ENCODED_BUFF_SIZE];
|
||||
uint8_t decoded_buff[FURI_HAL_COMPRESS_ICON_DECODED_BUFF_SIZE];
|
||||
} FuriHalCompressIcon;
|
||||
|
||||
struct FuriHalCompress {
|
||||
heatshrink_encoder* encoder;
|
||||
heatshrink_decoder* decoder;
|
||||
uint8_t* compress_buff;
|
||||
uint16_t compress_buff_size;
|
||||
};
|
||||
|
||||
static FuriHalCompressIcon* icon_decoder;
|
||||
|
||||
static void furi_hal_compress_reset(FuriHalCompress* compress) {
|
||||
furi_assert(compress);
|
||||
heatshrink_encoder_reset(compress->encoder);
|
||||
heatshrink_decoder_reset(compress->decoder);
|
||||
memset(compress->compress_buff, 0, compress->compress_buff_size);
|
||||
}
|
||||
|
||||
void furi_hal_compress_icon_init() {
|
||||
icon_decoder = malloc(sizeof(FuriHalCompressIcon));
|
||||
icon_decoder->decoder = heatshrink_decoder_alloc(
|
||||
icon_decoder->compress_buff,
|
||||
FURI_HAL_COMPRESS_ICON_ENCODED_BUFF_SIZE,
|
||||
FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG,
|
||||
FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG);
|
||||
heatshrink_decoder_reset(icon_decoder->decoder);
|
||||
memset(icon_decoder->decoded_buff, 0, sizeof(icon_decoder->decoded_buff));
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
void furi_hal_compress_icon_decode(const uint8_t* icon_data, uint8_t** decoded_buff) {
|
||||
furi_assert(icon_data);
|
||||
furi_assert(decoded_buff);
|
||||
|
||||
FuriHalCompressHeader* header = (FuriHalCompressHeader*)icon_data;
|
||||
if(header->is_compressed) {
|
||||
size_t data_processed = 0;
|
||||
heatshrink_decoder_sink(
|
||||
icon_decoder->decoder,
|
||||
(uint8_t*)&icon_data[4],
|
||||
header->compressed_buff_size,
|
||||
&data_processed);
|
||||
while(1) {
|
||||
HSD_poll_res res = heatshrink_decoder_poll(
|
||||
icon_decoder->decoder,
|
||||
icon_decoder->decoded_buff,
|
||||
sizeof(icon_decoder->decoded_buff),
|
||||
&data_processed);
|
||||
furi_assert((res == HSDR_POLL_EMPTY) || (res == HSDR_POLL_MORE));
|
||||
if(res != HSDR_POLL_MORE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
heatshrink_decoder_reset(icon_decoder->decoder);
|
||||
memset(icon_decoder->compress_buff, 0, sizeof(icon_decoder->compress_buff));
|
||||
*decoded_buff = icon_decoder->decoded_buff;
|
||||
} else {
|
||||
*decoded_buff = (uint8_t*)&icon_data[1];
|
||||
}
|
||||
}
|
||||
|
||||
FuriHalCompress* furi_hal_compress_alloc(uint16_t compress_buff_size) {
|
||||
FuriHalCompress* compress = malloc(sizeof(FuriHalCompress));
|
||||
compress->compress_buff = malloc(compress_buff_size + FURI_HAL_COMPRESS_EXP_BUFF_SIZE);
|
||||
compress->encoder = heatshrink_encoder_alloc(
|
||||
compress->compress_buff,
|
||||
FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG,
|
||||
FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG);
|
||||
compress->decoder = heatshrink_decoder_alloc(
|
||||
compress->compress_buff,
|
||||
compress_buff_size,
|
||||
FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG,
|
||||
FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG);
|
||||
|
||||
return compress;
|
||||
}
|
||||
|
||||
void furi_hal_compress_free(FuriHalCompress* compress) {
|
||||
furi_assert(compress);
|
||||
|
||||
heatshrink_encoder_free(compress->encoder);
|
||||
heatshrink_decoder_free(compress->decoder);
|
||||
free(compress->compress_buff);
|
||||
free(compress);
|
||||
}
|
||||
|
||||
bool furi_hal_compress_encode(
|
||||
FuriHalCompress* compress,
|
||||
uint8_t* data_in,
|
||||
size_t data_in_size,
|
||||
uint8_t* data_out,
|
||||
size_t data_out_size,
|
||||
size_t* data_res_size) {
|
||||
furi_assert(compress);
|
||||
furi_assert(data_in);
|
||||
furi_assert(data_in_size);
|
||||
|
||||
size_t sink_size = 0;
|
||||
size_t poll_size = 0;
|
||||
HSE_sink_res sink_res;
|
||||
HSE_poll_res poll_res;
|
||||
HSE_finish_res finish_res;
|
||||
bool encode_failed = false;
|
||||
size_t sunk = 0;
|
||||
size_t res_buff_size = sizeof(FuriHalCompressHeader);
|
||||
|
||||
// Sink data to encoding buffer
|
||||
while((sunk < data_in_size) && !encode_failed) {
|
||||
sink_res = heatshrink_encoder_sink(
|
||||
compress->encoder, &data_in[sunk], data_in_size - sunk, &sink_size);
|
||||
if(sink_res != HSER_SINK_OK) {
|
||||
encode_failed = true;
|
||||
break;
|
||||
}
|
||||
sunk += sink_size;
|
||||
do {
|
||||
poll_res = heatshrink_encoder_poll(
|
||||
compress->encoder,
|
||||
&data_out[res_buff_size],
|
||||
data_out_size - res_buff_size,
|
||||
&poll_size);
|
||||
if(poll_res < 0) {
|
||||
encode_failed = true;
|
||||
break;
|
||||
}
|
||||
res_buff_size += poll_size;
|
||||
} while(poll_res == HSER_POLL_MORE);
|
||||
}
|
||||
|
||||
// Notify sinking complete and poll encoded data
|
||||
finish_res = heatshrink_encoder_finish(compress->encoder);
|
||||
if(finish_res < 0) {
|
||||
encode_failed = true;
|
||||
} else {
|
||||
do {
|
||||
poll_res = heatshrink_encoder_poll(
|
||||
compress->encoder,
|
||||
&data_out[res_buff_size],
|
||||
data_out_size - 4 - res_buff_size,
|
||||
&poll_size);
|
||||
if(poll_res < 0) {
|
||||
encode_failed = true;
|
||||
break;
|
||||
}
|
||||
res_buff_size += poll_size;
|
||||
finish_res = heatshrink_encoder_finish(compress->encoder);
|
||||
} while(finish_res != HSER_FINISH_DONE);
|
||||
}
|
||||
|
||||
bool result = true;
|
||||
// Write encoded data to output buffer if compression is efficient. Else - write header and original data
|
||||
if(!encode_failed && (res_buff_size < data_in_size + 1)) {
|
||||
FuriHalCompressHeader header = {
|
||||
.is_compressed = 0x01, .reserved = 0x00, .compressed_buff_size = res_buff_size};
|
||||
memcpy(data_out, &header, sizeof(header));
|
||||
*data_res_size = res_buff_size;
|
||||
} else if(data_out_size > data_in_size) {
|
||||
data_out[0] = 0x00;
|
||||
memcpy(&data_out[1], data_in, data_in_size);
|
||||
*data_res_size = data_in_size + 1;
|
||||
} else {
|
||||
*data_res_size = 0;
|
||||
result = false;
|
||||
}
|
||||
furi_hal_compress_reset(compress);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool furi_hal_compress_decode(
|
||||
FuriHalCompress* compress,
|
||||
uint8_t* data_in,
|
||||
size_t data_in_size,
|
||||
uint8_t* data_out,
|
||||
size_t data_out_size,
|
||||
size_t* data_res_size) {
|
||||
furi_assert(compress);
|
||||
furi_assert(data_in);
|
||||
furi_assert(data_out);
|
||||
furi_assert(data_res_size);
|
||||
|
||||
bool result = false;
|
||||
bool decode_failed = false;
|
||||
HSD_sink_res sink_res;
|
||||
HSD_poll_res poll_res;
|
||||
HSD_finish_res finish_res;
|
||||
size_t sink_size = 0;
|
||||
size_t res_buff_size = 0;
|
||||
size_t poll_size = 0;
|
||||
|
||||
FuriHalCompressHeader* header = (FuriHalCompressHeader*)data_in;
|
||||
if(header->is_compressed) {
|
||||
// Sink data to decoding buffer
|
||||
size_t compressed_size = header->compressed_buff_size;
|
||||
size_t sunk = sizeof(FuriHalCompressHeader);
|
||||
while(sunk < compressed_size && !decode_failed) {
|
||||
sink_res = heatshrink_decoder_sink(
|
||||
compress->decoder, &data_in[sunk], compressed_size - sunk, &sink_size);
|
||||
if(sink_res < 0) {
|
||||
decode_failed = true;
|
||||
break;
|
||||
}
|
||||
sunk += sink_size;
|
||||
do {
|
||||
poll_res = heatshrink_decoder_poll(
|
||||
compress->decoder, &data_out[res_buff_size], data_out_size, &poll_size);
|
||||
if(poll_res < 0) {
|
||||
decode_failed = true;
|
||||
break;
|
||||
}
|
||||
res_buff_size += poll_size;
|
||||
} while(poll_res == HSDR_POLL_MORE);
|
||||
}
|
||||
// Notify sinking complete and poll decoded data
|
||||
if(!decode_failed) {
|
||||
finish_res = heatshrink_decoder_finish(compress->decoder);
|
||||
if(finish_res < 0) {
|
||||
decode_failed = true;
|
||||
} else {
|
||||
do {
|
||||
poll_res = heatshrink_decoder_poll(
|
||||
compress->decoder, &data_out[res_buff_size], data_out_size, &poll_size);
|
||||
res_buff_size += poll_size;
|
||||
finish_res = heatshrink_decoder_finish(compress->decoder);
|
||||
} while(finish_res != HSDR_FINISH_DONE);
|
||||
}
|
||||
}
|
||||
*data_res_size = res_buff_size;
|
||||
result = !decode_failed;
|
||||
} else if(data_out_size >= data_in_size - 1) {
|
||||
memcpy(data_out, &data_in[1], data_in_size);
|
||||
*data_res_size = data_in_size - 1;
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
furi_hal_compress_reset(compress);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_cortex.h"
|
||||
#include <furi_hal_cortex.h>
|
||||
|
||||
#include <stm32wbxx.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <stm32wbxx_ll_comp.h>
|
||||
|
||||
#define GET_SYSCFG_EXTI_PORT(gpio) \
|
||||
@@ -224,85 +225,85 @@ static void furi_hal_gpio_int_call(uint16_t pin_num) {
|
||||
/* Interrupt handlers */
|
||||
void EXTI0_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_0)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
|
||||
furi_hal_gpio_int_call(0);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI1_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_1)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1);
|
||||
furi_hal_gpio_int_call(1);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_1);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI2_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_2)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
|
||||
furi_hal_gpio_int_call(2);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_2);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI3_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_3)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3);
|
||||
furi_hal_gpio_int_call(3);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_3);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI4_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_4)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4);
|
||||
furi_hal_gpio_int_call(4);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_4);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI9_5_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_5)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
|
||||
furi_hal_gpio_int_call(5);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_5);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
|
||||
furi_hal_gpio_int_call(6);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_7)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7);
|
||||
furi_hal_gpio_int_call(7);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_7);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_8)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8);
|
||||
furi_hal_gpio_int_call(8);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_8);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
|
||||
furi_hal_gpio_int_call(9);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
|
||||
}
|
||||
}
|
||||
|
||||
void EXTI15_10_IRQHandler(void) {
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_10)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10);
|
||||
furi_hal_gpio_int_call(10);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_10);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_11)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11);
|
||||
furi_hal_gpio_int_call(11);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_11);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_12)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12);
|
||||
furi_hal_gpio_int_call(12);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_12);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13);
|
||||
furi_hal_gpio_int_call(13);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_14)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14);
|
||||
furi_hal_gpio_int_call(14);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_14);
|
||||
}
|
||||
if(LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_15)) {
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15);
|
||||
furi_hal_gpio_int_call(15);
|
||||
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_15);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_i2c_config.h"
|
||||
#include <furi_hal_i2c_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalIbutton"
|
||||
#define FURI_HAL_IBUTTON_TIMER TIM1
|
||||
#define FURI_HAL_IBUTTON_TIMER_IRQ FuriHalInterruptIdTim1UpTim16
|
||||
|
||||
@@ -33,6 +34,8 @@ static void furi_hal_ibutton_emulate_isr() {
|
||||
void furi_hal_ibutton_init() {
|
||||
furi_hal_ibutton = malloc(sizeof(FuriHalIbutton));
|
||||
furi_hal_ibutton->state = FuriHalIbuttonStateIdle;
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_emulate_start(
|
||||
@@ -89,47 +92,16 @@ void furi_hal_ibutton_emulate_stop() {
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_start_drive() {
|
||||
furi_hal_ibutton_pin_high();
|
||||
void furi_hal_ibutton_pin_configure() {
|
||||
furi_hal_gpio_write(&ibutton_gpio, true);
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_start_drive_in_isr() {
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow);
|
||||
LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_start_interrupt() {
|
||||
furi_hal_ibutton_pin_high();
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_start_interrupt_in_isr() {
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow);
|
||||
LL_EXTI_ClearFlag_0_31(ibutton_gpio.pin);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_stop() {
|
||||
furi_hal_ibutton_pin_high();
|
||||
void furi_hal_ibutton_pin_reset() {
|
||||
furi_hal_gpio_write(&ibutton_gpio, true);
|
||||
furi_hal_gpio_init(&ibutton_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context) {
|
||||
furi_hal_gpio_add_int_callback(&ibutton_gpio, cb, context);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_remove_interrupt() {
|
||||
furi_hal_gpio_remove_int_callback(&ibutton_gpio);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_pin_low() {
|
||||
furi_hal_gpio_write(&ibutton_gpio, false);
|
||||
}
|
||||
|
||||
void furi_hal_ibutton_pin_high() {
|
||||
furi_hal_gpio_write(&ibutton_gpio, true);
|
||||
}
|
||||
|
||||
bool furi_hal_ibutton_pin_get_level() {
|
||||
return furi_hal_gpio_read(&ibutton_gpio);
|
||||
void furi_hal_ibutton_pin_write(const bool state) {
|
||||
furi_hal_gpio_write(&ibutton_gpio, state);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file furi_hal_ibutton.h
|
||||
* iButton HAL API
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*FuriHalIbuttonEmulateCallback)(void* context);
|
||||
|
||||
/** Initialize */
|
||||
void furi_hal_ibutton_init();
|
||||
|
||||
/**
|
||||
* Start emulation timer
|
||||
* @param period timer period
|
||||
* @param callback timer callback
|
||||
* @param context callback context
|
||||
*/
|
||||
void furi_hal_ibutton_emulate_start(
|
||||
uint32_t period,
|
||||
FuriHalIbuttonEmulateCallback callback,
|
||||
void* context);
|
||||
|
||||
/**
|
||||
* Update emulation timer period
|
||||
* @param period new timer period
|
||||
*/
|
||||
void furi_hal_ibutton_emulate_set_next(uint32_t period);
|
||||
|
||||
/**
|
||||
* Stop emulation timer
|
||||
*/
|
||||
void furi_hal_ibutton_emulate_stop();
|
||||
|
||||
/**
|
||||
* Set the pin to normal mode (open collector), and sets it to float
|
||||
*/
|
||||
void furi_hal_ibutton_pin_configure();
|
||||
|
||||
/**
|
||||
* Sets the pin to analog mode, and sets it to float
|
||||
*/
|
||||
void furi_hal_ibutton_pin_reset();
|
||||
|
||||
/**
|
||||
* iButton write pin
|
||||
* @param state true / false
|
||||
*/
|
||||
void furi_hal_ibutton_pin_write(const bool state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_infrared.h"
|
||||
#include <furi_hal_infrared.h>
|
||||
#include <core/check.h>
|
||||
#include "stm32wbxx_ll_dma.h"
|
||||
#include "sys/_stdint.h"
|
||||
@@ -28,6 +28,15 @@ const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GPIO_PIN_7};
|
||||
#define INFRARED_TX_CCMR_LOW \
|
||||
(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
|
||||
|
||||
typedef struct {
|
||||
FuriHalInfraredRxCaptureCallback capture_callback;
|
||||
void* capture_context;
|
||||
@@ -213,15 +222,15 @@ void furi_hal_infrared_async_rx_set_timeout_isr_callback(
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_terminate(void) {
|
||||
LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableIT_TC(IR_DMA_CH1_DEF);
|
||||
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_DisableIT_TC(IR_DMA_CH2_DEF);
|
||||
|
||||
furi_assert(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress);
|
||||
|
||||
LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
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);
|
||||
FuriStatus status = furi_semaphore_release(infrared_tim_tx.stop_semaphore);
|
||||
furi_check(status == FuriStatusOk);
|
||||
@@ -230,7 +239,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(DMA1, LL_DMA_CHANNEL_2);
|
||||
uint32_t buffer_adr = LL_DMA_GetMemoryAddress(IR_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) {
|
||||
@@ -242,12 +251,13 @@ static uint8_t furi_hal_infrared_get_current_dma_tx_buffer(void) {
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_polarity_isr() {
|
||||
if(LL_DMA_IsActiveFlag_TE1(DMA1)) {
|
||||
LL_DMA_ClearFlag_TE1(DMA1);
|
||||
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
if(LL_DMA_IsActiveFlag_TE1(IR_DMA)) {
|
||||
LL_DMA_ClearFlag_TE1(IR_DMA);
|
||||
furi_crash(NULL);
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_TC1(DMA1) && LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_1)) {
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
if(LL_DMA_IsActiveFlag_TC1(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH1_DEF)) {
|
||||
LL_DMA_ClearFlag_TC1(IR_DMA);
|
||||
|
||||
furi_check(
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTx) ||
|
||||
@@ -257,25 +267,29 @@ static void furi_hal_infrared_tx_dma_polarity_isr() {
|
||||
uint8_t next_buf_num = furi_hal_infrared_get_current_dma_tx_buffer();
|
||||
furi_hal_infrared_tx_dma_set_polarity(next_buf_num, 0);
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_dma_isr() {
|
||||
if(LL_DMA_IsActiveFlag_TE2(DMA1)) {
|
||||
LL_DMA_ClearFlag_TE2(DMA1);
|
||||
#if IR_DMA_CH2_CHANNEL == LL_DMA_CHANNEL_2
|
||||
if(LL_DMA_IsActiveFlag_TE2(IR_DMA)) {
|
||||
LL_DMA_ClearFlag_TE2(IR_DMA);
|
||||
furi_crash(NULL);
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_HT2(DMA1) && LL_DMA_IsEnabledIT_HT(DMA1, LL_DMA_CHANNEL_2)) {
|
||||
LL_DMA_ClearFlag_HT2(DMA1);
|
||||
if(LL_DMA_IsActiveFlag_HT2(IR_DMA) && LL_DMA_IsEnabledIT_HT(IR_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_HT2(IR_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(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableIT_HT(IR_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(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableIT_HT(IR_DMA_CH2_DEF);
|
||||
}
|
||||
} else if(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) {
|
||||
/* fallthrough */
|
||||
@@ -283,8 +297,8 @@ static void furi_hal_infrared_tx_dma_isr() {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_TC2(DMA1) && LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_2)) {
|
||||
LL_DMA_ClearFlag_TC2(DMA1);
|
||||
if(LL_DMA_IsActiveFlag_TC2(IR_DMA) && LL_DMA_IsEnabledIT_TC(IR_DMA_CH2_DEF)) {
|
||||
LL_DMA_ClearFlag_TC2(IR_DMA);
|
||||
furi_check(
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopInProgress) ||
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopReq) ||
|
||||
@@ -310,6 +324,9 @@ static void furi_hal_infrared_tx_dma_isr() {
|
||||
infrared_tim_tx.signal_sent_callback(infrared_tim_tx.signal_sent_context);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
|
||||
@@ -369,16 +386,19 @@ 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(DMA1, LL_DMA_CHANNEL_1, &dma_config);
|
||||
LL_DMA_Init(IR_DMA_CH1_DEF, &dma_config);
|
||||
|
||||
LL_DMA_ClearFlag_TE1(DMA1);
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
#if IR_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
LL_DMA_ClearFlag_TE1(IR_DMA);
|
||||
LL_DMA_ClearFlag_TC1(IR_DMA);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_TE(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_TC(IR_DMA_CH1_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(
|
||||
FuriHalInterruptIdDma1Ch1, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
|
||||
furi_hal_interrupt_set_isr_ex(IR_DMA_CH1_IRQ, 4, furi_hal_infrared_tx_dma_polarity_isr, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_configure_tim_rcr_dma_tx(void) {
|
||||
@@ -394,18 +414,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(DMA1, LL_DMA_CHANNEL_2, &dma_config);
|
||||
LL_DMA_Init(IR_DMA_CH2_DEF, &dma_config);
|
||||
|
||||
LL_DMA_ClearFlag_TC2(DMA1);
|
||||
LL_DMA_ClearFlag_HT2(DMA1);
|
||||
LL_DMA_ClearFlag_TE2(DMA1);
|
||||
#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);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_EnableIT_TC(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_HT(IR_DMA_CH2_DEF);
|
||||
LL_DMA_EnableIT_TE(IR_DMA_CH2_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr_ex(
|
||||
FuriHalInterruptIdDma1Ch2, 5, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
furi_hal_interrupt_set_isr_ex(IR_DMA_CH2_IRQ, 5, furi_hal_infrared_tx_dma_isr, NULL);
|
||||
}
|
||||
|
||||
static void furi_hal_infrared_tx_fill_buffer_last(uint8_t buf_num) {
|
||||
@@ -507,14 +530,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(DMA1, LL_DMA_CHANNEL_1);
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH1_DEF);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(IR_DMA_CH1_DEF);
|
||||
}
|
||||
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)buffer->polarity);
|
||||
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, buffer->size + polarity_shift);
|
||||
LL_DMA_SetMemoryAddress(IR_DMA_CH1_DEF, (uint32_t)buffer->polarity);
|
||||
LL_DMA_SetDataLength(IR_DMA_CH1_DEF, buffer->size + polarity_shift);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@@ -527,14 +550,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(DMA1, LL_DMA_CHANNEL_2);
|
||||
bool channel_enabled = LL_DMA_IsEnabledChannel(IR_DMA_CH2_DEF);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableChannel(IR_DMA_CH2_DEF);
|
||||
}
|
||||
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)buffer->data);
|
||||
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, buffer->size);
|
||||
LL_DMA_SetMemoryAddress(IR_DMA_CH2_DEF, (uint32_t)buffer->data);
|
||||
LL_DMA_SetDataLength(IR_DMA_CH2_DEF, buffer->size);
|
||||
if(channel_enabled) {
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
@@ -545,8 +568,8 @@ static void furi_hal_infrared_async_tx_free_resources(void) {
|
||||
(furi_hal_infrared_state == InfraredStateAsyncTxStopped));
|
||||
|
||||
furi_hal_gpio_init(&gpio_infrared_tx, GpioModeOutputOpenDrain, GpioPullDown, GpioSpeedLow);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch2, NULL, NULL);
|
||||
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_semaphore_free(infrared_tim_tx.stop_semaphore);
|
||||
@@ -597,8 +620,8 @@ 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(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(IR_DMA_CH2_DEF);
|
||||
furi_delay_us(5);
|
||||
LL_TIM_GenerateEvent_UPDATE(TIM1); /* DMA -> TIMx_RCR */
|
||||
furi_delay_us(5);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "furi_hal_interrupt.h"
|
||||
#include "furi_hal_os.h"
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_os.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
@@ -74,6 +74,21 @@ __attribute__((always_inline)) static inline void
|
||||
NVIC_EnableIRQ(furi_hal_interrupt_irqn[index]);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
furi_hal_interrupt_clear_pending(FuriHalInterruptId index) {
|
||||
NVIC_ClearPendingIRQ(furi_hal_interrupt_irqn[index]);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
furi_hal_interrupt_get_pending(FuriHalInterruptId index) {
|
||||
NVIC_GetPendingIRQ(furi_hal_interrupt_irqn[index]);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
furi_hal_interrupt_set_pending(FuriHalInterruptId index) {
|
||||
NVIC_SetPendingIRQ(furi_hal_interrupt_irqn[index]);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
furi_hal_interrupt_disable(FuriHalInterruptId index) {
|
||||
NVIC_DisableIRQ(furi_hal_interrupt_irqn[index]);
|
||||
@@ -123,6 +138,7 @@ void furi_hal_interrupt_set_isr_ex(
|
||||
// Pre ISR clear
|
||||
furi_assert(furi_hal_interrupt_isr[index].isr != NULL);
|
||||
furi_hal_interrupt_disable(index);
|
||||
furi_hal_interrupt_clear_pending(index);
|
||||
}
|
||||
|
||||
furi_hal_interrupt_isr[index].isr = isr;
|
||||
@@ -131,6 +147,7 @@ void furi_hal_interrupt_set_isr_ex(
|
||||
|
||||
if(isr) {
|
||||
// Post ISR set
|
||||
furi_hal_interrupt_clear_pending(index);
|
||||
furi_hal_interrupt_enable(index, priority);
|
||||
} else {
|
||||
// Post ISR clear
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <core/common_defines.h>
|
||||
#include "furi_hal_resources.h"
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_light.h>
|
||||
#include <lp5562.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <limits.h>
|
||||
#include "furi_hal_nfc.h"
|
||||
#include <furi_hal_nfc.h>
|
||||
#include <st25r3916.h>
|
||||
#include <st25r3916_irq.h>
|
||||
#include <rfal_rf.h>
|
||||
@@ -24,13 +24,29 @@ FuriEventFlag* event = NULL;
|
||||
#define FURI_HAL_NFC_UID_INCOMPLETE (0x04)
|
||||
|
||||
void furi_hal_nfc_init() {
|
||||
furi_assert(!event);
|
||||
event = furi_event_flag_alloc();
|
||||
|
||||
ReturnCode ret = rfalNfcInitialize();
|
||||
if(ret == ERR_NONE) {
|
||||
furi_hal_nfc_start_sleep();
|
||||
event = furi_event_flag_alloc();
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Initialization failed, RFAL returned: %d", ret);
|
||||
FURI_LOG_W(TAG, "Init Failed, RFAL returned: %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_nfc_deinit() {
|
||||
ReturnCode ret = rfalDeinitialize();
|
||||
if(ret == ERR_NONE) {
|
||||
FURI_LOG_I(TAG, "Deinit OK");
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "Deinit Failed, RFAL returned: %d", ret);
|
||||
}
|
||||
|
||||
if(event) {
|
||||
furi_event_flag_free(event);
|
||||
event = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -112,6 +112,10 @@ typedef struct {
|
||||
*/
|
||||
void furi_hal_nfc_init();
|
||||
|
||||
/** Deinit nfc
|
||||
*/
|
||||
void furi_hal_nfc_deinit();
|
||||
|
||||
/** Check if nfc worker is busy
|
||||
*
|
||||
* @return true if busy
|
||||
@@ -341,14 +341,14 @@ bool furi_hal_power_is_otg_enabled() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
float furi_hal_power_get_battery_charging_voltage() {
|
||||
float furi_hal_power_get_battery_charge_voltage_limit() {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
float ret = (float)bq25896_get_vreg_voltage(&furi_hal_i2c_handle_power) / 1000.0f;
|
||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void furi_hal_power_set_battery_charging_voltage(float voltage) {
|
||||
void furi_hal_power_set_battery_charge_voltage_limit(float voltage) {
|
||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
// Adding 0.0005 is necessary because 4.016f is 4.015999794000, which gets truncated
|
||||
bq25896_set_vreg_voltage(&furi_hal_i2c_handle_power, (uint16_t)(voltage * 1000.0f + 0.0005f));
|
||||
@@ -486,7 +486,7 @@ void furi_hal_power_info_get(PropertyValueCallback out, char sep, void* context)
|
||||
property_value_out(&property_context, NULL, 2, "format", "major", "2");
|
||||
property_value_out(&property_context, NULL, 2, "format", "minor", "1");
|
||||
} else {
|
||||
property_value_out(&property_context, NULL, 3, "power", "info", "major", "1");
|
||||
property_value_out(&property_context, NULL, 3, "power", "info", "major", "2");
|
||||
property_value_out(&property_context, NULL, 3, "power", "info", "minor", "1");
|
||||
}
|
||||
|
||||
@@ -505,8 +505,10 @@ void furi_hal_power_info_get(PropertyValueCallback out, char sep, void* context)
|
||||
}
|
||||
|
||||
property_value_out(&property_context, NULL, 2, "charge", "state", charge_state);
|
||||
uint16_t charge_voltage = (uint16_t)(furi_hal_power_get_battery_charging_voltage() * 1000.f);
|
||||
property_value_out(&property_context, "%u", 2, "charge", "voltage", charge_voltage);
|
||||
uint16_t charge_voltage_limit =
|
||||
(uint16_t)(furi_hal_power_get_battery_charge_voltage_limit() * 1000.f);
|
||||
property_value_out(
|
||||
&property_context, "%u", 3, "charge", "voltage", "limit", charge_voltage_limit);
|
||||
uint16_t voltage =
|
||||
(uint16_t)(furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge) * 1000.f);
|
||||
property_value_out(&property_context, "%u", 2, "battery", "voltage", voltage);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_pwm.h"
|
||||
#include <furi_hal_pwm.h>
|
||||
#include <core/check.h>
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "furi_hal_random.h"
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
|
||||
#define TAG "FuriHalResources"
|
||||
|
||||
const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin};
|
||||
const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin};
|
||||
|
||||
@@ -62,6 +64,23 @@ const GpioPin periph_power = {.port = GPIOA, .pin = LL_GPIO_PIN_3};
|
||||
const GpioPin gpio_usb_dm = {.port = GPIOA, .pin = LL_GPIO_PIN_11};
|
||||
const GpioPin gpio_usb_dp = {.port = GPIOA, .pin = LL_GPIO_PIN_12};
|
||||
|
||||
const GpioPinRecord gpio_pins[] = {
|
||||
{.pin = &gpio_ext_pa7, .name = "PA7", .debug = false},
|
||||
{.pin = &gpio_ext_pa6, .name = "PA6", .debug = false},
|
||||
{.pin = &gpio_ext_pa4, .name = "PA4", .debug = false},
|
||||
{.pin = &gpio_ext_pb3, .name = "PB3", .debug = false},
|
||||
{.pin = &gpio_ext_pb2, .name = "PB2", .debug = false},
|
||||
{.pin = &gpio_ext_pc3, .name = "PC3", .debug = false},
|
||||
{.pin = &gpio_ext_pc1, .name = "PC1", .debug = false},
|
||||
{.pin = &gpio_ext_pc0, .name = "PC0", .debug = false},
|
||||
|
||||
/* Dangerous pins, may damage hardware */
|
||||
{.pin = &gpio_usart_rx, .name = "PB7", .debug = true},
|
||||
{.pin = &gpio_speaker, .name = "PB8", .debug = true},
|
||||
};
|
||||
|
||||
const size_t gpio_pins_count = sizeof(gpio_pins) / sizeof(GpioPinRecord);
|
||||
|
||||
const InputPin input_pins[] = {
|
||||
{.gpio = &gpio_button_up, .key = InputKeyUp, .inverted = true, .name = "Up"},
|
||||
{.gpio = &gpio_button_down, .key = InputKeyDown, .inverted = true, .name = "Down"},
|
||||
@@ -73,8 +92,18 @@ const InputPin input_pins[] = {
|
||||
|
||||
const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
||||
|
||||
static void furi_hal_resources_init_input_pins(GpioMode mode) {
|
||||
for(size_t i = 0; i < input_pins_count; i++) {
|
||||
furi_hal_gpio_init(
|
||||
input_pins[i].gpio,
|
||||
mode,
|
||||
(input_pins[i].inverted) ? GpioPullUp : GpioPullDown,
|
||||
GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_resources_init_early() {
|
||||
furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
furi_hal_resources_init_input_pins(GpioModeInput);
|
||||
|
||||
// SD Card stepdown control
|
||||
furi_hal_gpio_write(&periph_power, 1);
|
||||
@@ -117,14 +146,12 @@ void furi_hal_resources_init_early() {
|
||||
}
|
||||
|
||||
void furi_hal_resources_deinit_early() {
|
||||
furi_hal_resources_init_input_pins(GpioModeAnalog);
|
||||
}
|
||||
|
||||
void furi_hal_resources_init() {
|
||||
// Button pins
|
||||
for(size_t i = 0; i < input_pins_count; i++) {
|
||||
furi_hal_gpio_init(
|
||||
input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow);
|
||||
}
|
||||
furi_hal_resources_init_input_pins(GpioModeInterruptRiseFall);
|
||||
|
||||
// Display pins
|
||||
furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
@@ -165,4 +192,29 @@ void furi_hal_resources_init() {
|
||||
|
||||
NVIC_SetPriority(EXTI15_10_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
NVIC_EnableIRQ(EXTI15_10_IRQn);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio) {
|
||||
if(gpio == &gpio_ext_pa7)
|
||||
return 2;
|
||||
else if(gpio == &gpio_ext_pa6)
|
||||
return 3;
|
||||
else if(gpio == &gpio_ext_pa4)
|
||||
return 4;
|
||||
else if(gpio == &gpio_ext_pb3)
|
||||
return 5;
|
||||
else if(gpio == &gpio_ext_pb2)
|
||||
return 6;
|
||||
else if(gpio == &gpio_ext_pc3)
|
||||
return 7;
|
||||
else if(gpio == &gpio_ext_pc1)
|
||||
return 15;
|
||||
else if(gpio == &gpio_ext_pc0)
|
||||
return 16;
|
||||
else if(gpio == &ibutton_gpio)
|
||||
return 17;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -38,9 +38,18 @@ typedef struct {
|
||||
const char* name;
|
||||
} InputPin;
|
||||
|
||||
typedef struct {
|
||||
const GpioPin* pin;
|
||||
const char* name;
|
||||
const bool debug;
|
||||
} GpioPinRecord;
|
||||
|
||||
extern const InputPin input_pins[];
|
||||
extern const size_t input_pins_count;
|
||||
|
||||
extern const GpioPinRecord gpio_pins[];
|
||||
extern const size_t gpio_pins_count;
|
||||
|
||||
extern const GpioPin vibro_gpio;
|
||||
extern const GpioPin ibutton_gpio;
|
||||
|
||||
@@ -207,6 +216,13 @@ void furi_hal_resources_deinit_early();
|
||||
|
||||
void furi_hal_resources_init();
|
||||
|
||||
/**
|
||||
* Get a corresponding external connector pin number for a gpio
|
||||
* @param gpio GpioPin
|
||||
* @return pin number or -1 if gpio is not on the external connector
|
||||
*/
|
||||
int32_t furi_hal_resources_get_ext_pin_number(const GpioPin* gpio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
#define RFID_CAPTURE_IND_CH LL_TIM_CHANNEL_CH3
|
||||
#define RFID_CAPTURE_DIR_CH LL_TIM_CHANNEL_CH4
|
||||
|
||||
/* DMA Channels definition */
|
||||
#define RFID_DMA DMA2
|
||||
#define RFID_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
|
||||
#define RFID_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
|
||||
#define RFID_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
|
||||
#define RFID_DMA_CH1_DEF RFID_DMA, RFID_DMA_CH1_CHANNEL
|
||||
#define RFID_DMA_CH2_DEF RFID_DMA, RFID_DMA_CH2_CHANNEL
|
||||
|
||||
typedef struct {
|
||||
FuriHalRfidEmulateCallback callback;
|
||||
FuriHalRfidDMACallback dma_callback;
|
||||
@@ -69,7 +77,7 @@ void furi_hal_rfid_init() {
|
||||
|
||||
void furi_hal_rfid_pins_reset() {
|
||||
// ibutton bus disable
|
||||
furi_hal_ibutton_stop();
|
||||
furi_hal_ibutton_pin_reset();
|
||||
|
||||
// pulldown rfid antenna
|
||||
furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
@@ -86,8 +94,8 @@ void furi_hal_rfid_pins_reset() {
|
||||
|
||||
void furi_hal_rfid_pins_emulate() {
|
||||
// ibutton low
|
||||
furi_hal_ibutton_start_drive();
|
||||
furi_hal_ibutton_pin_low();
|
||||
furi_hal_ibutton_pin_configure();
|
||||
furi_hal_ibutton_pin_write(false);
|
||||
|
||||
// pull pin to timer out
|
||||
furi_hal_gpio_init_ex(
|
||||
@@ -107,8 +115,8 @@ void furi_hal_rfid_pins_emulate() {
|
||||
|
||||
void furi_hal_rfid_pins_read() {
|
||||
// ibutton low
|
||||
furi_hal_ibutton_start_drive();
|
||||
furi_hal_ibutton_pin_low();
|
||||
furi_hal_ibutton_pin_configure();
|
||||
furi_hal_ibutton_pin_write(false);
|
||||
|
||||
// dont pull rfid antenna
|
||||
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||
@@ -302,15 +310,19 @@ void furi_hal_rfid_tim_read_capture_stop() {
|
||||
}
|
||||
|
||||
static void furi_hal_rfid_dma_isr() {
|
||||
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
LL_DMA_ClearFlag_HT1(DMA1);
|
||||
#if RFID_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
if(LL_DMA_IsActiveFlag_HT1(RFID_DMA)) {
|
||||
LL_DMA_ClearFlag_HT1(RFID_DMA);
|
||||
furi_hal_rfid->dma_callback(true, furi_hal_rfid->context);
|
||||
}
|
||||
|
||||
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
if(LL_DMA_IsActiveFlag_TC1(RFID_DMA)) {
|
||||
LL_DMA_ClearFlag_TC1(RFID_DMA);
|
||||
furi_hal_rfid->dma_callback(false, furi_hal_rfid->context);
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
void furi_hal_rfid_tim_emulate_dma_start(
|
||||
@@ -347,8 +359,8 @@ void furi_hal_rfid_tim_emulate_dma_start(
|
||||
dma_config.NbData = length;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_Init(RFID_DMA_CH1_DEF, &dma_config);
|
||||
LL_DMA_EnableChannel(RFID_DMA_CH1_DEF);
|
||||
|
||||
// configure DMA "mem -> CCR3" channel
|
||||
#if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3
|
||||
@@ -366,13 +378,13 @@ void furi_hal_rfid_tim_emulate_dma_start(
|
||||
dma_config.NbData = length;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_Init(RFID_DMA_CH2_DEF, &dma_config);
|
||||
LL_DMA_EnableChannel(RFID_DMA_CH2_DEF);
|
||||
|
||||
// attach interrupt to one of DMA channels
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, furi_hal_rfid_dma_isr, NULL);
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
furi_hal_interrupt_set_isr(RFID_DMA_CH1_IRQ, furi_hal_rfid_dma_isr, NULL);
|
||||
LL_DMA_EnableIT_TC(RFID_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_HT(RFID_DMA_CH1_DEF);
|
||||
|
||||
// start
|
||||
LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
@@ -385,14 +397,14 @@ void furi_hal_rfid_tim_emulate_dma_stop() {
|
||||
LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
|
||||
LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
furi_hal_interrupt_set_isr(RFID_DMA_CH1_IRQ, NULL, NULL);
|
||||
LL_DMA_DisableIT_TC(RFID_DMA_CH1_DEF);
|
||||
LL_DMA_DisableIT_HT(RFID_DMA_CH1_DEF);
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
|
||||
LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DeInit(RFID_DMA_CH1_DEF);
|
||||
LL_DMA_DeInit(RFID_DMA_CH2_DEF);
|
||||
LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER);
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
@@ -471,4 +483,4 @@ void COMP_IRQHandler() {
|
||||
(LL_COMP_ReadOutputLevel(COMP1) == LL_COMP_OUTPUT_LEVEL_LOW),
|
||||
furi_hal_rfid_comp_callback_context);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,21 @@
|
||||
#include "furi_hal_sd.h"
|
||||
#include <furi_hal_sd.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
void hal_sd_detect_init(void) {
|
||||
// low speed input with pullup
|
||||
LL_GPIO_SetPinMode(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_MODE_INPUT);
|
||||
LL_GPIO_SetPinSpeed(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_SPEED_FREQ_LOW);
|
||||
LL_GPIO_SetPinPull(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_PULL_UP);
|
||||
furi_hal_gpio_init(&gpio_sdcard_cd, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||
}
|
||||
|
||||
void hal_sd_detect_set_low(void) {
|
||||
// low speed input with pullup
|
||||
LL_GPIO_SetPinMode(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetPinOutputType(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_OUTPUT_OPENDRAIN);
|
||||
LL_GPIO_ResetOutputPin(SD_CD_GPIO_Port, SD_CD_Pin);
|
||||
furi_hal_gpio_init_simple(&gpio_sdcard_cd, GpioModeOutputOpenDrain);
|
||||
furi_hal_gpio_write(&gpio_sdcard_cd, 0);
|
||||
}
|
||||
|
||||
bool hal_sd_detect(void) {
|
||||
bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin));
|
||||
bool result = !furi_hal_gpio_read(&gpio_sdcard_cd);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,31 @@
|
||||
#include "furi_hal_spi.h"
|
||||
#include "furi_hal_resources.h"
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
#include <stm32wbxx_ll_spi.h>
|
||||
#include <stm32wbxx_ll_utils.h>
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
|
||||
#define TAG "FuriHalSpi"
|
||||
|
||||
void furi_hal_spi_init_early() {
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
|
||||
}
|
||||
#define SPI_DMA DMA2
|
||||
#define SPI_DMA_RX_CHANNEL LL_DMA_CHANNEL_3
|
||||
#define SPI_DMA_TX_CHANNEL LL_DMA_CHANNEL_4
|
||||
#define SPI_DMA_RX_IRQ FuriHalInterruptIdDma2Ch3
|
||||
#define SPI_DMA_TX_IRQ FuriHalInterruptIdDma2Ch4
|
||||
#define SPI_DMA_RX_DEF SPI_DMA, SPI_DMA_RX_CHANNEL
|
||||
#define SPI_DMA_TX_DEF SPI_DMA, SPI_DMA_TX_CHANNEL
|
||||
|
||||
void furi_hal_spi_deinit_early() {
|
||||
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_display);
|
||||
furi_hal_spi_bus_deinit(&furi_hal_spi_bus_d);
|
||||
}
|
||||
// For simplicity, I assume that only one SPI DMA transaction can occur at a time.
|
||||
static FuriSemaphore* spi_dma_lock = NULL;
|
||||
static FuriSemaphore* spi_dma_completed = NULL;
|
||||
|
||||
void furi_hal_spi_init() {
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
|
||||
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
void furi_hal_spi_dma_init() {
|
||||
spi_dma_lock = furi_semaphore_alloc(1, 1);
|
||||
spi_dma_completed = furi_semaphore_alloc(1, 1);
|
||||
}
|
||||
|
||||
void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
|
||||
@@ -108,7 +103,7 @@ bool furi_hal_spi_bus_rx(
|
||||
|
||||
bool furi_hal_spi_bus_tx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buffer,
|
||||
const uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
furi_assert(handle);
|
||||
@@ -133,7 +128,7 @@ bool furi_hal_spi_bus_tx(
|
||||
|
||||
bool furi_hal_spi_bus_trx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx_buffer,
|
||||
const uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
@@ -173,3 +168,209 @@ bool furi_hal_spi_bus_trx(
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void spi_dma_isr() {
|
||||
#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3
|
||||
if(LL_DMA_IsActiveFlag_TC3(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_RX_DEF)) {
|
||||
LL_DMA_ClearFlag_TC3(SPI_DMA);
|
||||
furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk);
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4
|
||||
if(LL_DMA_IsActiveFlag_TC4(SPI_DMA) && LL_DMA_IsEnabledIT_TC(SPI_DMA_TX_DEF)) {
|
||||
LL_DMA_ClearFlag_TC4(SPI_DMA);
|
||||
furi_check(furi_semaphore_release(spi_dma_completed) == FuriStatusOk);
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
bool furi_hal_spi_bus_trx_dma(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout_ms) {
|
||||
furi_assert(handle);
|
||||
furi_assert(handle->bus->current_handle == handle);
|
||||
furi_assert(size > 0);
|
||||
|
||||
// If scheduler is not running, use blocking mode
|
||||
if(xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
|
||||
return furi_hal_spi_bus_trx(handle, tx_buffer, rx_buffer, size, timeout_ms);
|
||||
}
|
||||
|
||||
// Lock DMA
|
||||
furi_check(furi_semaphore_acquire(spi_dma_lock, FuriWaitForever) == FuriStatusOk);
|
||||
|
||||
const uint32_t dma_dummy_u32 = 0xFFFFFFFF;
|
||||
|
||||
bool ret = true;
|
||||
SPI_TypeDef* spi = handle->bus->spi;
|
||||
uint32_t dma_rx_req;
|
||||
uint32_t dma_tx_req;
|
||||
|
||||
if(spi == SPI1) {
|
||||
dma_rx_req = LL_DMAMUX_REQ_SPI1_RX;
|
||||
dma_tx_req = LL_DMAMUX_REQ_SPI1_TX;
|
||||
} else if(spi == SPI2) {
|
||||
dma_rx_req = LL_DMAMUX_REQ_SPI2_RX;
|
||||
dma_tx_req = LL_DMAMUX_REQ_SPI2_TX;
|
||||
} else {
|
||||
furi_crash(NULL);
|
||||
}
|
||||
|
||||
if(rx_buffer == NULL) {
|
||||
// Only TX mode, do not use RX channel
|
||||
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
|
||||
dma_config.NbData = size;
|
||||
dma_config.PeriphRequest = dma_tx_req;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
|
||||
LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config);
|
||||
|
||||
#if SPI_DMA_TX_CHANNEL == LL_DMA_CHANNEL_4
|
||||
LL_DMA_ClearFlag_TC4(SPI_DMA);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, spi_dma_isr, NULL);
|
||||
|
||||
bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi);
|
||||
if(!dma_tx_was_enabled) {
|
||||
LL_SPI_EnableDMAReq_TX(spi);
|
||||
}
|
||||
|
||||
// acquire semaphore before enabling DMA
|
||||
furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk);
|
||||
|
||||
LL_DMA_EnableIT_TC(SPI_DMA_TX_DEF);
|
||||
LL_DMA_EnableChannel(SPI_DMA_TX_DEF);
|
||||
|
||||
// and wait for it to be released (DMA transfer complete)
|
||||
if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) {
|
||||
ret = false;
|
||||
FURI_LOG_E(TAG, "DMA timeout\r\n");
|
||||
}
|
||||
// release semaphore, because we are using it as a flag
|
||||
furi_semaphore_release(spi_dma_completed);
|
||||
|
||||
LL_DMA_DisableIT_TC(SPI_DMA_TX_DEF);
|
||||
LL_DMA_DisableChannel(SPI_DMA_TX_DEF);
|
||||
if(!dma_tx_was_enabled) {
|
||||
LL_SPI_DisableDMAReq_TX(spi);
|
||||
}
|
||||
furi_hal_interrupt_set_isr(SPI_DMA_TX_IRQ, NULL, NULL);
|
||||
|
||||
LL_DMA_DeInit(SPI_DMA_TX_DEF);
|
||||
} else {
|
||||
// TRX or RX mode, use both channels
|
||||
uint32_t tx_mem_increase_mode;
|
||||
|
||||
if(tx_buffer == NULL) {
|
||||
// RX mode, use dummy data instead of TX buffer
|
||||
tx_buffer = (uint8_t*)&dma_dummy_u32;
|
||||
tx_mem_increase_mode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
} else {
|
||||
tx_mem_increase_mode = LL_DMA_MEMORY_INCREMENT;
|
||||
}
|
||||
|
||||
LL_DMA_InitTypeDef dma_config = {0};
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)tx_buffer;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH;
|
||||
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
dma_config.MemoryOrM2MDstIncMode = tx_mem_increase_mode;
|
||||
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
|
||||
dma_config.NbData = size;
|
||||
dma_config.PeriphRequest = dma_tx_req;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
|
||||
LL_DMA_Init(SPI_DMA_TX_DEF, &dma_config);
|
||||
|
||||
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (spi->DR);
|
||||
dma_config.MemoryOrM2MDstAddress = (uint32_t)rx_buffer;
|
||||
dma_config.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||
dma_config.Mode = LL_DMA_MODE_NORMAL;
|
||||
dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT;
|
||||
dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
|
||||
dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
|
||||
dma_config.NbData = size;
|
||||
dma_config.PeriphRequest = dma_rx_req;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_MEDIUM;
|
||||
LL_DMA_Init(SPI_DMA_RX_DEF, &dma_config);
|
||||
|
||||
#if SPI_DMA_RX_CHANNEL == LL_DMA_CHANNEL_3
|
||||
LL_DMA_ClearFlag_TC3(SPI_DMA);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, spi_dma_isr, NULL);
|
||||
|
||||
bool dma_tx_was_enabled = LL_SPI_IsEnabledDMAReq_TX(spi);
|
||||
bool dma_rx_was_enabled = LL_SPI_IsEnabledDMAReq_RX(spi);
|
||||
|
||||
if(!dma_tx_was_enabled) {
|
||||
LL_SPI_EnableDMAReq_TX(spi);
|
||||
}
|
||||
|
||||
if(!dma_rx_was_enabled) {
|
||||
LL_SPI_EnableDMAReq_RX(spi);
|
||||
}
|
||||
|
||||
// acquire semaphore before enabling DMA
|
||||
furi_check(furi_semaphore_acquire(spi_dma_completed, timeout_ms) == FuriStatusOk);
|
||||
|
||||
LL_DMA_EnableIT_TC(SPI_DMA_RX_DEF);
|
||||
LL_DMA_EnableChannel(SPI_DMA_RX_DEF);
|
||||
LL_DMA_EnableChannel(SPI_DMA_TX_DEF);
|
||||
|
||||
// and wait for it to be released (DMA transfer complete)
|
||||
if(furi_semaphore_acquire(spi_dma_completed, timeout_ms) != FuriStatusOk) {
|
||||
ret = false;
|
||||
FURI_LOG_E(TAG, "DMA timeout\r\n");
|
||||
}
|
||||
// release semaphore, because we are using it as a flag
|
||||
furi_semaphore_release(spi_dma_completed);
|
||||
|
||||
LL_DMA_DisableIT_TC(SPI_DMA_RX_DEF);
|
||||
|
||||
LL_DMA_DisableChannel(SPI_DMA_TX_DEF);
|
||||
LL_DMA_DisableChannel(SPI_DMA_RX_DEF);
|
||||
|
||||
if(!dma_tx_was_enabled) {
|
||||
LL_SPI_DisableDMAReq_TX(spi);
|
||||
}
|
||||
|
||||
if(!dma_rx_was_enabled) {
|
||||
LL_SPI_DisableDMAReq_RX(spi);
|
||||
}
|
||||
|
||||
furi_hal_interrupt_set_isr(SPI_DMA_RX_IRQ, NULL, NULL);
|
||||
|
||||
LL_DMA_DeInit(SPI_DMA_TX_DEF);
|
||||
LL_DMA_DeInit(SPI_DMA_RX_DEF);
|
||||
}
|
||||
|
||||
furi_hal_spi_bus_end_txrx(handle, timeout_ms);
|
||||
|
||||
furi_check(furi_semaphore_release(spi_dma_lock) == FuriStatusOk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
#include <furi_hal_spi_config.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalSpiConfig"
|
||||
|
||||
/* SPI Presets */
|
||||
|
||||
@@ -72,6 +76,27 @@ const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
|
||||
|
||||
FuriMutex* furi_hal_spi_bus_r_mutex = NULL;
|
||||
|
||||
void furi_hal_spi_config_init_early() {
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
|
||||
}
|
||||
|
||||
void furi_hal_spi_config_deinit_early() {
|
||||
furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_display);
|
||||
furi_hal_spi_bus_deinit(&furi_hal_spi_bus_d);
|
||||
}
|
||||
|
||||
void furi_hal_spi_config_init() {
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
|
||||
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
|
||||
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "furi_hal_subghz.h"
|
||||
#include "furi_hal_subghz_configs.h"
|
||||
#include <furi_hal_subghz.h>
|
||||
#include <furi_hal_subghz_configs.h>
|
||||
|
||||
#include <furi_hal_region.h>
|
||||
#include <furi_hal_version.h>
|
||||
@@ -18,6 +18,14 @@
|
||||
|
||||
static uint32_t furi_hal_subghz_debug_gpio_buff[2];
|
||||
|
||||
/* DMA Channels definition */
|
||||
#define SUBGHZ_DMA DMA2
|
||||
#define SUBGHZ_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1
|
||||
#define SUBGHZ_DMA_CH2_CHANNEL LL_DMA_CHANNEL_2
|
||||
#define SUBGHZ_DMA_CH1_IRQ FuriHalInterruptIdDma2Ch1
|
||||
#define SUBGHZ_DMA_CH1_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH1_CHANNEL
|
||||
#define SUBGHZ_DMA_CH2_DEF SUBGHZ_DMA, SUBGHZ_DMA_CH2_CHANNEL
|
||||
|
||||
typedef struct {
|
||||
volatile SubGhzState state;
|
||||
volatile SubGhzRegulation regulation;
|
||||
@@ -430,7 +438,7 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
TIM_InitStruct.Prescaler = 64 - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0x7FFFFFFE;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV4; // Clock division for capture filter
|
||||
LL_TIM_Init(TIM2, &TIM_InitStruct);
|
||||
|
||||
// Timer: advanced
|
||||
@@ -447,13 +455,15 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1);
|
||||
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING);
|
||||
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1);
|
||||
|
||||
// Timer: channel 2 direct
|
||||
LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI);
|
||||
LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1);
|
||||
LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING);
|
||||
LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV32_N8);
|
||||
LL_TIM_IC_SetFilter(
|
||||
TIM2,
|
||||
LL_TIM_CHANNEL_CH2,
|
||||
LL_TIM_IC_FILTER_FDIV32_N8); // Capture filter: 1/(64000000/64/4/32*8) = 16us
|
||||
|
||||
// ISR setup
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, furi_hal_subghz_capture_ISR, NULL);
|
||||
@@ -473,6 +483,9 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void*
|
||||
|
||||
// Switch to RX
|
||||
furi_hal_subghz_rx();
|
||||
|
||||
//Clear the variable after the end of the session
|
||||
furi_hal_subghz_capture_delta_duration = 0;
|
||||
}
|
||||
|
||||
void furi_hal_subghz_stop_async_rx() {
|
||||
@@ -525,8 +538,8 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
*buffer = 0;
|
||||
buffer++;
|
||||
samples--;
|
||||
LL_DMA_DisableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableIT_HT(SUBGHZ_DMA_CH1_DEF);
|
||||
LL_DMA_DisableIT_TC(SUBGHZ_DMA_CH1_DEF);
|
||||
LL_TIM_EnableIT_UPDATE(TIM2);
|
||||
break;
|
||||
} else {
|
||||
@@ -567,17 +580,22 @@ static void furi_hal_subghz_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||
|
||||
static void furi_hal_subghz_async_tx_dma_isr() {
|
||||
furi_assert(furi_hal_subghz.state == SubGhzStateAsyncTx);
|
||||
if(LL_DMA_IsActiveFlag_HT1(DMA1)) {
|
||||
LL_DMA_ClearFlag_HT1(DMA1);
|
||||
|
||||
#if SUBGHZ_DMA_CH1_CHANNEL == LL_DMA_CHANNEL_1
|
||||
if(LL_DMA_IsActiveFlag_HT1(SUBGHZ_DMA)) {
|
||||
LL_DMA_ClearFlag_HT1(SUBGHZ_DMA);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer, API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
if(LL_DMA_IsActiveFlag_TC1(DMA1)) {
|
||||
LL_DMA_ClearFlag_TC1(DMA1);
|
||||
if(LL_DMA_IsActiveFlag_TC1(SUBGHZ_DMA)) {
|
||||
LL_DMA_ClearFlag_TC1(SUBGHZ_DMA);
|
||||
furi_hal_subghz_async_tx_refill(
|
||||
furi_hal_subghz_async_tx.buffer + API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF,
|
||||
API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF);
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_subghz_async_tx_timer_isr() {
|
||||
@@ -586,7 +604,7 @@ static void furi_hal_subghz_async_tx_timer_isr() {
|
||||
if(LL_TIM_GetAutoReload(TIM2) == 0) {
|
||||
if(furi_hal_subghz.state == SubGhzStateAsyncTx) {
|
||||
furi_hal_subghz.state = SubGhzStateAsyncTxLast;
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DisableChannel(SUBGHZ_DMA_CH1_DEF);
|
||||
} else if(furi_hal_subghz.state == SubGhzStateAsyncTxLast) {
|
||||
furi_hal_subghz.state = SubGhzStateAsyncTxEnd;
|
||||
//forcibly pulls the pin to the ground so that there is no carrier
|
||||
@@ -634,11 +652,11 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.NbData = API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_MODE_NORMAL;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, furi_hal_subghz_async_tx_dma_isr, NULL);
|
||||
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_Init(SUBGHZ_DMA_CH1_DEF, &dma_config);
|
||||
furi_hal_interrupt_set_isr(SUBGHZ_DMA_CH1_IRQ, furi_hal_subghz_async_tx_dma_isr, NULL);
|
||||
LL_DMA_EnableIT_TC(SUBGHZ_DMA_CH1_DEF);
|
||||
LL_DMA_EnableIT_HT(SUBGHZ_DMA_CH1_DEF);
|
||||
LL_DMA_EnableChannel(SUBGHZ_DMA_CH1_DEF);
|
||||
|
||||
// Configure TIM2
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
@@ -696,9 +714,9 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void*
|
||||
dma_config.NbData = 2;
|
||||
dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP;
|
||||
dma_config.Priority = LL_DMA_PRIORITY_VERYHIGH;
|
||||
LL_DMA_Init(DMA1, LL_DMA_CHANNEL_2, &dma_config);
|
||||
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 2);
|
||||
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_Init(SUBGHZ_DMA_CH2_DEF, &dma_config);
|
||||
LL_DMA_SetDataLength(SUBGHZ_DMA_CH2_DEF, 2);
|
||||
LL_DMA_EnableChannel(SUBGHZ_DMA_CH2_DEF);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -726,16 +744,16 @@ void furi_hal_subghz_stop_async_tx() {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTIM2, NULL, NULL);
|
||||
|
||||
// Deinitialize DMA
|
||||
LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1);
|
||||
LL_DMA_DeInit(SUBGHZ_DMA_CH1_DEF);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL);
|
||||
furi_hal_interrupt_set_isr(SUBGHZ_DMA_CH1_IRQ, NULL, NULL);
|
||||
|
||||
// Deinitialize GPIO
|
||||
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
// Stop debug
|
||||
if(furi_hal_subghz_stop_debug()) {
|
||||
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2);
|
||||
LL_DMA_DisableChannel(SUBGHZ_DMA_CH2_DEF);
|
||||
}
|
||||
|
||||
FURI_CRITICAL_EXIT();
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi_hal_subghz.h>
|
||||
#include <furi_hal_ibutton.h>
|
||||
#include <furi_hal_rfid.h>
|
||||
#include <furi_hal_nfc.h>
|
||||
@@ -44,7 +44,8 @@ static void furi_hal_usart_init(uint32_t baud) {
|
||||
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
|
||||
;
|
||||
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
LL_USART_DisableIT_ERROR(USART1);
|
||||
|
||||
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
}
|
||||
|
||||
@@ -79,8 +80,8 @@ static void furi_hal_lpuart_init(uint32_t baud) {
|
||||
;
|
||||
|
||||
furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
|
||||
LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
}
|
||||
|
||||
@@ -190,19 +191,25 @@ void furi_hal_uart_set_irq_cb(
|
||||
void (*cb)(UartIrqEvent ev, uint8_t data, void* ctx),
|
||||
void* ctx) {
|
||||
if(cb == NULL) {
|
||||
if(ch == FuriHalUartIdUSART1)
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_DisableIRQ(USART1_IRQn);
|
||||
else if(ch == FuriHalUartIdLPUART1)
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_DisableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
irq_cb[ch] = cb;
|
||||
irq_ctx[ch] = ctx;
|
||||
} else {
|
||||
irq_ctx[ch] = ctx;
|
||||
irq_cb[ch] = cb;
|
||||
if(ch == FuriHalUartIdUSART1)
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_EnableIRQ(USART1_IRQn);
|
||||
else if(ch == FuriHalUartIdLPUART1)
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_EnableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "furi_hal_version.h"
|
||||
#include "furi_hal_usb_i.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <furi.h>
|
||||
@@ -340,7 +340,7 @@ static void usb_process_mode_start(FuriHalUsbInterface* interface, void* context
|
||||
}
|
||||
|
||||
static void usb_process_mode_change(FuriHalUsbInterface* interface, void* context) {
|
||||
if(interface != usb.interface) {
|
||||
if((interface != usb.interface) || (context != usb.interface_context)) {
|
||||
if(usb.enabled) {
|
||||
// Disable current interface
|
||||
susp_evt(&udev, 0, 0);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "furi_hal_version.h"
|
||||
#include "furi_hal_usb_i.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include "furi_hal_usb_cdc.h"
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_cdc.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "usb.h"
|
||||
|
||||
@@ -1,35 +1,29 @@
|
||||
#include "furi_hal_version.h"
|
||||
#include "furi_hal_usb_i.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include "furi_hal_usb_hid.h"
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_hid.h"
|
||||
|
||||
#define HID_EP_IN 0x81
|
||||
#define HID_EP_OUT 0x01
|
||||
#define HID_EP_SZ 0x10
|
||||
|
||||
#define HID_KB_MAX_KEYS 6
|
||||
#define HID_CONSUMER_MAX_KEYS 2
|
||||
|
||||
#define HID_INTERVAL 2
|
||||
|
||||
#define HID_VID_DEFAULT 0x046D
|
||||
#define HID_PID_DEFAULT 0xC529
|
||||
|
||||
struct HidIadDescriptor {
|
||||
struct usb_iad_descriptor hid_iad;
|
||||
struct HidIntfDescriptor {
|
||||
struct usb_interface_descriptor hid;
|
||||
struct usb_hid_descriptor hid_desc;
|
||||
struct usb_endpoint_descriptor hid_ep_in;
|
||||
struct usb_endpoint_descriptor hid_ep_out;
|
||||
};
|
||||
|
||||
struct HidConfigDescriptor {
|
||||
struct usb_config_descriptor config;
|
||||
struct HidIadDescriptor iad_0;
|
||||
struct HidIntfDescriptor intf_0;
|
||||
} __attribute__((packed));
|
||||
|
||||
enum HidReportId {
|
||||
@@ -38,78 +32,98 @@ enum HidReportId {
|
||||
ReportIdConsumer = 3,
|
||||
};
|
||||
|
||||
/* HID report: keyboard+mouse */
|
||||
/* HID report descriptor: keyboard + mouse + consumer control */
|
||||
static const uint8_t hid_report_desc[] = {
|
||||
// clang-format off
|
||||
HID_USAGE_PAGE(HID_PAGE_DESKTOP),
|
||||
HID_USAGE(HID_DESKTOP_KEYBOARD),
|
||||
HID_COLLECTION(HID_APPLICATION_COLLECTION),
|
||||
HID_REPORT_ID(ReportIdKeyboard),
|
||||
HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
|
||||
HID_USAGE_MINIMUM(HID_KEYBOARD_L_CTRL),
|
||||
HID_USAGE_MAXIMUM(HID_KEYBOARD_R_GUI),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(1),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_REPORT_COUNT(8),
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_REPORT_COUNT(1),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_USAGE_PAGE(HID_PAGE_LED),
|
||||
HID_REPORT_COUNT(8),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_USAGE_MINIMUM(1),
|
||||
HID_USAGE_MAXIMUM(8),
|
||||
HID_OUTPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_REPORT_COUNT(HID_KB_MAX_KEYS),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(101),
|
||||
HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
|
||||
HID_USAGE_MINIMUM(0),
|
||||
HID_USAGE_MAXIMUM(101),
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_REPORT_ID(ReportIdKeyboard),
|
||||
// Keyboard report
|
||||
HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
|
||||
HID_USAGE_MINIMUM(HID_KEYBOARD_L_CTRL),
|
||||
HID_USAGE_MAXIMUM(HID_KEYBOARD_R_GUI),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(1),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_REPORT_COUNT(8),
|
||||
// Input - Modifier keys byte
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_REPORT_COUNT(1),
|
||||
HID_REPORT_SIZE(8),
|
||||
// Input - Reserved byte
|
||||
HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_USAGE_PAGE(HID_PAGE_LED),
|
||||
HID_REPORT_COUNT(8),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_USAGE_MINIMUM(1),
|
||||
HID_USAGE_MAXIMUM(8),
|
||||
// Output - LEDs
|
||||
HID_OUTPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_REPORT_COUNT(HID_KB_MAX_KEYS),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(101),
|
||||
HID_USAGE_PAGE(HID_DESKTOP_KEYPAD),
|
||||
HID_USAGE_MINIMUM(0),
|
||||
HID_USAGE_MAXIMUM(101),
|
||||
// Input - Key codes
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_END_COLLECTION,
|
||||
|
||||
HID_USAGE_PAGE(HID_PAGE_DESKTOP),
|
||||
HID_USAGE(HID_DESKTOP_MOUSE),
|
||||
HID_COLLECTION(HID_APPLICATION_COLLECTION),
|
||||
HID_USAGE(HID_DESKTOP_POINTER),
|
||||
HID_COLLECTION(HID_PHYSICAL_COLLECTION),
|
||||
HID_REPORT_ID(ReportIdMouse),
|
||||
HID_USAGE_PAGE(HID_PAGE_BUTTON),
|
||||
HID_USAGE_MINIMUM(1),
|
||||
HID_USAGE_MAXIMUM(3),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(1),
|
||||
HID_REPORT_COUNT(3),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_REPORT_COUNT(5),
|
||||
HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
HID_USAGE_PAGE(HID_PAGE_DESKTOP),
|
||||
HID_USAGE(HID_DESKTOP_X),
|
||||
HID_USAGE(HID_DESKTOP_Y),
|
||||
HID_USAGE(HID_DESKTOP_WHEEL),
|
||||
HID_LOGICAL_MINIMUM(-127),
|
||||
HID_LOGICAL_MAXIMUM(127),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_REPORT_COUNT(3),
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
|
||||
HID_END_COLLECTION,
|
||||
HID_USAGE(HID_DESKTOP_POINTER),
|
||||
HID_COLLECTION(HID_PHYSICAL_COLLECTION),
|
||||
HID_REPORT_ID(ReportIdMouse),
|
||||
// Mouse report
|
||||
HID_USAGE_PAGE(HID_PAGE_BUTTON),
|
||||
HID_USAGE_MINIMUM(1),
|
||||
HID_USAGE_MAXIMUM(3),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_LOGICAL_MAXIMUM(1),
|
||||
HID_REPORT_COUNT(3),
|
||||
HID_REPORT_SIZE(1),
|
||||
// Input - Mouse keys
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_REPORT_SIZE(1),
|
||||
HID_REPORT_COUNT(5),
|
||||
// Input - Mouse keys padding
|
||||
HID_INPUT(HID_IOF_CONSTANT | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
HID_USAGE_PAGE(HID_PAGE_DESKTOP),
|
||||
HID_USAGE(HID_DESKTOP_X),
|
||||
HID_USAGE(HID_DESKTOP_Y),
|
||||
HID_USAGE(HID_DESKTOP_WHEEL),
|
||||
HID_LOGICAL_MINIMUM(-127),
|
||||
HID_LOGICAL_MAXIMUM(127),
|
||||
HID_REPORT_SIZE(8),
|
||||
HID_REPORT_COUNT(3),
|
||||
// Input - Mouse movement data (x, y, scroll)
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
|
||||
HID_END_COLLECTION,
|
||||
HID_END_COLLECTION,
|
||||
|
||||
HID_USAGE_PAGE(HID_PAGE_CONSUMER),
|
||||
HID_USAGE(HID_CONSUMER_CONTROL),
|
||||
HID_COLLECTION(HID_APPLICATION_COLLECTION),
|
||||
HID_REPORT_ID(ReportIdConsumer),
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_RI_LOGICAL_MAXIMUM(16, 0x3FF),
|
||||
HID_USAGE_MINIMUM(0),
|
||||
HID_RI_USAGE_MAXIMUM(16, 0x3FF),
|
||||
HID_REPORT_COUNT(HID_CONSUMER_MAX_KEYS),
|
||||
HID_REPORT_SIZE(16),
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_REPORT_ID(ReportIdConsumer),
|
||||
// Consumer report
|
||||
HID_LOGICAL_MINIMUM(0),
|
||||
HID_RI_LOGICAL_MAXIMUM(16, 0x3FF),
|
||||
HID_USAGE_MINIMUM(0),
|
||||
HID_RI_USAGE_MAXIMUM(16, 0x3FF),
|
||||
HID_REPORT_COUNT(HID_CONSUMER_MAX_KEYS),
|
||||
HID_REPORT_SIZE(16),
|
||||
// Input - Consumer control keys
|
||||
HID_INPUT(HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
|
||||
HID_END_COLLECTION,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
/* Device descriptor */
|
||||
@@ -117,9 +131,9 @@ static struct usb_device_descriptor hid_device_desc = {
|
||||
.bLength = sizeof(struct usb_device_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_DEVICE,
|
||||
.bcdUSB = VERSION_BCD(2, 0, 0),
|
||||
.bDeviceClass = USB_CLASS_IAD,
|
||||
.bDeviceSubClass = USB_SUBCLASS_IAD,
|
||||
.bDeviceProtocol = USB_PROTO_IAD,
|
||||
.bDeviceClass = USB_CLASS_PER_INTERFACE,
|
||||
.bDeviceSubClass = USB_SUBCLASS_NONE,
|
||||
.bDeviceProtocol = USB_PROTO_NONE,
|
||||
.bMaxPacketSize0 = USB_EP0_SIZE,
|
||||
.idVendor = HID_VID_DEFAULT,
|
||||
.idProduct = HID_PID_DEFAULT,
|
||||
@@ -143,29 +157,18 @@ static const struct HidConfigDescriptor hid_cfg_desc = {
|
||||
.bmAttributes = USB_CFG_ATTR_RESERVED | USB_CFG_ATTR_SELFPOWERED,
|
||||
.bMaxPower = USB_CFG_POWER_MA(100),
|
||||
},
|
||||
.iad_0 =
|
||||
.intf_0 =
|
||||
{
|
||||
.hid_iad =
|
||||
{
|
||||
.bLength = sizeof(struct usb_iad_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_INTERFASEASSOC,
|
||||
.bFirstInterface = 0,
|
||||
.bInterfaceCount = 1,
|
||||
.bFunctionClass = USB_CLASS_PER_INTERFACE,
|
||||
.bFunctionSubClass = USB_SUBCLASS_NONE,
|
||||
.bFunctionProtocol = USB_PROTO_NONE,
|
||||
.iFunction = NO_DESCRIPTOR,
|
||||
},
|
||||
.hid =
|
||||
{
|
||||
.bLength = sizeof(struct usb_interface_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0,
|
||||
.bAlternateSetting = 0,
|
||||
.bNumEndpoints = 2,
|
||||
.bNumEndpoints = 1,
|
||||
.bInterfaceClass = USB_CLASS_HID,
|
||||
.bInterfaceSubClass = USB_HID_SUBCLASS_NONBOOT,
|
||||
.bInterfaceProtocol = USB_HID_PROTO_NONBOOT,
|
||||
.bInterfaceSubClass = USB_HID_SUBCLASS_BOOT,
|
||||
.bInterfaceProtocol = USB_HID_PROTO_KEYBOARD,
|
||||
.iInterface = NO_DESCRIPTOR,
|
||||
},
|
||||
.hid_desc =
|
||||
@@ -187,15 +190,6 @@ static const struct HidConfigDescriptor hid_cfg_desc = {
|
||||
.wMaxPacketSize = HID_EP_SZ,
|
||||
.bInterval = HID_INTERVAL,
|
||||
},
|
||||
.hid_ep_out =
|
||||
{
|
||||
.bLength = sizeof(struct usb_endpoint_descriptor),
|
||||
.bDescriptorType = USB_DTYPE_ENDPOINT,
|
||||
.bEndpointAddress = HID_EP_OUT,
|
||||
.bmAttributes = USB_EPTYPE_INTERRUPT,
|
||||
.wMaxPacketSize = HID_EP_SZ,
|
||||
.bInterval = HID_INTERVAL,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -209,9 +203,11 @@ struct HidReportMouse {
|
||||
|
||||
struct HidReportKB {
|
||||
uint8_t report_id;
|
||||
uint8_t mods;
|
||||
uint8_t reserved;
|
||||
uint8_t btn[HID_KB_MAX_KEYS];
|
||||
struct {
|
||||
uint8_t mods;
|
||||
uint8_t reserved;
|
||||
uint8_t btn[HID_KB_MAX_KEYS];
|
||||
} boot;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HidReportConsumer {
|
||||
@@ -259,6 +255,7 @@ static bool hid_connected = false;
|
||||
static HidStateCallback callback;
|
||||
static void* cb_ctx;
|
||||
static uint8_t led_state;
|
||||
static bool boot_protocol = false;
|
||||
|
||||
bool furi_hal_hid_is_connected() {
|
||||
return hid_connected;
|
||||
@@ -283,31 +280,31 @@ void furi_hal_hid_set_state_callback(HidStateCallback cb, void* ctx) {
|
||||
|
||||
bool furi_hal_hid_kb_press(uint16_t button) {
|
||||
for(uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
|
||||
if(hid_report.keyboard.btn[key_nb] == 0) {
|
||||
hid_report.keyboard.btn[key_nb] = button & 0xFF;
|
||||
if(hid_report.keyboard.boot.btn[key_nb] == 0) {
|
||||
hid_report.keyboard.boot.btn[key_nb] = button & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_report.keyboard.mods |= (button >> 8);
|
||||
hid_report.keyboard.boot.mods |= (button >> 8);
|
||||
return hid_send_report(ReportIdKeyboard);
|
||||
}
|
||||
|
||||
bool furi_hal_hid_kb_release(uint16_t button) {
|
||||
for(uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
|
||||
if(hid_report.keyboard.btn[key_nb] == (button & 0xFF)) {
|
||||
hid_report.keyboard.btn[key_nb] = 0;
|
||||
if(hid_report.keyboard.boot.btn[key_nb] == (button & 0xFF)) {
|
||||
hid_report.keyboard.boot.btn[key_nb] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
hid_report.keyboard.mods &= ~(button >> 8);
|
||||
hid_report.keyboard.boot.mods &= ~(button >> 8);
|
||||
return hid_send_report(ReportIdKeyboard);
|
||||
}
|
||||
|
||||
bool furi_hal_hid_kb_release_all() {
|
||||
for(uint8_t key_nb = 0; key_nb < HID_KB_MAX_KEYS; key_nb++) {
|
||||
hid_report.keyboard.btn[key_nb] = 0;
|
||||
hid_report.keyboard.boot.btn[key_nb] = 0;
|
||||
}
|
||||
hid_report.keyboard.mods = 0;
|
||||
hid_report.keyboard.boot.mods = 0;
|
||||
return hid_send_report(ReportIdKeyboard);
|
||||
}
|
||||
|
||||
@@ -437,27 +434,35 @@ static void hid_on_suspend(usbd_device* dev) {
|
||||
|
||||
static bool hid_send_report(uint8_t report_id) {
|
||||
if((hid_semaphore == NULL) || (hid_connected == false)) return false;
|
||||
if((boot_protocol == true) && (report_id != ReportIdKeyboard)) return false;
|
||||
|
||||
furi_check(furi_semaphore_acquire(hid_semaphore, FuriWaitForever) == FuriStatusOk);
|
||||
if(hid_connected == true) {
|
||||
if(hid_connected == false) {
|
||||
return false;
|
||||
}
|
||||
if(boot_protocol == true) {
|
||||
usbd_ep_write(
|
||||
usb_dev, HID_EP_IN, &hid_report.keyboard.boot, sizeof(hid_report.keyboard.boot));
|
||||
} else {
|
||||
if(report_id == ReportIdKeyboard)
|
||||
usbd_ep_write(usb_dev, HID_EP_IN, &hid_report.keyboard, sizeof(hid_report.keyboard));
|
||||
else if(report_id == ReportIdMouse)
|
||||
usbd_ep_write(usb_dev, HID_EP_IN, &hid_report.mouse, sizeof(hid_report.mouse));
|
||||
else if(report_id == ReportIdConsumer)
|
||||
usbd_ep_write(usb_dev, HID_EP_IN, &hid_report.consumer, sizeof(hid_report.consumer));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void hid_txrx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
|
||||
UNUSED(dev);
|
||||
if(event == usbd_evt_eptx) {
|
||||
furi_semaphore_release(hid_semaphore);
|
||||
} else if(boot_protocol == true) {
|
||||
usbd_ep_read(usb_dev, ep, &led_state, sizeof(led_state));
|
||||
} else {
|
||||
struct HidReportLED leds;
|
||||
usbd_ep_read(usb_dev, ep, &leds, 2);
|
||||
usbd_ep_read(usb_dev, ep, &leds, sizeof(leds));
|
||||
led_state = leds.led_state;
|
||||
}
|
||||
}
|
||||
@@ -467,18 +472,15 @@ static usbd_respond hid_ep_config(usbd_device* dev, uint8_t cfg) {
|
||||
switch(cfg) {
|
||||
case 0:
|
||||
/* deconfiguring device */
|
||||
usbd_ep_deconfig(dev, HID_EP_OUT);
|
||||
usbd_ep_deconfig(dev, HID_EP_IN);
|
||||
usbd_reg_endpoint(dev, HID_EP_OUT, 0);
|
||||
usbd_reg_endpoint(dev, HID_EP_IN, 0);
|
||||
return usbd_ack;
|
||||
case 1:
|
||||
/* configuring device */
|
||||
usbd_ep_config(dev, HID_EP_IN, USB_EPTYPE_INTERRUPT, HID_EP_SZ);
|
||||
usbd_ep_config(dev, HID_EP_OUT, USB_EPTYPE_INTERRUPT, HID_EP_SZ);
|
||||
usbd_reg_endpoint(dev, HID_EP_IN, hid_txrx_ep_callback);
|
||||
usbd_reg_endpoint(dev, HID_EP_OUT, hid_txrx_ep_callback);
|
||||
usbd_ep_write(dev, HID_EP_IN, 0, 0);
|
||||
boot_protocol = false; /* BIOS will SET_PROTOCOL if it wants this */
|
||||
return usbd_ack;
|
||||
default:
|
||||
return usbd_fail;
|
||||
@@ -496,8 +498,21 @@ static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_cal
|
||||
case USB_HID_SETIDLE:
|
||||
return usbd_ack;
|
||||
case USB_HID_GETREPORT:
|
||||
dev->status.data_ptr = &hid_report;
|
||||
dev->status.data_count = sizeof(hid_report);
|
||||
if(boot_protocol == true) {
|
||||
dev->status.data_ptr = &hid_report.keyboard.boot;
|
||||
dev->status.data_count = sizeof(hid_report.keyboard.boot);
|
||||
} else {
|
||||
dev->status.data_ptr = &hid_report;
|
||||
dev->status.data_count = sizeof(hid_report);
|
||||
}
|
||||
return usbd_ack;
|
||||
case USB_HID_SETPROTOCOL:
|
||||
if(req->wValue == 0)
|
||||
boot_protocol = true;
|
||||
else if(req->wValue == 1)
|
||||
boot_protocol = false;
|
||||
else
|
||||
return usbd_fail;
|
||||
return usbd_ack;
|
||||
default:
|
||||
return usbd_fail;
|
||||
@@ -508,10 +523,11 @@ static usbd_respond hid_control(usbd_device* dev, usbd_ctlreq* req, usbd_rqc_cal
|
||||
req->wIndex == 0 && req->bRequest == USB_STD_GET_DESCRIPTOR) {
|
||||
switch(req->wValue >> 8) {
|
||||
case USB_DTYPE_HID:
|
||||
dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.iad_0.hid_desc);
|
||||
dev->status.data_count = sizeof(hid_cfg_desc.iad_0.hid_desc);
|
||||
dev->status.data_ptr = (uint8_t*)&(hid_cfg_desc.intf_0.hid_desc);
|
||||
dev->status.data_count = sizeof(hid_cfg_desc.intf_0.hid_desc);
|
||||
return usbd_ack;
|
||||
case USB_DTYPE_HID_REPORT:
|
||||
boot_protocol = false; /* BIOS does not read this */
|
||||
dev->status.data_ptr = (uint8_t*)hid_report_desc;
|
||||
dev->status.data_count = sizeof(hid_report_desc);
|
||||
return usbd_ack;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "furi_hal_version.h"
|
||||
#include "furi_hal_usb_i.h"
|
||||
#include "furi_hal_usb_hid_u2f.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_usb_i.h>
|
||||
#include <furi_hal_usb_hid_u2f.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi.h>
|
||||
#include "usb.h"
|
||||
#include "usb_hid.h"
|
||||
|
||||
@@ -195,14 +195,6 @@ void furi_hal_version_init() {
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
||||
bool furi_hal_version_do_i_belong_here() {
|
||||
return furi_hal_version_get_hw_target() == 7;
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_model_name() {
|
||||
return "Flipper Zero";
|
||||
}
|
||||
|
||||
FuriHalVersionOtpVersion furi_hal_version_get_otp_version() {
|
||||
if(*(uint64_t*)FURI_HAL_VERSION_OTP_ADDRESS == 0xFFFFFFFF) {
|
||||
return FuriHalVersionOtpVersionEmpty;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <furi_hal_version.h>
|
||||
|
||||
bool furi_hal_version_do_i_belong_here() {
|
||||
return (furi_hal_version_get_hw_target() == 7) || (furi_hal_version_get_hw_target() == 0);
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_model_name() {
|
||||
return "Flipper Zero";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_model_code() {
|
||||
return "FZ.1";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_fcc_id() {
|
||||
return "2A2V6-FZ";
|
||||
}
|
||||
|
||||
const char* furi_hal_version_get_ic_id() {
|
||||
return "27624-FZ";
|
||||
}
|
||||
@@ -8,6 +8,8 @@ void flipper_boot_update_exec();
|
||||
|
||||
void flipper_boot_dfu_exec();
|
||||
|
||||
void flipper_boot_recovery_exec();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -4,10 +4,11 @@
|
||||
#include <alt_boot.h>
|
||||
#include <u8g2_glue.h>
|
||||
#include <assets_icons.h>
|
||||
#include <toolbox/compress.h>
|
||||
|
||||
void flipper_boot_dfu_show_splash() {
|
||||
// Initialize
|
||||
furi_hal_compress_icon_init();
|
||||
CompressIcon* compress_icon = compress_icon_alloc();
|
||||
|
||||
u8g2_t* fb = malloc(sizeof(u8g2_t));
|
||||
memset(fb, 0, sizeof(u8g2_t));
|
||||
@@ -15,13 +16,15 @@ void flipper_boot_dfu_show_splash() {
|
||||
u8g2_InitDisplay(fb);
|
||||
u8g2_SetDrawColor(fb, 0x01);
|
||||
uint8_t* splash_data = NULL;
|
||||
furi_hal_compress_icon_decode(icon_get_data(&I_DFU_128x50), &splash_data);
|
||||
compress_icon_decode(compress_icon, icon_get_data(&I_DFU_128x50), &splash_data);
|
||||
u8g2_DrawXBM(fb, 0, 64 - 50, 128, 50, splash_data);
|
||||
u8g2_SetFont(fb, u8g2_font_helvB08_tr);
|
||||
u8g2_DrawStr(fb, 2, 8, "Update & Recovery Mode");
|
||||
u8g2_DrawStr(fb, 2, 21, "DFU Started");
|
||||
u8g2_SetPowerSave(fb, 0);
|
||||
u8g2_SendBuffer(fb);
|
||||
|
||||
compress_icon_free(compress_icon);
|
||||
}
|
||||
|
||||
void flipper_boot_dfu_exec() {
|
||||
@@ -49,6 +49,10 @@ int main() {
|
||||
// But if we do, abandon to avoid bootloops
|
||||
furi_hal_rtc_set_boot_mode(FuriHalRtcBootModeNormal);
|
||||
furi_hal_power_reset();
|
||||
} else if(!furi_hal_gpio_read(&gpio_button_up)) {
|
||||
furi_hal_light_sequence("rgb WR");
|
||||
flipper_boot_recovery_exec();
|
||||
furi_hal_power_reset();
|
||||
} else {
|
||||
furi_hal_light_sequence("rgb G");
|
||||
furi_thread_start(main_thread);
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <flipper.h>
|
||||
#include <alt_boot.h>
|
||||
#include <u8g2_glue.h>
|
||||
#include <assets_icons.h>
|
||||
#include <toolbox/compress.h>
|
||||
|
||||
#define COUNTER_VALUE (136U)
|
||||
|
||||
static void flipper_boot_recovery_draw_splash(u8g2_t* fb, size_t progress) {
|
||||
if(progress < COUNTER_VALUE) {
|
||||
// Fill the progress bar while the progress is going down
|
||||
u8g2_SetDrawColor(fb, 0x01);
|
||||
u8g2_DrawRFrame(fb, 59, 41, 69, 8, 2);
|
||||
size_t width = (COUNTER_VALUE - progress) * 68 / COUNTER_VALUE;
|
||||
u8g2_DrawBox(fb, 60, 42, width, 6);
|
||||
} else {
|
||||
u8g2_SetDrawColor(fb, 0x00);
|
||||
u8g2_DrawRBox(fb, 59, 41, 69, 8, 2);
|
||||
}
|
||||
|
||||
u8g2_SendBuffer(fb);
|
||||
}
|
||||
|
||||
void flipper_boot_recovery_exec() {
|
||||
u8g2_t* fb = malloc(sizeof(u8g2_t));
|
||||
u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
|
||||
u8g2_InitDisplay(fb);
|
||||
|
||||
CompressIcon* compress_icon = compress_icon_alloc();
|
||||
uint8_t* splash_data = NULL;
|
||||
compress_icon_decode(compress_icon, icon_get_data(&I_Erase_pin_128x64), &splash_data);
|
||||
|
||||
u8g2_ClearBuffer(fb);
|
||||
u8g2_SetDrawColor(fb, 0x01);
|
||||
|
||||
// Draw the recovery picture
|
||||
u8g2_DrawXBM(fb, 0, 0, 128, 64, splash_data);
|
||||
u8g2_SendBuffer(fb);
|
||||
u8g2_SetPowerSave(fb, 0);
|
||||
compress_icon_free(compress_icon);
|
||||
|
||||
size_t counter = COUNTER_VALUE;
|
||||
while(counter) {
|
||||
if(!furi_hal_gpio_read(&gpio_button_down)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!furi_hal_gpio_read(&gpio_button_right)) {
|
||||
counter--;
|
||||
} else {
|
||||
counter = COUNTER_VALUE;
|
||||
}
|
||||
|
||||
flipper_boot_recovery_draw_splash(fb, counter);
|
||||
}
|
||||
|
||||
if(!counter) {
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset);
|
||||
furi_hal_rtc_set_pin_fails(0);
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLock);
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ static FATFS* pfs = NULL;
|
||||
}
|
||||
|
||||
static bool flipper_update_mount_sd() {
|
||||
for(int i = 0; i < BSP_SD_MaxMountRetryCount(); ++i) {
|
||||
if(BSP_SD_Init((i % 2) == 0) != MSD_OK) {
|
||||
for(int i = 0; i < sd_max_mount_retry_count(); ++i) {
|
||||
if(sd_init((i % 2) == 0) != SdSpiStatusOK) {
|
||||
/* Next attempt will be without card reset, let it settle */
|
||||
furi_delay_ms(1000);
|
||||
continue;
|
||||
@@ -42,9 +42,9 @@ static bool flipper_update_init() {
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
|
||||
furi_hal_spi_init();
|
||||
furi_hal_spi_config_init();
|
||||
|
||||
MX_FATFS_Init();
|
||||
fatfs_init();
|
||||
if(!hal_sd_detect()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
*****************************************************************************
|
||||
**
|
||||
** File : stm32wb55xx_flash_cm4.ld
|
||||
** File : stm32wb55xx_flash.ld
|
||||
**
|
||||
** Abstract : System Workbench Minimal System calls file
|
||||
**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
*****************************************************************************
|
||||
**
|
||||
** File : stm32wb55xx_flash_cm4.ld
|
||||
** File : stm32wb55xx_ram_fw.ld
|
||||
**
|
||||
** Abstract : System Workbench Minimal System calls file
|
||||
**
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"include_paths": [
|
||||
"ble_glue",
|
||||
"fatfs",
|
||||
"furi_hal",
|
||||
"inc"
|
||||
],
|
||||
"sdk_header_paths": [
|
||||
"../furi_hal_include",
|
||||
"furi_hal",
|
||||
"platform_specific"
|
||||
],
|
||||
"startup_script": "startup_stm32wb55xx_cm4.s",
|
||||
"linker_script_flash": "stm32wb55xx_flash.ld",
|
||||
"linker_script_ram": "stm32wb55xx_ram_fw.ld",
|
||||
"linker_script_app": "application_ext.ld",
|
||||
"sdk_symbols": "api_symbols.csv",
|
||||
"linker_dependencies": [
|
||||
"print",
|
||||
"flipper7",
|
||||
"furi",
|
||||
"freertos",
|
||||
"stm32cubewb",
|
||||
"hwdrivers",
|
||||
"fatfs",
|
||||
"littlefs",
|
||||
"subghz",
|
||||
"flipperformat",
|
||||
"toolbox",
|
||||
"nfc",
|
||||
"microtar",
|
||||
"usb_stm32",
|
||||
"st25rfal002",
|
||||
"infrared",
|
||||
"appframe",
|
||||
"assets",
|
||||
"one_wire",
|
||||
"ibutton",
|
||||
"misc",
|
||||
"mbedtls",
|
||||
"lfrfid",
|
||||
"flipper_application",
|
||||
"flipperformat",
|
||||
"toolbox"
|
||||
]
|
||||
}
|
||||
@@ -10,37 +10,33 @@ template <unsigned int N>
|
||||
struct STOP_EXTERNING_ME {};
|
||||
#endif
|
||||
|
||||
#include "furi_hal_cortex.h"
|
||||
#include "furi_hal_clock.h"
|
||||
#include "furi_hal_crypto.h"
|
||||
#include "furi_hal_console.h"
|
||||
#include "furi_hal_debug.h"
|
||||
#include "furi_hal_os.h"
|
||||
#include "furi_hal_sd.h"
|
||||
#include "furi_hal_i2c.h"
|
||||
#include "furi_hal_resources.h"
|
||||
#include "furi_hal_region.h"
|
||||
#include "furi_hal_rtc.h"
|
||||
#include "furi_hal_speaker.h"
|
||||
#include "furi_hal_gpio.h"
|
||||
#include "furi_hal_light.h"
|
||||
#include "furi_hal_power.h"
|
||||
#include "furi_hal_interrupt.h"
|
||||
#include "furi_hal_version.h"
|
||||
#include "furi_hal_bt.h"
|
||||
#include "furi_hal_spi.h"
|
||||
#include "furi_hal_flash.h"
|
||||
#include "furi_hal_subghz.h"
|
||||
#include "furi_hal_vibro.h"
|
||||
#include "furi_hal_ibutton.h"
|
||||
#include "furi_hal_rfid.h"
|
||||
#include "furi_hal_nfc.h"
|
||||
#include "furi_hal_usb.h"
|
||||
#include "furi_hal_usb_hid.h"
|
||||
#include "furi_hal_compress.h"
|
||||
#include "furi_hal_uart.h"
|
||||
#include "furi_hal_info.h"
|
||||
#include "furi_hal_random.h"
|
||||
#include <furi_hal_cortex.h>
|
||||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_os.h>
|
||||
#include <furi_hal_sd.h>
|
||||
#include <furi_hal_i2c.h>
|
||||
#include <furi_hal_region.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_speaker.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_light.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_version.h>
|
||||
#include <furi_hal_bt.h>
|
||||
#include <furi_hal_spi.h>
|
||||
#include <furi_hal_flash.h>
|
||||
#include <furi_hal_vibro.h>
|
||||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_info.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_target_hw.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <ble_glue.h>
|
||||
#include <ble_app.h>
|
||||
|
||||
#include "furi_hal_bt_serial.h"
|
||||
#include <furi_hal_bt_serial.h>
|
||||
|
||||
#define FURI_HAL_BT_STACK_VERSION_MAJOR (1)
|
||||
#define FURI_HAL_BT_STACK_VERSION_MINOR (12)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* @file furi_hal_compress.h
|
||||
* LZSS based compression HAL API
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Defines encoder and decoder window size */
|
||||
#define FURI_HAL_COMPRESS_EXP_BUFF_SIZE_LOG (8)
|
||||
|
||||
/** Defines encoder and decoder lookahead buffer size */
|
||||
#define FURI_HAL_COMPRESS_LOOKAHEAD_BUFF_SIZE_LOG (4)
|
||||
|
||||
/** FuriHalCompress control structure */
|
||||
typedef struct FuriHalCompress FuriHalCompress;
|
||||
|
||||
/** Initialize icon decoder
|
||||
*/
|
||||
void furi_hal_compress_icon_init();
|
||||
|
||||
/** Icon decoder
|
||||
*
|
||||
* @param icon_data pointer to icon data
|
||||
* @param decoded_buff pointer to decoded buffer
|
||||
*/
|
||||
void furi_hal_compress_icon_decode(const uint8_t* icon_data, uint8_t** decoded_buff);
|
||||
|
||||
/** Allocate encoder and decoder
|
||||
*
|
||||
* @param compress_buff_size size of decoder and encoder buffer to allocate
|
||||
*
|
||||
* @return FuriHalCompress instance
|
||||
*/
|
||||
FuriHalCompress* furi_hal_compress_alloc(uint16_t compress_buff_size);
|
||||
|
||||
/** Free encoder and decoder
|
||||
*
|
||||
* @param compress FuriHalCompress instance
|
||||
*/
|
||||
void furi_hal_compress_free(FuriHalCompress* compress);
|
||||
|
||||
/** Encode data
|
||||
*
|
||||
* @param compress FuriHalCompress instance
|
||||
* @param data_in pointer to input data
|
||||
* @param data_in_size size of input data
|
||||
* @param data_out maximum size of output data
|
||||
* @param data_res_size pointer to result output data size
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool furi_hal_compress_encode(
|
||||
FuriHalCompress* compress,
|
||||
uint8_t* data_in,
|
||||
size_t data_in_size,
|
||||
uint8_t* data_out,
|
||||
size_t data_out_size,
|
||||
size_t* data_res_size);
|
||||
|
||||
/** Decode data
|
||||
*
|
||||
* @param compress FuriHalCompress instance
|
||||
* @param data_in pointer to input data
|
||||
* @param data_in_size size of input data
|
||||
* @param data_out maximum size of output data
|
||||
* @param data_res_size pointer to result output data size
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool furi_hal_compress_decode(
|
||||
FuriHalCompress* compress,
|
||||
uint8_t* data_in,
|
||||
size_t data_in_size,
|
||||
uint8_t* data_out,
|
||||
size_t data_out_size,
|
||||
size_t* data_res_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* @file furi_hal_ibutton.h
|
||||
* iButton HAL API
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "furi_hal_gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*FuriHalIbuttonEmulateCallback)(void* context);
|
||||
|
||||
/** Initialize */
|
||||
void furi_hal_ibutton_init();
|
||||
|
||||
void furi_hal_ibutton_emulate_start(
|
||||
uint32_t period,
|
||||
FuriHalIbuttonEmulateCallback callback,
|
||||
void* context);
|
||||
|
||||
void furi_hal_ibutton_emulate_set_next(uint32_t period);
|
||||
|
||||
void furi_hal_ibutton_emulate_stop();
|
||||
|
||||
/**
|
||||
* Sets the pin to normal mode (open collector), and sets it to float
|
||||
*/
|
||||
void furi_hal_ibutton_start_drive();
|
||||
|
||||
/**
|
||||
* Sets the pin to normal mode (open collector), and clears pin EXTI interrupt.
|
||||
* Used in EXTI interrupt context.
|
||||
*/
|
||||
void furi_hal_ibutton_start_drive_in_isr();
|
||||
|
||||
/**
|
||||
* Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and sets it to float
|
||||
*/
|
||||
void furi_hal_ibutton_start_interrupt();
|
||||
|
||||
/**
|
||||
* Sets the pin to interrupt mode (EXTI interrupt on rise or fall), and clears pin EXTI interrupt.
|
||||
* Used in EXTI interrupt context.
|
||||
*/
|
||||
void furi_hal_ibutton_start_interrupt_in_isr();
|
||||
|
||||
/**
|
||||
* Sets the pin to analog mode, and sets it to float
|
||||
*/
|
||||
void furi_hal_ibutton_stop();
|
||||
|
||||
/**
|
||||
* Attach interrupt callback to iButton pin
|
||||
* @param cb callback
|
||||
* @param context context
|
||||
*/
|
||||
void furi_hal_ibutton_add_interrupt(GpioExtiCallback cb, void* context);
|
||||
|
||||
/**
|
||||
* Remove interrupt callback from iButton pin
|
||||
*/
|
||||
void furi_hal_ibutton_remove_interrupt();
|
||||
|
||||
/**
|
||||
* Sets the pin to low
|
||||
*/
|
||||
void furi_hal_ibutton_pin_low();
|
||||
|
||||
/**
|
||||
* Sets the pin to high (float in iButton pin modes)
|
||||
*/
|
||||
void furi_hal_ibutton_pin_high();
|
||||
|
||||
/**
|
||||
* Get pin level
|
||||
* @return true if level is high
|
||||
* @return false if level is low
|
||||
*/
|
||||
bool furi_hal_ibutton_pin_get_level();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -121,21 +121,21 @@ void furi_hal_power_check_otg_status();
|
||||
*/
|
||||
bool furi_hal_power_is_otg_enabled();
|
||||
|
||||
/** Get battery charging voltage in V
|
||||
/** Get battery charge voltage limit in V
|
||||
*
|
||||
* @return voltage in V
|
||||
*/
|
||||
float furi_hal_power_get_battery_charging_voltage();
|
||||
float furi_hal_power_get_battery_charge_voltage_limit();
|
||||
|
||||
/** Set battery charging voltage in V
|
||||
/** Set battery charge voltage limit in V
|
||||
*
|
||||
* Invalid values will be clamped to the nearest valid value.
|
||||
* Invalid values will be clamped downward to the nearest valid value.
|
||||
*
|
||||
* @param voltage[in] voltage in V
|
||||
*
|
||||
* @return voltage in V
|
||||
*/
|
||||
void furi_hal_power_set_battery_charging_voltage(float voltage);
|
||||
void furi_hal_power_set_battery_charge_voltage_limit(float voltage);
|
||||
|
||||
/** Get remaining battery battery capacity in mAh
|
||||
*
|
||||
|
||||
@@ -29,6 +29,7 @@ typedef enum {
|
||||
FuriHalRtcFlagFactoryReset = (1 << 1),
|
||||
FuriHalRtcFlagLock = (1 << 2),
|
||||
FuriHalRtcFlagC2Update = (1 << 3),
|
||||
FuriHalRtcFlagHandOrient = (1 << 4),
|
||||
} FuriHalRtcFlag;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -8,13 +8,16 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/** Early initialize SPI HAL */
|
||||
void furi_hal_spi_init_early();
|
||||
void furi_hal_spi_config_init_early();
|
||||
|
||||
/** Early deinitialize SPI HAL */
|
||||
void furi_hal_spi_deinit_early();
|
||||
void furi_hal_spi_config_deinit_early();
|
||||
|
||||
/** Initialize SPI HAL */
|
||||
void furi_hal_spi_init();
|
||||
void furi_hal_spi_config_init();
|
||||
|
||||
/** Initialize SPI DMA HAL */
|
||||
void furi_hal_spi_dma_init();
|
||||
|
||||
/** Initialize SPI Bus
|
||||
*
|
||||
@@ -82,7 +85,7 @@ bool furi_hal_spi_bus_rx(
|
||||
*/
|
||||
bool furi_hal_spi_bus_tx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buffer,
|
||||
const uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
@@ -98,11 +101,28 @@ bool furi_hal_spi_bus_tx(
|
||||
*/
|
||||
bool furi_hal_spi_bus_trx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx_buffer,
|
||||
const uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive with DMA
|
||||
*
|
||||
* @param handle pointer to FuriHalSpiBusHandle instance
|
||||
* @param tx_buffer pointer to tx buffer
|
||||
* @param rx_buffer pointer to rx buffer
|
||||
* @param size transaction size (buffer size)
|
||||
* @param timeout_ms operation timeout in ms
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool furi_hal_spi_bus_trx_dma(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout_ms);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Max number of simultaneously pressed keys (keyboard) */
|
||||
#define HID_KB_MAX_KEYS 6
|
||||
/** Max number of simultaneously pressed keys (consumer control) */
|
||||
#define HID_CONSUMER_MAX_KEYS 2
|
||||
|
||||
#define HID_KEYBOARD_NONE 0x00
|
||||
|
||||
/** HID keyboard modifier keys */
|
||||
|
||||
@@ -67,6 +67,24 @@ bool furi_hal_version_do_i_belong_here();
|
||||
*/
|
||||
const char* furi_hal_version_get_model_name();
|
||||
|
||||
/** Get model name
|
||||
*
|
||||
* @return model code C-string
|
||||
*/
|
||||
const char* furi_hal_version_get_model_code();
|
||||
|
||||
/** Get FCC ID
|
||||
*
|
||||
* @return FCC id as C-string
|
||||
*/
|
||||
const char* furi_hal_version_get_fcc_id();
|
||||
|
||||
/** Get IC id
|
||||
*
|
||||
* @return IC id as C-string
|
||||
*/
|
||||
const char* furi_hal_version_get_ic_id();
|
||||
|
||||
/** Get OTP version
|
||||
*
|
||||
* @return OTP Version
|
||||
|
||||
Reference in New Issue
Block a user