[FL-2060] FuriHal: SPI refactoring, flexible bus reconfiguration on fly, same design as i2c. (#853)
* FuriHal: SPI refactoring, flexible bus reconfigration on fly, same desiag as i2c. * Lib: update CC1101 driver documentation * FuriHal: update spi symbol names to match naming convention.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
#include <furi-hal-spi-config.h>
|
||||
#include <furi-hal-resources.h>
|
||||
|
||||
#define SPI_R SPI1
|
||||
#define SPI_D SPI2
|
||||
/* SPI Presets */
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
|
||||
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,
|
||||
@@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
|
||||
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,
|
||||
@@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
|
||||
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,
|
||||
@@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* SD Card in fast mode (after init)
|
||||
*/
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
|
||||
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,
|
||||
@@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* SD Card in slow mode (before init)
|
||||
*/
|
||||
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
|
||||
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,
|
||||
@@ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
|
||||
.CRCPoly = 7,
|
||||
};
|
||||
|
||||
const FuriHalSpiBus spi_r = {
|
||||
.spi = SPI_R,
|
||||
/* SPI Buses */
|
||||
|
||||
static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
}
|
||||
}
|
||||
|
||||
FuriHalSpiBus furi_hal_spi_bus_r = {
|
||||
.spi = SPI1,
|
||||
.callback = furi_hal_spi_bus_r_event_callback,
|
||||
};
|
||||
|
||||
static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
|
||||
if(event == FuriHalSpiBusEventInit) {
|
||||
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
bus->current_handle = NULL;
|
||||
} else if(event == FuriHalSpiBusEventDeinit) {
|
||||
} else if(event == FuriHalSpiBusEventLock) {
|
||||
} else if(event == FuriHalSpiBusEventUnlock) {
|
||||
} else if(event == FuriHalSpiBusEventActivate) {
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
} else if(event == FuriHalSpiBusEventDeactivate) {
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
hal_gpio_write(handle->cs, true);
|
||||
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeinit) {
|
||||
hal_gpio_write(handle->cs, true);
|
||||
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);
|
||||
|
||||
hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
|
||||
hal_gpio_write(handle->cs, false);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
|
||||
hal_gpio_write(handle->cs, true);
|
||||
|
||||
hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
LL_SPI_Disable(handle->bus->spi);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_spi_bus_handle_subghz_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = {
|
||||
.bus = &furi_hal_spi_bus_r,
|
||||
.callback = furi_hal_spi_bus_handle_subghz_event_callback,
|
||||
.miso = &gpio_spi_r_miso,
|
||||
.mosi = &gpio_spi_r_mosi,
|
||||
.clk = &gpio_spi_r_sck,
|
||||
.sck = &gpio_spi_r_sck,
|
||||
.cs = &gpio_subghz_cs,
|
||||
};
|
||||
|
||||
const FuriHalSpiBus spi_d = {
|
||||
.spi = SPI_D,
|
||||
static void furi_hal_spi_bus_handle_nfc_event_callback(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event) {
|
||||
furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m);
|
||||
}
|
||||
|
||||
FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = {
|
||||
.bus = &furi_hal_spi_bus_r,
|
||||
.callback = furi_hal_spi_bus_handle_nfc_event_callback,
|
||||
.miso = &gpio_spi_r_miso,
|
||||
.mosi = &gpio_spi_r_mosi,
|
||||
.sck = &gpio_spi_r_sck,
|
||||
.cs = &gpio_nfc_cs,
|
||||
};
|
||||
|
||||
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) {
|
||||
hal_gpio_write(handle->cs, true);
|
||||
hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh);
|
||||
|
||||
hal_gpio_init_ex(
|
||||
handle->miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
hal_gpio_init_ex(
|
||||
handle->mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
hal_gpio_init_ex(
|
||||
handle->sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
|
||||
} else if(event == FuriHalSpiBusHandleEventDeinit) {
|
||||
hal_gpio_write(handle->cs, true);
|
||||
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);
|
||||
hal_gpio_write(handle->cs, false);
|
||||
} else if(event == FuriHalSpiBusHandleEventDeactivate) {
|
||||
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,
|
||||
.clk = &gpio_spi_d_sck,
|
||||
.sck = &gpio_spi_d_sck,
|
||||
.cs = &gpio_display_cs,
|
||||
};
|
||||
|
||||
const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = {
|
||||
{
|
||||
.bus = &spi_r,
|
||||
.config = &furi_hal_spi_config_subghz,
|
||||
.chip_select = &gpio_subghz_cs,
|
||||
},
|
||||
{
|
||||
.bus = &spi_d,
|
||||
.config = &furi_hal_spi_config_display,
|
||||
.chip_select = &gpio_display_cs,
|
||||
},
|
||||
{
|
||||
.bus = &spi_d,
|
||||
.config = &furi_hal_spi_config_sd_fast,
|
||||
.chip_select = &gpio_sdcard_cs,
|
||||
},
|
||||
{
|
||||
.bus = &spi_d,
|
||||
.config = &furi_hal_spi_config_sd_slow,
|
||||
.chip_select = &gpio_sdcard_cs,
|
||||
},
|
||||
{.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_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,
|
||||
};
|
||||
|
@@ -1,60 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi-hal-gpio.h>
|
||||
#include <stm32wbxx_ll_spi.h>
|
||||
#include <furi-hal-spi-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc;
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz;
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_config_display;
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast;
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow;
|
||||
/** Preset for ST25R916 */
|
||||
extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
|
||||
|
||||
/** FURI HAL SPI BUS handler
|
||||
* Structure content may change at some point
|
||||
/** 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 (Radio: CC1101, Nfc, External)*/
|
||||
extern FuriHalSpiBus furi_hal_spi_bus_r;
|
||||
|
||||
/** Furi Hal Spi Bus D (Display, SdCard) */
|
||||
extern FuriHalSpiBus furi_hal_spi_bus_d;
|
||||
|
||||
/** CC1101 on `furi_hal_spi_bus_r` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz;
|
||||
|
||||
/** ST25R3916 on `furi_hal_spi_bus_r` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc;
|
||||
|
||||
/** 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
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
const SPI_TypeDef* spi;
|
||||
const GpioPin* miso;
|
||||
const GpioPin* mosi;
|
||||
const GpioPin* clk;
|
||||
} FuriHalSpiBus;
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
|
||||
|
||||
/** FURI HAL SPI Device handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
const FuriHalSpiBus* bus;
|
||||
const LL_SPI_InitTypeDef* config;
|
||||
const GpioPin* chip_select;
|
||||
} FuriHalSpiDevice;
|
||||
/** ST7567(Display) on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
|
||||
|
||||
/** FURI HAL SPI Standard Device IDs */
|
||||
typedef enum {
|
||||
FuriHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */
|
||||
FuriHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */
|
||||
FuriHalSpiDeviceIdSdCardFast, /** SDCARD: fast mode, after initialization */
|
||||
FuriHalSpiDeviceIdSdCardSlow, /** SDCARD: slow mode, before initialization */
|
||||
FuriHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
|
||||
/** SdCard in fast mode on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
|
||||
|
||||
FuriHalSpiDeviceIdMax, /** Service Value, do not use */
|
||||
} FuriHalSpiDeviceId;
|
||||
|
||||
/** Furi Hal Spi Bus R
|
||||
* CC1101, Nfc
|
||||
*/
|
||||
extern const FuriHalSpiBus spi_r;
|
||||
|
||||
/** Furi Hal Spi Bus D
|
||||
* Display, SdCard
|
||||
*/
|
||||
extern const FuriHalSpiBus spi_d;
|
||||
|
||||
/** Furi Hal Spi devices */
|
||||
extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax];
|
||||
/** SdCard in slow mode on `furi_hal_spi_bus_d` */
|
||||
extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
64
bootloader/targets/f7/furi-hal/furi-hal-spi-types.h
Normal file
64
bootloader/targets/f7/furi-hal/furi-hal-spi-types.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <furi-hal-gpio.h>
|
||||
|
||||
#include <stm32wbxx_ll_spi.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct FuriHalSpiBus FuriHalSpiBus;
|
||||
typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle;
|
||||
|
||||
/** FuriHal spi bus states */
|
||||
typedef enum {
|
||||
FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */
|
||||
FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */
|
||||
FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */
|
||||
FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */
|
||||
FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */
|
||||
FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation */
|
||||
} FuriHalSpiBusEvent;
|
||||
|
||||
/** FuriHal spi bus event callback */
|
||||
typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event);
|
||||
|
||||
/** FuriHal spi bus */
|
||||
struct FuriHalSpiBus {
|
||||
SPI_TypeDef* spi;
|
||||
FuriHalSpiBusEventCallback callback;
|
||||
FuriHalSpiBusHandle* current_handle;
|
||||
};
|
||||
|
||||
/** FuriHal spi handle states */
|
||||
typedef enum {
|
||||
FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */
|
||||
FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */
|
||||
FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */
|
||||
FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */
|
||||
} FuriHalSpiBusHandleEvent;
|
||||
|
||||
/** FuriHal spi handle event callback */
|
||||
typedef void (*FuriHalSpiBusHandleEventCallback)(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
FuriHalSpiBusHandleEvent event);
|
||||
|
||||
/** FuriHal spi handle */
|
||||
struct FuriHalSpiBusHandle {
|
||||
FuriHalSpiBus* bus;
|
||||
FuriHalSpiBusHandleEventCallback callback;
|
||||
const GpioPin* miso;
|
||||
const GpioPin* mosi;
|
||||
const GpioPin* sck;
|
||||
const GpioPin* cs;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@@ -2,239 +2,150 @@
|
||||
#include "furi-hal-resources.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <stm32wbxx_ll_spi.h>
|
||||
#include <stm32wbxx_ll_utils.h>
|
||||
#include <stm32wbxx_ll_cortex.h>
|
||||
|
||||
extern void Enable_SPI(SPI_TypeDef* spi);
|
||||
|
||||
void furi_hal_spi_init() {
|
||||
for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) {
|
||||
hal_gpio_write(furi_hal_spi_devices[i].chip_select, true);
|
||||
hal_gpio_init(
|
||||
furi_hal_spi_devices[i].chip_select,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh);
|
||||
}
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
|
||||
furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
|
||||
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_r_miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_r_mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_r_sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI1);
|
||||
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_d_miso,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_d_mosi,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
hal_gpio_init_ex(
|
||||
&gpio_spi_d_sck,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn5SPI2);
|
||||
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_display);
|
||||
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);
|
||||
}
|
||||
|
||||
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) {
|
||||
void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
|
||||
assert(bus);
|
||||
bus->callback(bus, FuriHalSpiBusEventInit);
|
||||
}
|
||||
|
||||
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) {
|
||||
void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) {
|
||||
assert(bus);
|
||||
bus->callback(bus, FuriHalSpiBusEventDeinit);
|
||||
}
|
||||
|
||||
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) {
|
||||
assert(bus);
|
||||
LL_SPI_DeInit((SPI_TypeDef*)bus->spi);
|
||||
LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config);
|
||||
LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER);
|
||||
LL_SPI_Enable((SPI_TypeDef*)bus->spi);
|
||||
void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
|
||||
assert(handle);
|
||||
handle->callback(handle, FuriHalSpiBusHandleEventInit);
|
||||
}
|
||||
|
||||
void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) {
|
||||
while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY)
|
||||
void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
|
||||
assert(handle);
|
||||
handle->callback(handle, FuriHalSpiBusHandleEventDeinit);
|
||||
}
|
||||
|
||||
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
|
||||
assert(handle);
|
||||
|
||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
|
||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
|
||||
|
||||
assert(handle->bus->current_handle == NULL);
|
||||
|
||||
handle->bus->current_handle = handle;
|
||||
handle->callback(handle, FuriHalSpiBusHandleEventActivate);
|
||||
}
|
||||
|
||||
void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
|
||||
assert(handle);
|
||||
assert(handle->bus->current_handle == handle);
|
||||
|
||||
// Handle event and unset handle
|
||||
handle->callback(handle, FuriHalSpiBusHandleEventDeactivate);
|
||||
handle->bus->current_handle = NULL;
|
||||
|
||||
// Bus events
|
||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate);
|
||||
handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock);
|
||||
}
|
||||
|
||||
static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) {
|
||||
while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY)
|
||||
;
|
||||
while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi))
|
||||
while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi))
|
||||
;
|
||||
while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
|
||||
LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi);
|
||||
while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
|
||||
LL_SPI_ReceiveData8(handle->bus->spi);
|
||||
}
|
||||
}
|
||||
|
||||
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
assert(bus);
|
||||
bool furi_hal_spi_bus_rx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(handle);
|
||||
assert(handle->bus->current_handle == handle);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
||||
return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout);
|
||||
return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout);
|
||||
}
|
||||
|
||||
bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
assert(bus);
|
||||
bool furi_hal_spi_bus_tx(
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(handle);
|
||||
assert(handle->bus->current_handle == handle);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
bool ret = true;
|
||||
|
||||
while(size > 0) {
|
||||
if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) {
|
||||
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer);
|
||||
if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
|
||||
LL_SPI_TransmitData8(handle->bus->spi, *buffer);
|
||||
buffer++;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_spi_bus_end_txrx(bus, timeout);
|
||||
LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi);
|
||||
furi_hal_spi_bus_end_txrx(handle, timeout);
|
||||
LL_SPI_ClearFlag_OVR(handle->bus->spi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool furi_hal_spi_bus_trx(
|
||||
const FuriHalSpiBus* bus,
|
||||
FuriHalSpiBusHandle* handle,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(bus);
|
||||
assert(handle);
|
||||
assert(handle->bus->current_handle == handle);
|
||||
assert(tx_buffer);
|
||||
assert(rx_buffer);
|
||||
assert(size > 0);
|
||||
|
||||
bool ret = true;
|
||||
size_t tx_size = size;
|
||||
bool tx_allowed = true;
|
||||
|
||||
while(size > 0) {
|
||||
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) {
|
||||
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer);
|
||||
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
|
||||
LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
|
||||
tx_buffer++;
|
||||
tx_size--;
|
||||
tx_allowed = false;
|
||||
}
|
||||
|
||||
if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) {
|
||||
*rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi);
|
||||
if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
|
||||
*rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
|
||||
rx_buffer++;
|
||||
size--;
|
||||
tx_allowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
furi_hal_spi_bus_end_txrx(bus, timeout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) {
|
||||
assert(device);
|
||||
assert(device->config);
|
||||
|
||||
furi_hal_spi_bus_configure(device->bus, device->config);
|
||||
}
|
||||
|
||||
const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
|
||||
assert(device_id < FuriHalSpiDeviceIdMax);
|
||||
|
||||
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
|
||||
assert(device);
|
||||
|
||||
furi_hal_spi_bus_lock(device->bus);
|
||||
furi_hal_spi_device_configure(device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void furi_hal_spi_device_return(const FuriHalSpiDevice* device) {
|
||||
furi_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
||||
bool furi_hal_spi_device_rx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(device);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool furi_hal_spi_device_tx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(device);
|
||||
assert(buffer);
|
||||
assert(size > 0);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool furi_hal_spi_device_trx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout) {
|
||||
assert(device);
|
||||
assert(tx_buffer);
|
||||
assert(rx_buffer);
|
||||
assert(size > 0);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout);
|
||||
|
||||
if(device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
furi_hal_spi_bus_end_txrx(handle, timeout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -1,129 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include "furi-hal-spi-config.h"
|
||||
#include <furi-hal-gpio.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Init SPI API
|
||||
*/
|
||||
void furi_hal_spi_init();
|
||||
|
||||
/* Bus Level API */
|
||||
|
||||
/** Lock SPI bus
|
||||
* Takes bus mutex, if used
|
||||
*/
|
||||
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus);
|
||||
|
||||
/** Unlock SPI bus
|
||||
* Releases BUS mutex, if used
|
||||
*/
|
||||
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus);
|
||||
|
||||
/**
|
||||
* Configure SPI bus
|
||||
* @param bus - spi bus handler
|
||||
* @param config - spi configuration structure
|
||||
*/
|
||||
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config);
|
||||
|
||||
/** SPI Receive
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param bus - spi bus handlere
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_bus_trx(
|
||||
const FuriHalSpiBus* bus,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/* Device Level API */
|
||||
|
||||
/** Reconfigure SPI bus for device
|
||||
* @param device - device description
|
||||
*/
|
||||
void furi_hal_spi_device_configure(const FuriHalSpiDevice* device);
|
||||
|
||||
/** Get Device handle
|
||||
* And lock access to the corresponding SPI BUS
|
||||
* @param device_id - device identifier
|
||||
* @return device handle
|
||||
*/
|
||||
const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id);
|
||||
|
||||
/** Return Device handle
|
||||
* And unlock access to the corresponding SPI BUS
|
||||
* @param device - device handle
|
||||
*/
|
||||
void furi_hal_spi_device_return(const FuriHalSpiDevice* device);
|
||||
|
||||
/** SPI Recieve
|
||||
* @param device - device handle
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_device_rx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param device - device handle
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_device_tx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param device - device handle
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool furi_hal_spi_device_trx(
|
||||
const FuriHalSpiDevice* device,
|
||||
uint8_t* tx_buffer,
|
||||
uint8_t* rx_buffer,
|
||||
size_t size,
|
||||
uint32_t timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user