diff --git a/applications/sd-filesystem/sd-filesystem.c b/applications/sd-filesystem/sd-filesystem.c index 0bb04aaa..b01aecf2 100644 --- a/applications/sd-filesystem/sd-filesystem.c +++ b/applications/sd-filesystem/sd-filesystem.c @@ -4,6 +4,7 @@ #include "menu/menu.h" #include "menu/menu_item.h" #include "cli/cli.h" +#include "api-hal-sd.h" FS_Api* fs_api_alloc() { FS_Api* fs_api = furi_alloc(sizeof(FS_Api)); @@ -316,6 +317,95 @@ void app_sd_format_callback(void* context) { view_port_enabled_set(sd_app->view_port, false); } +void app_sd_notify_wait_on() { + api_hal_light_set(LightRed, 0xFF); + api_hal_light_set(LightBlue, 0xFF); +} + +void app_sd_notify_wait_off() { + api_hal_light_set(LightRed, 0x00); + api_hal_light_set(LightBlue, 0x00); +} + +void app_sd_notify_success() { + for(uint8_t i = 0; i < 3; i++) { + delay(50); + api_hal_light_set(LightGreen, 0xFF); + delay(50); + api_hal_light_set(LightGreen, 0x00); + } +} + +void app_sd_notify_eject() { + for(uint8_t i = 0; i < 3; i++) { + delay(50); + api_hal_light_set(LightBlue, 0xFF); + delay(50); + api_hal_light_set(LightBlue, 0x00); + } +} + +void app_sd_notify_error() { + for(uint8_t i = 0; i < 3; i++) { + delay(50); + api_hal_light_set(LightRed, 0xFF); + delay(50); + api_hal_light_set(LightRed, 0x00); + } +} + +bool app_sd_mount_card(SdApp* sd_app) { + bool result = false; + const uint8_t max_init_counts = 10; + uint8_t counter = max_init_counts; + uint8_t bsp_result; + + _fs_lock(&sd_app->info); + + while(result == false && counter > 0 && hal_sd_detect()) { + app_sd_notify_wait_on(); + + if((counter % 10) == 0) { + // power reset sd card + bsp_result = BSP_SD_Init(true); + } else { + bsp_result = BSP_SD_Init(false); + } + + if(bsp_result) { + // bsp error + sd_app->info.status = SD_LOW_LEVEL_ERR; + } else { + sd_app->info.status = f_mount(&sd_app->info.fat_fs, sd_app->info.path, 1); + + if(sd_app->info.status == SD_OK || sd_app->info.status == SD_NO_FILESYSTEM) { + FATFS* fs; + uint32_t free_clusters; + + sd_app->info.status = f_getfree(sd_app->info.path, &free_clusters, &fs); + + if(sd_app->info.status == SD_OK || sd_app->info.status == SD_NO_FILESYSTEM) { + result = true; + } + } + } + app_sd_notify_wait_off(); + + if(!result) { + delay(1000); + printf( + "[sd_filesystem] init(%d), error: %s\r\n", + counter, + fs_error_get_internal_desc(sd_app->info.status)); + + counter--; + } + } + + _fs_unlock(&sd_app->info); + return result; +} + void app_sd_unmount_card(SdApp* sd_app) { _fs_lock(&sd_app->info); @@ -517,37 +607,44 @@ int32_t sd_filesystem(void* p) { // sd card cycle bool sd_was_present = true; + // init detect pins + hal_sd_detect_init(); + while(true) { if(sd_was_present) { - if(hal_gpio_read_sd_detect()) { + if(hal_sd_detect()) { printf("[sd_filesystem] card detected\r\n"); + app_sd_mount_card(sd_app); - uint8_t bsp_result = BSP_SD_Init(); - - if(bsp_result) { - sd_app->info.status = SD_LOW_LEVEL_ERR; - printf("[sd_filesystem] bsp error: %x\n", bsp_result); + if(sd_app->info.status != SD_OK) { + printf( + "[sd_filesystem] sd init error: %s\r\n", + fs_error_get_internal_desc(sd_app->info.status)); + app_sd_notify_error(); } else { - printf("[sd_filesystem] bsp ok\r\n"); - sd_app->info.status = f_mount(&sd_app->info.fat_fs, sd_app->info.path, 1); - - if(sd_app->info.status != SD_OK) { - printf("[sd_filesystem] mount error: %d\n", sd_app->info.status); - } else { - printf("[sd_filesystem] mount ok\r\n"); - } + printf("[sd_filesystem] sd init ok\r\n"); + app_sd_notify_success(); } view_port_enabled_set(sd_app->icon.view_port, true); sd_was_present = false; + + if(!hal_sd_detect()) { + printf("[sd_filesystem] card removed\r\n"); + + view_port_enabled_set(sd_app->icon.view_port, false); + app_sd_unmount_card(sd_app); + sd_was_present = true; + } } } else { - if(!hal_gpio_read_sd_detect()) { + if(!hal_sd_detect()) { printf("[sd_filesystem] card removed\r\n"); view_port_enabled_set(sd_app->icon.view_port, false); app_sd_unmount_card(sd_app); sd_was_present = true; + app_sd_notify_eject(); } } diff --git a/firmware/targets/api-hal-include/api-hal-power.h b/firmware/targets/api-hal-include/api-hal-power.h index 178270bc..8454a2c6 100644 --- a/firmware/targets/api-hal-include/api-hal-power.h +++ b/firmware/targets/api-hal-include/api-hal-power.h @@ -83,6 +83,16 @@ float api_hal_power_get_usb_voltage(); /* Get power system component state */ void api_hal_power_dump_state(string_t buffer); +/** + * @brief Enable 3.3v on external gpio and sd card + */ +void api_hal_power_enable_external_3_3v(); + +/** + * @brief Disable 3.3v on external gpio and sd card + */ +void api_hal_power_disable_external_3_3v(); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/api-hal-include/api-hal-sd.h b/firmware/targets/api-hal-include/api-hal-sd.h new file mode 100644 index 00000000..8d9f1374 --- /dev/null +++ b/firmware/targets/api-hal-include/api-hal-sd.h @@ -0,0 +1,30 @@ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Init SD card detect + * + */ +void hal_sd_detect_init(void); + +/** + * @brief Set SD card detect pin to low + * + */ +void hal_sd_detect_set_low(void); + +/** + * @brief Get SD card status + * + * @return true if SD card present + * @return false if SD card not present + */ +bool hal_sd_detect(void); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.c b/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.c index fbd5b3d6..6378bdbf 100644 --- a/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.c @@ -92,7 +92,9 @@ #include "string.h" #include "stdio.h" #include "spi.h" -#include "api-hal-spi.h" +#include +#include +#include /** @addtogroup BSP * @{ @@ -290,19 +292,33 @@ static uint8_t SD_ReadData(void); * - MSD_ERROR: Sequence failed * - MSD_OK: Sequence succeed */ -uint8_t BSP_SD_Init(void) { - /* Init to maximum slow speed */ - // TODO: SPI manager +uint8_t BSP_SD_Init(bool reset_card) { + /* Slow speed init */ + + /* TODO: SPI manager */ api_hal_spi_lock_device(&sd_slow_spi); + /* We must reset card in spi_lock context */ + if(reset_card) { + api_hal_power_disable_external_3_3v(); + delay(100); + api_hal_power_enable_external_3_3v(); + delay(100); + } + /* Configure IO functionalities for SD pin */ SD_IO_Init(); /* SD detection pin is not physically mapped on the Adafruit shield */ SdStatus = SD_PRESENT; - uint8_t res = SD_GoIdleState(); + uint8_t res = BSP_SD_ERROR; - // TODO: SPI manager + for(uint8_t i = 0; i < 128; i++) { + res = SD_GoIdleState(); + if(res == BSP_SD_OK) break; + } + + /* TODO: SPI manager */ api_hal_spi_unlock_device(&sd_slow_spi); /* SD initialized and set to SPI mode properly */ @@ -872,9 +888,10 @@ uint8_t SD_GetDataResponse(void) { */ uint8_t SD_GoIdleState(void) { SD_CmdAnswer_typedef response; - __IO uint8_t counter = 0; + __IO uint8_t counter; /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and wait for In Idle State Response (R1 Format) equal to 0x01 */ + counter = 0; do { counter++; response = SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95, SD_ANSWER_R1_EXPECTED); @@ -892,7 +909,9 @@ uint8_t SD_GoIdleState(void) { SD_IO_WriteByte(SD_DUMMY_BYTE); if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { /* initialise card V1 */ + counter = 0; do { + counter++; /* initialise card V1 */ /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); @@ -903,11 +922,16 @@ uint8_t SD_GoIdleState(void) { response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); flag_SDHC = 0; } else if(response.r1 == SD_R1_IN_IDLE_STATE) { /* initialise card V2 */ + counter = 0; do { + counter++; /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); @@ -917,10 +941,15 @@ uint8_t SD_GoIdleState(void) { response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { + counter = 0; do { + counter++; /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); @@ -933,6 +962,9 @@ uint8_t SD_GoIdleState(void) { SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); } diff --git a/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.h b/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.h index e2f754dd..63be4351 100644 --- a/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.h +++ b/firmware/targets/f4/Src/fatfs/stm32_adafruit_sd.h @@ -34,193 +34,185 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** - */ + */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32_ADAFRUIT_SD_H #define __STM32_ADAFRUIT_SD_H #ifdef __cplusplus - extern "C" { -#endif +extern "C" { +#endif /* Includes ------------------------------------------------------------------*/ #include +#include /** @addtogroup BSP * @{ - */ -#define __IO volatile - + */ +#define __IO volatile + /** @addtogroup STM32_ADAFRUIT * @{ */ - + /** @defgroup STM32_ADAFRUIT_SD * @{ - */ + */ /** @defgroup STM32_ADAFRUIT_SD_Exported_Types * @{ */ - + /** * @brief SD status structure definition - */ -enum { - BSP_SD_OK = 0x00, - MSD_OK = 0x00, - BSP_SD_ERROR = 0x01, - BSP_SD_TIMEOUT -}; - -typedef struct -{ - uint8_t Reserved1:2; /* Reserved */ - uint16_t DeviceSize:12; /* Device Size */ - uint8_t MaxRdCurrentVDDMin:3; /* Max. read current @ VDD min */ - uint8_t MaxRdCurrentVDDMax:3; /* Max. read current @ VDD max */ - uint8_t MaxWrCurrentVDDMin:3; /* Max. write current @ VDD min */ - uint8_t MaxWrCurrentVDDMax:3; /* Max. write current @ VDD max */ - uint8_t DeviceSizeMul:3; /* Device size multiplier */ + */ +enum { BSP_SD_OK = 0x00, MSD_OK = 0x00, BSP_SD_ERROR = 0x01, BSP_SD_TIMEOUT }; + +typedef struct { + uint8_t Reserved1 : 2; /* Reserved */ + uint16_t DeviceSize : 12; /* Device Size */ + uint8_t MaxRdCurrentVDDMin : 3; /* Max. read current @ VDD min */ + uint8_t MaxRdCurrentVDDMax : 3; /* Max. read current @ VDD max */ + uint8_t MaxWrCurrentVDDMin : 3; /* Max. write current @ VDD min */ + uint8_t MaxWrCurrentVDDMax : 3; /* Max. write current @ VDD max */ + uint8_t DeviceSizeMul : 3; /* Device size multiplier */ } struct_v1; - -typedef struct -{ - uint8_t Reserved1:6; /* Reserved */ - uint32_t DeviceSize:22; /* Device Size */ - uint8_t Reserved2:1; /* Reserved */ +typedef struct { + uint8_t Reserved1 : 6; /* Reserved */ + uint32_t DeviceSize : 22; /* Device Size */ + uint8_t Reserved2 : 1; /* Reserved */ } struct_v2; /** * @brief Card Specific Data: CSD Register - */ -typedef struct -{ - /* Header part */ - uint8_t CSDStruct:2; /* CSD structure */ - uint8_t Reserved1:6; /* Reserved */ - uint8_t TAAC:8; /* Data read access-time 1 */ - uint8_t NSAC:8; /* Data read access-time 2 in CLK cycles */ - uint8_t MaxBusClkFrec:8; /* Max. bus clock frequency */ - uint16_t CardComdClasses:12; /* Card command classes */ - uint8_t RdBlockLen:4; /* Max. read data block length */ - uint8_t PartBlockRead:1; /* Partial blocks for read allowed */ - uint8_t WrBlockMisalign:1; /* Write block misalignment */ - uint8_t RdBlockMisalign:1; /* Read block misalignment */ - uint8_t DSRImpl:1; /* DSR implemented */ - - /* v1 or v2 struct */ - union csd_version { - struct_v1 v1; - struct_v2 v2; - } version; - - uint8_t EraseSingleBlockEnable:1; /* Erase single block enable */ - uint8_t EraseSectorSize:7; /* Erase group size multiplier */ - uint8_t WrProtectGrSize:7; /* Write protect group size */ - uint8_t WrProtectGrEnable:1; /* Write protect group enable */ - uint8_t Reserved2:2; /* Reserved */ - uint8_t WrSpeedFact:3; /* Write speed factor */ - uint8_t MaxWrBlockLen:4; /* Max. write data block length */ - uint8_t WriteBlockPartial:1; /* Partial blocks for write allowed */ - uint8_t Reserved3:5; /* Reserved */ - uint8_t FileFormatGrouop:1; /* File format group */ - uint8_t CopyFlag:1; /* Copy flag (OTP) */ - uint8_t PermWrProtect:1; /* Permanent write protection */ - uint8_t TempWrProtect:1; /* Temporary write protection */ - uint8_t FileFormat:2; /* File Format */ - uint8_t Reserved4:2; /* Reserved */ - uint8_t crc:7; /* Reserved */ - uint8_t Reserved5:1; /* always 1*/ - + */ +typedef struct { + /* Header part */ + uint8_t CSDStruct : 2; /* CSD structure */ + uint8_t Reserved1 : 6; /* Reserved */ + uint8_t TAAC : 8; /* Data read access-time 1 */ + uint8_t NSAC : 8; /* Data read access-time 2 in CLK cycles */ + uint8_t MaxBusClkFrec : 8; /* Max. bus clock frequency */ + uint16_t CardComdClasses : 12; /* Card command classes */ + uint8_t RdBlockLen : 4; /* Max. read data block length */ + uint8_t PartBlockRead : 1; /* Partial blocks for read allowed */ + uint8_t WrBlockMisalign : 1; /* Write block misalignment */ + uint8_t RdBlockMisalign : 1; /* Read block misalignment */ + uint8_t DSRImpl : 1; /* DSR implemented */ + + /* v1 or v2 struct */ + union csd_version { + struct_v1 v1; + struct_v2 v2; + } version; + + uint8_t EraseSingleBlockEnable : 1; /* Erase single block enable */ + uint8_t EraseSectorSize : 7; /* Erase group size multiplier */ + uint8_t WrProtectGrSize : 7; /* Write protect group size */ + uint8_t WrProtectGrEnable : 1; /* Write protect group enable */ + uint8_t Reserved2 : 2; /* Reserved */ + uint8_t WrSpeedFact : 3; /* Write speed factor */ + uint8_t MaxWrBlockLen : 4; /* Max. write data block length */ + uint8_t WriteBlockPartial : 1; /* Partial blocks for write allowed */ + uint8_t Reserved3 : 5; /* Reserved */ + uint8_t FileFormatGrouop : 1; /* File format group */ + uint8_t CopyFlag : 1; /* Copy flag (OTP) */ + uint8_t PermWrProtect : 1; /* Permanent write protection */ + uint8_t TempWrProtect : 1; /* Temporary write protection */ + uint8_t FileFormat : 2; /* File Format */ + uint8_t Reserved4 : 2; /* Reserved */ + uint8_t crc : 7; /* Reserved */ + uint8_t Reserved5 : 1; /* always 1*/ + } SD_CSD; /** * @brief Card Identification Data: CID Register */ -typedef struct -{ - __IO uint8_t ManufacturerID; /* ManufacturerID */ - __IO uint16_t OEM_AppliID; /* OEM/Application ID */ - __IO uint32_t ProdName1; /* Product Name part1 */ - __IO uint8_t ProdName2; /* Product Name part2*/ - __IO uint8_t ProdRev; /* Product Revision */ - __IO uint32_t ProdSN; /* Product Serial Number */ - __IO uint8_t Reserved1; /* Reserved1 */ - __IO uint16_t ManufactDate; /* Manufacturing Date */ - __IO uint8_t CID_CRC; /* CID CRC */ - __IO uint8_t Reserved2; /* always 1 */ +typedef struct { + __IO uint8_t ManufacturerID; /* ManufacturerID */ + __IO uint16_t OEM_AppliID; /* OEM/Application ID */ + __IO uint32_t ProdName1; /* Product Name part1 */ + __IO uint8_t ProdName2; /* Product Name part2*/ + __IO uint8_t ProdRev; /* Product Revision */ + __IO uint32_t ProdSN; /* Product Serial Number */ + __IO uint8_t Reserved1; /* Reserved1 */ + __IO uint16_t ManufactDate; /* Manufacturing Date */ + __IO uint8_t CID_CRC; /* CID CRC */ + __IO uint8_t Reserved2; /* always 1 */ } SD_CID; /** * @brief SD Card information */ -typedef struct -{ - SD_CSD Csd; - SD_CID Cid; - uint64_t CardCapacity; /*!< Card Capacity */ - uint32_t CardBlockSize; /*!< Card Block Size */ - uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ - uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ +typedef struct { + SD_CSD Csd; + SD_CID Cid; + uint64_t CardCapacity; /*!< Card Capacity */ + uint32_t CardBlockSize; /*!< Card Block Size */ + uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ + uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ } SD_CardInfo; /** * @} */ - + /** @defgroup STM32_ADAFRUIT_SPI_SD_Exported_Constants * @{ - */ - + */ + /** * @brief Block Size */ -#define SD_BLOCK_SIZE 0x200 +#define SD_BLOCK_SIZE 0x200 /** * @brief SD detection on its memory slot */ -#define SD_PRESENT ((uint8_t)0x01) -#define SD_NOT_PRESENT ((uint8_t)0x00) +#define SD_PRESENT ((uint8_t)0x01) +#define SD_NOT_PRESENT ((uint8_t)0x00) -#define SD_DATATIMEOUT ((uint32_t)100000000) +#define SD_DATATIMEOUT ((uint32_t)100000000) /** * @brief SD Card information structure - */ + */ #define BSP_SD_CardInfo SD_CardInfo /** * @} */ - + /** @defgroup STM32_ADAFRUIT_SD_Exported_Macro * @{ - */ + */ /** * @} - */ + */ /** @defgroup STM32_ADAFRUIT_SD_Exported_Functions * @{ - */ -uint8_t BSP_SD_Init(void); -uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); -uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); + */ +uint8_t BSP_SD_Init(bool reset_card); +uint8_t +BSP_SD_ReadBlocks(uint32_t* pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); +uint8_t +BSP_SD_WriteBlocks(uint32_t* pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr); uint8_t BSP_SD_GetCardState(void); -uint8_t BSP_SD_GetCardInfo(SD_CardInfo *pCardInfo); - +uint8_t BSP_SD_GetCardInfo(SD_CardInfo* pCardInfo); + /* Link functions for SD Card peripheral*/ -void SD_SPI_Slow_Init(void); -void SD_SPI_Fast_Init(void); -void SD_IO_Init(void); -void SD_IO_CSState(uint8_t state); -void SD_IO_WriteReadData(const uint8_t *DataIn, uint8_t *DataOut, uint16_t DataLength); +void SD_SPI_Slow_Init(void); +void SD_SPI_Fast_Init(void); +void SD_IO_Init(void); +void SD_IO_CSState(uint8_t state); +void SD_IO_WriteReadData(const uint8_t* DataIn, uint8_t* DataOut, uint16_t DataLength); uint8_t SD_IO_WriteByte(uint8_t Data); /* Link function for HAL delay */ @@ -234,18 +226,18 @@ void HAL_Delay(__IO uint32_t Delay); /** * @} - */ + */ /** * @} - */ + */ /** * @} - */ + */ /** * @} - */ + */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f4/api-hal/api-hal-gpio.c b/firmware/targets/f4/api-hal/api-hal-gpio.c index 3dd06d30..b36e8a62 100644 --- a/firmware/targets/f4/api-hal/api-hal-gpio.c +++ b/firmware/targets/f4/api-hal/api-hal-gpio.c @@ -1,7 +1,4 @@ #include -#include -#include -#include // init GPIO void hal_gpio_init( @@ -20,33 +17,6 @@ void hal_gpio_init( HAL_GPIO_Init(gpio->port, &GPIO_InitStruct); } -bool hal_gpio_read_sd_detect(void) { - bool result = false; - - // TODO open record - const GpioPin* sd_cs_record = &sd_cs_gpio; - - // TODO: SPI manager - api_hal_spi_lock(sd_fast_spi.spi); - - // configure pin as input - gpio_init_ex(sd_cs_record, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); - delay(1); - - // if gpio_read == 0 return true else return false - result = !gpio_read(sd_cs_record); - - // configure pin back - gpio_init_ex(sd_cs_record, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - gpio_write(sd_cs_record, 1); - delay(1); - - // TODO: SPI manager - api_hal_spi_unlock(sd_fast_spi.spi); - - return result; -} - void enable_cc1101_irq() { HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0); HAL_NVIC_EnableIRQ(EXTI4_IRQn); diff --git a/firmware/targets/f4/api-hal/api-hal-gpio.h b/firmware/targets/f4/api-hal/api-hal-gpio.h index 60d3eb0f..af3c8735 100644 --- a/firmware/targets/f4/api-hal/api-hal-gpio.h +++ b/firmware/targets/f4/api-hal/api-hal-gpio.h @@ -68,8 +68,6 @@ static inline bool hal_gpio_read(const GpioPin* gpio) { } } -bool hal_gpio_read_sd_detect(void); - void enable_cc1101_irq(); #ifdef __cplusplus diff --git a/firmware/targets/f4/api-hal/api-hal-power.c b/firmware/targets/f4/api-hal/api-hal-power.c index 39f6903b..d0060d55 100644 --- a/firmware/targets/f4/api-hal/api-hal-power.c +++ b/firmware/targets/f4/api-hal/api-hal-power.c @@ -195,3 +195,11 @@ void api_hal_power_dump_state(string_t buffer) { bq25896_get_ntc_mpct() ); } + +void api_hal_power_enable_external_3_3v(){ + // nothing to do +} + +void api_hal_power_disable_external_3_3v(){ + // nothing to do +} \ No newline at end of file diff --git a/firmware/targets/f4/api-hal/api-hal-sd.c b/firmware/targets/f4/api-hal/api-hal-sd.c new file mode 100644 index 00000000..7e1e2ebe --- /dev/null +++ b/firmware/targets/f4/api-hal/api-hal-sd.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +void hal_sd_detect_init(void) { + // nothing to do +} + +void hal_sd_detect_set_low(void) { + // nothing to do +} + +bool hal_sd_detect(void) { + bool result = false; + + // TODO open record + const GpioPin* sd_cs_record = &sd_cs_gpio; + + // TODO: SPI manager + api_hal_spi_lock(sd_fast_spi.spi); + + // configure pin as input + gpio_init_ex(sd_cs_record, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); + delay(1); + + // if gpio_read == 0 return true else return false + result = !gpio_read(sd_cs_record); + + // configure pin back + gpio_init_ex(sd_cs_record, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); + gpio_write(sd_cs_record, 1); + delay(1); + + // TODO: SPI manager + api_hal_spi_unlock(sd_fast_spi.spi); + + return result; +} \ No newline at end of file diff --git a/firmware/targets/f5/Inc/spi.h b/firmware/targets/f5/Inc/spi.h index 755c9cfe..23beca24 100644 --- a/firmware/targets/f5/Inc/spi.h +++ b/firmware/targets/f5/Inc/spi.h @@ -46,6 +46,8 @@ void NFC_SPI_Reconfigure(); void SD_SPI_Reconfigure_Slow(); void SD_SPI_Reconfigure_Fast(); void CC1101_SPI_Reconfigure(); +void SD_SPI_Bus_To_Down_State(); +void SD_SPI_Bus_To_Normal_State(); /* USER CODE END Prototypes */ #ifdef __cplusplus diff --git a/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.c b/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.c index fbd5b3d6..21b3e9b3 100644 --- a/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.c +++ b/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.c @@ -92,7 +92,10 @@ #include "string.h" #include "stdio.h" #include "spi.h" -#include "api-hal-spi.h" +#include +#include +#include +#include /** @addtogroup BSP * @{ @@ -290,19 +293,40 @@ static uint8_t SD_ReadData(void); * - MSD_ERROR: Sequence failed * - MSD_OK: Sequence succeed */ -uint8_t BSP_SD_Init(void) { - /* Init to maximum slow speed */ - // TODO: SPI manager +uint8_t BSP_SD_Init(bool reset_card) { + /* Slow speed init */ + + /* TODO: SPI manager */ api_hal_spi_lock_device(&sd_slow_spi); + /* We must reset card in spi_lock context */ + if(reset_card) { + /* disable power and set low on all bus pins */ + api_hal_power_disable_external_3_3v(); + SD_SPI_Bus_To_Down_State(); + hal_sd_detect_set_low(); + delay(250); + + /* reinit bus and enable power */ + SD_SPI_Bus_To_Normal_State(); + hal_sd_detect_init(); + api_hal_power_enable_external_3_3v(); + delay(100); + } + /* Configure IO functionalities for SD pin */ SD_IO_Init(); /* SD detection pin is not physically mapped on the Adafruit shield */ SdStatus = SD_PRESENT; - uint8_t res = SD_GoIdleState(); + uint8_t res = BSP_SD_ERROR; - // TODO: SPI manager + for(uint8_t i = 0; i < 128; i++) { + res = SD_GoIdleState(); + if(res == BSP_SD_OK) break; + } + + /* TODO: SPI manager */ api_hal_spi_unlock_device(&sd_slow_spi); /* SD initialized and set to SPI mode properly */ @@ -872,9 +896,10 @@ uint8_t SD_GetDataResponse(void) { */ uint8_t SD_GoIdleState(void) { SD_CmdAnswer_typedef response; - __IO uint8_t counter = 0; + __IO uint8_t counter; /* Send CMD0 (SD_CMD_GO_IDLE_STATE) to put SD in SPI mode and wait for In Idle State Response (R1 Format) equal to 0x01 */ + counter = 0; do { counter++; response = SD_SendCmd(SD_CMD_GO_IDLE_STATE, 0, 0x95, SD_ANSWER_R1_EXPECTED); @@ -892,7 +917,9 @@ uint8_t SD_GoIdleState(void) { SD_IO_WriteByte(SD_DUMMY_BYTE); if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { /* initialise card V1 */ + counter = 0; do { + counter++; /* initialise card V1 */ /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); @@ -903,11 +930,16 @@ uint8_t SD_GoIdleState(void) { response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); flag_SDHC = 0; } else if(response.r1 == SD_R1_IN_IDLE_STATE) { /* initialise card V2 */ + counter = 0; do { + counter++; /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); @@ -917,10 +949,15 @@ uint8_t SD_GoIdleState(void) { response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND) { + counter = 0; do { + counter++; /* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */ response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); @@ -933,6 +970,9 @@ uint8_t SD_GoIdleState(void) { SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED); SD_IO_CSState(1); SD_IO_WriteByte(SD_DUMMY_BYTE); + if(counter >= SD_MAX_TRY) { + return BSP_SD_ERROR; + } } while(response.r1 == SD_R1_IN_IDLE_STATE); } diff --git a/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.h b/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.h index e2f754dd..38f9da49 100644 --- a/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.h +++ b/firmware/targets/f5/Src/fatfs/stm32_adafruit_sd.h @@ -46,6 +46,7 @@ /* Includes ------------------------------------------------------------------*/ #include +#include /** @addtogroup BSP * @{ @@ -208,7 +209,7 @@ typedef struct /** @defgroup STM32_ADAFRUIT_SD_Exported_Functions * @{ */ -uint8_t BSP_SD_Init(void); +uint8_t BSP_SD_Init(bool reset_card); uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr); diff --git a/firmware/targets/f5/Src/gpio.c b/firmware/targets/f5/Src/gpio.c index f1d32952..d682b18b 100644 --- a/firmware/targets/f5/Src/gpio.c +++ b/firmware/targets/f5/Src/gpio.c @@ -163,10 +163,9 @@ void MX_GPIO_Init(void) /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = SD_CS_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF6_LSCO; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(SD_CS_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : PtPin */ diff --git a/firmware/targets/f5/Src/spi.c b/firmware/targets/f5/Src/spi.c index 8fe11eaa..29c6da7a 100644 --- a/firmware/targets/f5/Src/spi.c +++ b/firmware/targets/f5/Src/spi.c @@ -339,6 +339,36 @@ void Enable_SPI(SPI_HandleTypeDef* spi_instance){ __HAL_SPI_ENABLE(spi_instance); } } + +void SD_SPI_Bus_To_Down_State(){ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = SPI_D_MOSI_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(SPI_D_MOSI_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = SPI_D_SCK_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(SPI_D_SCK_GPIO_Port, &GPIO_InitStruct); + + HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET); + HAL_GPIO_WritePin(SPI_D_MOSI_GPIO_Port, SPI_D_MOSI_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(SPI_D_SCK_GPIO_Port, SPI_D_SCK_Pin, GPIO_PIN_RESET); +} + +void SD_SPI_Bus_To_Normal_State(){ + HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_SET); + HAL_SPI_MspInit(&SPI_SD_HANDLE); +} /* USER CODE END 1 */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f5/api-hal/api-hal-gpio.c b/firmware/targets/f5/api-hal/api-hal-gpio.c index 3dd06d30..30c439ea 100644 --- a/firmware/targets/f5/api-hal/api-hal-gpio.c +++ b/firmware/targets/f5/api-hal/api-hal-gpio.c @@ -20,33 +20,6 @@ void hal_gpio_init( HAL_GPIO_Init(gpio->port, &GPIO_InitStruct); } -bool hal_gpio_read_sd_detect(void) { - bool result = false; - - // TODO open record - const GpioPin* sd_cs_record = &sd_cs_gpio; - - // TODO: SPI manager - api_hal_spi_lock(sd_fast_spi.spi); - - // configure pin as input - gpio_init_ex(sd_cs_record, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh); - delay(1); - - // if gpio_read == 0 return true else return false - result = !gpio_read(sd_cs_record); - - // configure pin back - gpio_init_ex(sd_cs_record, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh); - gpio_write(sd_cs_record, 1); - delay(1); - - // TODO: SPI manager - api_hal_spi_unlock(sd_fast_spi.spi); - - return result; -} - void enable_cc1101_irq() { HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0); HAL_NVIC_EnableIRQ(EXTI4_IRQn); diff --git a/firmware/targets/f5/api-hal/api-hal-gpio.h b/firmware/targets/f5/api-hal/api-hal-gpio.h index 60d3eb0f..af3c8735 100644 --- a/firmware/targets/f5/api-hal/api-hal-gpio.h +++ b/firmware/targets/f5/api-hal/api-hal-gpio.h @@ -68,8 +68,6 @@ static inline bool hal_gpio_read(const GpioPin* gpio) { } } -bool hal_gpio_read_sd_detect(void); - void enable_cc1101_irq(); #ifdef __cplusplus diff --git a/firmware/targets/f5/api-hal/api-hal-power.c b/firmware/targets/f5/api-hal/api-hal-power.c index 39f6903b..bbf66f64 100644 --- a/firmware/targets/f5/api-hal/api-hal-power.c +++ b/firmware/targets/f5/api-hal/api-hal-power.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -195,3 +196,11 @@ void api_hal_power_dump_state(string_t buffer) { bq25896_get_ntc_mpct() ); } + +void api_hal_power_enable_external_3_3v(){ + LL_GPIO_SetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin); +} + +void api_hal_power_disable_external_3_3v(){ + LL_GPIO_ResetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin); +} \ No newline at end of file diff --git a/firmware/targets/f5/api-hal/api-hal-resources.c b/firmware/targets/f5/api-hal/api-hal-resources.c index 7fd548a9..1ee91516 100644 --- a/firmware/targets/f5/api-hal/api-hal-resources.c +++ b/firmware/targets/f5/api-hal/api-hal-resources.c @@ -25,7 +25,6 @@ const InputPin input_pins[] = { const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); -const GpioPin sd_cs_gpio = {SD_CS_GPIO_Port, SD_CS_Pin}; const GpioPin vibro_gpio = {VIBRO_GPIO_Port, VIBRO_Pin}; const GpioPin ibutton_gpio = {iBTN_GPIO_Port, iBTN_Pin}; const GpioPin cc1101_g0_gpio = {CC1101_G0_GPIO_Port, CC1101_G0_Pin}; diff --git a/firmware/targets/f5/api-hal/api-hal-resources.h b/firmware/targets/f5/api-hal/api-hal-resources.h index d7a1493a..b205efb5 100644 --- a/firmware/targets/f5/api-hal/api-hal-resources.h +++ b/firmware/targets/f5/api-hal/api-hal-resources.h @@ -53,7 +53,6 @@ typedef struct { extern const InputPin input_pins[]; extern const size_t input_pins_count; -extern const GpioPin sd_cs_gpio; extern const GpioPin vibro_gpio; extern const GpioPin ibutton_gpio; extern const GpioPin cc1101_g0_gpio; diff --git a/firmware/targets/f5/api-hal/api-hal-sd.c b/firmware/targets/f5/api-hal/api-hal-sd.c new file mode 100644 index 00000000..14aafd4b --- /dev/null +++ b/firmware/targets/f5/api-hal/api-hal-sd.c @@ -0,0 +1,22 @@ +#include "api-hal-sd.h" +#include +#include + +void hal_sd_detect_init(void) { + // low speed input with pullup + LL_GPIO_SetPinMode(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_MODE_INPUT); + LL_GPIO_SetPinSpeed(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_SPEED_FREQ_LOW); + LL_GPIO_SetPinPull(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_PULL_UP); +} + +void hal_sd_detect_set_low(void) { + // low speed input with pullup + LL_GPIO_SetPinMode(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_MODE_OUTPUT); + LL_GPIO_SetPinOutputType(SD_CD_GPIO_Port, SD_CD_Pin, LL_GPIO_OUTPUT_OPENDRAIN); + LL_GPIO_ResetOutputPin(SD_CD_GPIO_Port, SD_CD_Pin); +} + +bool hal_sd_detect(void) { + bool result = !(LL_GPIO_IsInputPinSet(SD_CD_GPIO_Port, SD_CD_Pin)); + return result; +} \ No newline at end of file