From 879fdf35535f7b6f2af28720ed9b8c0bd4f7df3d Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Sat, 29 Jul 2023 13:14:33 +0400 Subject: [PATCH] SD card info in the service menu --- FdsKey/Core/Inc/sdcard.h | 24 ++- FdsKey/Core/Inc/servicemenu.h | 12 +- FdsKey/Core/Src/sdcard.c | 234 +++++++++++++++++----------- FdsKey/Core/Src/servicemenu.c | 100 +++++++++++- FdsKey_bootloader/Core/Inc/sdcard.h | 24 ++- FdsKey_bootloader/Core/Src/sdcard.c | 234 +++++++++++++++++----------- 6 files changed, 444 insertions(+), 184 deletions(-) diff --git a/FdsKey/Core/Inc/sdcard.h b/FdsKey/Core/Inc/sdcard.h index f8046e9..b05088e 100644 --- a/FdsKey/Core/Inc/sdcard.h +++ b/FdsKey/Core/Inc/sdcard.h @@ -75,12 +75,27 @@ typedef struct { } SD_CSD; +typedef struct { + uint8_t ManufacturerID; /* ManufacturerID */ + char OEM_AppliID[3]; /* OEM/Application ID */ + char ProdName[6]; /* Product Name */ + uint8_t ProdRev; /* Product Revision */ + uint32_t ProdSN; /* Product Serial Number */ + uint8_t Reserved1; /* Reserved1 */ + uint8_t ManufactYear; /* Manufacturing Year */ + uint8_t ManufactMonth; /* Manufacturing Month */ + uint8_t CID_CRC; /* CID CRC */ + uint8_t Reserved2; /* always 1 */ +} SD_CID; + extern SPI_HandleTypeDef SD_SPI_PORT; +// Initialization HAL_StatusTypeDef SD_init(); HAL_StatusTypeDef SD_init_try_speed(); -HAL_StatusTypeDef SD_read_csd(SD_CSD* csd); -uint64_t SD_get_capacity(); +uint32_t SD_get_spi_speed(); + +// Read/write single blocks HAL_StatusTypeDef SD_read_single_block(uint32_t blockNum, uint8_t* buff); // sizeof(buff) == 512! HAL_StatusTypeDef SD_write_single_block(uint32_t blockNum, const uint8_t* buff); // sizeof(buff) == 512! @@ -94,6 +109,11 @@ HAL_StatusTypeDef SD_write_begin(uint32_t blockNum); HAL_StatusTypeDef SD_write_data(const uint8_t* buff); // sizeof(buff) == 512! HAL_StatusTypeDef SD_write_end(); +// SD card info +HAL_StatusTypeDef SD_read_csd(SD_CSD* csd); +HAL_StatusTypeDef SD_read_cid(SD_CID* cid); +uint64_t SD_read_capacity(); + // TODO: read lock flag? CMD13, SEND_STATUS #endif // __SDCARD_H__ diff --git a/FdsKey/Core/Inc/servicemenu.h b/FdsKey/Core/Inc/servicemenu.h index 8a07182..b44b341 100644 --- a/FdsKey/Core/Inc/servicemenu.h +++ b/FdsKey/Core/Inc/servicemenu.h @@ -9,7 +9,8 @@ #define SERVICE_SETTINGS_FLASH_OFFSET (0x08080000 - FLASH_PAGE_SIZE * 3) #define HARDWARE_VERSION_FLASH_OFFSET (0x08080000 - FLASH_PAGE_SIZE * 4) -#define SERVICE_SETTINGS_ITEM_COUNT 7 + +#define SERVICE_SETTINGS_ITEM_COUNT 16 typedef enum { @@ -19,6 +20,15 @@ typedef enum SERVICE_SETTING_BUILD_DATE, SERVICE_SETTING_BUILD_TIME, SERVICE_SETTING_BL_COMMIT, + SERVICE_SETTING_SD_SPI_SPEED, + SERVICE_SETTING_SD_CAPACITY, + SERVICE_SETTING_SD_MANUFACTURER_ID, + SERVICE_SETTING_SD_OEM_ID, + SERVICE_SETTING_SD_PROD_NAME, + SERVICE_SETTING_SD_PROD_REV, + SERVICE_SETTING_SD_PROD_SN, + SERVICE_SETTING_SD_PROD_MANUFACT_YEAR, + SERVICE_SETTING_SD_PROD_MANUFACT_MONTH, SERVICE_SETTING_BL_UPDATE } SERVICE_SETTING_ID; diff --git a/FdsKey/Core/Src/sdcard.c b/FdsKey/Core/Src/sdcard.c index 1b9c57d..5516c7c 100644 --- a/FdsKey/Core/Src/sdcard.c +++ b/FdsKey/Core/Src/sdcard.c @@ -1,6 +1,8 @@ #include "sdcard.h" +#include "string.h" static uint8_t sd_high_capacity; +static uint32_t sd_spi_speed; static void SPI_transmit_receive(uint8_t* tx, uint8_t* rx, size_t buff_size) { @@ -331,114 +333,32 @@ HAL_StatusTypeDef SD_init_try_speed() HAL_StatusTypeDef r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + sd_spi_speed = SPI_BAUDRATEPRESCALER_2; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; + sd_spi_speed = SPI_BAUDRATEPRESCALER_4; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + sd_spi_speed = SPI_BAUDRATEPRESCALER_8; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; + sd_spi_speed = SPI_BAUDRATEPRESCALER_16; HAL_SPI_Init(&SD_SPI_PORT); return SD_init_tries(); } -HAL_StatusTypeDef SD_read_csd(SD_CSD* csd) +uint32_t SD_get_spi_speed() { - HAL_StatusTypeDef r; - uint8_t r1; - uint8_t csd_data[16]; - - // CMD9 - read CSD register and SD card capacity - SD_send_cmd(9, 0x00000000, 0xFF); - r = SD_read_r1(&r1); - if (r != HAL_OK) - return r; - if (r1 != 0x00) - return HAL_ERROR; - r = SD_wait_data_token(); - if (r != HAL_OK) - return r; - SD_read_bytes(csd_data, sizeof(csd_data)); - - SD_unselect_purge(); - - csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; - csd->Reserved1 = csd_data[0] & 0x3F; - csd->TAAC = csd_data[1]; - csd->NSAC = csd_data[2]; - csd->MaxBusClkFrec = csd_data[3]; - csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); - csd->RdBlockLen = csd_data[5] & 0x0F; - csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; - csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; - csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; - csd->DSRImpl = (csd_data[6] & 0x10) >> 4; - switch (csd->CSDStruct) { - case 0: - // CSD version 1 - csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); - csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | - ((csd_data[8] & 0xC0) >> 6); - csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; - csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); - csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; - csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; - csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | - ((csd_data[10] & 0x80) >> 7); - break; - case 1: - // CSD version 2 - csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | - ((csd_data[7] & 0xC0) >> 6); - csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | - csd_data[9]; - csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); - break; - default: - return HAL_ERROR; - } - csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; - csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); - csd->WrProtectGrSize = (csd_data[11] & 0x7F); - csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; - csd->Reserved2 = (csd_data[12] & 0x60) >> 5; - csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; - csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); - csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; - csd->Reserved3 = (csd_data[13] & 0x1F); - csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; - csd->CopyFlag = (csd_data[14] & 0x40) >> 6; - csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; - csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; - csd->FileFormat = (csd_data[14] & 0x0C) >> 2; - csd->Reserved4 = (csd_data[14] & 0x03); - csd->crc = (csd_data[15] & 0xFE) >> 1; - csd->Reserved5 = (csd_data[15] & 0x01); - - return HAL_OK; -} - -uint64_t SD_get_capacity() -{ - SD_CSD csd; - HAL_StatusTypeDef r; - r = SD_read_csd(&csd); - if (r == HAL_OK) - { - if (sd_high_capacity) - return (csd.version.v2.DeviceSize + 1) * SD_BLOCK_LENGTH * 1024; - else - return (csd.version.v1.DeviceSize + 1) * (1UL << (csd.version.v1.DeviceSizeMul + 2)) * (1UL << csd.RdBlockLen); - } - return 0; + return sd_spi_speed; } HAL_StatusTypeDef SD_read_single_block(uint32_t blockNum, uint8_t *buff) @@ -656,3 +576,141 @@ HAL_StatusTypeDef SD_write_end() SD_unselect_purge(); return HAL_OK; } + + +HAL_StatusTypeDef SD_read_csd(SD_CSD* csd) +{ + HAL_StatusTypeDef r; + uint8_t r1; + uint8_t csd_data[16]; + uint8_t crc[2]; + + // CMD9 - read CSD register and SD card capacity + SD_send_cmd(9, 0x00000000, 0xFF); + r = SD_read_r1(&r1); + if (r != HAL_OK) + return r; + if (r1 != 0x00) + return HAL_ERROR; + r = SD_wait_data_token(); + if (r != HAL_OK) + return r; + SD_read_bytes(csd_data, sizeof(csd_data)); + SD_read_bytes(crc, sizeof(crc)); + + SD_unselect_purge(); + + csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; + csd->Reserved1 = csd_data[0] & 0x3F; + csd->TAAC = csd_data[1]; + csd->NSAC = csd_data[2]; + csd->MaxBusClkFrec = csd_data[3]; + csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); + csd->RdBlockLen = csd_data[5] & 0x0F; + csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; + csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; + csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; + csd->DSRImpl = (csd_data[6] & 0x10) >> 4; + switch (csd->CSDStruct) { + case 0: + // CSD version 1 + csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); + csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | + ((csd_data[8] & 0xC0) >> 6); + csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; + csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); + csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; + csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; + csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | + ((csd_data[10] & 0x80) >> 7); + break; + case 1: + // CSD version 2 + csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | + ((csd_data[7] & 0xC0) >> 6); + csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | + csd_data[9]; + csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); + break; + default: + return HAL_ERROR; + } + csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; + csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); + csd->WrProtectGrSize = (csd_data[11] & 0x7F); + csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; + csd->Reserved2 = (csd_data[12] & 0x60) >> 5; + csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; + csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); + csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; + csd->Reserved3 = (csd_data[13] & 0x1F); + csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; + csd->CopyFlag = (csd_data[14] & 0x40) >> 6; + csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; + csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; + csd->FileFormat = (csd_data[14] & 0x0C) >> 2; + csd->Reserved4 = (csd_data[14] & 0x03); + csd->crc = (csd_data[15] & 0xFE) >> 1; + csd->Reserved5 = (csd_data[15] & 0x01); + + return HAL_OK; +} + +HAL_StatusTypeDef SD_read_cid(SD_CID* cid) +{ + HAL_StatusTypeDef r; + uint8_t r1; + uint8_t cid_data[16]; + uint8_t crc[2]; + + // CMD9 - read CSD register and SD card capacity + SD_send_cmd(10, 0x00000000, 0xFF); + r = SD_read_r1(&r1); + if (r != HAL_OK) + return r; + if (r1 != 0x00) + return HAL_ERROR; + r = SD_wait_data_token(); + if (r != HAL_OK) + return r; + SD_read_bytes(cid_data, sizeof(cid_data)); + SD_read_bytes(crc, sizeof(crc)); + + SD_unselect_purge(); + + cid->ManufacturerID = cid_data[0]; + memcpy(cid->OEM_AppliID, cid_data + 1, 2); + cid->OEM_AppliID[2] = 0; + memcpy(cid->ProdName, cid_data + 3, 5); + cid->ProdName[5] = 0; + cid->ProdRev = cid_data[8]; + cid->ProdSN = cid_data[9] << 24; + cid->ProdSN |= cid_data[10] << 16; + cid->ProdSN |= cid_data[11] << 8; + cid->ProdSN |= cid_data[12]; + cid->Reserved1 = (cid_data[13] & 0xF0) >> 4; + cid->ManufactYear = (cid_data[13] & 0x0F) << 4; + cid->ManufactYear |= (cid_data[14] & 0xF0) >> 4; + cid->ManufactMonth = (cid_data[14] & 0x0F); + cid->CID_CRC = (cid_data[15] & 0xFE) >> 1; + cid->Reserved2 = 1; + + return HAL_OK; +} + +uint64_t SD_read_capacity() +{ + SD_CSD csd; + HAL_StatusTypeDef r; + r = SD_read_csd(&csd); + if (r == HAL_OK) + { + if (sd_high_capacity) + return (uint64_t)(csd.version.v2.DeviceSize + 1) * SD_BLOCK_LENGTH * 1024; + else + return (uint64_t)(csd.version.v1.DeviceSize + 1) * (1UL << (csd.version.v1.DeviceSizeMul + 2)) * (1UL << csd.RdBlockLen); + } + return 0; +} + + diff --git a/FdsKey/Core/Src/servicemenu.c b/FdsKey/Core/Src/servicemenu.c index 2f6259b..686eced 100644 --- a/FdsKey/Core/Src/servicemenu.c +++ b/FdsKey/Core/Src/servicemenu.c @@ -7,10 +7,12 @@ #include "buttons.h" #include "commit.h" #include "splash.h" +#include "sdcard.h" #include "blupdater.h" FDSKEY_SERVICE_SETTINGS fdskey_service_settings; FDSKEY_HARDWARE_VERSION fdskey_hw_version; +//static SD_CID cid; void service_settings_load() { @@ -58,16 +60,46 @@ HAL_StatusTypeDef service_settings_save() return HAL_FLASH_Lock(); } +static void uint64_to_str(uint64_t d, char* str) +{ + int len = 0; + uint64_t tmp; + for (tmp = d; tmp; tmp /= 10) + { + len++; + } + if (!len) len++; + str[len] = 0; + for (; d; d/= 10, len--) + { + str[len - 1] = '0' + (d % 10); + } +} + static void draw_item(uint8_t line, SETTING_ID item, uint8_t is_selected) { char *parameter_name; char value_v[32] = ""; char *value = value_v; -// char* off = "\x86"; -// char* on = "\x87"; int l; + SD_CID cid; + + switch((int)item) + { + case SERVICE_SETTING_SD_MANUFACTURER_ID: + case SERVICE_SETTING_SD_OEM_ID: + case SERVICE_SETTING_SD_PROD_NAME: + case SERVICE_SETTING_SD_PROD_REV: + case SERVICE_SETTING_SD_PROD_SN: + case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR: + case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH: + memset(&cid, 0, sizeof(cid)); + SD_read_cid(&cid); + default: + break; + } - switch (item) + switch ((int)item) { case SERVICE_SETTING_OLED_CONTROLLER: parameter_name = "OLED controller"; @@ -100,6 +132,59 @@ static void draw_item(uint8_t line, SETTING_ID item, uint8_t is_selected) parameter_name = "BL commit"; value = fdskey_hw_version.bootloader_commit; break; + case SERVICE_SETTING_SD_SPI_SPEED: + parameter_name = "SD SPI speed"; + switch (SD_get_spi_speed()) + { + case SPI_BAUDRATEPRESCALER_2: + value = "/2"; + break; + case SPI_BAUDRATEPRESCALER_4: + value = "/4"; + break; + case SPI_BAUDRATEPRESCALER_8: + value = "/8"; + break; + case SPI_BAUDRATEPRESCALER_16: + value = "/16"; + break; + default: + value = "unknown"; + break; + } + break; + case SERVICE_SETTING_SD_CAPACITY: + parameter_name = "SD capacity"; + uint64_to_str(SD_read_capacity(), value_v); + break; + case SERVICE_SETTING_SD_MANUFACTURER_ID: + parameter_name = "SD manufacturer ID"; + sprintf(value_v, "%02X", cid.ManufacturerID); + break; + case SERVICE_SETTING_SD_OEM_ID: + parameter_name = "SD OEM ID"; + value = cid.OEM_AppliID; + break; + case SERVICE_SETTING_SD_PROD_NAME: + parameter_name = "SD product name"; + value = cid.ProdName; + break; + case SERVICE_SETTING_SD_PROD_REV: + parameter_name = "SD product rev."; + sprintf(value_v, "%d", cid.ProdRev); + break; + case SERVICE_SETTING_SD_PROD_SN: + parameter_name = "SD product s/n"; + sprintf(value_v, "%08X", (unsigned int)cid.ProdSN); + break; + case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR: + parameter_name = "SD manufacturing year"; + sprintf(value_v, "%d", cid.ManufactYear); + break; + case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH: + parameter_name = "SD manufacturing month"; + sprintf(value_v, "%d", cid.ManufactMonth); + break; case SERVICE_SETTING_BL_UPDATE: parameter_name = "[ Update bootloader ]"; break; @@ -169,6 +254,15 @@ void service_menu() case SERVICE_SETTING_BUILD_DATE: case SERVICE_SETTING_BUILD_TIME: case SERVICE_SETTING_BL_COMMIT: + case SERVICE_SETTING_SD_SPI_SPEED: + case SERVICE_SETTING_SD_CAPACITY: + case SERVICE_SETTING_SD_MANUFACTURER_ID: + case SERVICE_SETTING_SD_OEM_ID: + case SERVICE_SETTING_SD_PROD_NAME: + case SERVICE_SETTING_SD_PROD_REV: + case SERVICE_SETTING_SD_PROD_SN: + case SERVICE_SETTING_SD_PROD_MANUFACT_YEAR: + case SERVICE_SETTING_SD_PROD_MANUFACT_MONTH: break; case SERVICE_SETTING_BL_UPDATE: update_bootloader(); diff --git a/FdsKey_bootloader/Core/Inc/sdcard.h b/FdsKey_bootloader/Core/Inc/sdcard.h index f8046e9..b05088e 100644 --- a/FdsKey_bootloader/Core/Inc/sdcard.h +++ b/FdsKey_bootloader/Core/Inc/sdcard.h @@ -75,12 +75,27 @@ typedef struct { } SD_CSD; +typedef struct { + uint8_t ManufacturerID; /* ManufacturerID */ + char OEM_AppliID[3]; /* OEM/Application ID */ + char ProdName[6]; /* Product Name */ + uint8_t ProdRev; /* Product Revision */ + uint32_t ProdSN; /* Product Serial Number */ + uint8_t Reserved1; /* Reserved1 */ + uint8_t ManufactYear; /* Manufacturing Year */ + uint8_t ManufactMonth; /* Manufacturing Month */ + uint8_t CID_CRC; /* CID CRC */ + uint8_t Reserved2; /* always 1 */ +} SD_CID; + extern SPI_HandleTypeDef SD_SPI_PORT; +// Initialization HAL_StatusTypeDef SD_init(); HAL_StatusTypeDef SD_init_try_speed(); -HAL_StatusTypeDef SD_read_csd(SD_CSD* csd); -uint64_t SD_get_capacity(); +uint32_t SD_get_spi_speed(); + +// Read/write single blocks HAL_StatusTypeDef SD_read_single_block(uint32_t blockNum, uint8_t* buff); // sizeof(buff) == 512! HAL_StatusTypeDef SD_write_single_block(uint32_t blockNum, const uint8_t* buff); // sizeof(buff) == 512! @@ -94,6 +109,11 @@ HAL_StatusTypeDef SD_write_begin(uint32_t blockNum); HAL_StatusTypeDef SD_write_data(const uint8_t* buff); // sizeof(buff) == 512! HAL_StatusTypeDef SD_write_end(); +// SD card info +HAL_StatusTypeDef SD_read_csd(SD_CSD* csd); +HAL_StatusTypeDef SD_read_cid(SD_CID* cid); +uint64_t SD_read_capacity(); + // TODO: read lock flag? CMD13, SEND_STATUS #endif // __SDCARD_H__ diff --git a/FdsKey_bootloader/Core/Src/sdcard.c b/FdsKey_bootloader/Core/Src/sdcard.c index 1b9c57d..5516c7c 100644 --- a/FdsKey_bootloader/Core/Src/sdcard.c +++ b/FdsKey_bootloader/Core/Src/sdcard.c @@ -1,6 +1,8 @@ #include "sdcard.h" +#include "string.h" static uint8_t sd_high_capacity; +static uint32_t sd_spi_speed; static void SPI_transmit_receive(uint8_t* tx, uint8_t* rx, size_t buff_size) { @@ -331,114 +333,32 @@ HAL_StatusTypeDef SD_init_try_speed() HAL_StatusTypeDef r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + sd_spi_speed = SPI_BAUDRATEPRESCALER_2; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; + sd_spi_speed = SPI_BAUDRATEPRESCALER_4; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + sd_spi_speed = SPI_BAUDRATEPRESCALER_8; HAL_SPI_Init(&SD_SPI_PORT); r = SD_init_tries(); if (r == HAL_OK) return r; SD_SPI_PORT.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; + sd_spi_speed = SPI_BAUDRATEPRESCALER_16; HAL_SPI_Init(&SD_SPI_PORT); return SD_init_tries(); } -HAL_StatusTypeDef SD_read_csd(SD_CSD* csd) +uint32_t SD_get_spi_speed() { - HAL_StatusTypeDef r; - uint8_t r1; - uint8_t csd_data[16]; - - // CMD9 - read CSD register and SD card capacity - SD_send_cmd(9, 0x00000000, 0xFF); - r = SD_read_r1(&r1); - if (r != HAL_OK) - return r; - if (r1 != 0x00) - return HAL_ERROR; - r = SD_wait_data_token(); - if (r != HAL_OK) - return r; - SD_read_bytes(csd_data, sizeof(csd_data)); - - SD_unselect_purge(); - - csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; - csd->Reserved1 = csd_data[0] & 0x3F; - csd->TAAC = csd_data[1]; - csd->NSAC = csd_data[2]; - csd->MaxBusClkFrec = csd_data[3]; - csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); - csd->RdBlockLen = csd_data[5] & 0x0F; - csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; - csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; - csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; - csd->DSRImpl = (csd_data[6] & 0x10) >> 4; - switch (csd->CSDStruct) { - case 0: - // CSD version 1 - csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); - csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | - ((csd_data[8] & 0xC0) >> 6); - csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; - csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); - csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; - csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; - csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | - ((csd_data[10] & 0x80) >> 7); - break; - case 1: - // CSD version 2 - csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | - ((csd_data[7] & 0xC0) >> 6); - csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | - csd_data[9]; - csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); - break; - default: - return HAL_ERROR; - } - csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; - csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); - csd->WrProtectGrSize = (csd_data[11] & 0x7F); - csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; - csd->Reserved2 = (csd_data[12] & 0x60) >> 5; - csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; - csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); - csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; - csd->Reserved3 = (csd_data[13] & 0x1F); - csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; - csd->CopyFlag = (csd_data[14] & 0x40) >> 6; - csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; - csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; - csd->FileFormat = (csd_data[14] & 0x0C) >> 2; - csd->Reserved4 = (csd_data[14] & 0x03); - csd->crc = (csd_data[15] & 0xFE) >> 1; - csd->Reserved5 = (csd_data[15] & 0x01); - - return HAL_OK; -} - -uint64_t SD_get_capacity() -{ - SD_CSD csd; - HAL_StatusTypeDef r; - r = SD_read_csd(&csd); - if (r == HAL_OK) - { - if (sd_high_capacity) - return (csd.version.v2.DeviceSize + 1) * SD_BLOCK_LENGTH * 1024; - else - return (csd.version.v1.DeviceSize + 1) * (1UL << (csd.version.v1.DeviceSizeMul + 2)) * (1UL << csd.RdBlockLen); - } - return 0; + return sd_spi_speed; } HAL_StatusTypeDef SD_read_single_block(uint32_t blockNum, uint8_t *buff) @@ -656,3 +576,141 @@ HAL_StatusTypeDef SD_write_end() SD_unselect_purge(); return HAL_OK; } + + +HAL_StatusTypeDef SD_read_csd(SD_CSD* csd) +{ + HAL_StatusTypeDef r; + uint8_t r1; + uint8_t csd_data[16]; + uint8_t crc[2]; + + // CMD9 - read CSD register and SD card capacity + SD_send_cmd(9, 0x00000000, 0xFF); + r = SD_read_r1(&r1); + if (r != HAL_OK) + return r; + if (r1 != 0x00) + return HAL_ERROR; + r = SD_wait_data_token(); + if (r != HAL_OK) + return r; + SD_read_bytes(csd_data, sizeof(csd_data)); + SD_read_bytes(crc, sizeof(crc)); + + SD_unselect_purge(); + + csd->CSDStruct = (csd_data[0] & 0xC0) >> 6; + csd->Reserved1 = csd_data[0] & 0x3F; + csd->TAAC = csd_data[1]; + csd->NSAC = csd_data[2]; + csd->MaxBusClkFrec = csd_data[3]; + csd->CardComdClasses = (csd_data[4] << 4) | ((csd_data[5] & 0xF0) >> 4); + csd->RdBlockLen = csd_data[5] & 0x0F; + csd->PartBlockRead = (csd_data[6] & 0x80) >> 7; + csd->WrBlockMisalign = (csd_data[6] & 0x40) >> 6; + csd->RdBlockMisalign = (csd_data[6] & 0x20) >> 5; + csd->DSRImpl = (csd_data[6] & 0x10) >> 4; + switch (csd->CSDStruct) { + case 0: + // CSD version 1 + csd->version.v1.Reserved1 = ((csd_data[6] & 0x0C) >> 2); + csd->version.v1.DeviceSize = ((csd_data[6] & 0x03) << 10) | (csd_data[7] << 2) | + ((csd_data[8] & 0xC0) >> 6); + csd->version.v1.MaxRdCurrentVDDMin = (csd_data[8] & 0x38) >> 3; + csd->version.v1.MaxRdCurrentVDDMax = (csd_data[8] & 0x07); + csd->version.v1.MaxWrCurrentVDDMin = (csd_data[9] & 0xE0) >> 5; + csd->version.v1.MaxWrCurrentVDDMax = (csd_data[9] & 0x1C) >> 2; + csd->version.v1.DeviceSizeMul = ((csd_data[9] & 0x03) << 1) | + ((csd_data[10] & 0x80) >> 7); + break; + case 1: + // CSD version 2 + csd->version.v2.Reserved1 = ((csd_data[6] & 0x0F) << 2) | + ((csd_data[7] & 0xC0) >> 6); + csd->version.v2.DeviceSize = ((csd_data[7] & 0x3F) << 16) | (csd_data[8] << 8) | + csd_data[9]; + csd->version.v2.Reserved2 = ((csd_data[10] & 0x80) >> 8); + break; + default: + return HAL_ERROR; + } + csd->EraseSingleBlockEnable = (csd_data[10] & 0x40) >> 6; + csd->EraseSectorSize = ((csd_data[10] & 0x3F) << 1) | ((csd_data[11] & 0x80) >> 7); + csd->WrProtectGrSize = (csd_data[11] & 0x7F); + csd->WrProtectGrEnable = (csd_data[12] & 0x80) >> 7; + csd->Reserved2 = (csd_data[12] & 0x60) >> 5; + csd->WrSpeedFact = (csd_data[12] & 0x1C) >> 2; + csd->MaxWrBlockLen = ((csd_data[12] & 0x03) << 2) | ((csd_data[13] & 0xC0) >> 6); + csd->WriteBlockPartial = (csd_data[13] & 0x20) >> 5; + csd->Reserved3 = (csd_data[13] & 0x1F); + csd->FileFormatGrouop = (csd_data[14] & 0x80) >> 7; + csd->CopyFlag = (csd_data[14] & 0x40) >> 6; + csd->PermWrProtect = (csd_data[14] & 0x20) >> 5; + csd->TempWrProtect = (csd_data[14] & 0x10) >> 4; + csd->FileFormat = (csd_data[14] & 0x0C) >> 2; + csd->Reserved4 = (csd_data[14] & 0x03); + csd->crc = (csd_data[15] & 0xFE) >> 1; + csd->Reserved5 = (csd_data[15] & 0x01); + + return HAL_OK; +} + +HAL_StatusTypeDef SD_read_cid(SD_CID* cid) +{ + HAL_StatusTypeDef r; + uint8_t r1; + uint8_t cid_data[16]; + uint8_t crc[2]; + + // CMD9 - read CSD register and SD card capacity + SD_send_cmd(10, 0x00000000, 0xFF); + r = SD_read_r1(&r1); + if (r != HAL_OK) + return r; + if (r1 != 0x00) + return HAL_ERROR; + r = SD_wait_data_token(); + if (r != HAL_OK) + return r; + SD_read_bytes(cid_data, sizeof(cid_data)); + SD_read_bytes(crc, sizeof(crc)); + + SD_unselect_purge(); + + cid->ManufacturerID = cid_data[0]; + memcpy(cid->OEM_AppliID, cid_data + 1, 2); + cid->OEM_AppliID[2] = 0; + memcpy(cid->ProdName, cid_data + 3, 5); + cid->ProdName[5] = 0; + cid->ProdRev = cid_data[8]; + cid->ProdSN = cid_data[9] << 24; + cid->ProdSN |= cid_data[10] << 16; + cid->ProdSN |= cid_data[11] << 8; + cid->ProdSN |= cid_data[12]; + cid->Reserved1 = (cid_data[13] & 0xF0) >> 4; + cid->ManufactYear = (cid_data[13] & 0x0F) << 4; + cid->ManufactYear |= (cid_data[14] & 0xF0) >> 4; + cid->ManufactMonth = (cid_data[14] & 0x0F); + cid->CID_CRC = (cid_data[15] & 0xFE) >> 1; + cid->Reserved2 = 1; + + return HAL_OK; +} + +uint64_t SD_read_capacity() +{ + SD_CSD csd; + HAL_StatusTypeDef r; + r = SD_read_csd(&csd); + if (r == HAL_OK) + { + if (sd_high_capacity) + return (uint64_t)(csd.version.v2.DeviceSize + 1) * SD_BLOCK_LENGTH * 1024; + else + return (uint64_t)(csd.version.v1.DeviceSize + 1) * (1UL << (csd.version.v1.DeviceSizeMul + 2)) * (1UL << csd.RdBlockLen); + } + return 0; +} + +