[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:
		
							parent
							
								
									d86125c7f7
								
							
						
					
					
						commit
						9d27ef8901
					
				| @ -1,10 +1,9 @@ | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <furi-hal-resources.h> | ||||
| 
 | ||||
| #define SPI_R SPI1 | ||||
| #define SPI_D SPI2 | ||||
| /* SPI Presets */ | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in fast mode (after init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in slow mode (before init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_r = { | ||||
|     .spi = SPI_R, | ||||
| /* SPI Buses */ | ||||
| 
 | ||||
| static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if(event == FuriHalSpiBusEventInit) { | ||||
|         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if(event == FuriHalSpiBusEventDeinit) { | ||||
|     } else if(event == FuriHalSpiBusEventLock) { | ||||
|     } else if(event == FuriHalSpiBusEventUnlock) { | ||||
|     } else if(event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBus furi_hal_spi_bus_r = { | ||||
|     .spi = SPI1, | ||||
|     .callback = furi_hal_spi_bus_r_event_callback, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if(event == FuriHalSpiBusEventInit) { | ||||
|         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if(event == FuriHalSpiBusEventDeinit) { | ||||
|     } else if(event == FuriHalSpiBusEventLock) { | ||||
|     } else if(event == FuriHalSpiBusEventUnlock) { | ||||
|     } else if(event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBus furi_hal_spi_bus_d = { | ||||
|     .spi = SPI2, | ||||
|     .callback = furi_hal_spi_bus_d_event_callback, | ||||
| }; | ||||
| 
 | ||||
| /* SPI Bus Handles */ | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_r_handle_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event, | ||||
|     const LL_SPI_InitTypeDef* preset) { | ||||
|     if(event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
| 
 | ||||
|         hal_gpio_init_ex( | ||||
|             handle->miso, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->mosi, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->sck, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
| 
 | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
| 
 | ||||
|         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
| 
 | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_subghz_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_subghz_event_callback, | ||||
|     .miso = &gpio_spi_r_miso, | ||||
|     .mosi = &gpio_spi_r_mosi, | ||||
|     .clk = &gpio_spi_r_sck, | ||||
|     .sck = &gpio_spi_r_sck, | ||||
|     .cs = &gpio_subghz_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_d = { | ||||
|     .spi = SPI_D, | ||||
| static void furi_hal_spi_bus_handle_nfc_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_nfc_event_callback, | ||||
|     .miso = &gpio_spi_r_miso, | ||||
|     .mosi = &gpio_spi_r_mosi, | ||||
|     .sck = &gpio_spi_r_sck, | ||||
|     .cs = &gpio_nfc_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_external_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_external_event_callback, | ||||
|     .miso = &gpio_ext_pa6, | ||||
|     .mosi = &gpio_ext_pa7, | ||||
|     .sck = &gpio_ext_pb3, | ||||
|     .cs = &gpio_ext_pa4, | ||||
| }; | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_d_handle_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event, | ||||
|     const LL_SPI_InitTypeDef* preset) { | ||||
|     if(event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||
| 
 | ||||
|         hal_gpio_init_ex( | ||||
|             handle->miso, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->mosi, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->sck, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
| 
 | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_display_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_display_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .clk = &gpio_spi_d_sck, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_display_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | ||||
|     { | ||||
|         .bus = &spi_r, | ||||
|         .config = &furi_hal_spi_config_subghz, | ||||
|         .chip_select = &gpio_subghz_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_display, | ||||
|         .chip_select = &gpio_display_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_sd_fast, | ||||
|         .chip_select = &gpio_sdcard_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_sd_slow, | ||||
|         .chip_select = &gpio_sdcard_cs, | ||||
|     }, | ||||
|     {.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, | ||||
| static void furi_hal_spi_bus_handle_sd_fast_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_sdcard_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_sd_slow_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_sdcard_cs, | ||||
| }; | ||||
|  | ||||
| @ -1,60 +1,60 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; | ||||
| /** Preset for ST25R916 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||
| 
 | ||||
| /** FURI HAL SPI BUS handler
 | ||||
|  * Structure content may change at some point | ||||
| /** Preset for CC1101 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||
| 
 | ||||
| /** Preset for ST7567 (Display) */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||
| 
 | ||||
| /** Preset for SdCard in fast mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||
| 
 | ||||
| /** Preset for SdCard in slow mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||
| 
 | ||||
| /** CC1101 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||
| 
 | ||||
| /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||
| 
 | ||||
| /** External on `furi_hal_spi_bus_r`
 | ||||
|  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||
|  *  | ||||
|  * miso: pa6 | ||||
|  * mosi: pa7 | ||||
|  * sck: pb3 | ||||
|  * cs:  pa4 (software controlled) | ||||
|  *  | ||||
|  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||
|  * Bus pins are floating on inactive state, CS high after initialization | ||||
|  *  | ||||
|  */ | ||||
| typedef struct { | ||||
|     const SPI_TypeDef* spi; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* clk; | ||||
| } FuriHalSpiBus; | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||
| 
 | ||||
| /** FURI HAL SPI Device handler
 | ||||
|  * Structure content may change at some point | ||||
|  */ | ||||
| typedef struct { | ||||
|     const FuriHalSpiBus* bus; | ||||
|     const LL_SPI_InitTypeDef* config; | ||||
|     const GpioPin* chip_select; | ||||
| } FuriHalSpiDevice; | ||||
| /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||
| 
 | ||||
| /** FURI HAL SPI Standard Device IDs */ | ||||
| typedef enum { | ||||
|     FuriHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */ | ||||
|     FuriHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */ | ||||
|     FuriHalSpiDeviceIdSdCardFast, /** SDCARD: fast mode, after initialization */ | ||||
|     FuriHalSpiDeviceIdSdCardSlow, /** SDCARD: slow mode, before initialization */ | ||||
|     FuriHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ | ||||
| /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||
| 
 | ||||
|     FuriHalSpiDeviceIdMax, /** Service Value, do not use */ | ||||
| } FuriHalSpiDeviceId; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R
 | ||||
|  * CC1101, Nfc | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D
 | ||||
|  * Display, SdCard | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_d; | ||||
| 
 | ||||
| /** Furi Hal Spi devices */ | ||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; | ||||
| /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
							
								
								
									
										64
									
								
								bootloader/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								bootloader/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <stm32wbxx_ll_rcc.h> | ||||
| #include <stm32wbxx_ll_bus.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef struct FuriHalSpiBus FuriHalSpiBus; | ||||
| typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle; | ||||
| 
 | ||||
| /** FuriHal spi bus states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */ | ||||
|     FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */ | ||||
|     FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */ | ||||
|     FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */ | ||||
|     FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */ | ||||
|     FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation  */ | ||||
| } FuriHalSpiBusEvent; | ||||
| 
 | ||||
| /** FuriHal spi bus event callback */ | ||||
| typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event); | ||||
| 
 | ||||
| /** FuriHal spi bus */ | ||||
| struct FuriHalSpiBus { | ||||
|     SPI_TypeDef* spi; | ||||
|     FuriHalSpiBusEventCallback callback; | ||||
|     FuriHalSpiBusHandle* current_handle; | ||||
| }; | ||||
| 
 | ||||
| /** FuriHal spi handle states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */ | ||||
|     FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */ | ||||
|     FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */ | ||||
|     FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */ | ||||
| } FuriHalSpiBusHandleEvent; | ||||
| 
 | ||||
| /** FuriHal spi handle event callback */ | ||||
| typedef void (*FuriHalSpiBusHandleEventCallback)( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event); | ||||
| 
 | ||||
| /** FuriHal spi handle */ | ||||
| struct FuriHalSpiBusHandle { | ||||
|     FuriHalSpiBus* bus; | ||||
|     FuriHalSpiBusHandleEventCallback callback; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* sck; | ||||
|     const GpioPin* cs; | ||||
| }; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @ -2,239 +2,150 @@ | ||||
| #include "furi-hal-resources.h" | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <stm32wbxx_ll_utils.h> | ||||
| #include <stm32wbxx_ll_cortex.h> | ||||
| 
 | ||||
| extern void Enable_SPI(SPI_TypeDef* spi); | ||||
| 
 | ||||
| void furi_hal_spi_init() { | ||||
|     for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { | ||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); | ||||
|         hal_gpio_init( | ||||
|             furi_hal_spi_devices[i].chip_select, | ||||
|             GpioModeOutputPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh); | ||||
|     } | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||
| 
 | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_miso, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_mosi, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_sck, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
| 
 | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_miso, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_mosi, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_sck, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||
|     assert(bus); | ||||
|     bus->callback(bus, FuriHalSpiBusEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||
|     assert(bus); | ||||
|     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | ||||
|     assert(bus); | ||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); | ||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); | ||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); | ||||
| void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||
| void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
| 
 | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||
| 
 | ||||
|     assert(handle->bus->current_handle == NULL); | ||||
| 
 | ||||
|     handle->bus->current_handle = handle; | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
| 
 | ||||
|     // Handle event and unset handle
 | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||
|     handle->bus->current_handle = NULL; | ||||
| 
 | ||||
|     // Bus events
 | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||
|         ; | ||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi)) | ||||
|     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)) | ||||
|         ; | ||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); | ||||
|     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     assert(bus); | ||||
| bool furi_hal_spi_bus_rx( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); | ||||
|     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     assert(bus); | ||||
| bool furi_hal_spi_bus_tx( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
|     bool ret = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); | ||||
|         if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||
|             buffer++; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_trx( | ||||
|     const FuriHalSpiBus* bus, | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(bus); | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(tx_buffer); | ||||
|     assert(rx_buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     bool ret = true; | ||||
|     size_t tx_size = size; | ||||
|     bool tx_allowed = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||
|             tx_buffer++; | ||||
|             tx_size--; | ||||
|             tx_allowed = false; | ||||
|         } | ||||
| 
 | ||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); | ||||
|         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|             rx_buffer++; | ||||
|             size--; | ||||
|             tx_allowed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { | ||||
|     assert(device); | ||||
|     assert(device->config); | ||||
| 
 | ||||
|     furi_hal_spi_bus_configure(device->bus, device->config); | ||||
| } | ||||
| 
 | ||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { | ||||
|     assert(device_id < FuriHalSpiDeviceIdMax); | ||||
| 
 | ||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; | ||||
|     assert(device); | ||||
| 
 | ||||
|     furi_hal_spi_bus_lock(device->bus); | ||||
|     furi_hal_spi_device_configure(device); | ||||
| 
 | ||||
|     return device; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { | ||||
|     furi_hal_spi_bus_unlock(device->bus); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_rx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_tx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_trx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(tx_buffer); | ||||
|     assert(rx_buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| @ -1,129 +0,0 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "main.h" | ||||
| 
 | ||||
| #include "furi-hal-spi-config.h" | ||||
| #include <furi-hal-gpio.h> | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Init SPI API | ||||
|  */ | ||||
| void furi_hal_spi_init(); | ||||
| 
 | ||||
| /* Bus Level API */ | ||||
| 
 | ||||
| /** Lock SPI bus
 | ||||
|  * Takes bus mutex, if used | ||||
|  */ | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus); | ||||
| 
 | ||||
| /** Unlock SPI bus
 | ||||
|  * Releases BUS mutex, if used | ||||
|  */ | ||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus); | ||||
| 
 | ||||
| /**
 | ||||
|  * Configure SPI bus | ||||
|  * @param bus - spi bus handler | ||||
|  * @param config - spi configuration structure | ||||
|  */ | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config); | ||||
| 
 | ||||
| /** SPI Receive
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - receive buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - transmit buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit and Receive
 | ||||
|  * @param bus - spi bus handlere | ||||
|  * @param tx_buffer - device handle | ||||
|  * @param rx_buffer - device handle | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_trx( | ||||
|     const FuriHalSpiBus* bus, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /* Device Level API */ | ||||
| 
 | ||||
| /** Reconfigure SPI bus for device
 | ||||
|  * @param device - device description | ||||
|  */ | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device); | ||||
| 
 | ||||
| /** Get Device handle
 | ||||
|  * And lock access to the corresponding SPI BUS | ||||
|  * @param device_id - device identifier | ||||
|  * @return device handle | ||||
|  */ | ||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id); | ||||
| 
 | ||||
| /** Return Device handle
 | ||||
|  * And unlock access to the corresponding SPI BUS | ||||
|  * @param device - device handle | ||||
|  */ | ||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device); | ||||
| 
 | ||||
| /** SPI Recieve
 | ||||
|  * @param device - device handle | ||||
|  * @param buffer - receive buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_rx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit
 | ||||
|  * @param device - device handle | ||||
|  * @param buffer - transmit buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_tx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit and Receive
 | ||||
|  * @param device - device handle | ||||
|  * @param tx_buffer - device handle | ||||
|  * @param rx_buffer - device handle | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_trx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @ -1,10 +1,9 @@ | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <furi-hal-resources.h> | ||||
| 
 | ||||
| #define SPI_R SPI1 | ||||
| #define SPI_D SPI2 | ||||
| /* SPI Presets */ | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in fast mode (after init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in slow mode (before init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_r = { | ||||
|     .spi = SPI_R, | ||||
| /* SPI Buses */ | ||||
| 
 | ||||
| static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if(event == FuriHalSpiBusEventInit) { | ||||
|         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if(event == FuriHalSpiBusEventDeinit) { | ||||
|     } else if(event == FuriHalSpiBusEventLock) { | ||||
|     } else if(event == FuriHalSpiBusEventUnlock) { | ||||
|     } else if(event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBus furi_hal_spi_bus_r = { | ||||
|     .spi = SPI1, | ||||
|     .callback = furi_hal_spi_bus_r_event_callback, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||
|     if(event == FuriHalSpiBusEventInit) { | ||||
|         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|         bus->current_handle = NULL; | ||||
|     } else if(event == FuriHalSpiBusEventDeinit) { | ||||
|     } else if(event == FuriHalSpiBusEventLock) { | ||||
|     } else if(event == FuriHalSpiBusEventUnlock) { | ||||
|     } else if(event == FuriHalSpiBusEventActivate) { | ||||
|         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||
|         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBus furi_hal_spi_bus_d = { | ||||
|     .spi = SPI2, | ||||
|     .callback = furi_hal_spi_bus_d_event_callback, | ||||
| }; | ||||
| 
 | ||||
| /* SPI Bus Handles */ | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_r_handle_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event, | ||||
|     const LL_SPI_InitTypeDef* preset) { | ||||
|     if(event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
| 
 | ||||
|         hal_gpio_init_ex( | ||||
|             handle->miso, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->mosi, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->sck, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI1); | ||||
| 
 | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
| 
 | ||||
|         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
| 
 | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_subghz_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_subghz_event_callback, | ||||
|     .miso = &gpio_spi_r_miso, | ||||
|     .mosi = &gpio_spi_r_mosi, | ||||
|     .clk = &gpio_spi_r_sck, | ||||
|     .sck = &gpio_spi_r_sck, | ||||
|     .cs = &gpio_subghz_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_d = { | ||||
|     .spi = SPI_D, | ||||
| static void furi_hal_spi_bus_handle_nfc_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_nfc_event_callback, | ||||
|     .miso = &gpio_spi_r_miso, | ||||
|     .mosi = &gpio_spi_r_mosi, | ||||
|     .sck = &gpio_spi_r_sck, | ||||
|     .cs = &gpio_nfc_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_external_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||
|     .bus = &furi_hal_spi_bus_r, | ||||
|     .callback = furi_hal_spi_bus_handle_external_event_callback, | ||||
|     .miso = &gpio_ext_pa6, | ||||
|     .mosi = &gpio_ext_pa7, | ||||
|     .sck = &gpio_ext_pb3, | ||||
|     .cs = &gpio_ext_pa4, | ||||
| }; | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_d_handle_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event, | ||||
|     const LL_SPI_InitTypeDef* preset) { | ||||
|     if(event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||
| 
 | ||||
|         hal_gpio_init_ex( | ||||
|             handle->miso, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->mosi, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex( | ||||
|             handle->sck, | ||||
|             GpioModeAltFunctionPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh, | ||||
|             GpioAltFn5SPI2); | ||||
| 
 | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||
|     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_display_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_display_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .clk = &gpio_spi_d_sck, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_display_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | ||||
|     { | ||||
|         .bus = &spi_r, | ||||
|         .config = &furi_hal_spi_config_subghz, | ||||
|         .chip_select = &gpio_subghz_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_display, | ||||
|         .chip_select = &gpio_display_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_sd_fast, | ||||
|         .chip_select = &gpio_sdcard_cs, | ||||
|     }, | ||||
|     { | ||||
|         .bus = &spi_d, | ||||
|         .config = &furi_hal_spi_config_sd_slow, | ||||
|         .chip_select = &gpio_sdcard_cs, | ||||
|     }, | ||||
|     {.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, | ||||
| static void furi_hal_spi_bus_handle_sd_fast_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_sdcard_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_sd_slow_event_callback( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||
|     .bus = &furi_hal_spi_bus_d, | ||||
|     .callback = furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||
|     .miso = &gpio_spi_d_miso, | ||||
|     .mosi = &gpio_spi_d_mosi, | ||||
|     .sck = &gpio_spi_d_sck, | ||||
|     .cs = &gpio_sdcard_cs, | ||||
| }; | ||||
|  | ||||
| @ -1,60 +1,60 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; | ||||
| /** Preset for ST25R916 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||
| 
 | ||||
| /** FURI HAL SPI BUS handler
 | ||||
|  * Structure content may change at some point | ||||
| /** Preset for CC1101 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||
| 
 | ||||
| /** Preset for ST7567 (Display) */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||
| 
 | ||||
| /** Preset for SdCard in fast mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||
| 
 | ||||
| /** Preset for SdCard in slow mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||
| 
 | ||||
| /** CC1101 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||
| 
 | ||||
| /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||
| 
 | ||||
| /** External on `furi_hal_spi_bus_r`
 | ||||
|  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||
|  *  | ||||
|  * miso: pa6 | ||||
|  * mosi: pa7 | ||||
|  * sck: pb3 | ||||
|  * cs:  pa4 (software controlled) | ||||
|  *  | ||||
|  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||
|  * Bus pins are floating on inactive state, CS high after initialization | ||||
|  *  | ||||
|  */ | ||||
| typedef struct { | ||||
|     const SPI_TypeDef* spi; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* clk; | ||||
| } FuriHalSpiBus; | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||
| 
 | ||||
| /** FURI HAL SPI Device handler
 | ||||
|  * Structure content may change at some point | ||||
|  */ | ||||
| typedef struct { | ||||
|     const FuriHalSpiBus* bus; | ||||
|     const LL_SPI_InitTypeDef* config; | ||||
|     const GpioPin* chip_select; | ||||
| } FuriHalSpiDevice; | ||||
| /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||
| 
 | ||||
| /** FURI HAL SPI Standard Device IDs */ | ||||
| typedef enum { | ||||
|     FuriHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */ | ||||
|     FuriHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */ | ||||
|     FuriHalSpiDeviceIdSdCardFast, /** SDCARD: fast mode, after initialization */ | ||||
|     FuriHalSpiDeviceIdSdCardSlow, /** SDCARD: slow mode, before initialization */ | ||||
|     FuriHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ | ||||
| /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||
| 
 | ||||
|     FuriHalSpiDeviceIdMax, /** Service Value, do not use */ | ||||
| } FuriHalSpiDeviceId; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R
 | ||||
|  * CC1101, Nfc | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D
 | ||||
|  * Display, SdCard | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_d; | ||||
| 
 | ||||
| /** Furi Hal Spi devices */ | ||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; | ||||
| /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
							
								
								
									
										64
									
								
								bootloader/targets/f7/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								bootloader/targets/f7/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <stm32wbxx_ll_rcc.h> | ||||
| #include <stm32wbxx_ll_bus.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| typedef struct FuriHalSpiBus FuriHalSpiBus; | ||||
| typedef struct FuriHalSpiBusHandle FuriHalSpiBusHandle; | ||||
| 
 | ||||
| /** FuriHal spi bus states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusEventInit, /**< Bus initialization event, called on system start */ | ||||
|     FuriHalSpiBusEventDeinit, /**< Bus deinitialization event, called on system stop */ | ||||
|     FuriHalSpiBusEventLock, /**< Bus lock event, called before activation */ | ||||
|     FuriHalSpiBusEventUnlock, /**< Bus unlock event, called after deactivation */ | ||||
|     FuriHalSpiBusEventActivate, /**< Bus activation event, called before handle activation */ | ||||
|     FuriHalSpiBusEventDeactivate, /**< Bus deactivation event, called after handle deactivation  */ | ||||
| } FuriHalSpiBusEvent; | ||||
| 
 | ||||
| /** FuriHal spi bus event callback */ | ||||
| typedef void (*FuriHalSpiBusEventCallback)(FuriHalSpiBus* bus, FuriHalSpiBusEvent event); | ||||
| 
 | ||||
| /** FuriHal spi bus */ | ||||
| struct FuriHalSpiBus { | ||||
|     SPI_TypeDef* spi; | ||||
|     FuriHalSpiBusEventCallback callback; | ||||
|     FuriHalSpiBusHandle* current_handle; | ||||
| }; | ||||
| 
 | ||||
| /** FuriHal spi handle states */ | ||||
| typedef enum { | ||||
|     FuriHalSpiBusHandleEventInit, /**< Handle init, called on system start, initialize gpio for idle state */ | ||||
|     FuriHalSpiBusHandleEventDeinit, /**< Handle deinit, called on system stop, deinitialize gpio for default state */ | ||||
|     FuriHalSpiBusHandleEventActivate, /**< Handle activate: connect gpio and apply bus config */ | ||||
|     FuriHalSpiBusHandleEventDeactivate, /**< Handle deactivate: disconnect gpio and reset bus config */ | ||||
| } FuriHalSpiBusHandleEvent; | ||||
| 
 | ||||
| /** FuriHal spi handle event callback */ | ||||
| typedef void (*FuriHalSpiBusHandleEventCallback)( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     FuriHalSpiBusHandleEvent event); | ||||
| 
 | ||||
| /** FuriHal spi handle */ | ||||
| struct FuriHalSpiBusHandle { | ||||
|     FuriHalSpiBus* bus; | ||||
|     FuriHalSpiBusHandleEventCallback callback; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* sck; | ||||
|     const GpioPin* cs; | ||||
| }; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @ -2,239 +2,150 @@ | ||||
| #include "furi-hal-resources.h" | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <stm32wbxx_ll_utils.h> | ||||
| #include <stm32wbxx_ll_cortex.h> | ||||
| 
 | ||||
| extern void Enable_SPI(SPI_TypeDef* spi); | ||||
| 
 | ||||
| void furi_hal_spi_init() { | ||||
|     for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { | ||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); | ||||
|         hal_gpio_init( | ||||
|             furi_hal_spi_devices[i].chip_select, | ||||
|             GpioModeOutputPushPull, | ||||
|             GpioPullNo, | ||||
|             GpioSpeedVeryHigh); | ||||
|     } | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||
| 
 | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_miso, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_mosi, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_r_sck, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullNo, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI1); | ||||
| 
 | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_miso, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_mosi, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex( | ||||
|         &gpio_spi_d_sck, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn5SPI2); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||
|     assert(bus); | ||||
|     bus->callback(bus, FuriHalSpiBusEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | ||||
| void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||
|     assert(bus); | ||||
|     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | ||||
|     assert(bus); | ||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); | ||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); | ||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); | ||||
| void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||
| void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
| 
 | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||
| 
 | ||||
|     assert(handle->bus->current_handle == NULL); | ||||
| 
 | ||||
|     handle->bus->current_handle = handle; | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
| 
 | ||||
|     // Handle event and unset handle
 | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||
|     handle->bus->current_handle = NULL; | ||||
| 
 | ||||
|     // Bus events
 | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||
|         ; | ||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi)) | ||||
|     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)) | ||||
|         ; | ||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); | ||||
|     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     assert(bus); | ||||
| bool furi_hal_spi_bus_rx( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); | ||||
|     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     assert(bus); | ||||
| bool furi_hal_spi_bus_tx( | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
|     bool ret = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); | ||||
|         if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||
|             buffer++; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_trx( | ||||
|     const FuriHalSpiBus* bus, | ||||
|     FuriHalSpiBusHandle* handle, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(bus); | ||||
|     assert(handle); | ||||
|     assert(handle->bus->current_handle == handle); | ||||
|     assert(tx_buffer); | ||||
|     assert(rx_buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     bool ret = true; | ||||
|     size_t tx_size = size; | ||||
|     bool tx_allowed = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||
|             tx_buffer++; | ||||
|             tx_size--; | ||||
|             tx_allowed = false; | ||||
|         } | ||||
| 
 | ||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); | ||||
|         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|             rx_buffer++; | ||||
|             size--; | ||||
|             tx_allowed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { | ||||
|     assert(device); | ||||
|     assert(device->config); | ||||
| 
 | ||||
|     furi_hal_spi_bus_configure(device->bus, device->config); | ||||
| } | ||||
| 
 | ||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { | ||||
|     assert(device_id < FuriHalSpiDeviceIdMax); | ||||
| 
 | ||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; | ||||
|     assert(device); | ||||
| 
 | ||||
|     furi_hal_spi_bus_lock(device->bus); | ||||
|     furi_hal_spi_device_configure(device); | ||||
| 
 | ||||
|     return device; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { | ||||
|     furi_hal_spi_bus_unlock(device->bus); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_rx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_tx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_device_trx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout) { | ||||
|     assert(device); | ||||
|     assert(tx_buffer); | ||||
|     assert(rx_buffer); | ||||
|     assert(size > 0); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, false); | ||||
|     } | ||||
| 
 | ||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); | ||||
| 
 | ||||
|     if(device->chip_select) { | ||||
|         hal_gpio_write(device->chip_select, true); | ||||
|     } | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| @ -1,129 +0,0 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "main.h" | ||||
| 
 | ||||
| #include "furi-hal-spi-config.h" | ||||
| #include <furi-hal-gpio.h> | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Init SPI API | ||||
|  */ | ||||
| void furi_hal_spi_init(); | ||||
| 
 | ||||
| /* Bus Level API */ | ||||
| 
 | ||||
| /** Lock SPI bus
 | ||||
|  * Takes bus mutex, if used | ||||
|  */ | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus); | ||||
| 
 | ||||
| /** Unlock SPI bus
 | ||||
|  * Releases BUS mutex, if used | ||||
|  */ | ||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus); | ||||
| 
 | ||||
| /**
 | ||||
|  * Configure SPI bus | ||||
|  * @param bus - spi bus handler | ||||
|  * @param config - spi configuration structure | ||||
|  */ | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config); | ||||
| 
 | ||||
| /** SPI Receive
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - receive buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - transmit buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit and Receive
 | ||||
|  * @param bus - spi bus handlere | ||||
|  * @param tx_buffer - device handle | ||||
|  * @param rx_buffer - device handle | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_bus_trx( | ||||
|     const FuriHalSpiBus* bus, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /* Device Level API */ | ||||
| 
 | ||||
| /** Reconfigure SPI bus for device
 | ||||
|  * @param device - device description | ||||
|  */ | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device); | ||||
| 
 | ||||
| /** Get Device handle
 | ||||
|  * And lock access to the corresponding SPI BUS | ||||
|  * @param device_id - device identifier | ||||
|  * @return device handle | ||||
|  */ | ||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id); | ||||
| 
 | ||||
| /** Return Device handle
 | ||||
|  * And unlock access to the corresponding SPI BUS | ||||
|  * @param device - device handle | ||||
|  */ | ||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device); | ||||
| 
 | ||||
| /** SPI Recieve
 | ||||
|  * @param device - device handle | ||||
|  * @param buffer - receive buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_rx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit
 | ||||
|  * @param device - device handle | ||||
|  * @param buffer - transmit buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_tx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| /** SPI Transmit and Receive
 | ||||
|  * @param device - device handle | ||||
|  * @param tx_buffer - device handle | ||||
|  * @param rx_buffer - device handle | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  */ | ||||
| bool furi_hal_spi_device_trx( | ||||
|     const FuriHalSpiDevice* device, | ||||
|     uint8_t* tx_buffer, | ||||
|     uint8_t* rx_buffer, | ||||
|     size_t size, | ||||
|     uint32_t timeout); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										102
									
								
								bootloader/targets/furi-hal-include/furi-hal-spi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								bootloader/targets/furi-hal-include/furi-hal-spi.h
									
									
									
									
									
										Normal 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 | ||||
| @ -7,8 +7,6 @@ | ||||
| const uint32_t SpiTimeout = 1000; | ||||
| uint8_t SD_IO_WriteByte(uint8_t Data); | ||||
| 
 | ||||
| static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast]; | ||||
| 
 | ||||
| /******************************************************************************
 | ||||
|                             BUS OPERATIONS | ||||
|  *******************************************************************************/ | ||||
| @ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi | ||||
|  * @retval None | ||||
|  */ | ||||
| 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 | ||||
|  */ | ||||
| __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; | ||||
| 
 | ||||
|     /* 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); | ||||
| 
 | ||||
|     /* 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 */ | ||||
|     if(val == 1) { | ||||
|         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 { | ||||
|         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
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -91,12 +91,7 @@ | ||||
| #include "stdlib.h" | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include <furi-hal-spi.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> | ||||
| #include <furi-hal.h> | ||||
| 
 | ||||
| /** @addtogroup BSP
 | ||||
|   * @{ | ||||
| @ -284,22 +279,22 @@ static uint8_t SD_ReadData(void); | ||||
| /* Private functions ---------------------------------------------------------*/ | ||||
| 
 | ||||
| void SD_SPI_Bus_To_Down_State(){ | ||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_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->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, 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(&gpio_spi_d_miso, false); | ||||
|     hal_gpio_write(&gpio_spi_d_mosi, false); | ||||
|     hal_gpio_write(&gpio_spi_d_sck, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->miso, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->sck, false); | ||||
| } | ||||
| 
 | ||||
| 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(&gpio_spi_d_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->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
| } | ||||
| 
 | ||||
| /** @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) { | ||||
|     /* 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 */ | ||||
|     if(reset_card) { | ||||
| @ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) { | ||||
|         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 */ | ||||
|     return res; | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
| 
 | ||||
| /* Includes ------------------------------------------------------------------*/ | ||||
| #include "user_diskio.h" | ||||
| #include "furi-hal-spi.h" | ||||
| #include <furi-hal.h> | ||||
| /* Private typedef -----------------------------------------------------------*/ | ||||
| /* Private define ------------------------------------------------------------*/ | ||||
| 
 | ||||
| @ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = { | ||||
| DSTATUS USER_initialize(BYTE pdrv) { | ||||
|     /* 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); | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END INIT */ | ||||
| @ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | ||||
|     /* USER CODE BEGIN READ */ | ||||
|     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) { | ||||
|         /* 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; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END READ */ | ||||
| @ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | ||||
|     /* USER CODE HERE */ | ||||
|     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) { | ||||
|         /* 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; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END WRITE */ | ||||
| @ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | ||||
| 
 | ||||
|     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) { | ||||
|     /* Make sure that no pending write process */ | ||||
| @ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | ||||
|         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; | ||||
|     /* USER CODE END IOCTL */ | ||||
|  | ||||
| @ -20,3 +20,5 @@ bool hal_sd_detect(void) { | ||||
|     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL; | ||||
|  | ||||
| @ -1,10 +1,9 @@ | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <furi-hal-resources.h> | ||||
| 
 | ||||
| #define SPI_R SPI1 | ||||
| #define SPI_D SPI2 | ||||
| /* SPI Presets */ | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in fast mode (after init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in slow mode (before init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| osMutexId_t spi_mutex_d = NULL; | ||||
| osMutexId_t spi_mutex_r = NULL; | ||||
| /* SPI Buses */ | ||||
| 
 | ||||
| const FuriHalSpiBus spi_r = { | ||||
|     .spi=SPI_R, | ||||
|     .mutex=&spi_mutex_r, | ||||
| osMutexId_t furi_hal_spi_bus_r_mutex = NULL; | ||||
| 
 | ||||
| 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, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .clk=&gpio_spi_r_sck, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_subghz_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_d = { | ||||
|     .spi=SPI_D, | ||||
|     .mutex=&spi_mutex_d, | ||||
| static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_nfc_event_callback, | ||||
|     .miso=&gpio_spi_r_miso, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_nfc_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_external_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_external_event_callback, | ||||
|     .miso=&gpio_ext_pa6, | ||||
|     .mosi=&gpio_ext_pa7, | ||||
|     .sck=&gpio_ext_pb3, | ||||
|     .cs=&gpio_ext_pa4, | ||||
| }; | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_d_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||
|     if (event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||
| 
 | ||||
|         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
| 
 | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||
|     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_display_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_display_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .clk=&gpio_spi_d_sck, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_display_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_display, .chip_select=&gpio_display_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, | ||||
| static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_sd_slow_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
|  | ||||
| @ -1,62 +1,60 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <cmsis_os2.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; | ||||
| /** Preset for ST25R916 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||
| 
 | ||||
| /** FURI HAL SPI BUS handler
 | ||||
|  * Structure content may change at some point | ||||
| /** Preset for CC1101 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||
| 
 | ||||
| /** Preset for ST7567 (Display) */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||
| 
 | ||||
| /** Preset for SdCard in fast mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||
| 
 | ||||
| /** Preset for SdCard in slow mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||
| 
 | ||||
| /** CC1101 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||
| 
 | ||||
| /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||
| 
 | ||||
| /** External on `furi_hal_spi_bus_r`
 | ||||
|  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||
|  *  | ||||
|  * miso: pa6 | ||||
|  * mosi: pa7 | ||||
|  * sck: pb3 | ||||
|  * cs:  pa4 (software controlled) | ||||
|  *  | ||||
|  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||
|  * Bus pins are floating on inactive state, CS high after initialization | ||||
|  *  | ||||
|  */ | ||||
| typedef struct { | ||||
|     const SPI_TypeDef* spi; | ||||
|     const osMutexId_t* mutex; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* clk; | ||||
| } FuriHalSpiBus; | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||
| 
 | ||||
| /** FURI HAL SPI Device handler
 | ||||
|  * Structure content may change at some point | ||||
|  */ | ||||
| typedef struct { | ||||
|     const FuriHalSpiBus* bus; | ||||
|     const LL_SPI_InitTypeDef* config; | ||||
|     const GpioPin* chip_select; | ||||
| } FuriHalSpiDevice; | ||||
| /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||
| 
 | ||||
| /** FURI HAL SPI Standard Device IDs */ | ||||
| typedef enum { | ||||
|     FuriHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */ | ||||
|     FuriHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */ | ||||
|     FuriHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */ | ||||
|     FuriHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */ | ||||
|     FuriHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ | ||||
| /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||
| 
 | ||||
|     FuriHalSpiDeviceIdMax,           /** Service Value, do not use */ | ||||
| } FuriHalSpiDeviceId; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R
 | ||||
|  * CC1101, Nfc | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D
 | ||||
|  * Display, SdCard | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_d; | ||||
| 
 | ||||
| /** Furi Hal Spi devices */ | ||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; | ||||
| /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
							
								
								
									
										62
									
								
								firmware/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								firmware/targets/f6/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal 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 | ||||
| @ -12,89 +12,104 @@ | ||||
| #define TAG "FuriHalSpi" | ||||
| 
 | ||||
| void furi_hal_spi_init() { | ||||
|     // Spi structure is const, but mutex is not
 | ||||
|     // Need some hell-ish casting to make it work
 | ||||
|     *(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 | ||||
|         ); | ||||
|     } | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||
| 
 | ||||
|     hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
| 
 | ||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||
| 
 | ||||
|     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_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_check(osMutexRelease(*bus->mutex) == osOK); | ||||
|     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | ||||
|     furi_assert(bus); | ||||
| 
 | ||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); | ||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); | ||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); | ||||
| void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); | ||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
| void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     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) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     furi_assert(size > 0); | ||||
|     bool ret = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); | ||||
|         if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||
|             buffer++; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(tx_buffer); | ||||
|     furi_assert(rx_buffer); | ||||
|     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; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||
|             tx_buffer++; | ||||
|             tx_size--; | ||||
|             tx_allowed = false; | ||||
|         } | ||||
|          | ||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
|         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|             rx_buffer++; | ||||
|             size--; | ||||
|             tx_allowed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { | ||||
|     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); | ||||
|     } | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| @ -269,7 +269,7 @@ void furi_hal_subghz_init() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||
|     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 | ||||
|     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||
| @ -277,58 +277,58 @@ void furi_hal_subghz_init() { | ||||
| 
 | ||||
|     // Reset
 | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
| 
 | ||||
|     // Prepare GD0 for power on self test
 | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
| 
 | ||||
|     // 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) | ||||
|         ; | ||||
| 
 | ||||
|     // 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) | ||||
|         ; | ||||
| 
 | ||||
|     // 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); | ||||
| 
 | ||||
|     // RF switches
 | ||||
|     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
 | ||||
|     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"); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_sleep() { | ||||
|     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); | ||||
| 
 | ||||
|     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() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     printf( | ||||
|         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", | ||||
|         cc1101_get_partnumber(device), | ||||
|         cc1101_get_version(device)); | ||||
|     furi_hal_spi_device_return(device); | ||||
|         cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), | ||||
|         cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_reset(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     uint32_t 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++; | ||||
|     } | ||||
|     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]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_set_pa_table(device, data); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_tx(device); | ||||
|     cc1101_write_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_flush_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_read_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     cc1101_shutdown(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_idle() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_subghz_tx() { | ||||
|     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_tx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| float furi_hal_subghz_get_rssi() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     float rssi = rssi_dec; | ||||
|     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) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     //checking regional settings
 | ||||
|     bool txrx = false; | ||||
| @ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||
|     } | ||||
| 
 | ||||
|     uint32_t real_frequency = cc1101_set_frequency(device, value); | ||||
|     cc1101_calibrate(device); | ||||
|     uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); | ||||
|     cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     while(true) { | ||||
|         CC1101Status status = cc1101_get_status(device); | ||||
|         CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); | ||||
|         if(status.STATE == CC1101StateIDLE) break; | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     return real_frequency; | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         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 { | ||||
|         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; | ||||
|  | ||||
| @ -7,8 +7,6 @@ | ||||
| const uint32_t SpiTimeout = 1000; | ||||
| uint8_t SD_IO_WriteByte(uint8_t Data); | ||||
| 
 | ||||
| static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast]; | ||||
| 
 | ||||
| /******************************************************************************
 | ||||
|                             BUS OPERATIONS | ||||
|  *******************************************************************************/ | ||||
| @ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi | ||||
|  * @retval None | ||||
|  */ | ||||
| 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 | ||||
|  */ | ||||
| __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; | ||||
| 
 | ||||
|     /* 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); | ||||
| 
 | ||||
|     /* 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 */ | ||||
|     if(val == 1) { | ||||
|         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 { | ||||
|         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
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -91,12 +91,7 @@ | ||||
| #include "stdlib.h" | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include <furi-hal-spi.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> | ||||
| #include <furi-hal.h> | ||||
| 
 | ||||
| /** @addtogroup BSP
 | ||||
|   * @{ | ||||
| @ -284,22 +279,22 @@ static uint8_t SD_ReadData(void); | ||||
| /* Private functions ---------------------------------------------------------*/ | ||||
| 
 | ||||
| void SD_SPI_Bus_To_Down_State(){ | ||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_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->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, 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(&gpio_spi_d_miso, false); | ||||
|     hal_gpio_write(&gpio_spi_d_mosi, false); | ||||
|     hal_gpio_write(&gpio_spi_d_sck, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->miso, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); | ||||
|     hal_gpio_write(furi_hal_sd_spi_handle->sck, false); | ||||
| } | ||||
| 
 | ||||
| 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(&gpio_spi_d_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->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
| } | ||||
| 
 | ||||
| /** @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) { | ||||
|     /* 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 */ | ||||
|     if(reset_card) { | ||||
| @ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) { | ||||
|         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 */ | ||||
|     return res; | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
| 
 | ||||
| /* Includes ------------------------------------------------------------------*/ | ||||
| #include "user_diskio.h" | ||||
| #include "furi-hal-spi.h" | ||||
| #include <furi-hal.h> | ||||
| /* Private typedef -----------------------------------------------------------*/ | ||||
| /* Private define ------------------------------------------------------------*/ | ||||
| 
 | ||||
| @ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = { | ||||
| DSTATUS USER_initialize(BYTE pdrv) { | ||||
|     /* 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); | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END INIT */ | ||||
| @ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | ||||
|     /* USER CODE BEGIN READ */ | ||||
|     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) { | ||||
|         /* 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; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END READ */ | ||||
| @ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | ||||
|     /* USER CODE HERE */ | ||||
|     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) { | ||||
|         /* 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; | ||||
|     } | ||||
| 
 | ||||
|     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; | ||||
|     /* USER CODE END WRITE */ | ||||
| @ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | ||||
| 
 | ||||
|     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) { | ||||
|     /* Make sure that no pending write process */ | ||||
| @ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | ||||
|         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; | ||||
|     /* USER CODE END IOCTL */ | ||||
|  | ||||
| @ -20,3 +20,5 @@ bool hal_sd_detect(void) { | ||||
|     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL; | ||||
|  | ||||
| @ -1,10 +1,9 @@ | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <furi-hal-resources.h> | ||||
| 
 | ||||
| #define SPI_R SPI1 | ||||
| #define SPI_D SPI2 | ||||
| /* SPI Presets */ | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in fast mode (after init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * SD Card in slow mode (before init) | ||||
|  */ | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
| const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||
|     .Mode = LL_SPI_MODE_MASTER, | ||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||
| @ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | ||||
|     .CRCPoly = 7, | ||||
| }; | ||||
| 
 | ||||
| osMutexId_t spi_mutex_d = NULL; | ||||
| osMutexId_t spi_mutex_r = NULL; | ||||
| /* SPI Buses */ | ||||
| 
 | ||||
| const FuriHalSpiBus spi_r = { | ||||
|     .spi=SPI_R, | ||||
|     .mutex=&spi_mutex_r, | ||||
| osMutexId_t furi_hal_spi_bus_r_mutex = NULL; | ||||
| 
 | ||||
| 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, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .clk=&gpio_spi_r_sck, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_subghz_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiBus spi_d = { | ||||
|     .spi=SPI_D, | ||||
|     .mutex=&spi_mutex_d, | ||||
| static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_nfc_event_callback, | ||||
|     .miso=&gpio_spi_r_miso, | ||||
|     .mosi=&gpio_spi_r_mosi, | ||||
|     .sck=&gpio_spi_r_sck, | ||||
|     .cs=&gpio_nfc_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_external_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||
|     .bus=&furi_hal_spi_bus_r, | ||||
|     .callback=furi_hal_spi_bus_handle_external_event_callback, | ||||
|     .miso=&gpio_ext_pa6, | ||||
|     .mosi=&gpio_ext_pa7, | ||||
|     .sck=&gpio_ext_pb3, | ||||
|     .cs=&gpio_ext_pa4, | ||||
| }; | ||||
| 
 | ||||
| inline static void furi_hal_spi_bus_d_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||
|     if (event == FuriHalSpiBusHandleEventInit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||
| 
 | ||||
|         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
| 
 | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||
|     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||
|         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||
|         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|         LL_SPI_Enable(handle->bus->spi); | ||||
|         hal_gpio_write(handle->cs, false); | ||||
|     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||
|         hal_gpio_write(handle->cs, true); | ||||
|         LL_SPI_Disable(handle->bus->spi); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_display_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_display_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .clk=&gpio_spi_d_sck, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_display_cs, | ||||
| }; | ||||
| 
 | ||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_display, .chip_select=&gpio_display_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, }, | ||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, | ||||
| static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
| 
 | ||||
| static void furi_hal_spi_bus_handle_sd_slow_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||
|     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||
| } | ||||
| 
 | ||||
| FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||
|     .bus=&furi_hal_spi_bus_d, | ||||
|     .callback=furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||
|     .miso=&gpio_spi_d_miso, | ||||
|     .mosi=&gpio_spi_d_mosi, | ||||
|     .sck=&gpio_spi_d_sck, | ||||
|     .cs=&gpio_sdcard_cs, | ||||
| }; | ||||
|  | ||||
| @ -1,62 +1,60 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <furi-hal-gpio.h> | ||||
| #include <stm32wbxx_ll_spi.h> | ||||
| #include <cmsis_os2.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; | ||||
| /** Preset for ST25R916 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||
| 
 | ||||
| /** FURI HAL SPI BUS handler
 | ||||
|  * Structure content may change at some point | ||||
| /** Preset for CC1101 */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||
| 
 | ||||
| /** Preset for ST7567 (Display) */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||
| 
 | ||||
| /** Preset for SdCard in fast mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||
| 
 | ||||
| /** Preset for SdCard in slow mode */ | ||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||
| extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||
| 
 | ||||
| /** CC1101 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||
| 
 | ||||
| /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||
| 
 | ||||
| /** External on `furi_hal_spi_bus_r`
 | ||||
|  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||
|  *  | ||||
|  * miso: pa6 | ||||
|  * mosi: pa7 | ||||
|  * sck: pb3 | ||||
|  * cs:  pa4 (software controlled) | ||||
|  *  | ||||
|  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||
|  * Bus pins are floating on inactive state, CS high after initialization | ||||
|  *  | ||||
|  */ | ||||
| typedef struct { | ||||
|     const SPI_TypeDef* spi; | ||||
|     const osMutexId_t* mutex; | ||||
|     const GpioPin* miso; | ||||
|     const GpioPin* mosi; | ||||
|     const GpioPin* clk; | ||||
| } FuriHalSpiBus; | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||
| 
 | ||||
| /** FURI HAL SPI Device handler
 | ||||
|  * Structure content may change at some point | ||||
|  */ | ||||
| typedef struct { | ||||
|     const FuriHalSpiBus* bus; | ||||
|     const LL_SPI_InitTypeDef* config; | ||||
|     const GpioPin* chip_select; | ||||
| } FuriHalSpiDevice; | ||||
| /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||
| 
 | ||||
| /** FURI HAL SPI Standard Device IDs */ | ||||
| typedef enum { | ||||
|     FuriHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */ | ||||
|     FuriHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */ | ||||
|     FuriHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */ | ||||
|     FuriHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */ | ||||
|     FuriHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ | ||||
| /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||
| 
 | ||||
|     FuriHalSpiDeviceIdMax,           /** Service Value, do not use */ | ||||
| } FuriHalSpiDeviceId; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus R
 | ||||
|  * CC1101, Nfc | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_r; | ||||
| 
 | ||||
| /** Furi Hal Spi Bus D
 | ||||
|  * Display, SdCard | ||||
|  */ | ||||
| extern const FuriHalSpiBus spi_d; | ||||
| 
 | ||||
| /** Furi Hal Spi devices */ | ||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; | ||||
| /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||
| extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
							
								
								
									
										62
									
								
								firmware/targets/f7/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								firmware/targets/f7/furi-hal/furi-hal-spi-types.h
									
									
									
									
									
										Normal 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 | ||||
| @ -12,89 +12,104 @@ | ||||
| #define TAG "FuriHalSpi" | ||||
| 
 | ||||
| void furi_hal_spi_init() { | ||||
|     // Spi structure is const, but mutex is not
 | ||||
|     // Need some hell-ish casting to make it work
 | ||||
|     *(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 | ||||
|         ); | ||||
|     } | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||
|     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||
| 
 | ||||
|     hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
|     hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||
| 
 | ||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||
|     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||
| 
 | ||||
|     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_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_check(osMutexRelease(*bus->mutex) == osOK); | ||||
|     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | ||||
|     furi_assert(bus); | ||||
| 
 | ||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); | ||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); | ||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); | ||||
| void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | ||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); | ||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||
|         LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
| void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||
|     furi_assert(handle); | ||||
|     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     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) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(buffer); | ||||
|     furi_assert(size > 0); | ||||
|     bool ret = true; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); | ||||
|         if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||
|             buffer++; | ||||
|             size--; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
|     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(bus); | ||||
| bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||
|     furi_assert(handle); | ||||
|     furi_assert(handle->bus->current_handle == handle); | ||||
|     furi_assert(tx_buffer); | ||||
|     furi_assert(rx_buffer); | ||||
|     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; | ||||
| 
 | ||||
|     while(size > 0) { | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); | ||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||
|             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||
|             tx_buffer++; | ||||
|             tx_size--; | ||||
|             tx_allowed = false; | ||||
|         } | ||||
|          | ||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | ||||
|         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||
|             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||
|             rx_buffer++; | ||||
|             size--; | ||||
|             tx_allowed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { | ||||
|     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); | ||||
|     } | ||||
|     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| @ -269,7 +269,7 @@ void furi_hal_subghz_init() { | ||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||
|     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 | ||||
|     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||
| @ -277,58 +277,58 @@ void furi_hal_subghz_init() { | ||||
| 
 | ||||
|     // Reset
 | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
| 
 | ||||
|     // Prepare GD0 for power on self test
 | ||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||
| 
 | ||||
|     // 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) | ||||
|         ; | ||||
| 
 | ||||
|     // 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) | ||||
|         ; | ||||
| 
 | ||||
|     // 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); | ||||
| 
 | ||||
|     // RF switches
 | ||||
|     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
 | ||||
|     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"); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_sleep() { | ||||
|     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); | ||||
| 
 | ||||
|     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() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     printf( | ||||
|         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", | ||||
|         cc1101_get_partnumber(device), | ||||
|         cc1101_get_version(device)); | ||||
|     furi_hal_spi_device_return(device); | ||||
|         cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), | ||||
|         cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_reset(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     uint32_t 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++; | ||||
|     } | ||||
|     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]) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_set_pa_table(device, data); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_tx(device); | ||||
|     cc1101_write_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_flush_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_flush_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_read_fifo(device, data, size); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     cc1101_shutdown(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     cc1101_reset(device); | ||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_idle() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_idle(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_subghz_rx() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_rx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| } | ||||
| 
 | ||||
| bool furi_hal_subghz_tx() { | ||||
|     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     cc1101_switch_to_tx(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| float furi_hal_subghz_get_rssi() { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(device); | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
|     int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     float rssi = rssi_dec; | ||||
|     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) { | ||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     //checking regional settings
 | ||||
|     bool txrx = false; | ||||
| @ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||
|     } | ||||
| 
 | ||||
|     uint32_t real_frequency = cc1101_set_frequency(device, value); | ||||
|     cc1101_calibrate(device); | ||||
|     uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); | ||||
|     cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     while(true) { | ||||
|         CC1101Status status = cc1101_get_status(device); | ||||
|         CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); | ||||
|         if(status.STATE == CC1101StateIDLE) break; | ||||
|     } | ||||
| 
 | ||||
|     furi_hal_spi_device_return(device); | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||
| 
 | ||||
|     return real_frequency; | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         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) { | ||||
|         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 { | ||||
|         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; | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <furi-hal-spi-types.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| @ -24,6 +25,9 @@ void hal_sd_detect_set_low(void); | ||||
|  */ | ||||
| bool hal_sd_detect(void); | ||||
| 
 | ||||
| /** Pointer to currently used SPI Handle */ | ||||
| extern FuriHalSpiBusHandle* furi_hal_sd_spi_handle; | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -1,106 +1,88 @@ | ||||
| #pragma once | ||||
| #include "main.h" | ||||
| #include "furi-hal-spi-config.h" | ||||
| #include <furi-hal-gpio.h> | ||||
| 
 | ||||
| #include <furi-hal-spi-config.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * Init SPI API | ||||
|  */ | ||||
| /** Initialize SPI HAL */ | ||||
| void furi_hal_spi_init(); | ||||
| 
 | ||||
| /* Bus Level API */ | ||||
| 
 | ||||
| /** Lock SPI bus
 | ||||
|  * Takes bus mutex, if used | ||||
| /** Initialize SPI Bus
 | ||||
|  * | ||||
|  * @param      handle  pointer to FuriHalSpiBus instance | ||||
|  */ | ||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus); | ||||
| void furi_hal_spi_bus_init(FuriHalSpiBus* bus); | ||||
| 
 | ||||
| /** Unlock SPI bus
 | ||||
|  * Releases BUS mutex, if used | ||||
| /** Deinitialize SPI Bus
 | ||||
|  * | ||||
|  * @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
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param config - spi configuration structure | ||||
| /** Initialize SPI Bus Handle
 | ||||
|  * | ||||
|  * @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
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - receive buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  * | ||||
|  * @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(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
 | ||||
|  * @param bus - spi bus handler | ||||
|  * @param buffer - transmit buffer | ||||
|  * @param size - transaction size | ||||
|  * @param timeout - bus operation timeout in ms | ||||
|  * | ||||
|  * @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(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
 | ||||
|  * @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 | ||||
|  * | ||||
|  * @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(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); | ||||
| 
 | ||||
| bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|  | ||||
| @ -14,6 +14,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | ||||
| #include "furi-hal-crypto.h" | ||||
| #include "furi-hal-console.h" | ||||
| #include "furi-hal-os.h" | ||||
| #include "furi-hal-sd.h" | ||||
| #include "furi-hal-i2c.h" | ||||
| #include "furi-hal-resources.h" | ||||
| #include "furi-hal-gpio.h" | ||||
|  | ||||
| @ -7,7 +7,6 @@ | ||||
| static osThreadAttr_t platform_irq_thread_attr; | ||||
| static volatile osThreadId_t platform_irq_thread_id = NULL; | ||||
| static volatile PlatformIrqCallback platform_irq_callback = NULL; | ||||
| static FuriHalSpiDevice* platform_st25r3916 = NULL; | ||||
| static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; | ||||
| 
 | ||||
| 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) { | ||||
|     furi_assert(platform_st25r3916); | ||||
|     bool ret = false; | ||||
|     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) { | ||||
|         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) { | ||||
|         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) { | ||||
| @ -68,15 +66,9 @@ HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t | ||||
| } | ||||
| 
 | ||||
| void platformProtectST25RComm() { | ||||
|     // Don't check platform_st25r3916 since spi device is used simultaneously from nfc worker
 | ||||
|     // thread and platformIrqWorker thread with the highest priority
 | ||||
| 
 | ||||
|     // furi_assert(platform_st25r3916 == NULL);
 | ||||
|     platform_st25r3916 = (FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdNfc); | ||||
|     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc); | ||||
| } | ||||
| 
 | ||||
| void platformUnprotectST25RComm() { | ||||
|     // furi_assert(platform_st25r3916);
 | ||||
|     furi_hal_spi_device_return(platform_st25r3916); | ||||
|     // platform_st25r3916 = NULL;
 | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc); | ||||
| } | ||||
|  | ||||
| @ -4,180 +4,164 @@ | ||||
| #include <assert.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 }; | ||||
|     CC1101Status rx[1] = { 0 }; | ||||
| 
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT); | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT); | ||||
| 
 | ||||
|     assert(rx[0].CHIP_RDYn == 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 }; | ||||
|     CC1101Status rx[2] = { 0 }; | ||||
| 
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||
| 
 | ||||
|     assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0); | ||||
|     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); | ||||
|     uint8_t tx[2] = { reg|CC1101_READ, 0}; | ||||
|     CC1101Status rx[2] = { 0 }; | ||||
| 
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||
| 
 | ||||
|     assert((rx[0].CHIP_RDYn) == 0); | ||||
|     *data = *(uint8_t*)&rx[1]; | ||||
|     return rx[0]; | ||||
| } | ||||
| 
 | ||||
| uint8_t cc1101_get_partnumber(const FuriHalSpiDevice* device) { | ||||
| uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle) { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| uint8_t cc1101_get_version(const FuriHalSpiDevice* device) { | ||||
| uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle) { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| uint8_t cc1101_get_rssi(const FuriHalSpiDevice* device) { | ||||
| uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) { | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| void cc1101_reset(const FuriHalSpiDevice* device) { | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
| void cc1101_reset(FuriHalSpiBusHandle* handle) { | ||||
|     delay_us(1000); | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     delay_us(1000); | ||||
|     cc1101_strobe(device, CC1101_STROBE_SRES); | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SRES); | ||||
| } | ||||
| 
 | ||||
| CC1101Status cc1101_get_status(const FuriHalSpiDevice* device) { | ||||
|     return cc1101_strobe(device, CC1101_STROBE_SNOP); | ||||
| CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle) { | ||||
|     return cc1101_strobe(handle, CC1101_STROBE_SNOP); | ||||
| } | ||||
| 
 | ||||
| void cc1101_shutdown(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SPWD); | ||||
| void cc1101_shutdown(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SPWD); | ||||
| } | ||||
| 
 | ||||
| void cc1101_calibrate(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SCAL); | ||||
| void cc1101_calibrate(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SCAL); | ||||
| } | ||||
| 
 | ||||
| void cc1101_switch_to_idle(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SIDLE); | ||||
| void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SIDLE); | ||||
| } | ||||
| 
 | ||||
| void cc1101_switch_to_rx(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SRX); | ||||
| void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SRX); | ||||
| } | ||||
| 
 | ||||
| void cc1101_switch_to_tx(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_STX); | ||||
| void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_STX); | ||||
| } | ||||
| 
 | ||||
| void cc1101_flush_rx(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SFRX); | ||||
| void cc1101_flush_rx(FuriHalSpiBusHandle* handle) { | ||||
|     cc1101_strobe(handle, CC1101_STROBE_SFRX); | ||||
| } | ||||
| 
 | ||||
| void cc1101_flush_tx(const FuriHalSpiDevice* device) { | ||||
|     cc1101_strobe(device, CC1101_STROBE_SFTX); | ||||
| void cc1101_flush_tx(FuriHalSpiBusHandle* handle) { | ||||
|     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; | ||||
| 
 | ||||
|     // Sanity check
 | ||||
|     assert((real_value & CC1101_FMASK) == real_value); | ||||
| 
 | ||||
|     cc1101_write_reg(device, CC1101_FREQ2, (real_value >> 16) & 0xFF); | ||||
|     cc1101_write_reg(device, CC1101_FREQ1, (real_value >> 8 ) & 0xFF); | ||||
|     cc1101_write_reg(device, CC1101_FREQ0, (real_value >> 0 ) & 0xFF); | ||||
|     cc1101_write_reg(handle, CC1101_FREQ2, (real_value >> 16) & 0xFF); | ||||
|     cc1101_write_reg(handle, CC1101_FREQ1, (real_value >> 8 ) & 0xFF); | ||||
|     cc1101_write_reg(handle, CC1101_FREQ0, (real_value >> 0 ) & 0xFF); | ||||
| 
 | ||||
|     uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV; | ||||
| 
 | ||||
|     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; | ||||
|     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; | ||||
| 
 | ||||
|     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 }; | ||||
|     CC1101Status rx[9] = { 0 }; | ||||
| 
 | ||||
|     memcpy(&tx[1], &value[0], 8); | ||||
| 
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
|     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); | ||||
| 
 | ||||
|     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_rx[64]; | ||||
|     buff_tx[0] = CC1101_FIFO | CC1101_BURST; | ||||
|     memcpy(&buff_tx[1], data, size); | ||||
| 
 | ||||
|     // Start transaction
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     // Wait IC to become ready
 | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
|     // Tell IC what we want
 | ||||
|     furi_hal_spi_bus_trx(device->bus, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); | ||||
| 
 | ||||
|     // Finish transaction
 | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     furi_hal_spi_bus_trx(handle, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); | ||||
| 
 | ||||
|     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]; | ||||
|     buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; | ||||
|     uint8_t buff_rx[2]; | ||||
| 
 | ||||
|     // Start transaction
 | ||||
|     hal_gpio_write(device->chip_select, false); | ||||
|     // Wait IC to become ready
 | ||||
|     while(hal_gpio_read(device->bus->miso)); | ||||
|     while(hal_gpio_read(handle->miso)); | ||||
| 
 | ||||
|     // 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]; | ||||
|     furi_hal_spi_bus_trx(device->bus, &buff_tx[1], data, *size, CC1101_TIMEOUT); | ||||
|     cc1101_flush_rx(device); | ||||
|     furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT); | ||||
|     cc1101_flush_rx(handle); | ||||
| 
 | ||||
|     hal_gpio_write(device->chip_select, true); | ||||
|     return *size; | ||||
| } | ||||
|  | ||||
| @ -13,131 +13,167 @@ extern "C" { | ||||
| /* Low level API */ | ||||
| 
 | ||||
| /** Strobe command to the device
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      strobe  - command to execute | ||||
|  * | ||||
|  * @return     device status | ||||
|  */ | ||||
| CC1101Status cc1101_strobe(const FuriHalSpiDevice* device, uint8_t strobe); | ||||
| CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe); | ||||
| 
 | ||||
| /** Write device register
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      reg     - register | ||||
|  * @param      data    - data to write | ||||
|  * | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      reg     - register | ||||
|  * @param[out] data    - pointer to data | ||||
|  * | ||||
|  * @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 */ | ||||
| 
 | ||||
| /** Reset
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  */ | ||||
| void cc1101_reset(const FuriHalSpiDevice* device); | ||||
| void cc1101_reset(FuriHalSpiBusHandle* handle); | ||||
| 
 | ||||
| /** 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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  */ | ||||
| void cc1101_shutdown(const FuriHalSpiDevice* device); | ||||
| void cc1101_shutdown(FuriHalSpiBusHandle* handle); | ||||
| 
 | ||||
| /** 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
 | ||||
|  * @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
 | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  */ | ||||
| void cc1101_calibrate(const FuriHalSpiDevice* device); | ||||
| void cc1101_calibrate(FuriHalSpiBusHandle* handle); | ||||
| 
 | ||||
| /** 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
 | ||||
|  * @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
 | ||||
|  * @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
 | ||||
|  * @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
 | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      value   - frequency in herz | ||||
|  * | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      value   - frequency in herz | ||||
|  * | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * @param data, pointer to byte array | ||||
|  * @param size, write bytes count | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      data    pointer to byte array | ||||
|  * @param      size    write 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
 | ||||
|  * @param device - pointer to FuriHalSpiDevice | ||||
|  * @param data, pointer to byte array | ||||
|  * @param size, bytes to read from fifo | ||||
|  * | ||||
|  * @param      handle  - pointer to FuriHalSpiHandle | ||||
|  * @param      data    pointer to byte array | ||||
|  * @param      size    bytes to read from fifo | ||||
|  * | ||||
|  * @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 | ||||
| } | ||||
|  | ||||
| @ -2,8 +2,6 @@ | ||||
| 
 | ||||
| #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) { | ||||
|     switch(msg) { | ||||
|     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) { | ||||
|     switch(msg) { | ||||
|     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; | ||||
|     case U8X8_MSG_BYTE_SET_DC: | ||||
|         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: | ||||
|         break; | ||||
|     case U8X8_MSG_BYTE_START_TRANSFER: | ||||
|         furi_assert(u8g2_periphery_display == NULL); | ||||
|         u8g2_periphery_display = | ||||
|             (FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdDisplay); | ||||
|         hal_gpio_write(u8g2_periphery_display->chip_select, false); | ||||
|         furi_hal_spi_acquire(&furi_hal_spi_bus_handle_display); | ||||
|         break; | ||||
|     case U8X8_MSG_BYTE_END_TRANSFER: | ||||
|         furi_assert(u8g2_periphery_display); | ||||
|         hal_gpio_write(u8g2_periphery_display->chip_select, true); | ||||
|         furi_hal_spi_device_return(u8g2_periphery_display); | ||||
|         u8g2_periphery_display = NULL; | ||||
|         furi_hal_spi_release(&furi_hal_spi_bus_handle_display); | ||||
|         break; | ||||
|     default: | ||||
|         return 0; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく