[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:
あく 2021-11-30 15:09:43 +03:00 committed by GitHub
parent d86125c7f7
commit 9d27ef8901
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 2057 additions and 1612 deletions

View File

@ -1,10 +1,9 @@
#include <furi-hal-spi-config.h> #include <furi-hal-spi-config.h>
#include <furi-hal-resources.h> #include <furi-hal-resources.h>
#define SPI_R SPI1 /* SPI Presets */
#define SPI_D SPI2
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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
* SD Card in fast mode (after init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
* SD Card in slow mode (before init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
const FuriHalSpiBus spi_r = { /* SPI Buses */
.spi = SPI_R,
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, .miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi, .mosi = &gpio_spi_r_mosi,
.clk = &gpio_spi_r_sck, .sck = &gpio_spi_r_sck,
.cs = &gpio_subghz_cs,
}; };
const FuriHalSpiBus spi_d = { static void furi_hal_spi_bus_handle_nfc_event_callback(
.spi = SPI_D, 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, .miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi, .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] = { static void furi_hal_spi_bus_handle_sd_fast_event_callback(
{ FuriHalSpiBusHandle* handle,
.bus = &spi_r, FuriHalSpiBusHandleEvent event) {
.config = &furi_hal_spi_config_subghz, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
.chip_select = &gpio_subghz_cs, }
},
{ FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
.bus = &spi_d, .bus = &furi_hal_spi_bus_d,
.config = &furi_hal_spi_config_display, .callback = furi_hal_spi_bus_handle_sd_fast_event_callback,
.chip_select = &gpio_display_cs, .miso = &gpio_spi_d_miso,
}, .mosi = &gpio_spi_d_mosi,
{ .sck = &gpio_spi_d_sck,
.bus = &spi_d, .cs = &gpio_sdcard_cs,
.config = &furi_hal_spi_config_sd_fast, };
.chip_select = &gpio_sdcard_cs,
}, static void furi_hal_spi_bus_handle_sd_slow_event_callback(
{ FuriHalSpiBusHandle* handle,
.bus = &spi_d, FuriHalSpiBusHandleEvent event) {
.config = &furi_hal_spi_config_sd_slow, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
.chip_select = &gpio_sdcard_cs, }
},
{.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, 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,
}; };

View File

@ -1,60 +1,60 @@
#pragma once #pragma once
#include <furi-hal-gpio.h> #include <furi-hal-spi-types.h>
#include <stm32wbxx_ll_spi.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; /** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
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;
/** FURI HAL SPI BUS handler /** Preset for CC1101 */
* Structure content may change at some point 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 { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
const SPI_TypeDef* spi;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* clk;
} FuriHalSpiBus;
/** FURI HAL SPI Device handler /** ST7567(Display) on `furi_hal_spi_bus_d` */
* Structure content may change at some point extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
*/
typedef struct {
const FuriHalSpiBus* bus;
const LL_SPI_InitTypeDef* config;
const GpioPin* chip_select;
} FuriHalSpiDevice;
/** FURI HAL SPI Standard Device IDs */ /** SdCard in fast mode on `furi_hal_spi_bus_d` */
typedef enum { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
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 */
FuriHalSpiDeviceIdMax, /** Service Value, do not use */ /** SdCard in slow mode on `furi_hal_spi_bus_d` */
} FuriHalSpiDeviceId; extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
/** 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];
#ifdef __cplusplus #ifdef __cplusplus
} }

View 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

View File

@ -2,239 +2,150 @@
#include "furi-hal-resources.h" #include "furi-hal-resources.h"
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <stm32wbxx_ll_spi.h> #include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_utils.h> #include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_cortex.h> #include <stm32wbxx_ll_cortex.h>
extern void Enable_SPI(SPI_TypeDef* spi);
void furi_hal_spi_init() { void furi_hal_spi_init() {
for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
hal_gpio_init(
furi_hal_spi_devices[i].chip_select,
GpioModeOutputPushPull,
GpioPullNo,
GpioSpeedVeryHigh);
}
hal_gpio_init_ex( furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
&gpio_spi_r_miso, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
GpioModeAltFunctionPushPull, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
GpioPullNo, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
GpioSpeedVeryHigh, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
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);
} }
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
assert(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); assert(bus);
bus->callback(bus, FuriHalSpiBusEventDeinit);
} }
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
assert(bus); assert(handle);
LL_SPI_DeInit((SPI_TypeDef*)bus->spi); handle->callback(handle, FuriHalSpiBusHandleEventInit);
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_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) 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) { while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); LL_SPI_ReceiveData8(handle->bus->spi);
} }
} }
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { bool furi_hal_spi_bus_rx(
assert(bus); FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer); assert(buffer);
assert(size > 0); 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) { bool furi_hal_spi_bus_tx(
assert(bus); FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer); assert(buffer);
assert(size > 0); assert(size > 0);
bool ret = true; bool ret = true;
while(size > 0) { while(size > 0) {
if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++; buffer++;
size--; size--;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret; return ret;
} }
bool furi_hal_spi_bus_trx( bool furi_hal_spi_bus_trx(
const FuriHalSpiBus* bus, FuriHalSpiBusHandle* handle,
uint8_t* tx_buffer, uint8_t* tx_buffer,
uint8_t* rx_buffer, uint8_t* rx_buffer,
size_t size, size_t size,
uint32_t timeout) { uint32_t timeout) {
assert(bus); assert(handle);
assert(handle->bus->current_handle == handle);
assert(tx_buffer); assert(tx_buffer);
assert(rx_buffer); assert(rx_buffer);
assert(size > 0); assert(size > 0);
bool ret = true; bool ret = true;
size_t tx_size = size; size_t tx_size = size;
bool tx_allowed = true; bool tx_allowed = true;
while(size > 0) { while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++; tx_buffer++;
tx_size--; tx_size--;
tx_allowed = false; tx_allowed = false;
} }
if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++; rx_buffer++;
size--; size--;
tx_allowed = true; tx_allowed = true;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, 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);
}
return ret; return ret;
} }

View File

@ -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

View File

@ -1,10 +1,9 @@
#include <furi-hal-spi-config.h> #include <furi-hal-spi-config.h>
#include <furi-hal-resources.h> #include <furi-hal-resources.h>
#define SPI_R SPI1 /* SPI Presets */
#define SPI_D SPI2
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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
* SD Card in fast mode (after init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
* SD Card in slow mode (before init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
const FuriHalSpiBus spi_r = { /* SPI Buses */
.spi = SPI_R,
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, .miso = &gpio_spi_r_miso,
.mosi = &gpio_spi_r_mosi, .mosi = &gpio_spi_r_mosi,
.clk = &gpio_spi_r_sck, .sck = &gpio_spi_r_sck,
.cs = &gpio_subghz_cs,
}; };
const FuriHalSpiBus spi_d = { static void furi_hal_spi_bus_handle_nfc_event_callback(
.spi = SPI_D, 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, .miso = &gpio_spi_d_miso,
.mosi = &gpio_spi_d_mosi, .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] = { static void furi_hal_spi_bus_handle_sd_fast_event_callback(
{ FuriHalSpiBusHandle* handle,
.bus = &spi_r, FuriHalSpiBusHandleEvent event) {
.config = &furi_hal_spi_config_subghz, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
.chip_select = &gpio_subghz_cs, }
},
{ FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
.bus = &spi_d, .bus = &furi_hal_spi_bus_d,
.config = &furi_hal_spi_config_display, .callback = furi_hal_spi_bus_handle_sd_fast_event_callback,
.chip_select = &gpio_display_cs, .miso = &gpio_spi_d_miso,
}, .mosi = &gpio_spi_d_mosi,
{ .sck = &gpio_spi_d_sck,
.bus = &spi_d, .cs = &gpio_sdcard_cs,
.config = &furi_hal_spi_config_sd_fast, };
.chip_select = &gpio_sdcard_cs,
}, static void furi_hal_spi_bus_handle_sd_slow_event_callback(
{ FuriHalSpiBusHandle* handle,
.bus = &spi_d, FuriHalSpiBusHandleEvent event) {
.config = &furi_hal_spi_config_sd_slow, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m);
.chip_select = &gpio_sdcard_cs, }
},
{.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, 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,
}; };

View File

@ -1,60 +1,60 @@
#pragma once #pragma once
#include <furi-hal-gpio.h> #include <furi-hal-spi-types.h>
#include <stm32wbxx_ll_spi.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; /** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
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;
/** FURI HAL SPI BUS handler /** Preset for CC1101 */
* Structure content may change at some point 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 { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
const SPI_TypeDef* spi;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* clk;
} FuriHalSpiBus;
/** FURI HAL SPI Device handler /** ST7567(Display) on `furi_hal_spi_bus_d` */
* Structure content may change at some point extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
*/
typedef struct {
const FuriHalSpiBus* bus;
const LL_SPI_InitTypeDef* config;
const GpioPin* chip_select;
} FuriHalSpiDevice;
/** FURI HAL SPI Standard Device IDs */ /** SdCard in fast mode on `furi_hal_spi_bus_d` */
typedef enum { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
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 */
FuriHalSpiDeviceIdMax, /** Service Value, do not use */ /** SdCard in slow mode on `furi_hal_spi_bus_d` */
} FuriHalSpiDeviceId; extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
/** 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];
#ifdef __cplusplus #ifdef __cplusplus
} }

View 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

View File

@ -2,239 +2,150 @@
#include "furi-hal-resources.h" #include "furi-hal-resources.h"
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <stm32wbxx_ll_spi.h> #include <stm32wbxx_ll_spi.h>
#include <stm32wbxx_ll_utils.h> #include <stm32wbxx_ll_utils.h>
#include <stm32wbxx_ll_cortex.h> #include <stm32wbxx_ll_cortex.h>
extern void Enable_SPI(SPI_TypeDef* spi);
void furi_hal_spi_init() { void furi_hal_spi_init() {
for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
hal_gpio_init(
furi_hal_spi_devices[i].chip_select,
GpioModeOutputPushPull,
GpioPullNo,
GpioSpeedVeryHigh);
}
hal_gpio_init_ex( furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
&gpio_spi_r_miso, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
GpioModeAltFunctionPushPull, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display);
GpioPullNo, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast);
GpioSpeedVeryHigh, furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
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);
} }
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
assert(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); assert(bus);
bus->callback(bus, FuriHalSpiBusEventDeinit);
} }
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
assert(bus); assert(handle);
LL_SPI_DeInit((SPI_TypeDef*)bus->spi); handle->callback(handle, FuriHalSpiBusHandleEventInit);
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_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) 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) { while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) {
LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); LL_SPI_ReceiveData8(handle->bus->spi);
} }
} }
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { bool furi_hal_spi_bus_rx(
assert(bus); FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer); assert(buffer);
assert(size > 0); 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) { bool furi_hal_spi_bus_tx(
assert(bus); FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout) {
assert(handle);
assert(handle->bus->current_handle == handle);
assert(buffer); assert(buffer);
assert(size > 0); assert(size > 0);
bool ret = true; bool ret = true;
while(size > 0) { while(size > 0) {
if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++; buffer++;
size--; size--;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret; return ret;
} }
bool furi_hal_spi_bus_trx( bool furi_hal_spi_bus_trx(
const FuriHalSpiBus* bus, FuriHalSpiBusHandle* handle,
uint8_t* tx_buffer, uint8_t* tx_buffer,
uint8_t* rx_buffer, uint8_t* rx_buffer,
size_t size, size_t size,
uint32_t timeout) { uint32_t timeout) {
assert(bus); assert(handle);
assert(handle->bus->current_handle == handle);
assert(tx_buffer); assert(tx_buffer);
assert(rx_buffer); assert(rx_buffer);
assert(size > 0); assert(size > 0);
bool ret = true; bool ret = true;
size_t tx_size = size; size_t tx_size = size;
bool tx_allowed = true; bool tx_allowed = true;
while(size > 0) { while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++; tx_buffer++;
tx_size--; tx_size--;
tx_allowed = false; tx_allowed = false;
} }
if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++; rx_buffer++;
size--; size--;
tx_allowed = true; tx_allowed = true;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, 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);
}
return ret; return ret;
} }

View File

@ -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

View File

@ -0,0 +1,102 @@
#pragma once
#include <furi-hal-spi-config.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Initialize SPI HAL */
void furi_hal_spi_init();
/** Initialize SPI Bus
*
* @param handle pointer to FuriHalSpiBus instance
*/
void furi_hal_spi_bus_init(FuriHalSpiBus* bus);
/** Deinitialize SPI Bus
*
* @param handle pointer to FuriHalSpiBus instance
*/
void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus);
/** Initialize SPI Bus Handle
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle);
/** Deinitialize SPI Bus Handle
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle);
/** Acquire SPI bus
*
* @warning blocking, calls `furi_crash` on programming error, CS transition is up to handler event routine
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle);
/** Release SPI bus
*
* @warning calls `furi_crash` on programming error, CS transition is up to handler event routine
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_release(FuriHalSpiBusHandle* handle);
/** SPI Receive
*
* @param handle pointer to FuriHalSpiBusHandle instance
* @param buffer receive buffer
* @param size transaction size (buffer size)
* @param timeout operation timeout in ms
*
* @return true on sucess
*/
bool furi_hal_spi_bus_rx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout);
/** SPI Transmit
*
* @param handle pointer to FuriHalSpiBusHandle instance
* @param buffer transmit buffer
* @param size transaction size (buffer size)
* @param timeout operation timeout in ms
*
* @return true on success
*/
bool furi_hal_spi_bus_tx(
FuriHalSpiBusHandle* handle,
uint8_t* buffer,
size_t size,
uint32_t timeout);
/** SPI Transmit and Receive
*
* @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 operation timeout in ms
*
* @return true on success
*/
bool furi_hal_spi_bus_trx(
FuriHalSpiBusHandle* handle,
uint8_t* tx_buffer,
uint8_t* rx_buffer,
size_t size,
uint32_t timeout);
#ifdef __cplusplus
}
#endif

View File

@ -7,8 +7,6 @@
const uint32_t SpiTimeout = 1000; const uint32_t SpiTimeout = 1000;
uint8_t SD_IO_WriteByte(uint8_t Data); uint8_t SD_IO_WriteByte(uint8_t Data);
static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast];
/****************************************************************************** /******************************************************************************
BUS OPERATIONS BUS OPERATIONS
*******************************************************************************/ *******************************************************************************/
@ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi
* @retval None * @retval None
*/ */
static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
furi_check(furi_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout));
} }
/** /**
@ -30,7 +28,7 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t
* @retval None * @retval None
*/ */
__attribute__((unused)) static void SPIx_Write(uint8_t Value) { __attribute__((unused)) static void SPIx_Write(uint8_t Value) {
furi_check(furi_hal_spi_bus_tx(sd_spi_dev->bus, (uint8_t*)&Value, 1, SpiTimeout)); furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout));
} }
/****************************************************************************** /******************************************************************************
@ -47,7 +45,7 @@ void SD_IO_Init(void) {
uint8_t counter = 0; uint8_t counter = 0;
/* SD chip select high */ /* SD chip select high */
hal_gpio_write(sd_spi_dev->chip_select, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
delay_us(10); delay_us(10);
/* Send dummy byte 0xFF, 10 times with CS high */ /* Send dummy byte 0xFF, 10 times with CS high */
@ -67,9 +65,9 @@ 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 */ /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */
if(val == 1) { if(val == 1) {
delay_us(10); // Exit guard time for some SD cards delay_us(10); // Exit guard time for some SD cards
hal_gpio_write(sd_spi_dev->chip_select, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
} else { } else {
hal_gpio_write(sd_spi_dev->chip_select, false); hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
delay_us(10); // Entry guard time for some SD cards delay_us(10); // Entry guard time for some SD cards
} }
} }

View File

@ -91,12 +91,7 @@
#include "stdlib.h" #include "stdlib.h"
#include "string.h" #include "string.h"
#include "stdio.h" #include "stdio.h"
#include <furi-hal-spi.h> #include <furi-hal.h>
#include <furi-hal-gpio.h>
#include <furi-hal-resources.h>
#include <furi-hal-power.h>
#include <furi-hal-delay.h>
#include <furi-hal-sd.h>
/** @addtogroup BSP /** @addtogroup BSP
* @{ * @{
@ -284,22 +279,22 @@ static uint8_t SD_ReadData(void);
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
void SD_SPI_Bus_To_Down_State(){ void SD_SPI_Bus_To_Down_State(){
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_write(&gpio_sdcard_cs, false); hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
hal_gpio_write(&gpio_spi_d_miso, false); hal_gpio_write(furi_hal_sd_spi_handle->miso, false);
hal_gpio_write(&gpio_spi_d_mosi, false); hal_gpio_write(furi_hal_sd_spi_handle->mosi, false);
hal_gpio_write(&gpio_spi_d_sck, false); hal_gpio_write(furi_hal_sd_spi_handle->sck, false);
} }
void SD_SPI_Bus_To_Normal_State(){ void SD_SPI_Bus_To_Normal_State(){
hal_gpio_write(&gpio_sdcard_cs, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
} }
/** @defgroup STM32_ADAFRUIT_SD_Private_Functions /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
@ -315,7 +310,8 @@ void SD_SPI_Bus_To_Normal_State(){
*/ */
uint8_t BSP_SD_Init(bool reset_card) { uint8_t BSP_SD_Init(bool reset_card) {
/* Slow speed init */ /* Slow speed init */
const FuriHalSpiDevice* sd_spi_slow_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardSlow); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow;
/* We must reset card in spi_lock context */ /* We must reset card in spi_lock context */
if(reset_card) { if(reset_card) {
@ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) {
if(res == BSP_SD_OK) break; if(res == BSP_SD_OK) break;
} }
furi_hal_spi_device_return(sd_spi_slow_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow);
/* SD initialized and set to SPI mode properly */ /* SD initialized and set to SPI mode properly */
return res; return res;

View File

@ -35,7 +35,7 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "user_diskio.h" #include "user_diskio.h"
#include "furi-hal-spi.h" #include <furi-hal.h>
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = {
DSTATUS USER_initialize(BYTE pdrv) { DSTATUS USER_initialize(BYTE pdrv) {
/* USER CODE BEGIN INIT */ /* USER CODE BEGIN INIT */
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); 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 = User_CheckStatus(pdrv);
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return status; return status;
/* USER CODE END INIT */ /* USER CODE END INIT */
@ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
/* USER CODE BEGIN READ */ /* USER CODE BEGIN READ */
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
/* wait until the read operation is finished */ /* wait until the read operation is finished */
@ -129,7 +132,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
res = RES_OK; res = RES_OK;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END READ */ /* USER CODE END READ */
@ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
/* USER CODE HERE */ /* USER CODE HERE */
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
/* wait until the Write operation is finished */ /* wait until the Write operation is finished */
@ -158,7 +163,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
res = RES_OK; res = RES_OK;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END WRITE */ /* USER CODE END WRITE */
@ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
if(Stat & STA_NOINIT) return RES_NOTRDY; if(Stat & STA_NOINIT) return RES_NOTRDY;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
switch(cmd) { switch(cmd) {
/* Make sure that no pending write process */ /* Make sure that no pending write process */
@ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
res = RES_PARERR; res = RES_PARERR;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END IOCTL */ /* USER CODE END IOCTL */

View File

@ -20,3 +20,5 @@ bool hal_sd_detect(void) {
bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin));
return result; return result;
} }
FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL;

View File

@ -1,10 +1,9 @@
#include <furi-hal-spi-config.h> #include <furi-hal-spi-config.h>
#include <furi-hal-resources.h> #include <furi-hal-resources.h>
#define SPI_R SPI1 /* SPI Presets */
#define SPI_D SPI2
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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
* SD Card in fast mode (after init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
* SD Card in slow mode (before init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
osMutexId_t spi_mutex_d = NULL; /* SPI Buses */
osMutexId_t spi_mutex_r = NULL;
const FuriHalSpiBus spi_r = { osMutexId_t furi_hal_spi_bus_r_mutex = NULL;
.spi=SPI_R,
.mutex=&spi_mutex_r, static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if (event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_r_mutex = osMutexNew(NULL);
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) {
furi_check(osMutexDelete(furi_hal_spi_bus_r_mutex));
} else if (event == FuriHalSpiBusEventLock) {
furi_check(osMutexAcquire(furi_hal_spi_bus_r_mutex, osWaitForever) == osOK);
} else if (event == FuriHalSpiBusEventUnlock) {
furi_check(osMutexRelease(furi_hal_spi_bus_r_mutex) == osOK);
} 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,
};
osMutexId_t 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 = osMutexNew(NULL);
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) {
furi_check(osMutexDelete(furi_hal_spi_bus_d_mutex));
} else if (event == FuriHalSpiBusEventLock) {
furi_check(osMutexAcquire(furi_hal_spi_bus_d_mutex, osWaitForever) == osOK);
} else if (event == FuriHalSpiBusEventUnlock) {
furi_check(osMutexRelease(furi_hal_spi_bus_d_mutex) == osOK);
} 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, .miso=&gpio_spi_r_miso,
.mosi=&gpio_spi_r_mosi, .mosi=&gpio_spi_r_mosi,
.clk=&gpio_spi_r_sck, .sck=&gpio_spi_r_sck,
.cs=&gpio_subghz_cs,
}; };
const FuriHalSpiBus spi_d = { static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) {
.spi=SPI_D, furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m);
.mutex=&spi_mutex_d, }
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, .miso=&gpio_spi_d_miso,
.mosi=&gpio_spi_d_mosi, .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] = { static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) {
{ .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
{ .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, }, FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
{ .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, .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,
}; };

View File

@ -1,62 +1,60 @@
#pragma once #pragma once
#include <furi-hal-gpio.h> #include <furi-hal-spi-types.h>
#include <stm32wbxx_ll_spi.h>
#include <cmsis_os2.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; /** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
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;
/** FURI HAL SPI BUS handler /** Preset for CC1101 */
* Structure content may change at some point 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 { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
const SPI_TypeDef* spi;
const osMutexId_t* mutex;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* clk;
} FuriHalSpiBus;
/** FURI HAL SPI Device handler /** ST7567(Display) on `furi_hal_spi_bus_d` */
* Structure content may change at some point extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
*/
typedef struct {
const FuriHalSpiBus* bus;
const LL_SPI_InitTypeDef* config;
const GpioPin* chip_select;
} FuriHalSpiDevice;
/** FURI HAL SPI Standard Device IDs */ /** SdCard in fast mode on `furi_hal_spi_bus_d` */
typedef enum { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
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 */
FuriHalSpiDeviceIdMax, /** Service Value, do not use */ /** SdCard in slow mode on `furi_hal_spi_bus_d` */
} FuriHalSpiDeviceId; extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
/** 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];
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,62 @@
#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

View File

@ -12,89 +12,104 @@
#define TAG "FuriHalSpi" #define TAG "FuriHalSpi"
void furi_hal_spi_init() { void furi_hal_spi_init() {
// Spi structure is const, but mutex is not furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
// Need some hell-ish casting to make it work furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
*(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
*(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
//
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
);
}
hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); 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);
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
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_LOG_I(TAG, "Init OK"); FURI_LOG_I(TAG, "Init OK");
} }
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
furi_assert(bus); furi_assert(bus);
furi_check(osMutexAcquire(*bus->mutex, osWaitForever) == osOK); bus->callback(bus, FuriHalSpiBusEventInit);
} }
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) {
furi_assert(bus); furi_assert(bus);
furi_check(osMutexRelease(*bus->mutex) == osOK); bus->callback(bus, FuriHalSpiBusEventDeinit);
} }
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
furi_assert(bus); furi_assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventInit);
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_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); furi_assert(handle);
while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); handle->callback(handle, FuriHalSpiBusHandleEventDeinit);
while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { }
LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi);
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
furi_assert(handle);
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
furi_assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->callback(handle, FuriHalSpiBusHandleEventActivate);
}
void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
furi_assert(handle);
furi_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(handle->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) { bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(buffer); furi_assert(buffer);
furi_assert(size > 0); furi_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) { bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(buffer); furi_assert(buffer);
furi_assert(size > 0); furi_assert(size > 0);
bool ret = true; bool ret = true;
while(size > 0) { while(size > 0) {
if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++; buffer++;
size--; size--;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret; return ret;
} }
bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(tx_buffer); furi_assert(tx_buffer);
furi_assert(rx_buffer); furi_assert(rx_buffer);
furi_assert(size > 0); furi_assert(size > 0);
@ -104,99 +119,22 @@ bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t*
bool tx_allowed = true; bool tx_allowed = true;
while(size > 0) { while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++; tx_buffer++;
tx_size--; tx_size--;
tx_allowed = false; tx_allowed = false;
} }
if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++; rx_buffer++;
size--; size--;
tx_allowed = true; tx_allowed = true;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
return ret;
}
void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) {
furi_assert(device);
furi_assert(device->config);
furi_hal_spi_bus_configure(device->bus, device->config);
}
const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
furi_assert(device_id < FuriHalSpiDeviceIdMax);
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
furi_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) {
furi_assert(device);
furi_assert(buffer);
furi_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) {
furi_assert(device);
furi_assert(buffer);
furi_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) {
furi_assert(device);
furi_assert(tx_buffer);
furi_assert(rx_buffer);
furi_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);
}
return ret; return ret;
} }

View File

@ -269,7 +269,7 @@ void furi_hal_subghz_init() {
furi_assert(furi_hal_subghz_state == SubGhzStateInit); furi_assert(furi_hal_subghz_state == SubGhzStateInit);
furi_hal_subghz_state = SubGhzStateIdle; furi_hal_subghz_state = SubGhzStateIdle;
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
#ifdef FURI_HAL_SUBGHZ_TX_GPIO #ifdef FURI_HAL_SUBGHZ_TX_GPIO
hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
@ -277,58 +277,58 @@ void furi_hal_subghz_init() {
// Reset // Reset
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
// Prepare GD0 for power on self test // Prepare GD0 for power on self test
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
// GD0 low // GD0 low
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW);
while(hal_gpio_read(&gpio_cc1101_g0) != false) while(hal_gpio_read(&gpio_cc1101_g0) != false)
; ;
// GD0 high // GD0 high
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
while(hal_gpio_read(&gpio_cc1101_g0) != true) while(hal_gpio_read(&gpio_cc1101_g0) != true)
; ;
// Reset GD0 to floating state // Reset GD0 to floating state
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
// RF switches // RF switches
hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
// Go to sleep // Go to sleep
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
FURI_LOG_I(TAG, "Init OK"); FURI_LOG_I(TAG, "Init OK");
} }
void furi_hal_subghz_sleep() { void furi_hal_subghz_sleep() {
furi_assert(furi_hal_subghz_state == SubGhzStateIdle); furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_dump_state() { void furi_hal_subghz_dump_state() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
printf( printf(
"[furi_hal_subghz] cc1101 chip %d, version %d\r\n", "[furi_hal_subghz] cc1101 chip %d, version %d\r\n",
cc1101_get_partnumber(device), cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz),
cc1101_get_version(device)); cc1101_get_version(&furi_hal_spi_bus_handle_subghz));
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
@ -350,81 +350,81 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
} }
void furi_hal_subghz_load_registers(const uint8_t data[][2]) { void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
uint32_t i = 0; uint32_t i = 0;
while(data[i][0]) { while(data[i][0]) {
cc1101_write_reg(device, data[i][0], data[i][1]); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]);
i++; i++;
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_load_patable(const uint8_t data[8]) { void furi_hal_subghz_load_patable(const uint8_t data[8]) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_set_pa_table(device, data); cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_tx(device); cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz);
cc1101_write_fifo(device, data, size); cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_flush_rx() { void furi_hal_subghz_flush_rx() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_rx(device); cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_read_fifo(device, data, size); cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_shutdown() { void furi_hal_subghz_shutdown() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
// Reset and shutdown // Reset and shutdown
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_reset() { void furi_hal_subghz_reset() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_idle() { void furi_hal_subghz_idle() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_rx() { void furi_hal_subghz_rx() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_rx(device); cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
bool furi_hal_subghz_tx() { bool furi_hal_subghz_tx() {
if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false;
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_tx(device); cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
return true; return true;
} }
float furi_hal_subghz_get_rssi() { float furi_hal_subghz_get_rssi() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
int32_t rssi_dec = cc1101_get_rssi(device); int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
float rssi = rssi_dec; float rssi = rssi_dec;
if(rssi_dec >= 128) { if(rssi_dec >= 128) {
@ -461,7 +461,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) {
} }
uint32_t furi_hal_subghz_set_frequency(uint32_t value) { uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
//checking regional settings //checking regional settings
bool txrx = false; bool txrx = false;
@ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; furi_hal_subghz_regulation = SubGhzRegulationOnlyRx;
} }
uint32_t real_frequency = cc1101_set_frequency(device, value); uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value);
cc1101_calibrate(device); cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
while(true) { while(true) {
CC1101Status status = cc1101_get_status(device); CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
if(status.STATE == CC1101StateIDLE) break; if(status.STATE == CC1101StateIDLE) break;
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
return real_frequency; return real_frequency;
} }
void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
if(path == FuriHalSubGhzPath433) { if(path == FuriHalSubGhzPath433) {
hal_gpio_write(&gpio_rf_sw_0, 0); hal_gpio_write(&gpio_rf_sw_0, 0);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
} else if(path == FuriHalSubGhzPath315) { } else if(path == FuriHalSubGhzPath315) {
hal_gpio_write(&gpio_rf_sw_0, 1); hal_gpio_write(&gpio_rf_sw_0, 1);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
} else if(path == FuriHalSubGhzPath868) { } else if(path == FuriHalSubGhzPath868) {
hal_gpio_write(&gpio_rf_sw_0, 1); hal_gpio_write(&gpio_rf_sw_0, 1);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
} else if(path == FuriHalSubGhzPathIsolate) { } else if(path == FuriHalSubGhzPathIsolate) {
hal_gpio_write(&gpio_rf_sw_0, 0); hal_gpio_write(&gpio_rf_sw_0, 0);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
} else { } else {
furi_crash(NULL); furi_crash(NULL);
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;

View File

@ -7,8 +7,6 @@
const uint32_t SpiTimeout = 1000; const uint32_t SpiTimeout = 1000;
uint8_t SD_IO_WriteByte(uint8_t Data); uint8_t SD_IO_WriteByte(uint8_t Data);
static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast];
/****************************************************************************** /******************************************************************************
BUS OPERATIONS BUS OPERATIONS
*******************************************************************************/ *******************************************************************************/
@ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi
* @retval None * @retval None
*/ */
static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
furi_check(furi_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout));
} }
/** /**
@ -30,7 +28,7 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t
* @retval None * @retval None
*/ */
__attribute__((unused)) static void SPIx_Write(uint8_t Value) { __attribute__((unused)) static void SPIx_Write(uint8_t Value) {
furi_check(furi_hal_spi_bus_tx(sd_spi_dev->bus, (uint8_t*)&Value, 1, SpiTimeout)); furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout));
} }
/****************************************************************************** /******************************************************************************
@ -47,7 +45,7 @@ void SD_IO_Init(void) {
uint8_t counter = 0; uint8_t counter = 0;
/* SD chip select high */ /* SD chip select high */
hal_gpio_write(sd_spi_dev->chip_select, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
delay_us(10); delay_us(10);
/* Send dummy byte 0xFF, 10 times with CS high */ /* Send dummy byte 0xFF, 10 times with CS high */
@ -67,9 +65,9 @@ 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 */ /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */
if(val == 1) { if(val == 1) {
delay_us(10); // Exit guard time for some SD cards delay_us(10); // Exit guard time for some SD cards
hal_gpio_write(sd_spi_dev->chip_select, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
} else { } else {
hal_gpio_write(sd_spi_dev->chip_select, false); hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
delay_us(10); // Entry guard time for some SD cards delay_us(10); // Entry guard time for some SD cards
} }
} }

View File

@ -91,12 +91,7 @@
#include "stdlib.h" #include "stdlib.h"
#include "string.h" #include "string.h"
#include "stdio.h" #include "stdio.h"
#include <furi-hal-spi.h> #include <furi-hal.h>
#include <furi-hal-gpio.h>
#include <furi-hal-resources.h>
#include <furi-hal-power.h>
#include <furi-hal-delay.h>
#include <furi-hal-sd.h>
/** @addtogroup BSP /** @addtogroup BSP
* @{ * @{
@ -284,22 +279,22 @@ static uint8_t SD_ReadData(void);
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
void SD_SPI_Bus_To_Down_State(){ void SD_SPI_Bus_To_Down_State(){
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused);
hal_gpio_write(&gpio_sdcard_cs, false); hal_gpio_write(furi_hal_sd_spi_handle->cs, false);
hal_gpio_write(&gpio_spi_d_miso, false); hal_gpio_write(furi_hal_sd_spi_handle->miso, false);
hal_gpio_write(&gpio_spi_d_mosi, false); hal_gpio_write(furi_hal_sd_spi_handle->mosi, false);
hal_gpio_write(&gpio_spi_d_sck, false); hal_gpio_write(furi_hal_sd_spi_handle->sck, false);
} }
void SD_SPI_Bus_To_Normal_State(){ void SD_SPI_Bus_To_Normal_State(){
hal_gpio_write(&gpio_sdcard_cs, true); hal_gpio_write(furi_hal_sd_spi_handle->cs, true);
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2);
} }
/** @defgroup STM32_ADAFRUIT_SD_Private_Functions /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
@ -315,7 +310,8 @@ void SD_SPI_Bus_To_Normal_State(){
*/ */
uint8_t BSP_SD_Init(bool reset_card) { uint8_t BSP_SD_Init(bool reset_card) {
/* Slow speed init */ /* Slow speed init */
const FuriHalSpiDevice* sd_spi_slow_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardSlow); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow;
/* We must reset card in spi_lock context */ /* We must reset card in spi_lock context */
if(reset_card) { if(reset_card) {
@ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) {
if(res == BSP_SD_OK) break; if(res == BSP_SD_OK) break;
} }
furi_hal_spi_device_return(sd_spi_slow_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow);
/* SD initialized and set to SPI mode properly */ /* SD initialized and set to SPI mode properly */
return res; return res;

View File

@ -35,7 +35,7 @@
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
#include "user_diskio.h" #include "user_diskio.h"
#include "furi-hal-spi.h" #include <furi-hal.h>
/* Private typedef -----------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
@ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = {
DSTATUS USER_initialize(BYTE pdrv) { DSTATUS USER_initialize(BYTE pdrv) {
/* USER CODE BEGIN INIT */ /* USER CODE BEGIN INIT */
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); 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 = User_CheckStatus(pdrv);
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return status; return status;
/* USER CODE END INIT */ /* USER CODE END INIT */
@ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
/* USER CODE BEGIN READ */ /* USER CODE BEGIN READ */
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
/* wait until the read operation is finished */ /* wait until the read operation is finished */
@ -129,7 +132,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
res = RES_OK; res = RES_OK;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END READ */ /* USER CODE END READ */
@ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
/* USER CODE HERE */ /* USER CODE HERE */
DRESULT res = RES_ERROR; DRESULT res = RES_ERROR;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
/* wait until the Write operation is finished */ /* wait until the Write operation is finished */
@ -158,7 +163,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
res = RES_OK; res = RES_OK;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END WRITE */ /* USER CODE END WRITE */
@ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
if(Stat & STA_NOINIT) return RES_NOTRDY; if(Stat & STA_NOINIT) return RES_NOTRDY;
const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast);
furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast;
switch(cmd) { switch(cmd) {
/* Make sure that no pending write process */ /* Make sure that no pending write process */
@ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
res = RES_PARERR; res = RES_PARERR;
} }
furi_hal_spi_device_return(sd_spi_fast_dev); furi_hal_sd_spi_handle = NULL;
furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast);
return res; return res;
/* USER CODE END IOCTL */ /* USER CODE END IOCTL */

View File

@ -20,3 +20,5 @@ bool hal_sd_detect(void) {
bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin));
return result; return result;
} }
FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL;

View File

@ -1,10 +1,9 @@
#include <furi-hal-spi-config.h> #include <furi-hal-spi-config.h>
#include <furi-hal-resources.h> #include <furi-hal-resources.h>
#define SPI_R SPI1 /* SPI Presets */
#define SPI_D SPI2
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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = {
.CRCPoly = 7, .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, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = {
* SD Card in fast mode (after init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
/** const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = {
* SD Card in slow mode (before init)
*/
const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.Mode = LL_SPI_MODE_MASTER, .Mode = LL_SPI_MODE_MASTER,
.TransferDirection = LL_SPI_FULL_DUPLEX, .TransferDirection = LL_SPI_FULL_DUPLEX,
.DataWidth = LL_SPI_DATAWIDTH_8BIT, .DataWidth = LL_SPI_DATAWIDTH_8BIT,
@ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = {
.CRCPoly = 7, .CRCPoly = 7,
}; };
osMutexId_t spi_mutex_d = NULL; /* SPI Buses */
osMutexId_t spi_mutex_r = NULL;
const FuriHalSpiBus spi_r = { osMutexId_t furi_hal_spi_bus_r_mutex = NULL;
.spi=SPI_R,
.mutex=&spi_mutex_r, static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) {
if (event == FuriHalSpiBusEventInit) {
furi_hal_spi_bus_r_mutex = osMutexNew(NULL);
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) {
furi_check(osMutexDelete(furi_hal_spi_bus_r_mutex));
} else if (event == FuriHalSpiBusEventLock) {
furi_check(osMutexAcquire(furi_hal_spi_bus_r_mutex, osWaitForever) == osOK);
} else if (event == FuriHalSpiBusEventUnlock) {
furi_check(osMutexRelease(furi_hal_spi_bus_r_mutex) == osOK);
} 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,
};
osMutexId_t 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 = osMutexNew(NULL);
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) {
furi_check(osMutexDelete(furi_hal_spi_bus_d_mutex));
} else if (event == FuriHalSpiBusEventLock) {
furi_check(osMutexAcquire(furi_hal_spi_bus_d_mutex, osWaitForever) == osOK);
} else if (event == FuriHalSpiBusEventUnlock) {
furi_check(osMutexRelease(furi_hal_spi_bus_d_mutex) == osOK);
} 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, .miso=&gpio_spi_r_miso,
.mosi=&gpio_spi_r_mosi, .mosi=&gpio_spi_r_mosi,
.clk=&gpio_spi_r_sck, .sck=&gpio_spi_r_sck,
.cs=&gpio_subghz_cs,
}; };
const FuriHalSpiBus spi_d = { static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) {
.spi=SPI_D, furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m);
.mutex=&spi_mutex_d, }
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, .miso=&gpio_spi_d_miso,
.mosi=&gpio_spi_d_mosi, .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] = { static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) {
{ .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m);
{ .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, }, FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = {
{ .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, .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,
}; };

View File

@ -1,62 +1,60 @@
#pragma once #pragma once
#include <furi-hal-gpio.h> #include <furi-hal-spi-types.h>
#include <stm32wbxx_ll_spi.h>
#include <cmsis_os2.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; /** Preset for ST25R916 */
extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m;
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;
/** FURI HAL SPI BUS handler /** Preset for CC1101 */
* Structure content may change at some point 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 { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external;
const SPI_TypeDef* spi;
const osMutexId_t* mutex;
const GpioPin* miso;
const GpioPin* mosi;
const GpioPin* clk;
} FuriHalSpiBus;
/** FURI HAL SPI Device handler /** ST7567(Display) on `furi_hal_spi_bus_d` */
* Structure content may change at some point extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display;
*/
typedef struct {
const FuriHalSpiBus* bus;
const LL_SPI_InitTypeDef* config;
const GpioPin* chip_select;
} FuriHalSpiDevice;
/** FURI HAL SPI Standard Device IDs */ /** SdCard in fast mode on `furi_hal_spi_bus_d` */
typedef enum { extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast;
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 */
FuriHalSpiDeviceIdMax, /** Service Value, do not use */ /** SdCard in slow mode on `furi_hal_spi_bus_d` */
} FuriHalSpiDeviceId; extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow;
/** 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];
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,62 @@
#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

View File

@ -12,89 +12,104 @@
#define TAG "FuriHalSpi" #define TAG "FuriHalSpi"
void furi_hal_spi_init() { void furi_hal_spi_init() {
// Spi structure is const, but mutex is not furi_hal_spi_bus_init(&furi_hal_spi_bus_r);
// Need some hell-ish casting to make it work furi_hal_spi_bus_init(&furi_hal_spi_bus_d);
*(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
*(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
//
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
);
}
hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz);
hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); 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);
hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow);
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_LOG_I(TAG, "Init OK"); FURI_LOG_I(TAG, "Init OK");
} }
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_init(FuriHalSpiBus* bus) {
furi_assert(bus); furi_assert(bus);
furi_check(osMutexAcquire(*bus->mutex, osWaitForever) == osOK); bus->callback(bus, FuriHalSpiBusEventInit);
} }
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) {
furi_assert(bus); furi_assert(bus);
furi_check(osMutexRelease(*bus->mutex) == osOK); bus->callback(bus, FuriHalSpiBusEventDeinit);
} }
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) {
furi_assert(bus); furi_assert(handle);
handle->callback(handle, FuriHalSpiBusHandleEventInit);
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_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) {
while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); furi_assert(handle);
while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); handle->callback(handle, FuriHalSpiBusHandleEventDeinit);
while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { }
LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi);
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) {
furi_assert(handle);
handle->bus->callback(handle->bus, FuriHalSpiBusEventLock);
handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate);
furi_assert(handle->bus->current_handle == NULL);
handle->bus->current_handle = handle;
handle->callback(handle, FuriHalSpiBusHandleEventActivate);
}
void furi_hal_spi_release(FuriHalSpiBusHandle* handle) {
furi_assert(handle);
furi_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(handle->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) { bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(buffer); furi_assert(buffer);
furi_assert(size > 0); furi_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) { bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(buffer); furi_assert(buffer);
furi_assert(size > 0); furi_assert(size > 0);
bool ret = true; bool ret = true;
while(size > 0) { while(size > 0) {
if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) {
LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); LL_SPI_TransmitData8(handle->bus->spi, *buffer);
buffer++; buffer++;
size--; size--;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); LL_SPI_ClearFlag_OVR(handle->bus->spi);
return ret; return ret;
} }
bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
furi_assert(bus); furi_assert(handle);
furi_assert(handle->bus->current_handle == handle);
furi_assert(tx_buffer); furi_assert(tx_buffer);
furi_assert(rx_buffer); furi_assert(rx_buffer);
furi_assert(size > 0); furi_assert(size > 0);
@ -104,99 +119,22 @@ bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t*
bool tx_allowed = true; bool tx_allowed = true;
while(size > 0) { while(size > 0) {
if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) {
LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer);
tx_buffer++; tx_buffer++;
tx_size--; tx_size--;
tx_allowed = false; tx_allowed = false;
} }
if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) {
*rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi);
rx_buffer++; rx_buffer++;
size--; size--;
tx_allowed = true; tx_allowed = true;
} }
} }
furi_hal_spi_bus_end_txrx(bus, timeout); furi_hal_spi_bus_end_txrx(handle, timeout);
return ret;
}
void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) {
furi_assert(device);
furi_assert(device->config);
furi_hal_spi_bus_configure(device->bus, device->config);
}
const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) {
furi_assert(device_id < FuriHalSpiDeviceIdMax);
const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id];
furi_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) {
furi_assert(device);
furi_assert(buffer);
furi_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) {
furi_assert(device);
furi_assert(buffer);
furi_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) {
furi_assert(device);
furi_assert(tx_buffer);
furi_assert(rx_buffer);
furi_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);
}
return ret; return ret;
} }

View File

@ -269,7 +269,7 @@ void furi_hal_subghz_init() {
furi_assert(furi_hal_subghz_state == SubGhzStateInit); furi_assert(furi_hal_subghz_state == SubGhzStateInit);
furi_hal_subghz_state = SubGhzStateIdle; furi_hal_subghz_state = SubGhzStateIdle;
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
#ifdef FURI_HAL_SUBGHZ_TX_GPIO #ifdef FURI_HAL_SUBGHZ_TX_GPIO
hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
@ -277,58 +277,58 @@ void furi_hal_subghz_init() {
// Reset // Reset
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
// Prepare GD0 for power on self test // Prepare GD0 for power on self test
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
// GD0 low // GD0 low
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW);
while(hal_gpio_read(&gpio_cc1101_g0) != false) while(hal_gpio_read(&gpio_cc1101_g0) != false)
; ;
// GD0 high // GD0 high
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV);
while(hal_gpio_read(&gpio_cc1101_g0) != true) while(hal_gpio_read(&gpio_cc1101_g0) != true)
; ;
// Reset GD0 to floating state // Reset GD0 to floating state
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
// RF switches // RF switches
hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
// Go to sleep // Go to sleep
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
FURI_LOG_I(TAG, "Init OK"); FURI_LOG_I(TAG, "Init OK");
} }
void furi_hal_subghz_sleep() { void furi_hal_subghz_sleep() {
furi_assert(furi_hal_subghz_state == SubGhzStateIdle); furi_assert(furi_hal_subghz_state == SubGhzStateIdle);
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_dump_state() { void furi_hal_subghz_dump_state() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
printf( printf(
"[furi_hal_subghz] cc1101 chip %d, version %d\r\n", "[furi_hal_subghz] cc1101 chip %d, version %d\r\n",
cc1101_get_partnumber(device), cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz),
cc1101_get_version(device)); cc1101_get_version(&furi_hal_spi_bus_handle_subghz));
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
@ -350,81 +350,81 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) {
} }
void furi_hal_subghz_load_registers(const uint8_t data[][2]) { void furi_hal_subghz_load_registers(const uint8_t data[][2]) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
uint32_t i = 0; uint32_t i = 0;
while(data[i][0]) { while(data[i][0]) {
cc1101_write_reg(device, data[i][0], data[i][1]); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]);
i++; i++;
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_load_patable(const uint8_t data[8]) { void furi_hal_subghz_load_patable(const uint8_t data[8]) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_set_pa_table(device, data); cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_tx(device); cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz);
cc1101_write_fifo(device, data, size); cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_flush_rx() { void furi_hal_subghz_flush_rx() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_flush_rx(device); cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_read_fifo(device, data, size); cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_shutdown() { void furi_hal_subghz_shutdown() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
// Reset and shutdown // Reset and shutdown
cc1101_shutdown(device); cc1101_shutdown(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_reset() { void furi_hal_subghz_reset() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
cc1101_reset(device); cc1101_reset(&furi_hal_spi_bus_handle_subghz);
cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_idle() { void furi_hal_subghz_idle() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_idle(device); cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
void furi_hal_subghz_rx() { void furi_hal_subghz_rx() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_rx(device); cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
bool furi_hal_subghz_tx() { bool furi_hal_subghz_tx() {
if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false;
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
cc1101_switch_to_tx(device); cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
return true; return true;
} }
float furi_hal_subghz_get_rssi() { float furi_hal_subghz_get_rssi() {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
int32_t rssi_dec = cc1101_get_rssi(device); int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz);
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
float rssi = rssi_dec; float rssi = rssi_dec;
if(rssi_dec >= 128) { if(rssi_dec >= 128) {
@ -461,7 +461,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) {
} }
uint32_t furi_hal_subghz_set_frequency(uint32_t value) { uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
//checking regional settings //checking regional settings
bool txrx = false; bool txrx = false;
@ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) {
furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; furi_hal_subghz_regulation = SubGhzRegulationOnlyRx;
} }
uint32_t real_frequency = cc1101_set_frequency(device, value); uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value);
cc1101_calibrate(device); cc1101_calibrate(&furi_hal_spi_bus_handle_subghz);
while(true) { while(true) {
CC1101Status status = cc1101_get_status(device); CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz);
if(status.STATE == CC1101StateIDLE) break; if(status.STATE == CC1101StateIDLE) break;
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
return real_frequency; return real_frequency;
} }
void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { void furi_hal_subghz_set_path(FuriHalSubGhzPath path) {
const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
if(path == FuriHalSubGhzPath433) { if(path == FuriHalSubGhzPath433) {
hal_gpio_write(&gpio_rf_sw_0, 0); hal_gpio_write(&gpio_rf_sw_0, 0);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
} else if(path == FuriHalSubGhzPath315) { } else if(path == FuriHalSubGhzPath315) {
hal_gpio_write(&gpio_rf_sw_0, 1); hal_gpio_write(&gpio_rf_sw_0, 1);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
} else if(path == FuriHalSubGhzPath868) { } else if(path == FuriHalSubGhzPath868) {
hal_gpio_write(&gpio_rf_sw_0, 1); hal_gpio_write(&gpio_rf_sw_0, 1);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV);
} else if(path == FuriHalSubGhzPathIsolate) { } else if(path == FuriHalSubGhzPathIsolate) {
hal_gpio_write(&gpio_rf_sw_0, 0); hal_gpio_write(&gpio_rf_sw_0, 0);
cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW);
} else { } else {
furi_crash(NULL); furi_crash(NULL);
} }
furi_hal_spi_device_return(device); furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz);
} }
volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; volatile uint32_t furi_hal_subghz_capture_delta_duration = 0;

View File

@ -5,6 +5,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <furi-hal-spi-types.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -24,6 +25,9 @@ void hal_sd_detect_set_low(void);
*/ */
bool hal_sd_detect(void); bool hal_sd_detect(void);
/** Pointer to currently used SPI Handle */
extern FuriHalSpiBusHandle* furi_hal_sd_spi_handle;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,106 +1,88 @@
#pragma once #pragma once
#include "main.h"
#include "furi-hal-spi-config.h" #include <furi-hal-spi-config.h>
#include <furi-hal-gpio.h>
#include <stdbool.h> #include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /** Initialize SPI HAL */
* Init SPI API
*/
void furi_hal_spi_init(); void furi_hal_spi_init();
/* Bus Level API */ /** Initialize SPI Bus
*
/** Lock SPI bus * @param handle pointer to FuriHalSpiBus instance
* Takes bus mutex, if used
*/ */
void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus); void furi_hal_spi_bus_init(FuriHalSpiBus* bus);
/** Unlock SPI bus /** Deinitialize SPI Bus
* Releases BUS mutex, if used *
* @param handle pointer to FuriHalSpiBus instance
*/ */
void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus); void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus);
/** Configure SPI bus /** Initialize SPI Bus Handle
* @param bus - spi bus handler *
* @param config - spi configuration structure * @param handle pointer to FuriHalSpiBusHandle instance
*/ */
void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config); void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle);
/** Deinitialize SPI Bus Handle
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle);
/** Acquire SPI bus
*
* @warning blocking, calls `furi_crash` on programming error, CS transition is up to handler event routine
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle);
/** Release SPI bus
*
* @warning calls `furi_crash` on programming error, CS transition is up to handler event routine
*
* @param handle pointer to FuriHalSpiBusHandle instance
*/
void furi_hal_spi_release(FuriHalSpiBusHandle* handle);
/** SPI Receive /** SPI Receive
* @param bus - spi bus handler *
* @param buffer - receive buffer * @param handle pointer to FuriHalSpiBusHandle instance
* @param size - transaction size * @param buffer receive buffer
* @param timeout - bus operation timeout in ms * @param size transaction size (buffer size)
* @param timeout operation timeout in ms
*
* @return true on sucess
*/ */
bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout);
/** SPI Transmit /** SPI Transmit
* @param bus - spi bus handler *
* @param buffer - transmit buffer * @param handle pointer to FuriHalSpiBusHandle instance
* @param size - transaction size * @param buffer transmit buffer
* @param timeout - bus operation timeout in ms * @param size transaction size (buffer size)
* @param timeout operation timeout in ms
*
* @return true on success
*/ */
bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout);
/** SPI Transmit and Receive /** SPI Transmit and Receive
* @param bus - spi bus handlere *
* @param tx_buffer - device handle * @param handle pointer to FuriHalSpiBusHandle instance
* @param rx_buffer - device handle * @param tx_buffer pointer to tx buffer
* @param size - transaction size * @param rx_buffer pointer to rx buffer
* @param timeout - bus operation timeout in ms * @param size transaction size (buffer size)
* @param timeout operation timeout in ms
*
* @return true on success
*/ */
bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, 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 #ifdef __cplusplus
} }

View File

@ -14,6 +14,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
#include "furi-hal-crypto.h" #include "furi-hal-crypto.h"
#include "furi-hal-console.h" #include "furi-hal-console.h"
#include "furi-hal-os.h" #include "furi-hal-os.h"
#include "furi-hal-sd.h"
#include "furi-hal-i2c.h" #include "furi-hal-i2c.h"
#include "furi-hal-resources.h" #include "furi-hal-resources.h"
#include "furi-hal-gpio.h" #include "furi-hal-gpio.h"

View File

@ -7,7 +7,6 @@
static osThreadAttr_t platform_irq_thread_attr; static osThreadAttr_t platform_irq_thread_attr;
static volatile osThreadId_t platform_irq_thread_id = NULL; static volatile osThreadId_t platform_irq_thread_id = NULL;
static volatile PlatformIrqCallback platform_irq_callback = NULL; static volatile PlatformIrqCallback platform_irq_callback = NULL;
static FuriHalSpiDevice* platform_st25r3916 = NULL;
static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN};
void nfc_isr(void* _ctx) { void nfc_isr(void* _ctx) {
@ -49,14 +48,13 @@ void platformSetIrqCallback(PlatformIrqCallback callback) {
} }
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) { HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) {
furi_assert(platform_st25r3916);
bool ret = false; bool ret = false;
if (txBuf && rxBuf) { if (txBuf && rxBuf) {
ret = furi_hal_spi_bus_trx(platform_st25r3916->bus, (uint8_t*)txBuf, rxBuf, len, 1000); ret = furi_hal_spi_bus_trx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, rxBuf, len, 1000);
} else if (txBuf) { } else if (txBuf) {
ret = furi_hal_spi_bus_tx(platform_st25r3916->bus, (uint8_t*)txBuf, len, 1000); ret = furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, len, 1000);
} else if (rxBuf) { } else if (rxBuf) {
ret = furi_hal_spi_bus_rx(platform_st25r3916->bus, (uint8_t*)rxBuf, len, 1000); ret = furi_hal_spi_bus_rx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)rxBuf, len, 1000);
} }
if(!ret) { if(!ret) {
@ -68,15 +66,9 @@ HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t
} }
void platformProtectST25RComm() { void platformProtectST25RComm() {
// Don't check platform_st25r3916 since spi device is used simultaneously from nfc worker furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc);
// thread and platformIrqWorker thread with the highest priority
// furi_assert(platform_st25r3916 == NULL);
platform_st25r3916 = (FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdNfc);
} }
void platformUnprotectST25RComm() { void platformUnprotectST25RComm() {
// furi_assert(platform_st25r3916); furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc);
furi_hal_spi_device_return(platform_st25r3916);
// platform_st25r3916 = NULL;
} }

View File

@ -4,180 +4,164 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
CC1101Status cc1101_strobe(const FuriHalSpiDevice* device, uint8_t strobe) { CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe) {
uint8_t tx[1] = { strobe }; uint8_t tx[1] = { strobe };
CC1101Status rx[1] = { 0 }; CC1101Status rx[1] = { 0 };
hal_gpio_write(device->chip_select, false); while(hal_gpio_read(handle->miso));
while(hal_gpio_read(device->bus->miso)); furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT);
furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT);
hal_gpio_write(device->chip_select, true);
assert(rx[0].CHIP_RDYn == 0); assert(rx[0].CHIP_RDYn == 0);
return rx[0]; return rx[0];
} }
CC1101Status cc1101_write_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t data) { CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) {
uint8_t tx[2] = { reg, data }; uint8_t tx[2] = { reg, data };
CC1101Status rx[2] = { 0 }; CC1101Status rx[2] = { 0 };
hal_gpio_write(device->chip_select, false); while(hal_gpio_read(handle->miso));
while(hal_gpio_read(device->bus->miso)); furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
hal_gpio_write(device->chip_select, true);
assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0); assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0);
return rx[1]; return rx[1];
} }
CC1101Status cc1101_read_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t* data) { CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) {
assert(sizeof(CC1101Status) == 1); assert(sizeof(CC1101Status) == 1);
uint8_t tx[2] = { reg|CC1101_READ, 0}; uint8_t tx[2] = { reg|CC1101_READ, 0};
CC1101Status rx[2] = { 0 }; CC1101Status rx[2] = { 0 };
hal_gpio_write(device->chip_select, false); while(hal_gpio_read(handle->miso));
while(hal_gpio_read(device->bus->miso)); furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
hal_gpio_write(device->chip_select, true);
assert((rx[0].CHIP_RDYn) == 0); assert((rx[0].CHIP_RDYn) == 0);
*data = *(uint8_t*)&rx[1]; *data = *(uint8_t*)&rx[1];
return rx[0]; return rx[0];
} }
uint8_t cc1101_get_partnumber(const FuriHalSpiDevice* device) { uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle) {
uint8_t partnumber=0; uint8_t partnumber=0;
cc1101_read_reg(device, CC1101_STATUS_PARTNUM|CC1101_BURST, &partnumber); cc1101_read_reg(handle, CC1101_STATUS_PARTNUM|CC1101_BURST, &partnumber);
return partnumber; return partnumber;
} }
uint8_t cc1101_get_version(const FuriHalSpiDevice* device) { uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle) {
uint8_t version=0; uint8_t version=0;
cc1101_read_reg(device, CC1101_STATUS_VERSION|CC1101_BURST, &version); cc1101_read_reg(handle, CC1101_STATUS_VERSION|CC1101_BURST, &version);
return version; return version;
} }
uint8_t cc1101_get_rssi(const FuriHalSpiDevice* device) { uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) {
uint8_t rssi=0; uint8_t rssi=0;
cc1101_read_reg(device, CC1101_STATUS_RSSI|CC1101_BURST, &rssi); cc1101_read_reg(handle, CC1101_STATUS_RSSI|CC1101_BURST, &rssi);
return rssi; return rssi;
} }
void cc1101_reset(const FuriHalSpiDevice* device) { void cc1101_reset(FuriHalSpiBusHandle* handle) {
hal_gpio_write(device->chip_select, false);
delay_us(1000); delay_us(1000);
hal_gpio_write(device->chip_select, true);
delay_us(1000); delay_us(1000);
cc1101_strobe(device, CC1101_STROBE_SRES); cc1101_strobe(handle, CC1101_STROBE_SRES);
} }
CC1101Status cc1101_get_status(const FuriHalSpiDevice* device) { CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle) {
return cc1101_strobe(device, CC1101_STROBE_SNOP); return cc1101_strobe(handle, CC1101_STROBE_SNOP);
} }
void cc1101_shutdown(const FuriHalSpiDevice* device) { void cc1101_shutdown(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SPWD); cc1101_strobe(handle, CC1101_STROBE_SPWD);
} }
void cc1101_calibrate(const FuriHalSpiDevice* device) { void cc1101_calibrate(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SCAL); cc1101_strobe(handle, CC1101_STROBE_SCAL);
} }
void cc1101_switch_to_idle(const FuriHalSpiDevice* device) { void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SIDLE); cc1101_strobe(handle, CC1101_STROBE_SIDLE);
} }
void cc1101_switch_to_rx(const FuriHalSpiDevice* device) { void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SRX); cc1101_strobe(handle, CC1101_STROBE_SRX);
} }
void cc1101_switch_to_tx(const FuriHalSpiDevice* device) { void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_STX); cc1101_strobe(handle, CC1101_STROBE_STX);
} }
void cc1101_flush_rx(const FuriHalSpiDevice* device) { void cc1101_flush_rx(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SFRX); cc1101_strobe(handle, CC1101_STROBE_SFRX);
} }
void cc1101_flush_tx(const FuriHalSpiDevice* device) { void cc1101_flush_tx(FuriHalSpiBusHandle* handle) {
cc1101_strobe(device, CC1101_STROBE_SFTX); cc1101_strobe(handle, CC1101_STROBE_SFTX);
} }
uint32_t cc1101_set_frequency(const FuriHalSpiDevice* device, uint32_t value) { uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ; uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ;
// Sanity check // Sanity check
assert((real_value & CC1101_FMASK) == real_value); assert((real_value & CC1101_FMASK) == real_value);
cc1101_write_reg(device, CC1101_FREQ2, (real_value >> 16) & 0xFF); cc1101_write_reg(handle, CC1101_FREQ2, (real_value >> 16) & 0xFF);
cc1101_write_reg(device, CC1101_FREQ1, (real_value >> 8 ) & 0xFF); cc1101_write_reg(handle, CC1101_FREQ1, (real_value >> 8 ) & 0xFF);
cc1101_write_reg(device, CC1101_FREQ0, (real_value >> 0 ) & 0xFF); cc1101_write_reg(handle, CC1101_FREQ0, (real_value >> 0 ) & 0xFF);
uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV; uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV;
return (uint32_t)real_frequency; return (uint32_t)real_frequency;
} }
uint32_t cc1101_set_intermediate_frequency(const FuriHalSpiDevice* device, uint32_t value) { uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ; uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ;
assert((real_value & 0xFF) == real_value); assert((real_value & 0xFF) == real_value);
cc1101_write_reg(device, CC1101_FSCTRL0, (real_value >> 0 ) & 0xFF); cc1101_write_reg(handle, CC1101_FSCTRL0, (real_value >> 0 ) & 0xFF);
uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV; uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV;
return (uint32_t)real_frequency; return (uint32_t)real_frequency;
} }
void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]) { void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) {
uint8_t tx[9] = { CC1101_PATABLE | CC1101_BURST }; uint8_t tx[9] = { CC1101_PATABLE | CC1101_BURST };
CC1101Status rx[9] = { 0 }; CC1101Status rx[9] = { 0 };
memcpy(&tx[1], &value[0], 8); memcpy(&tx[1], &value[0], 8);
hal_gpio_write(device->chip_select, false); while(hal_gpio_read(handle->miso));
while(hal_gpio_read(device->bus->miso)); furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT);
furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT);
hal_gpio_write(device->chip_select, true);
assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0);
} }
uint8_t cc1101_write_fifo(const FuriHalSpiDevice* device, const uint8_t* data, uint8_t size) { uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) {
uint8_t buff_tx[64]; uint8_t buff_tx[64];
uint8_t buff_rx[64]; uint8_t buff_rx[64];
buff_tx[0] = CC1101_FIFO | CC1101_BURST; buff_tx[0] = CC1101_FIFO | CC1101_BURST;
memcpy(&buff_tx[1], data, size); memcpy(&buff_tx[1], data, size);
// Start transaction // Start transaction
hal_gpio_write(device->chip_select, false);
// Wait IC to become ready // Wait IC to become ready
while(hal_gpio_read(device->bus->miso)); while(hal_gpio_read(handle->miso));
// Tell IC what we want // Tell IC what we want
furi_hal_spi_bus_trx(device->bus, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); furi_hal_spi_bus_trx(handle, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT);
// Finish transaction
hal_gpio_write(device->chip_select, true);
return size; return size;
} }
uint8_t cc1101_read_fifo(const FuriHalSpiDevice* device, uint8_t* data, uint8_t* size) { uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size) {
uint8_t buff_tx[64]; uint8_t buff_tx[64];
buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST;
uint8_t buff_rx[2]; uint8_t buff_rx[2];
// Start transaction // Start transaction
hal_gpio_write(device->chip_select, false);
// Wait IC to become ready // Wait IC to become ready
while(hal_gpio_read(device->bus->miso)); while(hal_gpio_read(handle->miso));
// First byte - packet length // First byte - packet length
furi_hal_spi_bus_trx(device->bus, buff_tx, buff_rx, 2, CC1101_TIMEOUT); furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT);
*size = buff_rx[1]; *size = buff_rx[1];
furi_hal_spi_bus_trx(device->bus, &buff_tx[1], data, *size, CC1101_TIMEOUT); furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT);
cc1101_flush_rx(device); cc1101_flush_rx(handle);
hal_gpio_write(device->chip_select, true);
return *size; return *size;
} }

View File

@ -13,131 +13,167 @@ extern "C" {
/* Low level API */ /* Low level API */
/** Strobe command to the device /** Strobe command to the device
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param strobe - command to execute * @param strobe - command to execute
*
* @return device status * @return device status
*/ */
CC1101Status cc1101_strobe(const FuriHalSpiDevice* device, uint8_t strobe); CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe);
/** Write device register /** Write device register
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param reg - register * @param reg - register
* @param data - data to write * @param data - data to write
*
* @return device status * @return device status
*/ */
CC1101Status cc1101_write_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t data); CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data);
/** Read device register /** Read device register
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param reg - register * @param reg - register
* @param[out] data - pointer to data * @param[out] data - pointer to data
*
* @return device status * @return device status
*/ */
CC1101Status cc1101_read_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t* data); CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data);
/* High level API */ /* High level API */
/** Reset /** Reset
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_reset(const FuriHalSpiDevice* device); void cc1101_reset(FuriHalSpiBusHandle* handle);
/** Get status /** Get status
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*
* @return CC1101Status structure
*/ */
CC1101Status cc1101_get_status(const FuriHalSpiDevice* device); CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle);
/** Enable shutdown mode /** Enable shutdown mode
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_shutdown(const FuriHalSpiDevice* device); void cc1101_shutdown(FuriHalSpiBusHandle* handle);
/** Get Partnumber /** Get Partnumber
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*
* @return part number id
*/ */
uint8_t cc1101_get_partnumber(const FuriHalSpiDevice* device); uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle);
/** Get Version /** Get Version
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*
* @return version
*/ */
uint8_t cc1101_get_version(const FuriHalSpiDevice* device); uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle);
/** Get raw RSSI value /** Get raw RSSI value
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*
* @return rssi value
*/ */
uint8_t cc1101_get_rssi(const FuriHalSpiDevice* device); uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle);
/** Calibrate oscillator /** Calibrate oscillator
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_calibrate(const FuriHalSpiDevice* device); void cc1101_calibrate(FuriHalSpiBusHandle* handle);
/** Switch to idle /** Switch to idle
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_switch_to_idle(const FuriHalSpiDevice* device); void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle);
/** Switch to RX /** Switch to RX
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_switch_to_rx(const FuriHalSpiDevice* device); void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle);
/** Switch to TX /** Switch to TX
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_switch_to_tx(const FuriHalSpiDevice* device); void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle);
/** Flush RX FIFO /** Flush RX FIFO
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_flush_rx(const FuriHalSpiDevice* device); void cc1101_flush_rx(FuriHalSpiBusHandle* handle);
/** Flush TX FIFO /** Flush TX FIFO
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
*/ */
void cc1101_flush_tx(const FuriHalSpiDevice* device); void cc1101_flush_tx(FuriHalSpiBusHandle* handle);
/** Set Frequency /** Set Frequency
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param value - frequency in herz * @param value - frequency in herz
*
* @return real frequency that were synthesized * @return real frequency that were synthesized
*/ */
uint32_t cc1101_set_frequency(const FuriHalSpiDevice* device, uint32_t value); uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value);
/** Set Intermediate Frequency /** Set Intermediate Frequency
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param value - frequency in herz * @param value - frequency in herz
*
* @return real inermediate frequency that were synthesized * @return real inermediate frequency that were synthesized
*/ */
uint32_t cc1101_set_intermediate_frequency(const FuriHalSpiDevice* device, uint32_t value); uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value);
/** Set Power Amplifier level table, ramp /** Set Power Amplifier level table, ramp
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param value - array of power level values * @param value - array of power level values
*/ */
void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]); void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]);
/** Set Power Amplifier level table, ramp /** Set Power Amplifier level table, ramp
* @param device - pointer to FuriHalSpiDevice *
* @param handle - pointer to FuriHalSpiHandle
* @param value - array of power level values * @param value - array of power level values
*/ */
void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]); void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]);
/** Write FIFO /** Write FIFO
* @param device - pointer to FuriHalSpiDevice *
* @param data, pointer to byte array * @param handle - pointer to FuriHalSpiHandle
* @param size, write bytes count * @param data pointer to byte array
* @param size write bytes count
*
* @return size, written bytes count * @return size, written bytes count
*/ */
uint8_t cc1101_write_fifo(const FuriHalSpiDevice* device, const uint8_t* data, uint8_t size); uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size);
/** Read FIFO /** Read FIFO
* @param device - pointer to FuriHalSpiDevice *
* @param data, pointer to byte array * @param handle - pointer to FuriHalSpiHandle
* @param size, bytes to read from fifo * @param data pointer to byte array
* @param size bytes to read from fifo
*
* @return size, read bytes count * @return size, read bytes count
*/ */
uint8_t cc1101_read_fifo(const FuriHalSpiDevice* device, uint8_t* data, uint8_t* size); uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -2,8 +2,6 @@
#include <furi-hal.h> #include <furi-hal.h>
static FuriHalSpiDevice* u8g2_periphery_display = NULL;
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
switch(msg) { switch(msg) {
case U8X8_MSG_GPIO_AND_DELAY_INIT: case U8X8_MSG_GPIO_AND_DELAY_INIT:
@ -31,7 +29,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
switch(msg) { switch(msg) {
case U8X8_MSG_BYTE_SEND: case U8X8_MSG_BYTE_SEND:
furi_hal_spi_bus_tx(u8g2_periphery_display->bus, (uint8_t*)arg_ptr, arg_int, 10000); furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_display, (uint8_t*)arg_ptr, arg_int, 10000);
break; break;
case U8X8_MSG_BYTE_SET_DC: case U8X8_MSG_BYTE_SET_DC:
hal_gpio_write(&gpio_display_di, arg_int); hal_gpio_write(&gpio_display_di, arg_int);
@ -39,16 +37,10 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
case U8X8_MSG_BYTE_INIT: case U8X8_MSG_BYTE_INIT:
break; break;
case U8X8_MSG_BYTE_START_TRANSFER: case U8X8_MSG_BYTE_START_TRANSFER:
furi_assert(u8g2_periphery_display == NULL); furi_hal_spi_acquire(&furi_hal_spi_bus_handle_display);
u8g2_periphery_display =
(FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdDisplay);
hal_gpio_write(u8g2_periphery_display->chip_select, false);
break; break;
case U8X8_MSG_BYTE_END_TRANSFER: case U8X8_MSG_BYTE_END_TRANSFER:
furi_assert(u8g2_periphery_display); furi_hal_spi_release(&furi_hal_spi_bus_handle_display);
hal_gpio_write(u8g2_periphery_display->chip_select, true);
furi_hal_spi_device_return(u8g2_periphery_display);
u8g2_periphery_display = NULL;
break; break;
default: default:
return 0; return 0;