瀏覽代碼

[FL-1111] SD card rework with SPI API (#496)

* api-hal-spi: make fast and slow sd card devices
* api-hal-spi: add configuration for spi bus
* fatfs: rework sd card driver with api-hal-spi
* api-hal-spi: enable spi in bus reset
gornekich 4 年之前
父節點
當前提交
d76283b1a0

+ 11 - 17
firmware/targets/f5/Src/fatfs/spi_sd_hal.c

@@ -1,12 +1,12 @@
 #include "main.h"
+#include "api-hal-spi.h"
 
 #define SD_DUMMY_BYTE 0xFF
-#define SD_CS_LOW() HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET)
-#define SD_CS_HIGH() HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_SET)
 
 const uint32_t SpiTimeout = 1000;
-extern SPI_HandleTypeDef SPI_SD_HANDLE;
 uint8_t SD_IO_WriteByte(uint8_t Data);
+static const ApiHalSpiDevice* sd_spi_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardFast];
+
 
 /******************************************************************************
                             BUS OPERATIONS
@@ -17,11 +17,8 @@ uint8_t SD_IO_WriteByte(uint8_t Data);
  * @retval None
  */
 static void SPIx_Error(void) {
-    /* De-initialize the SPI communication BUS */
-    HAL_SPI_DeInit(&SPI_SD_HANDLE);
-
     /* Re-Initiaize the SPI communication BUS */
-    HAL_SPI_Init(&SPI_SD_HANDLE);
+    api_hal_spi_bus_reset(sd_spi_dev->bus);
 }
 
 /**
@@ -32,12 +29,10 @@ static void SPIx_Error(void) {
  * @retval None
  */
 static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
-    HAL_StatusTypeDef status = HAL_OK;
-    status =
-        HAL_SPI_TransmitReceive(&SPI_SD_HANDLE, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout);
+    bool status = api_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout);
 
     /* Check the communication status */
-    if(status != HAL_OK) {
+    if(!status) {
         /* Execute user timeout callback */
         SPIx_Error();
     }
@@ -49,13 +44,12 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t
  * @retval None
  */
 __attribute__((unused)) static void SPIx_Write(uint8_t Value) {
-    HAL_StatusTypeDef status = HAL_OK;
     uint8_t data;
 
-    status = HAL_SPI_TransmitReceive(&SPI_SD_HANDLE, (uint8_t*)&Value, &data, 1, SpiTimeout);
+    bool status = api_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)&Value, &data, 1, SpiTimeout);
 
     /* Check the communication status */
-    if(status != HAL_OK) {
+    if(!status) {
         /* Execute user timeout callback */
         SPIx_Error();
     }
@@ -75,7 +69,7 @@ void SD_IO_Init(void) {
     uint8_t counter = 0;
 
     /* SD chip select high */
-    SD_CS_HIGH();
+    hal_gpio_write(sd_spi_dev->chip_select, true);
 
     /* Send dummy byte 0xFF, 10 times with CS high */
     /* Rise CS and MOSI for 80 clocks cycles */
@@ -92,9 +86,9 @@ void SD_IO_Init(void) {
  */
 void SD_IO_CSState(uint8_t val) {
     if(val == 1) {
-        SD_CS_HIGH();
+        hal_gpio_write(sd_spi_dev->chip_select, true);
     } else {
-        SD_CS_LOW();
+        hal_gpio_write(sd_spi_dev->chip_select, false);
     }
 }
 

+ 4 - 5
firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.c

@@ -295,9 +295,9 @@ static uint8_t SD_ReadData(void);
   */
 uint8_t BSP_SD_Init(bool reset_card) {
     /* Slow speed init */
-
-    /* TODO: SPI manager */
-    api_hal_spi_lock_device(&sd_slow_spi);
+    const ApiHalSpiDevice* sd_spi_slow_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardSlow];
+    api_hal_spi_bus_lock(sd_spi_slow_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_slow_dev->bus, sd_spi_slow_dev->config);
 
     /* We must reset card in spi_lock context */
     if(reset_card) {
@@ -326,8 +326,7 @@ uint8_t BSP_SD_Init(bool reset_card) {
         if(res == BSP_SD_OK) break;
     }
 
-    /* TODO: SPI manager */
-    api_hal_spi_unlock_device(&sd_slow_spi);
+    api_hal_spi_bus_unlock(sd_spi_slow_dev->bus);
 
     /* SD initialized and set to SPI mode properly */
     return res;

+ 15 - 16
firmware/targets/f5/Src/fatfs/user_diskio.c

@@ -52,6 +52,8 @@ static DSTATUS User_CheckStatus(BYTE lun) {
 
     return Stat;
 }
+
+static const ApiHalSpiDevice* sd_spi_fast_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardFast];
 /* USER CODE END DECL */
 
 /* Private function prototypes -----------------------------------------------*/
@@ -86,13 +88,13 @@ Diskio_drvTypeDef USER_Driver = {
   */
 DSTATUS USER_initialize(BYTE pdrv) {
     /* USER CODE BEGIN INIT */
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     DSTATUS status = User_CheckStatus(pdrv);
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return status;
     /* USER CODE END INIT */
@@ -121,8 +123,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
     /* USER CODE BEGIN READ */
     DRESULT res = RES_ERROR;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
         /* wait until the read operation is finished */
@@ -131,8 +133,7 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
         res = RES_OK;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END READ */
@@ -152,8 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
     /* USER CODE HERE */
     DRESULT res = RES_ERROR;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
         /* wait until the Write operation is finished */
@@ -162,8 +163,7 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
         res = RES_OK;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END WRITE */
@@ -185,8 +185,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
 
     if(Stat & STA_NOINIT) return RES_NOTRDY;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     switch(cmd) {
     /* Make sure that no pending write process */
@@ -219,8 +219,7 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
         res = RES_PARERR;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END IOCTL */

+ 40 - 44
firmware/targets/f5/api-hal/api-hal-spi-config.c

@@ -52,6 +52,44 @@ const SPI_InitTypeDef api_hal_spi_config_display = {
     .NSSPMode = SPI_NSS_PULSE_ENABLE,
 };
 
+/**
+ * SD Card in fast mode (after init)
+ */
+const SPI_InitTypeDef api_hal_spi_config_sd_fast = {
+    .Mode = SPI_MODE_MASTER,
+    .Direction = SPI_DIRECTION_2LINES,
+    .DataSize = SPI_DATASIZE_8BIT,
+    .CLKPolarity = SPI_POLARITY_LOW,
+    .CLKPhase = SPI_PHASE_1EDGE,
+    .NSS = SPI_NSS_SOFT,
+    .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2,
+    .FirstBit = SPI_FIRSTBIT_MSB,
+    .TIMode = SPI_TIMODE_DISABLE,
+    .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
+    .CRCPolynomial = 7,
+    .CRCLength = SPI_CRC_LENGTH_DATASIZE,
+    .NSSPMode = SPI_NSS_PULSE_ENABLE,
+};
+
+/**
+ * SD Card in slow mode (before init)
+ */
+const SPI_InitTypeDef api_hal_spi_config_sd_slow = {
+    .Mode = SPI_MODE_MASTER,
+    .Direction = SPI_DIRECTION_2LINES,
+    .DataSize = SPI_DATASIZE_8BIT,
+    .CLKPolarity = SPI_POLARITY_LOW,
+    .CLKPhase = SPI_PHASE_1EDGE,
+    .NSS = SPI_NSS_SOFT,
+    .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32,
+    .FirstBit = SPI_FIRSTBIT_MSB,
+    .TIMode = SPI_TIMODE_DISABLE,
+    .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
+    .CRCPolynomial = 7,
+    .CRCLength = SPI_CRC_LENGTH_DATASIZE,
+    .NSSPMode = SPI_NSS_PULSE_ENABLE,
+};
+
 osMutexId_t spi_mutex_d = NULL;
 osMutexId_t spi_mutex_r = NULL;
 
@@ -74,49 +112,7 @@ const ApiHalSpiBus spi_d = {
 const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax] = {
     { .bus=&spi_r, .config=&api_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, },
     { .bus=&spi_d, .config=&api_hal_spi_config_display, .chip_select=&gpio_display_cs, },
-    { .bus=&spi_d, .config=NULL, .chip_select=&gpio_sdcard_cs, },
+    { .bus=&spi_d, .config=&api_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, },
+    { .bus=&spi_d, .config=&api_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, },
     { .bus=&spi_r, .config=&api_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs },
 };
-
-
-/**
- * SD Card in fast mode (after init)
- */
-const SPIDevice sd_fast_spi = {
-    .bus= &spi_d,
-    .config = {
-        .Mode = SPI_MODE_MASTER,
-        .Direction = SPI_DIRECTION_2LINES,
-        .DataSize = SPI_DATASIZE_8BIT,
-        .CLKPolarity = SPI_POLARITY_LOW,
-        .CLKPhase = SPI_PHASE_1EDGE,
-        .NSS = SPI_NSS_SOFT,
-        .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2,
-        .FirstBit = SPI_FIRSTBIT_MSB,
-        .TIMode = SPI_TIMODE_DISABLE,
-        .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
-        .CRCPolynomial = 7,
-        .CRCLength = SPI_CRC_LENGTH_DATASIZE,
-        .NSSPMode = SPI_NSS_PULSE_ENABLE,
-    }};
-
-/**
- * SD Card in slow mode (before init)
- */
-const SPIDevice sd_slow_spi = {
-    .bus= &spi_d,
-    .config = {
-        .Mode = SPI_MODE_MASTER,
-        .Direction = SPI_DIRECTION_2LINES,
-        .DataSize = SPI_DATASIZE_8BIT,
-        .CLKPolarity = SPI_POLARITY_LOW,
-        .CLKPhase = SPI_PHASE_1EDGE,
-        .NSS = SPI_NSS_SOFT,
-        .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32,
-        .FirstBit = SPI_FIRSTBIT_MSB,
-        .TIMode = SPI_TIMODE_DISABLE,
-        .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
-        .CRCPolynomial = 7,
-        .CRCLength = SPI_CRC_LENGTH_DATASIZE,
-        .NSSPMode = SPI_NSS_PULSE_ENABLE,
-    }};

+ 8 - 8
firmware/targets/f5/api-hal/api-hal-spi-config.h

@@ -10,6 +10,8 @@ extern "C" {
 extern const SPI_InitTypeDef api_hal_spi_config_nfc;
 extern const SPI_InitTypeDef api_hal_spi_config_subghz;
 extern const SPI_InitTypeDef api_hal_spi_config_display;
+extern const SPI_InitTypeDef api_hal_spi_config_sd_fast;
+extern const SPI_InitTypeDef api_hal_spi_config_sd_slow;
 
 /** API HAL SPI BUS handler
  * Structure content may change at some point
@@ -33,12 +35,13 @@ typedef struct {
 
 /** API HAL SPI Standard Device IDs */
 typedef enum {
-    ApiHalSpiDeviceIdSubGhz,    /** SubGhz: CC1101, non-standard SPI usage */
-    ApiHalSpiDeviceIdDisplay,   /** Display: ERC12864, only have MOSI */
-    ApiHalSpiDeviceIdSdCard,    /** SDCARD: no default bus config, bus must explicitly be configured */
-    ApiHalSpiDeviceIdNfc,       /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
+    ApiHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */
+    ApiHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */
+    ApiHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */
+    ApiHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */
+    ApiHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
 
-    ApiHalSpiDeviceIdMax,       /** Service Value, do not use */
+    ApiHalSpiDeviceIdMax,           /** Service Value, do not use */
 } ApiHalSpiDeviceId;
 
 /** Api Hal Spi Bus R
@@ -59,9 +62,6 @@ typedef struct {
     const SPI_InitTypeDef config;
 } SPIDevice;
 
-extern const SPIDevice sd_fast_spi;
-extern const SPIDevice sd_slow_spi;
-
 #ifdef __cplusplus
 }
 #endif

+ 20 - 33
firmware/targets/f5/api-hal/api-hal-spi.c

@@ -38,6 +38,26 @@ void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
     }
 }
 
+void api_hal_spi_bus_configure(const ApiHalSpiBus* bus, const SPI_InitTypeDef* config) {
+    furi_assert(bus);
+
+    if(memcmp(&bus->spi->Init, config, sizeof(SPI_InitTypeDef))) {
+        memcpy((SPI_InitTypeDef*)&bus->spi->Init, config, sizeof(SPI_InitTypeDef));
+        if(HAL_SPI_Init((SPI_HandleTypeDef*)bus->spi) != HAL_OK) {
+            Error_Handler();
+        }
+        Enable_SPI((SPI_HandleTypeDef*)bus->spi);
+    }
+}
+
+void api_hal_spi_bus_reset(const ApiHalSpiBus* bus) {
+    furi_assert(bus);
+
+    HAL_SPI_DeInit((SPI_HandleTypeDef*)bus->spi);
+    HAL_SPI_Init((SPI_HandleTypeDef*)bus->spi);
+    Enable_SPI((SPI_HandleTypeDef*)bus->spi);
+}
+
 bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
     furi_assert(bus);
     furi_assert(buffer);
@@ -145,36 +165,3 @@ bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, u
 
     return ret;
 }
-
-void api_hal_spi_apply_config(const SPIDevice* device) {
-    osKernelLock();
-
-    memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
-
-    if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
-        Error_Handler();
-    }
-
-    Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
-
-    osKernelUnlock();
-}
-
-bool api_hal_spi_config_are_actual(const SPIDevice* device) {
-    return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
-}
-
-void api_hal_spi_config_device(const SPIDevice* device) {
-    if(!api_hal_spi_config_are_actual(device)) {
-        api_hal_spi_apply_config(device);
-    }
-}
-
-void api_hal_spi_lock_device(const SPIDevice* device) {
-    api_hal_spi_bus_lock(device->bus);
-    api_hal_spi_config_device(device);
-}
-
-void api_hal_spi_unlock_device(const SPIDevice* device) {
-    api_hal_spi_bus_unlock(device->bus);
-}

+ 13 - 0
firmware/targets/f5/api-hal/api-hal-spi.h

@@ -25,6 +25,19 @@ void api_hal_spi_bus_lock(const ApiHalSpiBus* bus);
  */
 void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus);
 
+/**
+ * Configure SPI bus
+ * @param bus - spi bus handler
+ * @param config - spi configuration structure
+ */
+void api_hal_spi_bus_configure(const ApiHalSpiBus* bus, const SPI_InitTypeDef* config);
+
+/**
+ * Reset SPI bus
+ * @param bus - spi bus handler
+ */
+void api_hal_spi_bus_reset(const ApiHalSpiBus* bus);
+
 /** SPI Receive
  * @param bus - spi bus handler
  * @param buffer - receive buffer

+ 11 - 17
firmware/targets/f6/Src/fatfs/spi_sd_hal.c

@@ -1,12 +1,12 @@
 #include "main.h"
+#include "api-hal-spi.h"
 
 #define SD_DUMMY_BYTE 0xFF
-#define SD_CS_LOW() HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET)
-#define SD_CS_HIGH() HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_SET)
 
 const uint32_t SpiTimeout = 1000;
-extern SPI_HandleTypeDef SPI_SD_HANDLE;
 uint8_t SD_IO_WriteByte(uint8_t Data);
+static const ApiHalSpiDevice* sd_spi_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardFast];
+
 
 /******************************************************************************
                             BUS OPERATIONS
@@ -17,11 +17,8 @@ uint8_t SD_IO_WriteByte(uint8_t Data);
  * @retval None
  */
 static void SPIx_Error(void) {
-    /* De-initialize the SPI communication BUS */
-    HAL_SPI_DeInit(&SPI_SD_HANDLE);
-
     /* Re-Initiaize the SPI communication BUS */
-    HAL_SPI_Init(&SPI_SD_HANDLE);
+    api_hal_spi_bus_reset(sd_spi_dev->bus);
 }
 
 /**
@@ -32,12 +29,10 @@ static void SPIx_Error(void) {
  * @retval None
  */
 static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength) {
-    HAL_StatusTypeDef status = HAL_OK;
-    status =
-        HAL_SPI_TransmitReceive(&SPI_SD_HANDLE, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout);
+    bool status = api_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)DataIn, DataOut, DataLength, SpiTimeout);
 
     /* Check the communication status */
-    if(status != HAL_OK) {
+    if(!status) {
         /* Execute user timeout callback */
         SPIx_Error();
     }
@@ -49,13 +44,12 @@ static void SPIx_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t
  * @retval None
  */
 __attribute__((unused)) static void SPIx_Write(uint8_t Value) {
-    HAL_StatusTypeDef status = HAL_OK;
     uint8_t data;
 
-    status = HAL_SPI_TransmitReceive(&SPI_SD_HANDLE, (uint8_t*)&Value, &data, 1, SpiTimeout);
+    bool status = api_hal_spi_bus_trx(sd_spi_dev->bus, (uint8_t*)&Value, &data, 1, SpiTimeout);
 
     /* Check the communication status */
-    if(status != HAL_OK) {
+    if(!status) {
         /* Execute user timeout callback */
         SPIx_Error();
     }
@@ -75,7 +69,7 @@ void SD_IO_Init(void) {
     uint8_t counter = 0;
 
     /* SD chip select high */
-    SD_CS_HIGH();
+    hal_gpio_write(sd_spi_dev->chip_select, true);
 
     /* Send dummy byte 0xFF, 10 times with CS high */
     /* Rise CS and MOSI for 80 clocks cycles */
@@ -92,9 +86,9 @@ void SD_IO_Init(void) {
  */
 void SD_IO_CSState(uint8_t val) {
     if(val == 1) {
-        SD_CS_HIGH();
+        hal_gpio_write(sd_spi_dev->chip_select, true);
     } else {
-        SD_CS_LOW();
+        hal_gpio_write(sd_spi_dev->chip_select, false);
     }
 }
 

+ 4 - 5
firmware/targets/f6/Src/fatfs/stm32_adafruit_sd.c

@@ -295,9 +295,9 @@ static uint8_t SD_ReadData(void);
   */
 uint8_t BSP_SD_Init(bool reset_card) {
     /* Slow speed init */
-
-    /* TODO: SPI manager */
-    api_hal_spi_lock_device(&sd_slow_spi);
+    const ApiHalSpiDevice* sd_spi_slow_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardSlow];
+    api_hal_spi_bus_lock(sd_spi_slow_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_slow_dev->bus, sd_spi_slow_dev->config);
 
     /* We must reset card in spi_lock context */
     if(reset_card) {
@@ -326,8 +326,7 @@ uint8_t BSP_SD_Init(bool reset_card) {
         if(res == BSP_SD_OK) break;
     }
 
-    /* TODO: SPI manager */
-    api_hal_spi_unlock_device(&sd_slow_spi);
+    api_hal_spi_bus_unlock(sd_spi_slow_dev->bus);
 
     /* SD initialized and set to SPI mode properly */
     return res;

+ 15 - 16
firmware/targets/f6/Src/fatfs/user_diskio.c

@@ -52,6 +52,8 @@ static DSTATUS User_CheckStatus(BYTE lun) {
 
     return Stat;
 }
+
+static const ApiHalSpiDevice* sd_spi_fast_dev = &api_hal_spi_devices[ApiHalSpiDeviceIdSdCardFast];
 /* USER CODE END DECL */
 
 /* Private function prototypes -----------------------------------------------*/
@@ -86,13 +88,13 @@ Diskio_drvTypeDef USER_Driver = {
   */
 DSTATUS USER_initialize(BYTE pdrv) {
     /* USER CODE BEGIN INIT */
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     DSTATUS status = User_CheckStatus(pdrv);
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return status;
     /* USER CODE END INIT */
@@ -121,8 +123,8 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
     /* USER CODE BEGIN READ */
     DRESULT res = RES_ERROR;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     if(BSP_SD_ReadBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
         /* wait until the read operation is finished */
@@ -131,8 +133,7 @@ DRESULT USER_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count) {
         res = RES_OK;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END READ */
@@ -152,8 +153,8 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
     /* USER CODE HERE */
     DRESULT res = RES_ERROR;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     if(BSP_SD_WriteBlocks((uint32_t*)buff, (uint32_t)(sector), count, SD_DATATIMEOUT) == MSD_OK) {
         /* wait until the Write operation is finished */
@@ -162,8 +163,7 @@ DRESULT USER_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count) {
         res = RES_OK;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END WRITE */
@@ -185,8 +185,8 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
 
     if(Stat & STA_NOINIT) return RES_NOTRDY;
 
-    // TODO: SPI manager
-    api_hal_spi_lock_device(&sd_fast_spi);
+    api_hal_spi_bus_lock(sd_spi_fast_dev->bus);
+    api_hal_spi_bus_configure(sd_spi_fast_dev->bus, sd_spi_fast_dev->config);
 
     switch(cmd) {
     /* Make sure that no pending write process */
@@ -219,8 +219,7 @@ DRESULT USER_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
         res = RES_PARERR;
     }
 
-    // TODO: SPI manager
-    api_hal_spi_unlock_device(&sd_fast_spi);
+    api_hal_spi_bus_unlock(sd_spi_fast_dev->bus);
 
     return res;
     /* USER CODE END IOCTL */

+ 40 - 44
firmware/targets/f6/api-hal/api-hal-spi-config.c

@@ -52,6 +52,44 @@ const SPI_InitTypeDef api_hal_spi_config_display = {
     .NSSPMode = SPI_NSS_PULSE_ENABLE,
 };
 
+/**
+ * SD Card in fast mode (after init)
+ */
+const SPI_InitTypeDef api_hal_spi_config_sd_fast = {
+    .Mode = SPI_MODE_MASTER,
+    .Direction = SPI_DIRECTION_2LINES,
+    .DataSize = SPI_DATASIZE_8BIT,
+    .CLKPolarity = SPI_POLARITY_LOW,
+    .CLKPhase = SPI_PHASE_1EDGE,
+    .NSS = SPI_NSS_SOFT,
+    .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2,
+    .FirstBit = SPI_FIRSTBIT_MSB,
+    .TIMode = SPI_TIMODE_DISABLE,
+    .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
+    .CRCPolynomial = 7,
+    .CRCLength = SPI_CRC_LENGTH_DATASIZE,
+    .NSSPMode = SPI_NSS_PULSE_ENABLE,
+};
+
+/**
+ * SD Card in slow mode (before init)
+ */
+const SPI_InitTypeDef api_hal_spi_config_sd_slow = {
+    .Mode = SPI_MODE_MASTER,
+    .Direction = SPI_DIRECTION_2LINES,
+    .DataSize = SPI_DATASIZE_8BIT,
+    .CLKPolarity = SPI_POLARITY_LOW,
+    .CLKPhase = SPI_PHASE_1EDGE,
+    .NSS = SPI_NSS_SOFT,
+    .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32,
+    .FirstBit = SPI_FIRSTBIT_MSB,
+    .TIMode = SPI_TIMODE_DISABLE,
+    .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
+    .CRCPolynomial = 7,
+    .CRCLength = SPI_CRC_LENGTH_DATASIZE,
+    .NSSPMode = SPI_NSS_PULSE_ENABLE,
+};
+
 osMutexId_t spi_mutex_d = NULL;
 osMutexId_t spi_mutex_r = NULL;
 
@@ -74,49 +112,7 @@ const ApiHalSpiBus spi_d = {
 const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax] = {
     { .bus=&spi_r, .config=&api_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, },
     { .bus=&spi_d, .config=&api_hal_spi_config_display, .chip_select=&gpio_display_cs, },
-    { .bus=&spi_d, .config=NULL, .chip_select=&gpio_sdcard_cs, },
+    { .bus=&spi_d, .config=&api_hal_spi_config_sd_fast, .chip_select=&gpio_sdcard_cs, },
+    { .bus=&spi_d, .config=&api_hal_spi_config_sd_slow, .chip_select=&gpio_sdcard_cs, },
     { .bus=&spi_r, .config=&api_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs },
 };
-
-
-/**
- * SD Card in fast mode (after init)
- */
-const SPIDevice sd_fast_spi = {
-    .bus= &spi_d,
-    .config = {
-        .Mode = SPI_MODE_MASTER,
-        .Direction = SPI_DIRECTION_2LINES,
-        .DataSize = SPI_DATASIZE_8BIT,
-        .CLKPolarity = SPI_POLARITY_LOW,
-        .CLKPhase = SPI_PHASE_1EDGE,
-        .NSS = SPI_NSS_SOFT,
-        .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2,
-        .FirstBit = SPI_FIRSTBIT_MSB,
-        .TIMode = SPI_TIMODE_DISABLE,
-        .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
-        .CRCPolynomial = 7,
-        .CRCLength = SPI_CRC_LENGTH_DATASIZE,
-        .NSSPMode = SPI_NSS_PULSE_ENABLE,
-    }};
-
-/**
- * SD Card in slow mode (before init)
- */
-const SPIDevice sd_slow_spi = {
-    .bus= &spi_d,
-    .config = {
-        .Mode = SPI_MODE_MASTER,
-        .Direction = SPI_DIRECTION_2LINES,
-        .DataSize = SPI_DATASIZE_8BIT,
-        .CLKPolarity = SPI_POLARITY_LOW,
-        .CLKPhase = SPI_PHASE_1EDGE,
-        .NSS = SPI_NSS_SOFT,
-        .BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32,
-        .FirstBit = SPI_FIRSTBIT_MSB,
-        .TIMode = SPI_TIMODE_DISABLE,
-        .CRCCalculation = SPI_CRCCALCULATION_DISABLE,
-        .CRCPolynomial = 7,
-        .CRCLength = SPI_CRC_LENGTH_DATASIZE,
-        .NSSPMode = SPI_NSS_PULSE_ENABLE,
-    }};

+ 8 - 8
firmware/targets/f6/api-hal/api-hal-spi-config.h

@@ -10,6 +10,8 @@ extern "C" {
 extern const SPI_InitTypeDef api_hal_spi_config_nfc;
 extern const SPI_InitTypeDef api_hal_spi_config_subghz;
 extern const SPI_InitTypeDef api_hal_spi_config_display;
+extern const SPI_InitTypeDef api_hal_spi_config_sd_fast;
+extern const SPI_InitTypeDef api_hal_spi_config_sd_slow;
 
 /** API HAL SPI BUS handler
  * Structure content may change at some point
@@ -33,12 +35,13 @@ typedef struct {
 
 /** API HAL SPI Standard Device IDs */
 typedef enum {
-    ApiHalSpiDeviceIdSubGhz,    /** SubGhz: CC1101, non-standard SPI usage */
-    ApiHalSpiDeviceIdDisplay,   /** Display: ERC12864, only have MOSI */
-    ApiHalSpiDeviceIdSdCard,    /** SDCARD: no default bus config, bus must explicitly be configured */
-    ApiHalSpiDeviceIdNfc,       /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
+    ApiHalSpiDeviceIdSubGhz,        /** SubGhz: CC1101, non-standard SPI usage */
+    ApiHalSpiDeviceIdDisplay,       /** Display: ERC12864, only have MOSI */
+    ApiHalSpiDeviceIdSdCardFast,    /** SDCARD: fast mode, after initialization */
+    ApiHalSpiDeviceIdSdCardSlow,    /** SDCARD: slow mode, before initialization */
+    ApiHalSpiDeviceIdNfc,           /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
 
-    ApiHalSpiDeviceIdMax,       /** Service Value, do not use */
+    ApiHalSpiDeviceIdMax,           /** Service Value, do not use */
 } ApiHalSpiDeviceId;
 
 /** Api Hal Spi Bus R
@@ -59,9 +62,6 @@ typedef struct {
     const SPI_InitTypeDef config;
 } SPIDevice;
 
-extern const SPIDevice sd_fast_spi;
-extern const SPIDevice sd_slow_spi;
-
 #ifdef __cplusplus
 }
 #endif

+ 20 - 33
firmware/targets/f6/api-hal/api-hal-spi.c

@@ -38,6 +38,26 @@ void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
     }
 }
 
+void api_hal_spi_bus_configure(const ApiHalSpiBus* bus, const SPI_InitTypeDef* config) {
+    furi_assert(bus);
+
+    if(memcmp(&bus->spi->Init, config, sizeof(SPI_InitTypeDef))) {
+        memcpy((SPI_InitTypeDef*)&bus->spi->Init, config, sizeof(SPI_InitTypeDef));
+        if(HAL_SPI_Init((SPI_HandleTypeDef*)bus->spi) != HAL_OK) {
+            Error_Handler();
+        }
+        Enable_SPI((SPI_HandleTypeDef*)bus->spi);
+    }
+}
+
+void api_hal_spi_bus_reset(const ApiHalSpiBus* bus) {
+    furi_assert(bus);
+
+    HAL_SPI_DeInit((SPI_HandleTypeDef*)bus->spi);
+    HAL_SPI_Init((SPI_HandleTypeDef*)bus->spi);
+    Enable_SPI((SPI_HandleTypeDef*)bus->spi);
+}
+
 bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
     furi_assert(bus);
     furi_assert(buffer);
@@ -145,36 +165,3 @@ bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, u
 
     return ret;
 }
-
-void api_hal_spi_apply_config(const SPIDevice* device) {
-    osKernelLock();
-
-    memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
-
-    if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
-        Error_Handler();
-    }
-
-    Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
-
-    osKernelUnlock();
-}
-
-bool api_hal_spi_config_are_actual(const SPIDevice* device) {
-    return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
-}
-
-void api_hal_spi_config_device(const SPIDevice* device) {
-    if(!api_hal_spi_config_are_actual(device)) {
-        api_hal_spi_apply_config(device);
-    }
-}
-
-void api_hal_spi_lock_device(const SPIDevice* device) {
-    api_hal_spi_bus_lock(device->bus);
-    api_hal_spi_config_device(device);
-}
-
-void api_hal_spi_unlock_device(const SPIDevice* device) {
-    api_hal_spi_bus_unlock(device->bus);
-}

+ 13 - 0
firmware/targets/f6/api-hal/api-hal-spi.h

@@ -25,6 +25,19 @@ void api_hal_spi_bus_lock(const ApiHalSpiBus* bus);
  */
 void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus);
 
+/**
+ * Configure SPI bus
+ * @param bus - spi bus handler
+ * @param config - spi configuration structure
+ */
+void api_hal_spi_bus_configure(const ApiHalSpiBus* bus, const SPI_InitTypeDef* config);
+
+/**
+ * Reset SPI bus
+ * @param bus - spi bus handler
+ */
+void api_hal_spi_bus_reset(const ApiHalSpiBus* bus);
+
 /** SPI Receive
  * @param bus - spi bus handler
  * @param buffer - receive buffer