[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-spi-config.h> | ||||||
| #include <furi-hal-resources.h> | #include <furi-hal-resources.h> | ||||||
| 
 | 
 | ||||||
| #define SPI_R SPI1 | /* SPI Presets */ | ||||||
| #define SPI_D SPI2 |  | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||||
|  * SD Card in fast mode (after init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||||
|  * SD Card in slow mode (before init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_r = { | /* SPI Buses */ | ||||||
|     .spi = SPI_R, | 
 | ||||||
|  | static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if(event == FuriHalSpiBusEventInit) { | ||||||
|  |         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeinit) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventLock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventUnlock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_r = { | ||||||
|  |     .spi = SPI1, | ||||||
|  |     .callback = furi_hal_spi_bus_r_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if(event == FuriHalSpiBusEventInit) { | ||||||
|  |         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeinit) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventLock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventUnlock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_d = { | ||||||
|  |     .spi = SPI2, | ||||||
|  |     .callback = furi_hal_spi_bus_d_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SPI Bus Handles */ | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_r_handle_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event, | ||||||
|  |     const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->miso, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->mosi, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->sck, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_subghz_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_subghz_event_callback, | ||||||
|     .miso = &gpio_spi_r_miso, |     .miso = &gpio_spi_r_miso, | ||||||
|     .mosi = &gpio_spi_r_mosi, |     .mosi = &gpio_spi_r_mosi, | ||||||
|     .clk = &gpio_spi_r_sck, |     .sck = &gpio_spi_r_sck, | ||||||
|  |     .cs = &gpio_subghz_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_d = { | static void furi_hal_spi_bus_handle_nfc_event_callback( | ||||||
|     .spi = SPI_D, |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_nfc_event_callback, | ||||||
|  |     .miso = &gpio_spi_r_miso, | ||||||
|  |     .mosi = &gpio_spi_r_mosi, | ||||||
|  |     .sck = &gpio_spi_r_sck, | ||||||
|  |     .cs = &gpio_nfc_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_external_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_external_event_callback, | ||||||
|  |     .miso = &gpio_ext_pa6, | ||||||
|  |     .mosi = &gpio_ext_pa7, | ||||||
|  |     .sck = &gpio_ext_pb3, | ||||||
|  |     .cs = &gpio_ext_pa4, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_d_handle_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event, | ||||||
|  |     const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->miso, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->mosi, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->sck, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  | 
 | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_display_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||||
|  |     .bus = &furi_hal_spi_bus_d, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_display_event_callback, | ||||||
|     .miso = &gpio_spi_d_miso, |     .miso = &gpio_spi_d_miso, | ||||||
|     .mosi = &gpio_spi_d_mosi, |     .mosi = &gpio_spi_d_mosi, | ||||||
|     .clk = &gpio_spi_d_sck, |     .sck = &gpio_spi_d_sck, | ||||||
|  |     .cs = &gpio_display_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | static void furi_hal_spi_bus_handle_sd_fast_event_callback( | ||||||
|     { |     FuriHalSpiBusHandle* handle, | ||||||
|         .bus = &spi_r, |     FuriHalSpiBusHandleEvent event) { | ||||||
|         .config = &furi_hal_spi_config_subghz, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||||
|         .chip_select = &gpio_subghz_cs, | } | ||||||
|     }, | 
 | ||||||
|     { | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||||
|         .bus = &spi_d, |     .bus = &furi_hal_spi_bus_d, | ||||||
|         .config = &furi_hal_spi_config_display, |     .callback = furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||||
|         .chip_select = &gpio_display_cs, |     .miso = &gpio_spi_d_miso, | ||||||
|     }, |     .mosi = &gpio_spi_d_mosi, | ||||||
|     { |     .sck = &gpio_spi_d_sck, | ||||||
|         .bus = &spi_d, |     .cs = &gpio_sdcard_cs, | ||||||
|         .config = &furi_hal_spi_config_sd_fast, | }; | ||||||
|         .chip_select = &gpio_sdcard_cs, | 
 | ||||||
|     }, | static void furi_hal_spi_bus_handle_sd_slow_event_callback( | ||||||
|     { |     FuriHalSpiBusHandle* handle, | ||||||
|         .bus = &spi_d, |     FuriHalSpiBusHandleEvent event) { | ||||||
|         .config = &furi_hal_spi_config_sd_slow, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|         .chip_select = &gpio_sdcard_cs, | } | ||||||
|     }, | 
 | ||||||
|     {.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||||
|  |     .bus = &furi_hal_spi_bus_d, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||||
|  |     .miso = &gpio_spi_d_miso, | ||||||
|  |     .mosi = &gpio_spi_d_mosi, | ||||||
|  |     .sck = &gpio_spi_d_sck, | ||||||
|  |     .cs = &gpio_sdcard_cs, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,60 +1,60 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <furi-hal-gpio.h> | #include <furi-hal-spi-types.h> | ||||||
| #include <stm32wbxx_ll_spi.h> |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | /** Preset for ST25R916 */ | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI BUS handler
 | /** Preset for CC1101 */ | ||||||
|  * Structure content may change at some point | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||||
|  | 
 | ||||||
|  | /** Preset for ST7567 (Display) */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in fast mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in slow mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||||
|  | 
 | ||||||
|  | /** CC1101 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||||
|  | 
 | ||||||
|  | /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||||
|  | 
 | ||||||
|  | /** External on `furi_hal_spi_bus_r`
 | ||||||
|  |  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||||
|  |  *  | ||||||
|  |  * miso: pa6 | ||||||
|  |  * mosi: pa7 | ||||||
|  |  * sck: pb3 | ||||||
|  |  * cs:  pa4 (software controlled) | ||||||
|  |  *  | ||||||
|  |  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||||
|  |  * Bus pins are floating on inactive state, CS high after initialization | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| typedef struct { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||||
|     const SPI_TypeDef* spi; |  | ||||||
|     const GpioPin* miso; |  | ||||||
|     const GpioPin* mosi; |  | ||||||
|     const GpioPin* clk; |  | ||||||
| } FuriHalSpiBus; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Device handler
 | /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||||
|  * Structure content may change at some point | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||||
|  */ |  | ||||||
| typedef struct { |  | ||||||
|     const FuriHalSpiBus* bus; |  | ||||||
|     const LL_SPI_InitTypeDef* config; |  | ||||||
|     const GpioPin* chip_select; |  | ||||||
| } FuriHalSpiDevice; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Standard Device IDs */ | /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||||
| typedef enum { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||||
|     FuriHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */ |  | ||||||
|     FuriHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardFast, /** SDCARD: fast mode, after initialization */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardSlow, /** SDCARD: slow mode, before initialization */ |  | ||||||
|     FuriHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ |  | ||||||
| 
 | 
 | ||||||
|     FuriHalSpiDeviceIdMax, /** Service Value, do not use */ | /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||||
| } FuriHalSpiDeviceId; | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus R
 |  | ||||||
|  * CC1101, Nfc |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_r; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus D
 |  | ||||||
|  * Display, SdCard |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_d; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi devices */ |  | ||||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										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 "furi-hal-resources.h" | ||||||
| 
 | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <string.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_spi.h> | #include <stm32wbxx_ll_spi.h> | ||||||
| #include <stm32wbxx_ll_utils.h> | #include <stm32wbxx_ll_utils.h> | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| 
 | 
 | ||||||
| extern void Enable_SPI(SPI_TypeDef* spi); |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_init() { | void furi_hal_spi_init() { | ||||||
|     for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { |     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); |     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||||
|         hal_gpio_init( | 
 | ||||||
|             furi_hal_spi_devices[i].chip_select, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||||
|             GpioModeOutputPushPull, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||||
|             GpioPullNo, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||||
|             GpioSpeedVeryHigh); |     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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex( | void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||||
|         &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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { |  | ||||||
|     assert(bus); |     assert(bus); | ||||||
|  |     bus->callback(bus, FuriHalSpiBusEventInit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||||
|     assert(bus); |     assert(bus); | ||||||
|  |     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||||
|     assert(bus); |     assert(handle); | ||||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); |     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); |  | ||||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |  | ||||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) |     assert(handle); | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||||
|  |     assert(handle); | ||||||
|  | 
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||||
|  | 
 | ||||||
|  |     assert(handle->bus->current_handle == NULL); | ||||||
|  | 
 | ||||||
|  |     handle->bus->current_handle = handle; | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|  | 
 | ||||||
|  |     // Handle event and unset handle
 | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||||
|  |     handle->bus->current_handle = NULL; | ||||||
|  | 
 | ||||||
|  |     // Bus events
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||||
|  |     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||||
|         ; |         ; | ||||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi)) |     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)) | ||||||
|         ; |         ; | ||||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { |     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||||
|         LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); |         LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_rx( | ||||||
|     assert(bus); |     FuriHalSpiBusHandle* handle, | ||||||
|  |     uint8_t* buffer, | ||||||
|  |     size_t size, | ||||||
|  |     uint32_t timeout) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(buffer); |     assert(buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
| 
 | 
 | ||||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); |     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_tx( | ||||||
|     assert(bus); |     FuriHalSpiBusHandle* handle, | ||||||
|  |     uint8_t* buffer, | ||||||
|  |     size_t size, | ||||||
|  |     uint32_t timeout) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(buffer); |     assert(buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { |         if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||||
|             buffer++; |             buffer++; | ||||||
|             size--; |             size--; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); |     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_trx( | bool furi_hal_spi_bus_trx( | ||||||
|     const FuriHalSpiBus* bus, |     FuriHalSpiBusHandle* handle, | ||||||
|     uint8_t* tx_buffer, |     uint8_t* tx_buffer, | ||||||
|     uint8_t* rx_buffer, |     uint8_t* rx_buffer, | ||||||
|     size_t size, |     size_t size, | ||||||
|     uint32_t timeout) { |     uint32_t timeout) { | ||||||
|     assert(bus); |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(tx_buffer); |     assert(tx_buffer); | ||||||
|     assert(rx_buffer); |     assert(rx_buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
|  | 
 | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
|     size_t tx_size = size; |     size_t tx_size = size; | ||||||
|     bool tx_allowed = true; |     bool tx_allowed = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { |         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||||
|             tx_buffer++; |             tx_buffer++; | ||||||
|             tx_size--; |             tx_size--; | ||||||
|             tx_allowed = false; |             tx_allowed = false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { |         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); |             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|             rx_buffer++; |             rx_buffer++; | ||||||
|             size--; |             size--; | ||||||
|             tx_allowed = true; |             tx_allowed = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(device->config); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_configure(device->bus, device->config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { |  | ||||||
|     assert(device_id < FuriHalSpiDeviceIdMax); |  | ||||||
| 
 |  | ||||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; |  | ||||||
|     assert(device); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_lock(device->bus); |  | ||||||
|     furi_hal_spi_device_configure(device); |  | ||||||
| 
 |  | ||||||
|     return device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_hal_spi_bus_unlock(device->bus); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_rx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_tx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_trx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* tx_buffer, |  | ||||||
|     uint8_t* rx_buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(tx_buffer); |  | ||||||
|     assert(rx_buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -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-spi-config.h> | ||||||
| #include <furi-hal-resources.h> | #include <furi-hal-resources.h> | ||||||
| 
 | 
 | ||||||
| #define SPI_R SPI1 | /* SPI Presets */ | ||||||
| #define SPI_D SPI2 |  | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||||
|  * SD Card in fast mode (after init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||||
|  * SD Card in slow mode (before init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -75,40 +68,223 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_r = { | /* SPI Buses */ | ||||||
|     .spi = SPI_R, | 
 | ||||||
|  | static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if(event == FuriHalSpiBusEventInit) { | ||||||
|  |         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeinit) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventLock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventUnlock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_r = { | ||||||
|  |     .spi = SPI1, | ||||||
|  |     .callback = furi_hal_spi_bus_r_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if(event == FuriHalSpiBusEventInit) { | ||||||
|  |         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeinit) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventLock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventUnlock) { | ||||||
|  |     } else if(event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } else if(event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_d = { | ||||||
|  |     .spi = SPI2, | ||||||
|  |     .callback = furi_hal_spi_bus_d_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SPI Bus Handles */ | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_r_handle_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event, | ||||||
|  |     const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->miso, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->mosi, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->sck, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI1); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_subghz_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_subghz_event_callback, | ||||||
|     .miso = &gpio_spi_r_miso, |     .miso = &gpio_spi_r_miso, | ||||||
|     .mosi = &gpio_spi_r_mosi, |     .mosi = &gpio_spi_r_mosi, | ||||||
|     .clk = &gpio_spi_r_sck, |     .sck = &gpio_spi_r_sck, | ||||||
|  |     .cs = &gpio_subghz_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_d = { | static void furi_hal_spi_bus_handle_nfc_event_callback( | ||||||
|     .spi = SPI_D, |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_nfc_event_callback, | ||||||
|  |     .miso = &gpio_spi_r_miso, | ||||||
|  |     .mosi = &gpio_spi_r_mosi, | ||||||
|  |     .sck = &gpio_spi_r_sck, | ||||||
|  |     .cs = &gpio_nfc_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_external_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||||
|  |     .bus = &furi_hal_spi_bus_r, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_external_event_callback, | ||||||
|  |     .miso = &gpio_ext_pa6, | ||||||
|  |     .mosi = &gpio_ext_pa7, | ||||||
|  |     .sck = &gpio_ext_pb3, | ||||||
|  |     .cs = &gpio_ext_pa4, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_d_handle_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event, | ||||||
|  |     const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if(event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->miso, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->mosi, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex( | ||||||
|  |             handle->sck, | ||||||
|  |             GpioModeAltFunctionPushPull, | ||||||
|  |             GpioPullNo, | ||||||
|  |             GpioSpeedVeryHigh, | ||||||
|  |             GpioAltFn5SPI2); | ||||||
|  | 
 | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if(event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_display_event_callback( | ||||||
|  |     FuriHalSpiBusHandle* handle, | ||||||
|  |     FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||||
|  |     .bus = &furi_hal_spi_bus_d, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_display_event_callback, | ||||||
|     .miso = &gpio_spi_d_miso, |     .miso = &gpio_spi_d_miso, | ||||||
|     .mosi = &gpio_spi_d_mosi, |     .mosi = &gpio_spi_d_mosi, | ||||||
|     .clk = &gpio_spi_d_sck, |     .sck = &gpio_spi_d_sck, | ||||||
|  |     .cs = &gpio_display_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | static void furi_hal_spi_bus_handle_sd_fast_event_callback( | ||||||
|     { |     FuriHalSpiBusHandle* handle, | ||||||
|         .bus = &spi_r, |     FuriHalSpiBusHandleEvent event) { | ||||||
|         .config = &furi_hal_spi_config_subghz, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||||
|         .chip_select = &gpio_subghz_cs, | } | ||||||
|     }, | 
 | ||||||
|     { | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||||
|         .bus = &spi_d, |     .bus = &furi_hal_spi_bus_d, | ||||||
|         .config = &furi_hal_spi_config_display, |     .callback = furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||||
|         .chip_select = &gpio_display_cs, |     .miso = &gpio_spi_d_miso, | ||||||
|     }, |     .mosi = &gpio_spi_d_mosi, | ||||||
|     { |     .sck = &gpio_spi_d_sck, | ||||||
|         .bus = &spi_d, |     .cs = &gpio_sdcard_cs, | ||||||
|         .config = &furi_hal_spi_config_sd_fast, | }; | ||||||
|         .chip_select = &gpio_sdcard_cs, | 
 | ||||||
|     }, | static void furi_hal_spi_bus_handle_sd_slow_event_callback( | ||||||
|     { |     FuriHalSpiBusHandle* handle, | ||||||
|         .bus = &spi_d, |     FuriHalSpiBusHandleEvent event) { | ||||||
|         .config = &furi_hal_spi_config_sd_slow, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|         .chip_select = &gpio_sdcard_cs, | } | ||||||
|     }, | 
 | ||||||
|     {.bus = &spi_r, .config = &furi_hal_spi_config_nfc, .chip_select = &gpio_nfc_cs}, | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||||
|  |     .bus = &furi_hal_spi_bus_d, | ||||||
|  |     .callback = furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||||
|  |     .miso = &gpio_spi_d_miso, | ||||||
|  |     .mosi = &gpio_spi_d_mosi, | ||||||
|  |     .sck = &gpio_spi_d_sck, | ||||||
|  |     .cs = &gpio_sdcard_cs, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,60 +1,60 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <furi-hal-gpio.h> | #include <furi-hal-spi-types.h> | ||||||
| #include <stm32wbxx_ll_spi.h> |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | /** Preset for ST25R916 */ | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI BUS handler
 | /** Preset for CC1101 */ | ||||||
|  * Structure content may change at some point | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||||
|  | 
 | ||||||
|  | /** Preset for ST7567 (Display) */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in fast mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in slow mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||||
|  | 
 | ||||||
|  | /** CC1101 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||||
|  | 
 | ||||||
|  | /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||||
|  | 
 | ||||||
|  | /** External on `furi_hal_spi_bus_r`
 | ||||||
|  |  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||||
|  |  *  | ||||||
|  |  * miso: pa6 | ||||||
|  |  * mosi: pa7 | ||||||
|  |  * sck: pb3 | ||||||
|  |  * cs:  pa4 (software controlled) | ||||||
|  |  *  | ||||||
|  |  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||||
|  |  * Bus pins are floating on inactive state, CS high after initialization | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| typedef struct { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||||
|     const SPI_TypeDef* spi; |  | ||||||
|     const GpioPin* miso; |  | ||||||
|     const GpioPin* mosi; |  | ||||||
|     const GpioPin* clk; |  | ||||||
| } FuriHalSpiBus; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Device handler
 | /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||||
|  * Structure content may change at some point | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||||
|  */ |  | ||||||
| typedef struct { |  | ||||||
|     const FuriHalSpiBus* bus; |  | ||||||
|     const LL_SPI_InitTypeDef* config; |  | ||||||
|     const GpioPin* chip_select; |  | ||||||
| } FuriHalSpiDevice; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Standard Device IDs */ | /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||||
| typedef enum { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||||
|     FuriHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */ |  | ||||||
|     FuriHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardFast, /** SDCARD: fast mode, after initialization */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardSlow, /** SDCARD: slow mode, before initialization */ |  | ||||||
|     FuriHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ |  | ||||||
| 
 | 
 | ||||||
|     FuriHalSpiDeviceIdMax, /** Service Value, do not use */ | /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||||
| } FuriHalSpiDeviceId; | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus R
 |  | ||||||
|  * CC1101, Nfc |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_r; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus D
 |  | ||||||
|  * Display, SdCard |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_d; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi devices */ |  | ||||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										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 "furi-hal-resources.h" | ||||||
| 
 | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <string.h> | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_spi.h> | #include <stm32wbxx_ll_spi.h> | ||||||
| #include <stm32wbxx_ll_utils.h> | #include <stm32wbxx_ll_utils.h> | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| 
 | 
 | ||||||
| extern void Enable_SPI(SPI_TypeDef* spi); |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_init() { | void furi_hal_spi_init() { | ||||||
|     for(size_t i = 0; i < FuriHalSpiDeviceIdMax; ++i) { |     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); |     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||||
|         hal_gpio_init( | 
 | ||||||
|             furi_hal_spi_devices[i].chip_select, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||||
|             GpioModeOutputPushPull, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||||
|             GpioPullNo, |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||||
|             GpioSpeedVeryHigh); |     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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex( | void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||||
|         &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); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { |  | ||||||
|     assert(bus); |     assert(bus); | ||||||
|  |     bus->callback(bus, FuriHalSpiBusEventInit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||||
|     assert(bus); |     assert(bus); | ||||||
|  |     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||||
|     assert(bus); |     assert(handle); | ||||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); |     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); |  | ||||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |  | ||||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_TX_FIFO_EMPTY) |     assert(handle); | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||||
|  |     assert(handle); | ||||||
|  | 
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||||
|  | 
 | ||||||
|  |     assert(handle->bus->current_handle == NULL); | ||||||
|  | 
 | ||||||
|  |     handle->bus->current_handle = handle; | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|  | 
 | ||||||
|  |     // Handle event and unset handle
 | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||||
|  |     handle->bus->current_handle = NULL; | ||||||
|  | 
 | ||||||
|  |     // Bus events
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||||
|  |     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY) | ||||||
|         ; |         ; | ||||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef*)bus->spi)) |     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)) | ||||||
|         ; |         ; | ||||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef*)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { |     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||||
|         LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); |         LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_rx( | ||||||
|     assert(bus); |     FuriHalSpiBusHandle* handle, | ||||||
|  |     uint8_t* buffer, | ||||||
|  |     size_t size, | ||||||
|  |     uint32_t timeout) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(buffer); |     assert(buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
| 
 | 
 | ||||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); |     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_tx( | ||||||
|     assert(bus); |     FuriHalSpiBusHandle* handle, | ||||||
|  |     uint8_t* buffer, | ||||||
|  |     size_t size, | ||||||
|  |     uint32_t timeout) { | ||||||
|  |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(buffer); |     assert(buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi)) { |         if(LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||||
|             buffer++; |             buffer++; | ||||||
|             size--; |             size--; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef*)bus->spi); |     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_trx( | bool furi_hal_spi_bus_trx( | ||||||
|     const FuriHalSpiBus* bus, |     FuriHalSpiBusHandle* handle, | ||||||
|     uint8_t* tx_buffer, |     uint8_t* tx_buffer, | ||||||
|     uint8_t* rx_buffer, |     uint8_t* rx_buffer, | ||||||
|     size_t size, |     size_t size, | ||||||
|     uint32_t timeout) { |     uint32_t timeout) { | ||||||
|     assert(bus); |     assert(handle); | ||||||
|  |     assert(handle->bus->current_handle == handle); | ||||||
|     assert(tx_buffer); |     assert(tx_buffer); | ||||||
|     assert(rx_buffer); |     assert(rx_buffer); | ||||||
|     assert(size > 0); |     assert(size > 0); | ||||||
|  | 
 | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
|     size_t tx_size = size; |     size_t tx_size = size; | ||||||
|     bool tx_allowed = true; |     bool tx_allowed = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef*)bus->spi) && tx_allowed) { |         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef*)bus->spi, *tx_buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||||
|             tx_buffer++; |             tx_buffer++; | ||||||
|             tx_size--; |             tx_size--; | ||||||
|             tx_allowed = false; |             tx_allowed = false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef*)bus->spi)) { |         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef*)bus->spi); |             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|             rx_buffer++; |             rx_buffer++; | ||||||
|             size--; |             size--; | ||||||
|             tx_allowed = true; |             tx_allowed = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(device->config); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_configure(device->bus, device->config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { |  | ||||||
|     assert(device_id < FuriHalSpiDeviceIdMax); |  | ||||||
| 
 |  | ||||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; |  | ||||||
|     assert(device); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_lock(device->bus); |  | ||||||
|     furi_hal_spi_device_configure(device); |  | ||||||
| 
 |  | ||||||
|     return device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_hal_spi_bus_unlock(device->bus); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_rx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_tx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_trx( |  | ||||||
|     const FuriHalSpiDevice* device, |  | ||||||
|     uint8_t* tx_buffer, |  | ||||||
|     uint8_t* rx_buffer, |  | ||||||
|     size_t size, |  | ||||||
|     uint32_t timeout) { |  | ||||||
|     assert(device); |  | ||||||
|     assert(tx_buffer); |  | ||||||
|     assert(rx_buffer); |  | ||||||
|     assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if(device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -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; | const uint32_t SpiTimeout = 1000; | ||||||
| uint8_t SD_IO_WriteByte(uint8_t Data); | uint8_t SD_IO_WriteByte(uint8_t Data); | ||||||
| 
 | 
 | ||||||
| static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast]; |  | ||||||
| 
 |  | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|                             BUS OPERATIONS |                             BUS OPERATIONS | ||||||
|  *******************************************************************************/ |  *******************************************************************************/ | ||||||
| @ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi | |||||||
|  * @retval None |  * @retval None | ||||||
|  */ |  */ | ||||||
| static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { | static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { | ||||||
|     furi_check(furi_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); |     furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -30,7 +28,7 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t | |||||||
|  * @retval None |  * @retval None | ||||||
|  */ |  */ | ||||||
| __attribute__((unused)) static void SPIx_Write(uint8_t Value) { | __attribute__((unused)) static void SPIx_Write(uint8_t Value) { | ||||||
|     furi_check(furi_hal_spi_bus_tx(sd_spi_dev->bus, (uint8_t*)&Value, 1, SpiTimeout)); |     furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
| @ -47,7 +45,7 @@ void SD_IO_Init(void) { | |||||||
|     uint8_t counter = 0; |     uint8_t counter = 0; | ||||||
| 
 | 
 | ||||||
|     /* SD chip select high */ |     /* SD chip select high */ | ||||||
|     hal_gpio_write(sd_spi_dev->chip_select, true); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
|     delay_us(10); |     delay_us(10); | ||||||
| 
 | 
 | ||||||
|     /* Send dummy byte 0xFF, 10 times with CS high */ |     /* Send dummy byte 0xFF, 10 times with CS high */ | ||||||
| @ -67,9 +65,9 @@ void SD_IO_CSState(uint8_t val) { | |||||||
|     /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */ |     /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */ | ||||||
|     if(val == 1) { |     if(val == 1) { | ||||||
|         delay_us(10); // Exit guard time for some SD cards
 |         delay_us(10); // Exit guard time for some SD cards
 | ||||||
|         hal_gpio_write(sd_spi_dev->chip_select, true); |         hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
|     } else { |     } else { | ||||||
|         hal_gpio_write(sd_spi_dev->chip_select, false); |         hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||||
|         delay_us(10); // Entry guard time for some SD cards
 |         delay_us(10); // Entry guard time for some SD cards
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -91,12 +91,7 @@ | |||||||
| #include "stdlib.h" | #include "stdlib.h" | ||||||
| #include "string.h" | #include "string.h" | ||||||
| #include "stdio.h" | #include "stdio.h" | ||||||
| #include <furi-hal-spi.h> | #include <furi-hal.h> | ||||||
| #include <furi-hal-gpio.h> |  | ||||||
| #include <furi-hal-resources.h> |  | ||||||
| #include <furi-hal-power.h> |  | ||||||
| #include <furi-hal-delay.h> |  | ||||||
| #include <furi-hal-sd.h> |  | ||||||
| 
 | 
 | ||||||
| /** @addtogroup BSP
 | /** @addtogroup BSP
 | ||||||
|   * @{ |   * @{ | ||||||
| @ -284,22 +279,22 @@ static uint8_t SD_ReadData(void); | |||||||
| /* Private functions ---------------------------------------------------------*/ | /* Private functions ---------------------------------------------------------*/ | ||||||
| 
 | 
 | ||||||
| void SD_SPI_Bus_To_Down_State(){ | void SD_SPI_Bus_To_Down_State(){ | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(&gpio_sdcard_cs, false); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_miso, false); |     hal_gpio_write(furi_hal_sd_spi_handle->miso, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_mosi, false); |     hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_sck, false); |     hal_gpio_write(furi_hal_sd_spi_handle->sck, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SD_SPI_Bus_To_Normal_State(){ | void SD_SPI_Bus_To_Normal_State(){ | ||||||
|     hal_gpio_write(&gpio_sdcard_cs, true); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
 | /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
 | ||||||
| @ -315,7 +310,8 @@ void SD_SPI_Bus_To_Normal_State(){ | |||||||
|   */ |   */ | ||||||
| uint8_t BSP_SD_Init(bool reset_card) { | uint8_t BSP_SD_Init(bool reset_card) { | ||||||
|     /* Slow speed init */ |     /* Slow speed init */ | ||||||
|     const FuriHalSpiDevice* sd_spi_slow_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardSlow); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 | 
 | ||||||
|     /* We must reset card in spi_lock context */ |     /* We must reset card in spi_lock context */ | ||||||
|     if(reset_card) { |     if(reset_card) { | ||||||
| @ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) { | |||||||
|         if(res == BSP_SD_OK) break; |         if(res == BSP_SD_OK) break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_slow_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); | ||||||
| 
 | 
 | ||||||
|     /* SD initialized and set to SPI mode properly */ |     /* SD initialized and set to SPI mode properly */ | ||||||
|     return res; |     return res; | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ | |||||||
| 
 | 
 | ||||||
| /* Includes ------------------------------------------------------------------*/ | /* Includes ------------------------------------------------------------------*/ | ||||||
| #include "user_diskio.h" | #include "user_diskio.h" | ||||||
| #include "furi-hal-spi.h" | #include <furi-hal.h> | ||||||
| /* Private typedef -----------------------------------------------------------*/ | /* Private typedef -----------------------------------------------------------*/ | ||||||
| /* Private define ------------------------------------------------------------*/ | /* Private define ------------------------------------------------------------*/ | ||||||
| 
 | 
 | ||||||
| @ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = { | |||||||
| DSTATUS USER_initialize(BYTE pdrv) { | DSTATUS USER_initialize(BYTE pdrv) { | ||||||
|     /* USER CODE BEGIN INIT */ |     /* USER CODE BEGIN INIT */ | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     DSTATUS status = User_CheckStatus(pdrv); |     DSTATUS status = User_CheckStatus(pdrv); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return status; |     return status; | ||||||
|     /* USER CODE END INIT */ |     /* USER CODE END INIT */ | ||||||
| @ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | |||||||
|     /* USER CODE BEGIN READ */ |     /* USER CODE BEGIN READ */ | ||||||
|     DRESULT res = RES_ERROR; |     DRESULT res = RES_ERROR; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { |     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { | ||||||
|         /* wait until the read operation is finished */ |         /* wait until the read operation is finished */ | ||||||
| @ -129,7 +132,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | |||||||
|         res = RES_OK; |         res = RES_OK; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END READ */ |     /* USER CODE END READ */ | ||||||
| @ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | |||||||
|     /* USER CODE HERE */ |     /* USER CODE HERE */ | ||||||
|     DRESULT res = RES_ERROR; |     DRESULT res = RES_ERROR; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { |     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { | ||||||
|         /* wait until the Write operation is finished */ |         /* wait until the Write operation is finished */ | ||||||
| @ -158,7 +163,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | |||||||
|         res = RES_OK; |         res = RES_OK; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END WRITE */ |     /* USER CODE END WRITE */ | ||||||
| @ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | |||||||
| 
 | 
 | ||||||
|     if(Stat & STA_NOINIT) return RES_NOTRDY; |     if(Stat & STA_NOINIT) return RES_NOTRDY; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     switch(cmd) { |     switch(cmd) { | ||||||
|     /* Make sure that no pending write process */ |     /* Make sure that no pending write process */ | ||||||
| @ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | |||||||
|         res = RES_PARERR; |         res = RES_PARERR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END IOCTL */ |     /* USER CODE END IOCTL */ | ||||||
|  | |||||||
| @ -20,3 +20,5 @@ bool hal_sd_detect(void) { | |||||||
|     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); |     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL; | ||||||
|  | |||||||
| @ -1,10 +1,9 @@ | |||||||
| #include <furi-hal-spi-config.h> | #include <furi-hal-spi-config.h> | ||||||
| #include <furi-hal-resources.h> | #include <furi-hal-resources.h> | ||||||
| 
 | 
 | ||||||
| #define SPI_R SPI1 | /* SPI Presets */ | ||||||
| #define SPI_D SPI2 |  | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||||
|  * SD Card in fast mode (after init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||||
|  * SD Card in slow mode (before init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| osMutexId_t spi_mutex_d = NULL; | /* SPI Buses */ | ||||||
| osMutexId_t spi_mutex_r = NULL; |  | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_r = { | osMutexId_t furi_hal_spi_bus_r_mutex = NULL; | ||||||
|     .spi=SPI_R, | 
 | ||||||
|     .mutex=&spi_mutex_r, | static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if (event == FuriHalSpiBusEventInit) { | ||||||
|  |         furi_hal_spi_bus_r_mutex = osMutexNew(NULL); | ||||||
|  |         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeinit) { | ||||||
|  |         furi_check(osMutexDelete(furi_hal_spi_bus_r_mutex)); | ||||||
|  |     } else if (event == FuriHalSpiBusEventLock) { | ||||||
|  |         furi_check(osMutexAcquire(furi_hal_spi_bus_r_mutex, osWaitForever) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventUnlock) { | ||||||
|  |         furi_check(osMutexRelease(furi_hal_spi_bus_r_mutex) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_r = { | ||||||
|  |     .spi=SPI1, | ||||||
|  |     .callback = furi_hal_spi_bus_r_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | osMutexId_t furi_hal_spi_bus_d_mutex = NULL; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if (event == FuriHalSpiBusEventInit) { | ||||||
|  |         furi_hal_spi_bus_d_mutex = osMutexNew(NULL); | ||||||
|  |         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeinit) { | ||||||
|  |         furi_check(osMutexDelete(furi_hal_spi_bus_d_mutex)); | ||||||
|  |     } else if (event == FuriHalSpiBusEventLock) { | ||||||
|  |         furi_check(osMutexAcquire(furi_hal_spi_bus_d_mutex, osWaitForever) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventUnlock) { | ||||||
|  |         furi_check(osMutexRelease(furi_hal_spi_bus_d_mutex) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_d = { | ||||||
|  |     .spi=SPI2, | ||||||
|  |     .callback = furi_hal_spi_bus_d_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SPI Bus Handles */ | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_r_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if (event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_subghz_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_subghz_event_callback, | ||||||
|     .miso=&gpio_spi_r_miso, |     .miso=&gpio_spi_r_miso, | ||||||
|     .mosi=&gpio_spi_r_mosi, |     .mosi=&gpio_spi_r_mosi, | ||||||
|     .clk=&gpio_spi_r_sck, |     .sck=&gpio_spi_r_sck, | ||||||
|  |     .cs=&gpio_subghz_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_d = { | static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|     .spi=SPI_D, |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||||
|     .mutex=&spi_mutex_d, | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_nfc_event_callback, | ||||||
|  |     .miso=&gpio_spi_r_miso, | ||||||
|  |     .mosi=&gpio_spi_r_mosi, | ||||||
|  |     .sck=&gpio_spi_r_sck, | ||||||
|  |     .cs=&gpio_nfc_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_external_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_external_event_callback, | ||||||
|  |     .miso=&gpio_ext_pa6, | ||||||
|  |     .mosi=&gpio_ext_pa7, | ||||||
|  |     .sck=&gpio_ext_pb3, | ||||||
|  |     .cs=&gpio_ext_pa4, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_d_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if (event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  | 
 | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_display_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||||
|  |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_display_event_callback, | ||||||
|     .miso=&gpio_spi_d_miso, |     .miso=&gpio_spi_d_miso, | ||||||
|     .mosi=&gpio_spi_d_mosi, |     .mosi=&gpio_spi_d_mosi, | ||||||
|     .clk=&gpio_spi_d_sck, |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_display_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_display, .chip_select=&gpio_display_cs, }, | } | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, }, | 
 | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, }, | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||||
|  |     .miso=&gpio_spi_d_miso, | ||||||
|  |     .mosi=&gpio_spi_d_mosi, | ||||||
|  |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_sdcard_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_sd_slow_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||||
|  |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||||
|  |     .miso=&gpio_spi_d_miso, | ||||||
|  |     .mosi=&gpio_spi_d_mosi, | ||||||
|  |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_sdcard_cs, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,62 +1,60 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <furi-hal-gpio.h> | #include <furi-hal-spi-types.h> | ||||||
| #include <stm32wbxx_ll_spi.h> |  | ||||||
| #include <cmsis_os2.h> |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | /** Preset for ST25R916 */ | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI BUS handler
 | /** Preset for CC1101 */ | ||||||
|  * Structure content may change at some point | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||||
|  | 
 | ||||||
|  | /** Preset for ST7567 (Display) */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in fast mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in slow mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||||
|  | 
 | ||||||
|  | /** CC1101 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||||
|  | 
 | ||||||
|  | /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||||
|  | 
 | ||||||
|  | /** External on `furi_hal_spi_bus_r`
 | ||||||
|  |  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||||
|  |  *  | ||||||
|  |  * miso: pa6 | ||||||
|  |  * mosi: pa7 | ||||||
|  |  * sck: pb3 | ||||||
|  |  * cs:  pa4 (software controlled) | ||||||
|  |  *  | ||||||
|  |  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||||
|  |  * Bus pins are floating on inactive state, CS high after initialization | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| typedef struct { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||||
|     const SPI_TypeDef* spi; |  | ||||||
|     const osMutexId_t* mutex; |  | ||||||
|     const GpioPin* miso; |  | ||||||
|     const GpioPin* mosi; |  | ||||||
|     const GpioPin* clk; |  | ||||||
| } FuriHalSpiBus; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Device handler
 | /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||||
|  * Structure content may change at some point | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||||
|  */ |  | ||||||
| typedef struct { |  | ||||||
|     const FuriHalSpiBus* bus; |  | ||||||
|     const LL_SPI_InitTypeDef* config; |  | ||||||
|     const GpioPin* chip_select; |  | ||||||
| } FuriHalSpiDevice; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Standard Device IDs */ | /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||||
| typedef enum { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||||
|     FuriHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */ |  | ||||||
|     FuriHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */ |  | ||||||
|     FuriHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ |  | ||||||
| 
 | 
 | ||||||
|     FuriHalSpiDeviceIdMax,           /** Service Value, do not use */ | /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||||
| } FuriHalSpiDeviceId; | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus R
 |  | ||||||
|  * CC1101, Nfc |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_r; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus D
 |  | ||||||
|  * Display, SdCard |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_d; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi devices */ |  | ||||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										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" | #define TAG "FuriHalSpi" | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_init() { | void furi_hal_spi_init() { | ||||||
|     // Spi structure is const, but mutex is not
 |     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||||
|     // Need some hell-ish casting to make it work
 |     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||||
|     *(osMutexId_t*)spi_r.mutex = osMutexNew(NULL); |  | ||||||
|     *(osMutexId_t*)spi_d.mutex = osMutexNew(NULL); |  | ||||||
|     // 
 |  | ||||||
|     for (size_t i=0; i<FuriHalSpiDeviceIdMax; ++i) { |  | ||||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); |  | ||||||
|         hal_gpio_init( |  | ||||||
|             furi_hal_spi_devices[i].chip_select, |  | ||||||
|             GpioModeOutputPushPull, |  | ||||||
|             GpioPullNo, |  | ||||||
|             GpioSpeedVeryHigh |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||||
| 
 |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |  | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |  | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||||
|     furi_assert(bus); |     furi_assert(bus); | ||||||
|     furi_check(osMutexAcquire(*bus->mutex, osWaitForever) == osOK); |     bus->callback(bus, FuriHalSpiBusEventInit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||||
|     furi_assert(bus); |     furi_assert(bus); | ||||||
|     furi_check(osMutexRelease(*bus->mutex) == osOK); |     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
| 
 |     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); |  | ||||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); |  | ||||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |  | ||||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); |     furi_assert(handle); | ||||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); |     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | } | ||||||
|         LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | 
 | ||||||
|  | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||||
|  |     furi_assert(handle); | ||||||
|  | 
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||||
|  | 
 | ||||||
|  |     furi_assert(handle->bus->current_handle == NULL); | ||||||
|  | 
 | ||||||
|  |     handle->bus->current_handle = handle; | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||||
|  |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|  | 
 | ||||||
|  |     // Handle event and unset handle
 | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||||
|  |     handle->bus->current_handle = NULL; | ||||||
|  | 
 | ||||||
|  |     // Bus events
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||||
|  |     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||||
|  |     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)); | ||||||
|  |     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||||
|  |         LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(buffer); |     furi_assert(buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
| 
 | 
 | ||||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); |     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(buffer); |     furi_assert(buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { |         if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||||
|             buffer++; |             buffer++; | ||||||
|             size--; |             size--; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); |     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(tx_buffer); |     furi_assert(tx_buffer); | ||||||
|     furi_assert(rx_buffer); |     furi_assert(rx_buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
| @ -104,99 +119,22 @@ bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* | |||||||
|     bool tx_allowed = true; |     bool tx_allowed = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { |         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||||
|             tx_buffer++; |             tx_buffer++; | ||||||
|             tx_size--; |             tx_size--; | ||||||
|             tx_allowed = false; |             tx_allowed = false; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { |         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); |             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|             rx_buffer++; |             rx_buffer++; | ||||||
|             size--; |             size--; | ||||||
|             tx_allowed = true; |             tx_allowed = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(device->config); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_configure(device->bus, device->config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { |  | ||||||
|     furi_assert(device_id < FuriHalSpiDeviceIdMax); |  | ||||||
| 
 |  | ||||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_hal_spi_bus_lock(device->bus); |  | ||||||
|     furi_hal_spi_device_configure(device); |  | ||||||
| 
 |  | ||||||
|     return device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_hal_spi_bus_unlock(device->bus); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_rx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_tx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_trx(const FuriHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(tx_buffer); |  | ||||||
|     furi_assert(rx_buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -269,7 +269,7 @@ void furi_hal_subghz_init() { | |||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
|     furi_hal_subghz_state = SubGhzStateIdle; |     furi_hal_subghz_state = SubGhzStateIdle; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
| #ifdef FURI_HAL_SUBGHZ_TX_GPIO | #ifdef FURI_HAL_SUBGHZ_TX_GPIO | ||||||
|     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
| @ -277,58 +277,58 @@ void furi_hal_subghz_init() { | |||||||
| 
 | 
 | ||||||
|     // Reset
 |     // Reset
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
| 
 | 
 | ||||||
|     // Prepare GD0 for power on self test
 |     // Prepare GD0 for power on self test
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     // GD0 low
 |     // GD0 low
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != false) |     while(hal_gpio_read(&gpio_cc1101_g0) != false) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     // GD0 high
 |     // GD0 high
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != true) |     while(hal_gpio_read(&gpio_cc1101_g0) != true) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     // Reset GD0 to floating state
 |     // Reset GD0 to floating state
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     // RF switches
 |     // RF switches
 | ||||||
|     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
| 
 | 
 | ||||||
|     // Go to sleep
 |     // Go to sleep
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_sleep() { | void furi_hal_subghz_sleep() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateIdle); |     furi_assert(furi_hal_subghz_state == SubGhzStateIdle); | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_dump_state() { | void furi_hal_subghz_dump_state() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     printf( |     printf( | ||||||
|         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", |         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", | ||||||
|         cc1101_get_partnumber(device), |         cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), | ||||||
|         cc1101_get_version(device)); |         cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||||
| @ -350,81 +350,81 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_registers(const uint8_t data[][2]) { | void furi_hal_subghz_load_registers(const uint8_t data[][2]) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     uint32_t i = 0; |     uint32_t i = 0; | ||||||
|     while(data[i][0]) { |     while(data[i][0]) { | ||||||
|         cc1101_write_reg(device, data[i][0], data[i][1]); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]); | ||||||
|         i++; |         i++; | ||||||
|     } |     } | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_patable(const uint8_t data[8]) { | void furi_hal_subghz_load_patable(const uint8_t data[8]) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_set_pa_table(device, data); |     cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_tx(device); |     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_fifo(device, data, size); |     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_flush_rx() { | void furi_hal_subghz_flush_rx() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_rx(device); |     cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_read_fifo(device, data, size); |     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_shutdown() { | void furi_hal_subghz_shutdown() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     // Reset and shutdown
 |     // Reset and shutdown
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_reset() { | void furi_hal_subghz_reset() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_idle() { | void furi_hal_subghz_idle() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_rx() { | void furi_hal_subghz_rx() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_rx(device); |     cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_subghz_tx() { | bool furi_hal_subghz_tx() { | ||||||
|     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; |     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_tx(device); |     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float furi_hal_subghz_get_rssi() { | float furi_hal_subghz_get_rssi() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     int32_t rssi_dec = cc1101_get_rssi(device); |     int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     float rssi = rssi_dec; |     float rssi = rssi_dec; | ||||||
|     if(rssi_dec >= 128) { |     if(rssi_dec >= 128) { | ||||||
| @ -461,7 +461,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     //checking regional settings
 |     //checking regional settings
 | ||||||
|     bool txrx = false; |     bool txrx = false; | ||||||
| @ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; |         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint32_t real_frequency = cc1101_set_frequency(device, value); |     uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); | ||||||
|     cc1101_calibrate(device); |     cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     while(true) { |     while(true) { | ||||||
|         CC1101Status status = cc1101_get_status(device); |         CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); | ||||||
|         if(status.STATE == CC1101StateIDLE) break; |         if(status.STATE == CC1101StateIDLE) break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     return real_frequency; |     return real_frequency; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     if(path == FuriHalSubGhzPath433) { |     if(path == FuriHalSubGhzPath433) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     } else if(path == FuriHalSubGhzPath315) { |     } else if(path == FuriHalSubGhzPath315) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|     } else if(path == FuriHalSubGhzPath868) { |     } else if(path == FuriHalSubGhzPath868) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     } else if(path == FuriHalSubGhzPathIsolate) { |     } else if(path == FuriHalSubGhzPathIsolate) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash(NULL); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; | volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; | ||||||
|  | |||||||
| @ -7,8 +7,6 @@ | |||||||
| const uint32_t SpiTimeout = 1000; | const uint32_t SpiTimeout = 1000; | ||||||
| uint8_t SD_IO_WriteByte(uint8_t Data); | uint8_t SD_IO_WriteByte(uint8_t Data); | ||||||
| 
 | 
 | ||||||
| static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDeviceIdSdCardFast]; |  | ||||||
| 
 |  | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|                             BUS OPERATIONS |                             BUS OPERATIONS | ||||||
|  *******************************************************************************/ |  *******************************************************************************/ | ||||||
| @ -21,7 +19,7 @@ static const FuriHalSpiDevice* sd_spi_dev = &furi_hal_spi_devices[FuriHalSpiDevi | |||||||
|  * @retval None |  * @retval None | ||||||
|  */ |  */ | ||||||
| static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { | static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) { | ||||||
|     furi_check(furi_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); |     furi_check(furi_hal_spi_bus_trx(furi_hal_sd_spi_handle, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -30,7 +28,7 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t | |||||||
|  * @retval None |  * @retval None | ||||||
|  */ |  */ | ||||||
| __attribute__((unused)) static void SPIx_Write(uint8_t Value) { | __attribute__((unused)) static void SPIx_Write(uint8_t Value) { | ||||||
|     furi_check(furi_hal_spi_bus_tx(sd_spi_dev->bus, (uint8_t*)&Value, 1, SpiTimeout)); |     furi_check(furi_hal_spi_bus_tx(furi_hal_sd_spi_handle, (uint8_t*)&Value, 1, SpiTimeout)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
| @ -47,7 +45,7 @@ void SD_IO_Init(void) { | |||||||
|     uint8_t counter = 0; |     uint8_t counter = 0; | ||||||
| 
 | 
 | ||||||
|     /* SD chip select high */ |     /* SD chip select high */ | ||||||
|     hal_gpio_write(sd_spi_dev->chip_select, true); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
|     delay_us(10); |     delay_us(10); | ||||||
| 
 | 
 | ||||||
|     /* Send dummy byte 0xFF, 10 times with CS high */ |     /* Send dummy byte 0xFF, 10 times with CS high */ | ||||||
| @ -67,9 +65,9 @@ void SD_IO_CSState(uint8_t val) { | |||||||
|     /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */ |     /* Some SD Cards are prone to fail if CLK-ed too soon after CS transition. Worst case found: 8us */ | ||||||
|     if(val == 1) { |     if(val == 1) { | ||||||
|         delay_us(10); // Exit guard time for some SD cards
 |         delay_us(10); // Exit guard time for some SD cards
 | ||||||
|         hal_gpio_write(sd_spi_dev->chip_select, true); |         hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
|     } else { |     } else { | ||||||
|         hal_gpio_write(sd_spi_dev->chip_select, false); |         hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||||
|         delay_us(10); // Entry guard time for some SD cards
 |         delay_us(10); // Entry guard time for some SD cards
 | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -91,12 +91,7 @@ | |||||||
| #include "stdlib.h" | #include "stdlib.h" | ||||||
| #include "string.h" | #include "string.h" | ||||||
| #include "stdio.h" | #include "stdio.h" | ||||||
| #include <furi-hal-spi.h> | #include <furi-hal.h> | ||||||
| #include <furi-hal-gpio.h> |  | ||||||
| #include <furi-hal-resources.h> |  | ||||||
| #include <furi-hal-power.h> |  | ||||||
| #include <furi-hal-delay.h> |  | ||||||
| #include <furi-hal-sd.h> |  | ||||||
| 
 | 
 | ||||||
| /** @addtogroup BSP
 | /** @addtogroup BSP
 | ||||||
|   * @{ |   * @{ | ||||||
| @ -284,22 +279,22 @@ static uint8_t SD_ReadData(void); | |||||||
| /* Private functions ---------------------------------------------------------*/ | /* Private functions ---------------------------------------------------------*/ | ||||||
| 
 | 
 | ||||||
| void SD_SPI_Bus_To_Down_State(){ | void SD_SPI_Bus_To_Down_State(){ | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(&gpio_sdcard_cs, false); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_miso, false); |     hal_gpio_write(furi_hal_sd_spi_handle->miso, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_mosi, false); |     hal_gpio_write(furi_hal_sd_spi_handle->mosi, false); | ||||||
|     hal_gpio_write(&gpio_spi_d_sck, false); |     hal_gpio_write(furi_hal_sd_spi_handle->sck, false); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SD_SPI_Bus_To_Normal_State(){ | void SD_SPI_Bus_To_Normal_State(){ | ||||||
|     hal_gpio_write(&gpio_sdcard_cs, true); |     hal_gpio_write(furi_hal_sd_spi_handle->cs, true); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     hal_gpio_init_ex(furi_hal_sd_spi_handle->sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
 | /** @defgroup STM32_ADAFRUIT_SD_Private_Functions
 | ||||||
| @ -315,7 +310,8 @@ void SD_SPI_Bus_To_Normal_State(){ | |||||||
|   */ |   */ | ||||||
| uint8_t BSP_SD_Init(bool reset_card) { | uint8_t BSP_SD_Init(bool reset_card) { | ||||||
|     /* Slow speed init */ |     /* Slow speed init */ | ||||||
|     const FuriHalSpiDevice* sd_spi_slow_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardSlow); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_slow); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 | 
 | ||||||
|     /* We must reset card in spi_lock context */ |     /* We must reset card in spi_lock context */ | ||||||
|     if(reset_card) { |     if(reset_card) { | ||||||
| @ -344,7 +340,8 @@ uint8_t BSP_SD_Init(bool reset_card) { | |||||||
|         if(res == BSP_SD_OK) break; |         if(res == BSP_SD_OK) break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_slow_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); | ||||||
| 
 | 
 | ||||||
|     /* SD initialized and set to SPI mode properly */ |     /* SD initialized and set to SPI mode properly */ | ||||||
|     return res; |     return res; | ||||||
|  | |||||||
| @ -35,7 +35,7 @@ | |||||||
| 
 | 
 | ||||||
| /* Includes ------------------------------------------------------------------*/ | /* Includes ------------------------------------------------------------------*/ | ||||||
| #include "user_diskio.h" | #include "user_diskio.h" | ||||||
| #include "furi-hal-spi.h" | #include <furi-hal.h> | ||||||
| /* Private typedef -----------------------------------------------------------*/ | /* Private typedef -----------------------------------------------------------*/ | ||||||
| /* Private define ------------------------------------------------------------*/ | /* Private define ------------------------------------------------------------*/ | ||||||
| 
 | 
 | ||||||
| @ -87,11 +87,13 @@ Diskio_drvTypeDef USER_Driver = { | |||||||
| DSTATUS USER_initialize(BYTE pdrv) { | DSTATUS USER_initialize(BYTE pdrv) { | ||||||
|     /* USER CODE BEGIN INIT */ |     /* USER CODE BEGIN INIT */ | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     DSTATUS status = User_CheckStatus(pdrv); |     DSTATUS status = User_CheckStatus(pdrv); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return status; |     return status; | ||||||
|     /* USER CODE END INIT */ |     /* USER CODE END INIT */ | ||||||
| @ -120,7 +122,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | |||||||
|     /* USER CODE BEGIN READ */ |     /* USER CODE BEGIN READ */ | ||||||
|     DRESULT res = RES_ERROR; |     DRESULT res = RES_ERROR; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { |     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { | ||||||
|         /* wait until the read operation is finished */ |         /* wait until the read operation is finished */ | ||||||
| @ -129,7 +132,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) { | |||||||
|         res = RES_OK; |         res = RES_OK; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END READ */ |     /* USER CODE END READ */ | ||||||
| @ -149,7 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | |||||||
|     /* USER CODE HERE */ |     /* USER CODE HERE */ | ||||||
|     DRESULT res = RES_ERROR; |     DRESULT res = RES_ERROR; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { |     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) { | ||||||
|         /* wait until the Write operation is finished */ |         /* wait until the Write operation is finished */ | ||||||
| @ -158,7 +163,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) { | |||||||
|         res = RES_OK; |         res = RES_OK; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END WRITE */ |     /* USER CODE END WRITE */ | ||||||
| @ -180,7 +186,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | |||||||
| 
 | 
 | ||||||
|     if(Stat & STA_NOINIT) return RES_NOTRDY; |     if(Stat & STA_NOINIT) return RES_NOTRDY; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* sd_spi_fast_dev = furi_hal_spi_device_get(FuriHalSpiDeviceIdSdCardFast); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|  |     furi_hal_sd_spi_handle = &furi_hal_spi_bus_handle_sd_fast; | ||||||
| 
 | 
 | ||||||
|     switch(cmd) { |     switch(cmd) { | ||||||
|     /* Make sure that no pending write process */ |     /* Make sure that no pending write process */ | ||||||
| @ -213,7 +220,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) { | |||||||
|         res = RES_PARERR; |         res = RES_PARERR; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(sd_spi_fast_dev); |     furi_hal_sd_spi_handle = NULL; | ||||||
|  |     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_fast); | ||||||
| 
 | 
 | ||||||
|     return res; |     return res; | ||||||
|     /* USER CODE END IOCTL */ |     /* USER CODE END IOCTL */ | ||||||
|  | |||||||
| @ -20,3 +20,5 @@ bool hal_sd_detect(void) { | |||||||
|     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); |     bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle* furi_hal_sd_spi_handle = NULL; | ||||||
|  | |||||||
| @ -1,10 +1,9 @@ | |||||||
| #include <furi-hal-spi-config.h> | #include <furi-hal-spi-config.h> | ||||||
| #include <furi-hal-resources.h> | #include <furi-hal-resources.h> | ||||||
| 
 | 
 | ||||||
| #define SPI_R SPI1 | /* SPI Presets */ | ||||||
| #define SPI_D SPI2 |  | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -17,7 +16,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_nfc = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -30,7 +29,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_subghz = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m = { | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -43,10 +42,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_display = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m = { | ||||||
|  * SD Card in fast mode (after init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -59,10 +55,7 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /**
 | const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m = { | ||||||
|  * SD Card in slow mode (before init) |  | ||||||
|  */ |  | ||||||
| const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { |  | ||||||
|     .Mode = LL_SPI_MODE_MASTER, |     .Mode = LL_SPI_MODE_MASTER, | ||||||
|     .TransferDirection = LL_SPI_FULL_DUPLEX, |     .TransferDirection = LL_SPI_FULL_DUPLEX, | ||||||
|     .DataWidth = LL_SPI_DATAWIDTH_8BIT, |     .DataWidth = LL_SPI_DATAWIDTH_8BIT, | ||||||
| @ -75,29 +68,187 @@ const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow = { | |||||||
|     .CRCPoly = 7, |     .CRCPoly = 7, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| osMutexId_t spi_mutex_d = NULL; | /* SPI Buses */ | ||||||
| osMutexId_t spi_mutex_r = NULL; |  | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_r = { | osMutexId_t furi_hal_spi_bus_r_mutex = NULL; | ||||||
|     .spi=SPI_R, | 
 | ||||||
|     .mutex=&spi_mutex_r, | static void furi_hal_spi_bus_r_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if (event == FuriHalSpiBusEventInit) { | ||||||
|  |         furi_hal_spi_bus_r_mutex = osMutexNew(NULL); | ||||||
|  |         LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeinit) { | ||||||
|  |         furi_check(osMutexDelete(furi_hal_spi_bus_r_mutex)); | ||||||
|  |     } else if (event == FuriHalSpiBusEventLock) { | ||||||
|  |         furi_check(osMutexAcquire(furi_hal_spi_bus_r_mutex, osWaitForever) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventUnlock) { | ||||||
|  |         furi_check(osMutexRelease(furi_hal_spi_bus_r_mutex) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_r = { | ||||||
|  |     .spi=SPI1, | ||||||
|  |     .callback = furi_hal_spi_bus_r_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | osMutexId_t furi_hal_spi_bus_d_mutex = NULL; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_d_event_callback(FuriHalSpiBus* bus, FuriHalSpiBusEvent event) { | ||||||
|  |     if (event == FuriHalSpiBusEventInit) { | ||||||
|  |         furi_hal_spi_bus_d_mutex = osMutexNew(NULL); | ||||||
|  |         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |         bus->current_handle = NULL; | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeinit) { | ||||||
|  |         furi_check(osMutexDelete(furi_hal_spi_bus_d_mutex)); | ||||||
|  |     } else if (event == FuriHalSpiBusEventLock) { | ||||||
|  |         furi_check(osMutexAcquire(furi_hal_spi_bus_d_mutex, osWaitForever) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventUnlock) { | ||||||
|  |         furi_check(osMutexRelease(furi_hal_spi_bus_d_mutex) == osOK); | ||||||
|  |     } else if (event == FuriHalSpiBusEventActivate) { | ||||||
|  |         LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } else if (event == FuriHalSpiBusEventDeactivate) { | ||||||
|  |         LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBus furi_hal_spi_bus_d = { | ||||||
|  |     .spi=SPI2, | ||||||
|  |     .callback = furi_hal_spi_bus_d_event_callback, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* SPI Bus Handles */ | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_r_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if (event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  |         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init(handle->miso, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->mosi, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |         hal_gpio_init(handle->sck, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_subghz_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_8m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_subghz_event_callback, | ||||||
|     .miso=&gpio_spi_r_miso, |     .miso=&gpio_spi_r_miso, | ||||||
|     .mosi=&gpio_spi_r_mosi, |     .mosi=&gpio_spi_r_mosi, | ||||||
|     .clk=&gpio_spi_r_sck, |     .sck=&gpio_spi_r_sck, | ||||||
|  |     .cs=&gpio_subghz_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiBus spi_d = { | static void furi_hal_spi_bus_handle_nfc_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|     .spi=SPI_D, |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_2edge_low_8m); | ||||||
|     .mutex=&spi_mutex_d, | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_nfc_event_callback, | ||||||
|  |     .miso=&gpio_spi_r_miso, | ||||||
|  |     .mosi=&gpio_spi_r_mosi, | ||||||
|  |     .sck=&gpio_spi_r_sck, | ||||||
|  |     .cs=&gpio_nfc_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_external_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_r_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_external = { | ||||||
|  |     .bus=&furi_hal_spi_bus_r, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_external_event_callback, | ||||||
|  |     .miso=&gpio_ext_pa6, | ||||||
|  |     .mosi=&gpio_ext_pa7, | ||||||
|  |     .sck=&gpio_ext_pb3, | ||||||
|  |     .cs=&gpio_ext_pa4, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | inline static void furi_hal_spi_bus_d_handle_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event, const LL_SPI_InitTypeDef* preset) { | ||||||
|  |     if (event == FuriHalSpiBusHandleEventInit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeOutputPushPull, GpioPullUp, GpioSpeedVeryHigh); | ||||||
|  | 
 | ||||||
|  |         hal_gpio_init_ex(handle->miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex(handle->mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  |         hal_gpio_init_ex(handle->sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI2); | ||||||
|  | 
 | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeinit) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         hal_gpio_init(handle->cs, GpioModeAnalog, GpioPullUp, GpioSpeedLow); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventActivate) { | ||||||
|  |         LL_SPI_Init(handle->bus->spi, (LL_SPI_InitTypeDef*)preset); | ||||||
|  |         LL_SPI_SetRxFIFOThreshold(handle->bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); | ||||||
|  |         LL_SPI_Enable(handle->bus->spi); | ||||||
|  |         hal_gpio_write(handle->cs, false); | ||||||
|  |     } else if (event == FuriHalSpiBusHandleEventDeactivate) { | ||||||
|  |         hal_gpio_write(handle->cs, true); | ||||||
|  |         LL_SPI_Disable(handle->bus->spi); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_display_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_4m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_display = { | ||||||
|  |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_display_event_callback, | ||||||
|     .miso=&gpio_spi_d_miso, |     .miso=&gpio_spi_d_miso, | ||||||
|     .mosi=&gpio_spi_d_mosi, |     .mosi=&gpio_spi_d_mosi, | ||||||
|     .clk=&gpio_spi_d_sck, |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_display_cs, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax] = { | static void furi_hal_spi_bus_handle_sd_fast_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, }, |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_16m); | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_display, .chip_select=&gpio_display_cs, }, | } | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, }, | 
 | ||||||
|     { .bus=&spi_d, .config=&furi_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, }, | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast = { | ||||||
|     { .bus=&spi_r, .config=&furi_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs }, |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_sd_fast_event_callback, | ||||||
|  |     .miso=&gpio_spi_d_miso, | ||||||
|  |     .mosi=&gpio_spi_d_mosi, | ||||||
|  |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_sdcard_cs, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_handle_sd_slow_event_callback(FuriHalSpiBusHandle* handle, FuriHalSpiBusHandleEvent event) { | ||||||
|  |     furi_hal_spi_bus_d_handle_event_callback(handle, event, &furi_hal_spi_preset_1edge_low_2m); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow = { | ||||||
|  |     .bus=&furi_hal_spi_bus_d, | ||||||
|  |     .callback=furi_hal_spi_bus_handle_sd_slow_event_callback, | ||||||
|  |     .miso=&gpio_spi_d_miso, | ||||||
|  |     .mosi=&gpio_spi_d_mosi, | ||||||
|  |     .sck=&gpio_spi_d_sck, | ||||||
|  |     .cs=&gpio_sdcard_cs, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -1,62 +1,60 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <furi-hal-gpio.h> | #include <furi-hal-spi-types.h> | ||||||
| #include <stm32wbxx_ll_spi.h> |  | ||||||
| #include <cmsis_os2.h> |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_nfc; | /** Preset for ST25R916 */ | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_subghz; | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_2edge_low_8m; | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_display; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_fast; |  | ||||||
| extern const LL_SPI_InitTypeDef furi_hal_spi_config_sd_slow; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI BUS handler
 | /** Preset for CC1101 */ | ||||||
|  * Structure content may change at some point | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_8m; | ||||||
|  | 
 | ||||||
|  | /** Preset for ST7567 (Display) */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_4m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in fast mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_16m; | ||||||
|  | 
 | ||||||
|  | /** Preset for SdCard in slow mode */ | ||||||
|  | extern const LL_SPI_InitTypeDef furi_hal_spi_preset_1edge_low_2m; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus R (Radio: CC1101, Nfc, External)*/ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_r; | ||||||
|  | 
 | ||||||
|  | /** Furi Hal Spi Bus D (Display, SdCard) */ | ||||||
|  | extern FuriHalSpiBus furi_hal_spi_bus_d; | ||||||
|  | 
 | ||||||
|  | /** CC1101 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_subghz; | ||||||
|  | 
 | ||||||
|  | /** ST25R3916 on `furi_hal_spi_bus_r` */ | ||||||
|  | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_nfc; | ||||||
|  | 
 | ||||||
|  | /** External on `furi_hal_spi_bus_r`
 | ||||||
|  |  * Preset: `furi_hal_spi_preset_1edge_low_2m` | ||||||
|  |  *  | ||||||
|  |  * miso: pa6 | ||||||
|  |  * mosi: pa7 | ||||||
|  |  * sck: pb3 | ||||||
|  |  * cs:  pa4 (software controlled) | ||||||
|  |  *  | ||||||
|  |  * @warning not initialized by default, call `furi_hal_spi_bus_handle_init` to initialize | ||||||
|  |  * Bus pins are floating on inactive state, CS high after initialization | ||||||
|  |  *  | ||||||
|  */ |  */ | ||||||
| typedef struct { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_external; | ||||||
|     const SPI_TypeDef* spi; |  | ||||||
|     const osMutexId_t* mutex; |  | ||||||
|     const GpioPin* miso; |  | ||||||
|     const GpioPin* mosi; |  | ||||||
|     const GpioPin* clk; |  | ||||||
| } FuriHalSpiBus; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Device handler
 | /** ST7567(Display) on `furi_hal_spi_bus_d` */ | ||||||
|  * Structure content may change at some point | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_display; | ||||||
|  */ |  | ||||||
| typedef struct { |  | ||||||
|     const FuriHalSpiBus* bus; |  | ||||||
|     const LL_SPI_InitTypeDef* config; |  | ||||||
|     const GpioPin* chip_select; |  | ||||||
| } FuriHalSpiDevice; |  | ||||||
| 
 | 
 | ||||||
| /** FURI HAL SPI Standard Device IDs */ | /** SdCard in fast mode on `furi_hal_spi_bus_d` */ | ||||||
| typedef enum { | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_fast; | ||||||
|     FuriHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */ |  | ||||||
|     FuriHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */ |  | ||||||
|     FuriHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */ |  | ||||||
|     FuriHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */ |  | ||||||
| 
 | 
 | ||||||
|     FuriHalSpiDeviceIdMax,           /** Service Value, do not use */ | /** SdCard in slow mode on `furi_hal_spi_bus_d` */ | ||||||
| } FuriHalSpiDeviceId; | extern FuriHalSpiBusHandle furi_hal_spi_bus_handle_sd_slow; | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus R
 |  | ||||||
|  * CC1101, Nfc |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_r; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi Bus D
 |  | ||||||
|  * Display, SdCard |  | ||||||
|  */ |  | ||||||
| extern const FuriHalSpiBus spi_d; |  | ||||||
| 
 |  | ||||||
| /** Furi Hal Spi devices */ |  | ||||||
| extern const FuriHalSpiDevice furi_hal_spi_devices[FuriHalSpiDeviceIdMax]; |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										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" | #define TAG "FuriHalSpi" | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_init() { | void furi_hal_spi_init() { | ||||||
|     // Spi structure is const, but mutex is not
 |     furi_hal_spi_bus_init(&furi_hal_spi_bus_r); | ||||||
|     // Need some hell-ish casting to make it work
 |     furi_hal_spi_bus_init(&furi_hal_spi_bus_d); | ||||||
|     *(osMutexId_t*)spi_r.mutex = osMutexNew(NULL); |  | ||||||
|     *(osMutexId_t*)spi_d.mutex = osMutexNew(NULL); |  | ||||||
|     // 
 |  | ||||||
|     for (size_t i=0; i<FuriHalSpiDeviceIdMax; ++i) { |  | ||||||
|         hal_gpio_write(furi_hal_spi_devices[i].chip_select, true); |  | ||||||
|         hal_gpio_init( |  | ||||||
|             furi_hal_spi_devices[i].chip_select, |  | ||||||
|             GpioModeOutputPushPull, |  | ||||||
|             GpioPullNo, |  | ||||||
|             GpioSpeedVeryHigh |  | ||||||
|         ); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_miso, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_subghz); | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_mosi, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); | ||||||
|     hal_gpio_init_ex(&gpio_spi_r_sck, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedVeryHigh, GpioAltFn5SPI1); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_display); | ||||||
| 
 |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_fast); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_miso, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |     furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_sd_slow); | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_mosi, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |  | ||||||
|     hal_gpio_init_ex(&gpio_spi_d_sck, GpioModeAltFunctionPushPull, GpioPullUp, GpioSpeedVeryHigh, GpioAltFn5SPI2); |  | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_init(FuriHalSpiBus* bus) { | ||||||
|     furi_assert(bus); |     furi_assert(bus); | ||||||
|     furi_check(osMutexAcquire(*bus->mutex, osWaitForever) == osOK); |     bus->callback(bus, FuriHalSpiBusEventInit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus) { | void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus) { | ||||||
|     furi_assert(bus); |     furi_assert(bus); | ||||||
|     furi_check(osMutexRelease(*bus->mutex) == osOK); |     bus->callback(bus, FuriHalSpiBusEventDeinit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config) { | void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
| 
 |     handle->callback(handle, FuriHalSpiBusHandleEventInit); | ||||||
|     LL_SPI_DeInit((SPI_TypeDef*)bus->spi); |  | ||||||
|     LL_SPI_Init((SPI_TypeDef*)bus->spi, (LL_SPI_InitTypeDef*)config); |  | ||||||
|     LL_SPI_SetRxFIFOThreshold((SPI_TypeDef*)bus->spi, LL_SPI_RX_FIFO_TH_QUARTER); |  | ||||||
|     LL_SPI_Enable((SPI_TypeDef*)bus->spi); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_spi_bus_end_txrx(const FuriHalSpiBus* bus, uint32_t timeout) { | void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | ||||||
|     while(LL_SPI_GetTxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_TX_FIFO_EMPTY); |     furi_assert(handle); | ||||||
|     while(LL_SPI_IsActiveFlag_BSY((SPI_TypeDef *)bus->spi)); |     handle->callback(handle, FuriHalSpiBusHandleEventDeinit); | ||||||
|     while(LL_SPI_GetRxFIFOLevel((SPI_TypeDef *)bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | } | ||||||
|         LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); | 
 | ||||||
|  | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||||
|  |     furi_assert(handle); | ||||||
|  | 
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||||
|  | 
 | ||||||
|  |     furi_assert(handle->bus->current_handle == NULL); | ||||||
|  | 
 | ||||||
|  |     handle->bus->current_handle = handle; | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventActivate); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | ||||||
|  |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|  | 
 | ||||||
|  |     // Handle event and unset handle
 | ||||||
|  |     handle->callback(handle, FuriHalSpiBusHandleEventDeactivate); | ||||||
|  |     handle->bus->current_handle = NULL; | ||||||
|  | 
 | ||||||
|  |     // Bus events
 | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||||
|  |     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||||
|  |     while(LL_SPI_GetTxFIFOLevel(handle->bus->spi) != LL_SPI_TX_FIFO_EMPTY); | ||||||
|  |     while(LL_SPI_IsActiveFlag_BSY(handle->bus->spi)); | ||||||
|  |     while(LL_SPI_GetRxFIFOLevel(handle->bus->spi) != LL_SPI_RX_FIFO_EMPTY) { | ||||||
|  |         LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(buffer); |     furi_assert(buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
| 
 | 
 | ||||||
|     return furi_hal_spi_bus_trx(bus, buffer, buffer, size, timeout); |     return furi_hal_spi_bus_trx(handle, buffer, buffer, size, timeout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(buffer); |     furi_assert(buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if (LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi)) { |         if (LL_SPI_IsActiveFlag_TXE(handle->bus->spi)) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *buffer); | ||||||
|             buffer++; |             buffer++; | ||||||
|             size--; |             size--; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
|     LL_SPI_ClearFlag_OVR((SPI_TypeDef *)bus->spi); |     LL_SPI_ClearFlag_OVR(handle->bus->spi); | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { | ||||||
|     furi_assert(bus); |     furi_assert(handle); | ||||||
|  |     furi_assert(handle->bus->current_handle == handle); | ||||||
|     furi_assert(tx_buffer); |     furi_assert(tx_buffer); | ||||||
|     furi_assert(rx_buffer); |     furi_assert(rx_buffer); | ||||||
|     furi_assert(size > 0); |     furi_assert(size > 0); | ||||||
| @ -104,99 +119,22 @@ bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* | |||||||
|     bool tx_allowed = true; |     bool tx_allowed = true; | ||||||
| 
 | 
 | ||||||
|     while(size > 0) { |     while(size > 0) { | ||||||
|         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE((SPI_TypeDef *)bus->spi) && tx_allowed) { |         if(tx_size > 0 && LL_SPI_IsActiveFlag_TXE(handle->bus->spi) && tx_allowed) { | ||||||
|             LL_SPI_TransmitData8((SPI_TypeDef *)bus->spi, *tx_buffer); |             LL_SPI_TransmitData8(handle->bus->spi, *tx_buffer); | ||||||
|             tx_buffer++; |             tx_buffer++; | ||||||
|             tx_size--; |             tx_size--; | ||||||
|             tx_allowed = false; |             tx_allowed = false; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if(LL_SPI_IsActiveFlag_RXNE((SPI_TypeDef *)bus->spi)) { |         if(LL_SPI_IsActiveFlag_RXNE(handle->bus->spi)) { | ||||||
|             *rx_buffer = LL_SPI_ReceiveData8((SPI_TypeDef *)bus->spi); |             *rx_buffer = LL_SPI_ReceiveData8(handle->bus->spi); | ||||||
|             rx_buffer++; |             rx_buffer++; | ||||||
|             size--; |             size--; | ||||||
|             tx_allowed = true; |             tx_allowed = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_bus_end_txrx(bus, timeout); |     furi_hal_spi_bus_end_txrx(handle, timeout); | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(device->config); |  | ||||||
| 
 |  | ||||||
|     furi_hal_spi_bus_configure(device->bus, device->config); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id) { |  | ||||||
|     furi_assert(device_id < FuriHalSpiDeviceIdMax); |  | ||||||
| 
 |  | ||||||
|     const FuriHalSpiDevice* device = &furi_hal_spi_devices[device_id]; |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_hal_spi_bus_lock(device->bus); |  | ||||||
|     furi_hal_spi_device_configure(device); |  | ||||||
| 
 |  | ||||||
|     return device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device) { |  | ||||||
|     furi_hal_spi_bus_unlock(device->bus); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_rx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_rx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_tx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_tx(device->bus, buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool furi_hal_spi_device_trx(const FuriHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) { |  | ||||||
|     furi_assert(device); |  | ||||||
|     furi_assert(tx_buffer); |  | ||||||
|     furi_assert(rx_buffer); |  | ||||||
|     furi_assert(size > 0); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, false); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     bool ret = furi_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, timeout); |  | ||||||
| 
 |  | ||||||
|     if (device->chip_select) { |  | ||||||
|         hal_gpio_write(device->chip_select, true); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -269,7 +269,7 @@ void furi_hal_subghz_init() { | |||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateInit); |     furi_assert(furi_hal_subghz_state == SubGhzStateInit); | ||||||
|     furi_hal_subghz_state = SubGhzStateIdle; |     furi_hal_subghz_state = SubGhzStateIdle; | ||||||
| 
 | 
 | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
| #ifdef FURI_HAL_SUBGHZ_TX_GPIO | #ifdef FURI_HAL_SUBGHZ_TX_GPIO | ||||||
|     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&FURI_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
| @ -277,58 +277,58 @@ void furi_hal_subghz_init() { | |||||||
| 
 | 
 | ||||||
|     // Reset
 |     // Reset
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
| 
 | 
 | ||||||
|     // Prepare GD0 for power on self test
 |     // Prepare GD0 for power on self test
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     // GD0 low
 |     // GD0 low
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != false) |     while(hal_gpio_read(&gpio_cc1101_g0) != false) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     // GD0 high
 |     // GD0 high
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != true) |     while(hal_gpio_read(&gpio_cc1101_g0) != true) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     // Reset GD0 to floating state
 |     // Reset GD0 to floating state
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     // RF switches
 |     // RF switches
 | ||||||
|     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
| 
 | 
 | ||||||
|     // Go to sleep
 |     // Go to sleep
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_sleep() { | void furi_hal_subghz_sleep() { | ||||||
|     furi_assert(furi_hal_subghz_state == SubGhzStateIdle); |     furi_assert(furi_hal_subghz_state == SubGhzStateIdle); | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_dump_state() { | void furi_hal_subghz_dump_state() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     printf( |     printf( | ||||||
|         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", |         "[furi_hal_subghz] cc1101 chip %d, version %d\r\n", | ||||||
|         cc1101_get_partnumber(device), |         cc1101_get_partnumber(&furi_hal_spi_bus_handle_subghz), | ||||||
|         cc1101_get_version(device)); |         cc1101_get_version(&furi_hal_spi_bus_handle_subghz)); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | ||||||
| @ -350,81 +350,81 @@ void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_registers(const uint8_t data[][2]) { | void furi_hal_subghz_load_registers(const uint8_t data[][2]) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     uint32_t i = 0; |     uint32_t i = 0; | ||||||
|     while(data[i][0]) { |     while(data[i][0]) { | ||||||
|         cc1101_write_reg(device, data[i][0], data[i][1]); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, data[i][0], data[i][1]); | ||||||
|         i++; |         i++; | ||||||
|     } |     } | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_load_patable(const uint8_t data[8]) { | void furi_hal_subghz_load_patable(const uint8_t data[8]) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_set_pa_table(device, data); |     cc1101_set_pa_table(&furi_hal_spi_bus_handle_subghz, data); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | void furi_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_tx(device); |     cc1101_flush_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_fifo(device, data, size); |     cc1101_write_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_flush_rx() { | void furi_hal_subghz_flush_rx() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_flush_rx(device); |     cc1101_flush_rx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | void furi_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_read_fifo(device, data, size); |     cc1101_read_fifo(&furi_hal_spi_bus_handle_subghz, data, size); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_shutdown() { | void furi_hal_subghz_shutdown() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     // Reset and shutdown
 |     // Reset and shutdown
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_reset() { | void furi_hal_subghz_reset() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_reset(device); |     cc1101_reset(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_idle() { | void furi_hal_subghz_idle() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_idle(device); |     cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_rx() { | void furi_hal_subghz_rx() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_rx(device); |     cc1101_switch_to_rx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_subghz_tx() { | bool furi_hal_subghz_tx() { | ||||||
|     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; |     if(furi_hal_subghz_regulation != SubGhzRegulationTxRx) return false; | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     cc1101_switch_to_tx(device); |     cc1101_switch_to_tx(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float furi_hal_subghz_get_rssi() { | float furi_hal_subghz_get_rssi() { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     int32_t rssi_dec = cc1101_get_rssi(device); |     int32_t rssi_dec = cc1101_get_rssi(&furi_hal_spi_bus_handle_subghz); | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     float rssi = rssi_dec; |     float rssi = rssi_dec; | ||||||
|     if(rssi_dec >= 128) { |     if(rssi_dec >= 128) { | ||||||
| @ -461,7 +461,7 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     //checking regional settings
 |     //checking regional settings
 | ||||||
|     bool txrx = false; |     bool txrx = false; | ||||||
| @ -503,37 +503,37 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { | |||||||
|         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; |         furi_hal_subghz_regulation = SubGhzRegulationOnlyRx; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint32_t real_frequency = cc1101_set_frequency(device, value); |     uint32_t real_frequency = cc1101_set_frequency(&furi_hal_spi_bus_handle_subghz, value); | ||||||
|     cc1101_calibrate(device); |     cc1101_calibrate(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     while(true) { |     while(true) { | ||||||
|         CC1101Status status = cc1101_get_status(device); |         CC1101Status status = cc1101_get_status(&furi_hal_spi_bus_handle_subghz); | ||||||
|         if(status.STATE == CC1101StateIDLE) break; |         if(status.STATE == CC1101StateIDLE) break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| 
 | 
 | ||||||
|     return real_frequency; |     return real_frequency; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | void furi_hal_subghz_set_path(FuriHalSubGhzPath path) { | ||||||
|     const FuriHalSpiDevice* device = furi_hal_spi_device_get(FuriHalSpiDeviceIdSubGhz); |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz); | ||||||
|     if(path == FuriHalSubGhzPath433) { |     if(path == FuriHalSubGhzPath433) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     } else if(path == FuriHalSubGhzPath315) { |     } else if(path == FuriHalSubGhzPath315) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|     } else if(path == FuriHalSubGhzPath868) { |     } else if(path == FuriHalSubGhzPath868) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 1); |         hal_gpio_write(&gpio_rf_sw_0, 1); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     } else if(path == FuriHalSubGhzPathIsolate) { |     } else if(path == FuriHalSubGhzPathIsolate) { | ||||||
|         hal_gpio_write(&gpio_rf_sw_0, 0); |         hal_gpio_write(&gpio_rf_sw_0, 0); | ||||||
|         cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |         cc1101_write_reg(&furi_hal_spi_bus_handle_subghz, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
|     } else { |     } else { | ||||||
|         furi_crash(NULL); |         furi_crash(NULL); | ||||||
|     } |     } | ||||||
|     furi_hal_spi_device_return(device); |     furi_hal_spi_release(&furi_hal_spi_bus_handle_subghz); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; | volatile uint32_t furi_hal_subghz_capture_delta_duration = 0; | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
|  | #include <furi-hal-spi-types.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| @ -24,6 +25,9 @@ void hal_sd_detect_set_low(void); | |||||||
|  */ |  */ | ||||||
| bool hal_sd_detect(void); | bool hal_sd_detect(void); | ||||||
| 
 | 
 | ||||||
|  | /** Pointer to currently used SPI Handle */ | ||||||
|  | extern FuriHalSpiBusHandle* furi_hal_sd_spi_handle; | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1,106 +1,88 @@ | |||||||
| #pragma once | #pragma once | ||||||
| #include "main.h" | 
 | ||||||
| #include "furi-hal-spi-config.h" | #include <furi-hal-spi-config.h> | ||||||
| #include <furi-hal-gpio.h> |  | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /**
 | /** Initialize SPI HAL */ | ||||||
|  * Init SPI API |  | ||||||
|  */ |  | ||||||
| void furi_hal_spi_init(); | void furi_hal_spi_init(); | ||||||
| 
 | 
 | ||||||
| /* Bus Level API */ | /** Initialize SPI Bus
 | ||||||
| 
 |  * | ||||||
| /** Lock SPI bus
 |  * @param      handle  pointer to FuriHalSpiBus instance | ||||||
|  * Takes bus mutex, if used |  | ||||||
|  */ |  */ | ||||||
| void furi_hal_spi_bus_lock(const FuriHalSpiBus* bus); | void furi_hal_spi_bus_init(FuriHalSpiBus* bus); | ||||||
| 
 | 
 | ||||||
| /** Unlock SPI bus
 | /** Deinitialize SPI Bus
 | ||||||
|  * Releases BUS mutex, if used |  * | ||||||
|  |  * @param      handle  pointer to FuriHalSpiBus instance | ||||||
|  */ |  */ | ||||||
| void furi_hal_spi_bus_unlock(const FuriHalSpiBus* bus); | void furi_hal_spi_bus_deinit(FuriHalSpiBus* bus); | ||||||
| 
 | 
 | ||||||
| /** Configure SPI bus
 | /** Initialize SPI Bus Handle
 | ||||||
|  * @param bus - spi bus handler |  * | ||||||
|  * @param config - spi configuration structure |  * @param      handle  pointer to FuriHalSpiBusHandle instance | ||||||
|  */ |  */ | ||||||
| void furi_hal_spi_bus_configure(const FuriHalSpiBus* bus, const LL_SPI_InitTypeDef* config); | void furi_hal_spi_bus_handle_init(FuriHalSpiBusHandle* handle); | ||||||
|  | 
 | ||||||
|  | /** Deinitialize SPI Bus Handle
 | ||||||
|  |  * | ||||||
|  |  * @param      handle  pointer to FuriHalSpiBusHandle instance | ||||||
|  |  */ | ||||||
|  | void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle); | ||||||
|  | 
 | ||||||
|  | /** Acquire SPI bus
 | ||||||
|  |  * | ||||||
|  |  * @warning blocking, calls `furi_crash` on programming error, CS transition is up to handler event routine | ||||||
|  |  * | ||||||
|  |  * @param      handle  pointer to FuriHalSpiBusHandle instance | ||||||
|  |  */ | ||||||
|  | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle); | ||||||
|  | 
 | ||||||
|  | /** Release SPI bus
 | ||||||
|  |  * | ||||||
|  |  * @warning calls `furi_crash` on programming error, CS transition is up to handler event routine | ||||||
|  |  *  | ||||||
|  |  * @param      handle  pointer to FuriHalSpiBusHandle instance | ||||||
|  |  */ | ||||||
|  | void furi_hal_spi_release(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** SPI Receive
 | /** SPI Receive
 | ||||||
|  * @param bus - spi bus handler |  * | ||||||
|  * @param buffer - receive buffer |  * @param      handle   pointer to FuriHalSpiBusHandle instance | ||||||
|  * @param size - transaction size |  * @param      buffer   receive buffer | ||||||
|  * @param timeout - bus operation timeout in ms |  * @param      size     transaction size (buffer size) | ||||||
|  |  * @param      timeout  operation timeout in ms | ||||||
|  |  * | ||||||
|  |  * @return     true on sucess | ||||||
|  */ |  */ | ||||||
| bool furi_hal_spi_bus_rx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | bool furi_hal_spi_bus_rx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout); | ||||||
| 
 | 
 | ||||||
| /** SPI Transmit
 | /** SPI Transmit
 | ||||||
|  * @param bus - spi bus handler |  * | ||||||
|  * @param buffer - transmit buffer |  * @param      handle   pointer to FuriHalSpiBusHandle instance | ||||||
|  * @param size - transaction size |  * @param      buffer   transmit buffer | ||||||
|  * @param timeout - bus operation timeout in ms |  * @param      size     transaction size (buffer size) | ||||||
|  |  * @param      timeout  operation timeout in ms | ||||||
|  |  * | ||||||
|  |  * @return     true on success | ||||||
|  */ |  */ | ||||||
| bool furi_hal_spi_bus_tx(const FuriHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout); | bool furi_hal_spi_bus_tx(FuriHalSpiBusHandle* handle, uint8_t* buffer, size_t size, uint32_t timeout); | ||||||
| 
 | 
 | ||||||
| /** SPI Transmit and Receive
 | /** SPI Transmit and Receive
 | ||||||
|  * @param bus - spi bus handlere |  * | ||||||
|  * @param tx_buffer - device handle |  * @param      handle     pointer to FuriHalSpiBusHandle instance | ||||||
|  * @param rx_buffer - device handle |  * @param      tx_buffer  pointer to tx buffer | ||||||
|  * @param size - transaction size |  * @param      rx_buffer  pointer to rx buffer | ||||||
|  * @param timeout - bus operation timeout in ms |  * @param      size       transaction size (buffer size) | ||||||
|  |  * @param      timeout    operation timeout in ms | ||||||
|  |  * | ||||||
|  |  * @return     true on success | ||||||
|  */ |  */ | ||||||
| bool furi_hal_spi_bus_trx(const FuriHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); | bool furi_hal_spi_bus_trx(FuriHalSpiBusHandle* handle, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); | ||||||
| 
 |  | ||||||
| /* Device Level API */ |  | ||||||
| 
 |  | ||||||
| /** Reconfigure SPI bus for device
 |  | ||||||
|  * @param device - device description |  | ||||||
|  */ |  | ||||||
| void furi_hal_spi_device_configure(const FuriHalSpiDevice* device); |  | ||||||
| 
 |  | ||||||
| /** Get Device handle
 |  | ||||||
|  * And lock access to the corresponding SPI BUS |  | ||||||
|  * @param device_id - device identifier |  | ||||||
|  * @return device handle |  | ||||||
|  */ |  | ||||||
| const FuriHalSpiDevice* furi_hal_spi_device_get(FuriHalSpiDeviceId device_id); |  | ||||||
| 
 |  | ||||||
| /** Return Device handle
 |  | ||||||
|  * And unlock access to the corresponding SPI BUS |  | ||||||
|  * @param device - device handle |  | ||||||
|  */ |  | ||||||
| void furi_hal_spi_device_return(const FuriHalSpiDevice* device); |  | ||||||
| 
 |  | ||||||
| /** SPI Recieve
 |  | ||||||
|  * @param device - device handle |  | ||||||
|  * @param buffer - receive buffer |  | ||||||
|  * @param size - transaction size |  | ||||||
|  * @param timeout - bus operation timeout in ms |  | ||||||
|  */ |  | ||||||
| bool furi_hal_spi_device_rx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout); |  | ||||||
| 
 |  | ||||||
| /** SPI Transmit
 |  | ||||||
|  * @param device - device handle |  | ||||||
|  * @param buffer - transmit buffer |  | ||||||
|  * @param size - transaction size |  | ||||||
|  * @param timeout - bus operation timeout in ms |  | ||||||
|  */ |  | ||||||
| bool furi_hal_spi_device_tx(const FuriHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout); |  | ||||||
| 
 |  | ||||||
| /** SPI Transmit and Receive
 |  | ||||||
|  * @param device - device handle |  | ||||||
|  * @param tx_buffer - device handle |  | ||||||
|  * @param rx_buffer - device handle |  | ||||||
|  * @param size - transaction size |  | ||||||
|  * @param timeout - bus operation timeout in ms |  | ||||||
|  */ |  | ||||||
| bool furi_hal_spi_device_trx(const FuriHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout); |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | |||||||
| #include "furi-hal-crypto.h" | #include "furi-hal-crypto.h" | ||||||
| #include "furi-hal-console.h" | #include "furi-hal-console.h" | ||||||
| #include "furi-hal-os.h" | #include "furi-hal-os.h" | ||||||
|  | #include "furi-hal-sd.h" | ||||||
| #include "furi-hal-i2c.h" | #include "furi-hal-i2c.h" | ||||||
| #include "furi-hal-resources.h" | #include "furi-hal-resources.h" | ||||||
| #include "furi-hal-gpio.h" | #include "furi-hal-gpio.h" | ||||||
|  | |||||||
| @ -7,7 +7,6 @@ | |||||||
| static osThreadAttr_t platform_irq_thread_attr; | static osThreadAttr_t platform_irq_thread_attr; | ||||||
| static volatile osThreadId_t platform_irq_thread_id = NULL; | static volatile osThreadId_t platform_irq_thread_id = NULL; | ||||||
| static volatile PlatformIrqCallback platform_irq_callback = NULL; | static volatile PlatformIrqCallback platform_irq_callback = NULL; | ||||||
| static FuriHalSpiDevice* platform_st25r3916 = NULL; |  | ||||||
| static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; | static const GpioPin pin = {ST25R_INT_PORT, ST25R_INT_PIN}; | ||||||
| 
 | 
 | ||||||
| void nfc_isr(void* _ctx) { | void nfc_isr(void* _ctx) { | ||||||
| @ -49,14 +48,13 @@ void platformSetIrqCallback(PlatformIrqCallback callback) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) { | HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) { | ||||||
|     furi_assert(platform_st25r3916); |  | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|     if (txBuf && rxBuf) { |     if (txBuf && rxBuf) { | ||||||
|         ret = furi_hal_spi_bus_trx(platform_st25r3916->bus, (uint8_t*)txBuf, rxBuf, len, 1000); |         ret = furi_hal_spi_bus_trx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, rxBuf, len, 1000); | ||||||
|     } else if (txBuf) { |     } else if (txBuf) { | ||||||
|         ret = furi_hal_spi_bus_tx(platform_st25r3916->bus, (uint8_t*)txBuf, len, 1000); |         ret = furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)txBuf, len, 1000); | ||||||
|     } else if (rxBuf) { |     } else if (rxBuf) { | ||||||
|         ret = furi_hal_spi_bus_rx(platform_st25r3916->bus, (uint8_t*)rxBuf, len, 1000); |         ret = furi_hal_spi_bus_rx(&furi_hal_spi_bus_handle_nfc, (uint8_t*)rxBuf, len, 1000); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(!ret) { |     if(!ret) { | ||||||
| @ -68,15 +66,9 @@ HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void platformProtectST25RComm() { | void platformProtectST25RComm() { | ||||||
|     // Don't check platform_st25r3916 since spi device is used simultaneously from nfc worker
 |     furi_hal_spi_acquire(&furi_hal_spi_bus_handle_nfc); | ||||||
|     // thread and platformIrqWorker thread with the highest priority
 |  | ||||||
| 
 |  | ||||||
|     // furi_assert(platform_st25r3916 == NULL);
 |  | ||||||
|     platform_st25r3916 = (FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdNfc); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void platformUnprotectST25RComm() { | void platformUnprotectST25RComm() { | ||||||
|     // furi_assert(platform_st25r3916);
 |     furi_hal_spi_release(&furi_hal_spi_bus_handle_nfc); | ||||||
|     furi_hal_spi_device_return(platform_st25r3916); |  | ||||||
|     // platform_st25r3916 = NULL;
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,180 +4,164 @@ | |||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| CC1101Status cc1101_strobe(const FuriHalSpiDevice* device, uint8_t strobe) { | CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe) { | ||||||
|     uint8_t tx[1] = { strobe }; |     uint8_t tx[1] = { strobe }; | ||||||
|     CC1101Status rx[1] = { 0 }; |     CC1101Status rx[1] = { 0 }; | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, false); |     while(hal_gpio_read(handle->miso)); | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT); | ||||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT); |  | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
| 
 | 
 | ||||||
|     assert(rx[0].CHIP_RDYn == 0); |     assert(rx[0].CHIP_RDYn == 0); | ||||||
|     return rx[0]; |     return rx[0]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CC1101Status cc1101_write_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t data) { | CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) { | ||||||
|     uint8_t tx[2] = { reg, data }; |     uint8_t tx[2] = { reg, data }; | ||||||
|     CC1101Status rx[2] = { 0 }; |     CC1101Status rx[2] = { 0 }; | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, false); |     while(hal_gpio_read(handle->miso)); | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); |  | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0); | ||||||
|     return rx[1]; |     return rx[1]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CC1101Status cc1101_read_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t* data) { | CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) { | ||||||
|     assert(sizeof(CC1101Status) == 1); |     assert(sizeof(CC1101Status) == 1); | ||||||
|     uint8_t tx[2] = { reg|CC1101_READ, 0}; |     uint8_t tx[2] = { reg|CC1101_READ, 0}; | ||||||
|     CC1101Status rx[2] = { 0 }; |     CC1101Status rx[2] = { 0 }; | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, false); |     while(hal_gpio_read(handle->miso)); | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); | ||||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); |  | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn) == 0); | ||||||
|     *data = *(uint8_t*)&rx[1]; |     *data = *(uint8_t*)&rx[1]; | ||||||
|     return rx[0]; |     return rx[0]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_get_partnumber(const FuriHalSpiDevice* device) { | uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle) { | ||||||
|     uint8_t partnumber=0; |     uint8_t partnumber=0; | ||||||
|     cc1101_read_reg(device, CC1101_STATUS_PARTNUM|CC1101_BURST, &partnumber); |     cc1101_read_reg(handle, CC1101_STATUS_PARTNUM|CC1101_BURST, &partnumber); | ||||||
|     return partnumber; |     return partnumber; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_get_version(const FuriHalSpiDevice* device) { | uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle) { | ||||||
|     uint8_t version=0; |     uint8_t version=0; | ||||||
|     cc1101_read_reg(device, CC1101_STATUS_VERSION|CC1101_BURST, &version); |     cc1101_read_reg(handle, CC1101_STATUS_VERSION|CC1101_BURST, &version); | ||||||
|     return version; |     return version; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_get_rssi(const FuriHalSpiDevice* device) { | uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) { | ||||||
|     uint8_t rssi=0; |     uint8_t rssi=0; | ||||||
|     cc1101_read_reg(device, CC1101_STATUS_RSSI|CC1101_BURST, &rssi); |     cc1101_read_reg(handle, CC1101_STATUS_RSSI|CC1101_BURST, &rssi); | ||||||
|     return rssi; |     return rssi; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_reset(const FuriHalSpiDevice* device) { | void cc1101_reset(FuriHalSpiBusHandle* handle) { | ||||||
|     hal_gpio_write(device->chip_select, false); |  | ||||||
|     delay_us(1000); |     delay_us(1000); | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
|     delay_us(1000); |     delay_us(1000); | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SRES); |     cc1101_strobe(handle, CC1101_STROBE_SRES); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CC1101Status cc1101_get_status(const FuriHalSpiDevice* device) { | CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle) { | ||||||
|     return cc1101_strobe(device, CC1101_STROBE_SNOP); |     return cc1101_strobe(handle, CC1101_STROBE_SNOP); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_shutdown(const FuriHalSpiDevice* device) { | void cc1101_shutdown(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SPWD); |     cc1101_strobe(handle, CC1101_STROBE_SPWD); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_calibrate(const FuriHalSpiDevice* device) { | void cc1101_calibrate(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SCAL); |     cc1101_strobe(handle, CC1101_STROBE_SCAL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_switch_to_idle(const FuriHalSpiDevice* device) { | void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SIDLE); |     cc1101_strobe(handle, CC1101_STROBE_SIDLE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_switch_to_rx(const FuriHalSpiDevice* device) { | void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SRX); |     cc1101_strobe(handle, CC1101_STROBE_SRX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_switch_to_tx(const FuriHalSpiDevice* device) { | void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_STX); |     cc1101_strobe(handle, CC1101_STROBE_STX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_flush_rx(const FuriHalSpiDevice* device) { | void cc1101_flush_rx(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SFRX); |     cc1101_strobe(handle, CC1101_STROBE_SFRX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_flush_tx(const FuriHalSpiDevice* device) { | void cc1101_flush_tx(FuriHalSpiBusHandle* handle) { | ||||||
|     cc1101_strobe(device, CC1101_STROBE_SFTX); |     cc1101_strobe(handle, CC1101_STROBE_SFTX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t cc1101_set_frequency(const FuriHalSpiDevice* device, uint32_t value) { | uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value) { | ||||||
|     uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ; |     uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ; | ||||||
| 
 | 
 | ||||||
|     // Sanity check
 |     // Sanity check
 | ||||||
|     assert((real_value & CC1101_FMASK) == real_value); |     assert((real_value & CC1101_FMASK) == real_value); | ||||||
| 
 | 
 | ||||||
|     cc1101_write_reg(device, CC1101_FREQ2, (real_value >> 16) & 0xFF); |     cc1101_write_reg(handle, CC1101_FREQ2, (real_value >> 16) & 0xFF); | ||||||
|     cc1101_write_reg(device, CC1101_FREQ1, (real_value >> 8 ) & 0xFF); |     cc1101_write_reg(handle, CC1101_FREQ1, (real_value >> 8 ) & 0xFF); | ||||||
|     cc1101_write_reg(device, CC1101_FREQ0, (real_value >> 0 ) & 0xFF); |     cc1101_write_reg(handle, CC1101_FREQ0, (real_value >> 0 ) & 0xFF); | ||||||
| 
 | 
 | ||||||
|     uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV; |     uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV; | ||||||
| 
 | 
 | ||||||
|     return (uint32_t)real_frequency; |     return (uint32_t)real_frequency; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t cc1101_set_intermediate_frequency(const FuriHalSpiDevice* device, uint32_t value) { | uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value) { | ||||||
|     uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ; |     uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ; | ||||||
|     assert((real_value & 0xFF) == real_value); |     assert((real_value & 0xFF) == real_value); | ||||||
| 
 | 
 | ||||||
|     cc1101_write_reg(device, CC1101_FSCTRL0, (real_value >> 0 ) & 0xFF); |     cc1101_write_reg(handle, CC1101_FSCTRL0, (real_value >> 0 ) & 0xFF); | ||||||
| 
 | 
 | ||||||
|     uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV; |     uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV; | ||||||
| 
 | 
 | ||||||
|     return (uint32_t)real_frequency; |     return (uint32_t)real_frequency; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]) { | void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) { | ||||||
|     uint8_t tx[9] = { CC1101_PATABLE | CC1101_BURST }; |     uint8_t tx[9] = { CC1101_PATABLE | CC1101_BURST }; | ||||||
|     CC1101Status rx[9] = { 0 }; |     CC1101Status rx[9] = { 0 }; | ||||||
| 
 | 
 | ||||||
|     memcpy(&tx[1], &value[0], 8); |     memcpy(&tx[1], &value[0], 8); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, false); |     while(hal_gpio_read(handle->miso)); | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     furi_hal_spi_bus_trx(handle, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); | ||||||
|     furi_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); |  | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_write_fifo(const FuriHalSpiDevice* device, const uint8_t* data, uint8_t size) { | uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) { | ||||||
|     uint8_t buff_tx[64]; |     uint8_t buff_tx[64]; | ||||||
|     uint8_t buff_rx[64]; |     uint8_t buff_rx[64]; | ||||||
|     buff_tx[0] = CC1101_FIFO | CC1101_BURST; |     buff_tx[0] = CC1101_FIFO | CC1101_BURST; | ||||||
|     memcpy(&buff_tx[1], data, size); |     memcpy(&buff_tx[1], data, size); | ||||||
| 
 | 
 | ||||||
|     // Start transaction
 |     // Start transaction
 | ||||||
|     hal_gpio_write(device->chip_select, false); |  | ||||||
|     // Wait IC to become ready
 |     // Wait IC to become ready
 | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     while(hal_gpio_read(handle->miso)); | ||||||
|     // Tell IC what we want
 |     // Tell IC what we want
 | ||||||
|     furi_hal_spi_bus_trx(device->bus, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); | ||||||
| 
 |  | ||||||
|     // Finish transaction
 |  | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
| 
 | 
 | ||||||
|     return size; |     return size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t cc1101_read_fifo(const FuriHalSpiDevice* device, uint8_t* data, uint8_t* size) { | uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size) { | ||||||
|     uint8_t buff_tx[64]; |     uint8_t buff_tx[64]; | ||||||
|     buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; |     buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; | ||||||
|     uint8_t buff_rx[2]; |     uint8_t buff_rx[2]; | ||||||
| 
 | 
 | ||||||
|     // Start transaction
 |     // Start transaction
 | ||||||
|     hal_gpio_write(device->chip_select, false); |  | ||||||
|     // Wait IC to become ready
 |     // Wait IC to become ready
 | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     while(hal_gpio_read(handle->miso)); | ||||||
| 
 | 
 | ||||||
|     // First byte - packet length
 |     // First byte - packet length
 | ||||||
|     furi_hal_spi_bus_trx(device->bus, buff_tx, buff_rx, 2, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, buff_tx, buff_rx, 2, CC1101_TIMEOUT); | ||||||
|     *size = buff_rx[1]; |     *size = buff_rx[1]; | ||||||
|     furi_hal_spi_bus_trx(device->bus, &buff_tx[1], data, *size, CC1101_TIMEOUT); |     furi_hal_spi_bus_trx(handle, &buff_tx[1], data, *size, CC1101_TIMEOUT); | ||||||
|     cc1101_flush_rx(device); |     cc1101_flush_rx(handle); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, true); |  | ||||||
|     return *size; |     return *size; | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,131 +13,167 @@ extern "C" { | |||||||
| /* Low level API */ | /* Low level API */ | ||||||
| 
 | 
 | ||||||
| /** Strobe command to the device
 | /** Strobe command to the device
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      strobe  - command to execute |  * @param      strobe  - command to execute | ||||||
|  |  * | ||||||
|  * @return     device status |  * @return     device status | ||||||
|  */ |  */ | ||||||
| CC1101Status cc1101_strobe(const FuriHalSpiDevice* device, uint8_t strobe); | CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe); | ||||||
| 
 | 
 | ||||||
| /** Write device register
 | /** Write device register
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      reg     - register |  * @param      reg     - register | ||||||
|  * @param      data    - data to write |  * @param      data    - data to write | ||||||
|  |  * | ||||||
|  * @return     device status |  * @return     device status | ||||||
|  */ |  */ | ||||||
| CC1101Status cc1101_write_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t data); | CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data); | ||||||
| 
 | 
 | ||||||
| /** Read device register
 | /** Read device register
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      reg     - register |  * @param      reg     - register | ||||||
|  * @param[out] data    - pointer to data |  * @param[out] data    - pointer to data | ||||||
|  |  * | ||||||
|  * @return     device status |  * @return     device status | ||||||
|  */ |  */ | ||||||
| CC1101Status cc1101_read_reg(const FuriHalSpiDevice* device, uint8_t reg, uint8_t* data); | CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data); | ||||||
| 
 | 
 | ||||||
| /* High level API */ | /* High level API */ | ||||||
| 
 | 
 | ||||||
| /** Reset
 | /** Reset
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_reset(const FuriHalSpiDevice* device); | void cc1101_reset(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Get status
 | /** Get status
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  |  * | ||||||
|  |  * @return     CC1101Status structure | ||||||
|  */ |  */ | ||||||
| CC1101Status cc1101_get_status(const FuriHalSpiDevice* device); | CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Enable shutdown mode
 | /** Enable shutdown mode
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_shutdown(const FuriHalSpiDevice* device); | void cc1101_shutdown(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Get Partnumber
 | /** Get Partnumber
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  |  * | ||||||
|  |  * @return     part number id | ||||||
|  */ |  */ | ||||||
| uint8_t cc1101_get_partnumber(const FuriHalSpiDevice* device); | uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Get Version
 | /** Get Version
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  |  * | ||||||
|  |  * @return     version | ||||||
|  */ |  */ | ||||||
| uint8_t cc1101_get_version(const FuriHalSpiDevice* device); | uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Get raw RSSI value
 | /** Get raw RSSI value
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  |  * | ||||||
|  |  * @return     rssi value | ||||||
|  */ |  */ | ||||||
| uint8_t cc1101_get_rssi(const FuriHalSpiDevice* device); | uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Calibrate oscillator
 | /** Calibrate oscillator
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_calibrate(const FuriHalSpiDevice* device); | void cc1101_calibrate(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Switch to idle
 | /** Switch to idle
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_switch_to_idle(const FuriHalSpiDevice* device); | void cc1101_switch_to_idle(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Switch to RX
 | /** Switch to RX
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_switch_to_rx(const FuriHalSpiDevice* device); | void cc1101_switch_to_rx(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Switch to TX
 | /** Switch to TX
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_switch_to_tx(const FuriHalSpiDevice* device); | void cc1101_switch_to_tx(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Flush RX FIFO
 | /** Flush RX FIFO
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_flush_rx(const FuriHalSpiDevice* device); | void cc1101_flush_rx(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Flush TX FIFO
 | /** Flush TX FIFO
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  */ |  */ | ||||||
| void cc1101_flush_tx(const FuriHalSpiDevice* device); | void cc1101_flush_tx(FuriHalSpiBusHandle* handle); | ||||||
| 
 | 
 | ||||||
| /** Set Frequency
 | /** Set Frequency
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      value   - frequency in herz |  * @param      value   - frequency in herz | ||||||
|  |  * | ||||||
|  * @return     real frequency that were synthesized |  * @return     real frequency that were synthesized | ||||||
|  */ |  */ | ||||||
| uint32_t cc1101_set_frequency(const FuriHalSpiDevice* device, uint32_t value); | uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value); | ||||||
| 
 | 
 | ||||||
| /** Set Intermediate Frequency
 | /** Set Intermediate Frequency
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      value   - frequency in herz |  * @param      value   - frequency in herz | ||||||
|  |  * | ||||||
|  * @return     real inermediate frequency that were synthesized |  * @return     real inermediate frequency that were synthesized | ||||||
|  */ |  */ | ||||||
| uint32_t cc1101_set_intermediate_frequency(const FuriHalSpiDevice* device, uint32_t value); | uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value); | ||||||
| 
 | 
 | ||||||
| /** Set Power Amplifier level table, ramp
 | /** Set Power Amplifier level table, ramp
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      value   - array of power level values |  * @param      value   - array of power level values | ||||||
|  */ |  */ | ||||||
| void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]); | void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]); | ||||||
| 
 | 
 | ||||||
| /** Set Power Amplifier level table, ramp
 | /** Set Power Amplifier level table, ramp
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param      value   - array of power level values |  * @param      value   - array of power level values | ||||||
|  */ |  */ | ||||||
| void cc1101_set_pa_table(const FuriHalSpiDevice* device, const uint8_t value[8]); | void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]); | ||||||
| 
 | 
 | ||||||
| /** Write FIFO
 | /** Write FIFO
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  * @param data, pointer to byte array |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param size, write bytes count |  * @param      data    pointer to byte array | ||||||
|  |  * @param      size    write bytes count | ||||||
|  |  * | ||||||
|  * @return     size, written bytes count |  * @return     size, written bytes count | ||||||
|  */ |  */ | ||||||
| uint8_t cc1101_write_fifo(const FuriHalSpiDevice* device, const uint8_t* data, uint8_t size); | uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size); | ||||||
| 
 | 
 | ||||||
| /** Read FIFO
 | /** Read FIFO
 | ||||||
|  * @param device - pointer to FuriHalSpiDevice |  * | ||||||
|  * @param data, pointer to byte array |  * @param      handle  - pointer to FuriHalSpiHandle | ||||||
|  * @param size, bytes to read from fifo |  * @param      data    pointer to byte array | ||||||
|  |  * @param      size    bytes to read from fifo | ||||||
|  |  * | ||||||
|  * @return     size, read bytes count |  * @return     size, read bytes count | ||||||
|  */ |  */ | ||||||
| uint8_t cc1101_read_fifo(const FuriHalSpiDevice* device, uint8_t* data, uint8_t* size); | uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,8 +2,6 @@ | |||||||
| 
 | 
 | ||||||
| #include <furi-hal.h> | #include <furi-hal.h> | ||||||
| 
 | 
 | ||||||
| static FuriHalSpiDevice* u8g2_periphery_display = NULL; |  | ||||||
| 
 |  | ||||||
| uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { | uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { | ||||||
|     switch(msg) { |     switch(msg) { | ||||||
|     case U8X8_MSG_GPIO_AND_DELAY_INIT: |     case U8X8_MSG_GPIO_AND_DELAY_INIT: | ||||||
| @ -31,7 +29,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo | |||||||
| uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { | uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { | ||||||
|     switch(msg) { |     switch(msg) { | ||||||
|     case U8X8_MSG_BYTE_SEND: |     case U8X8_MSG_BYTE_SEND: | ||||||
|         furi_hal_spi_bus_tx(u8g2_periphery_display->bus, (uint8_t*)arg_ptr, arg_int, 10000); |         furi_hal_spi_bus_tx(&furi_hal_spi_bus_handle_display, (uint8_t*)arg_ptr, arg_int, 10000); | ||||||
|         break; |         break; | ||||||
|     case U8X8_MSG_BYTE_SET_DC: |     case U8X8_MSG_BYTE_SET_DC: | ||||||
|         hal_gpio_write(&gpio_display_di, arg_int); |         hal_gpio_write(&gpio_display_di, arg_int); | ||||||
| @ -39,16 +37,10 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ | |||||||
|     case U8X8_MSG_BYTE_INIT: |     case U8X8_MSG_BYTE_INIT: | ||||||
|         break; |         break; | ||||||
|     case U8X8_MSG_BYTE_START_TRANSFER: |     case U8X8_MSG_BYTE_START_TRANSFER: | ||||||
|         furi_assert(u8g2_periphery_display == NULL); |         furi_hal_spi_acquire(&furi_hal_spi_bus_handle_display); | ||||||
|         u8g2_periphery_display = |  | ||||||
|             (FuriHalSpiDevice*)furi_hal_spi_device_get(FuriHalSpiDeviceIdDisplay); |  | ||||||
|         hal_gpio_write(u8g2_periphery_display->chip_select, false); |  | ||||||
|         break; |         break; | ||||||
|     case U8X8_MSG_BYTE_END_TRANSFER: |     case U8X8_MSG_BYTE_END_TRANSFER: | ||||||
|         furi_assert(u8g2_periphery_display); |         furi_hal_spi_release(&furi_hal_spi_bus_handle_display); | ||||||
|         hal_gpio_write(u8g2_periphery_display->chip_select, true); |  | ||||||
|         furi_hal_spi_device_return(u8g2_periphery_display); |  | ||||||
|         u8g2_periphery_display = NULL; |  | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return 0; |         return 0; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく