diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 0635b425e2d..754c8d1cbfc 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -1259,6 +1259,10 @@ void printAudioVars() #include "hal/switch_driver.h" +#if defined(DISK_CACHE) +#include "disk_cache.h" +#endif + int cliDisplay(const char ** argv) { long long int address = 0; diff --git a/radio/src/disk_cache.cpp b/radio/src/disk_cache.cpp index 1e17ddb71fe..d54f6af5ac9 100644 --- a/radio/src/disk_cache.cpp +++ b/radio/src/disk_cache.cpp @@ -19,22 +19,48 @@ * GNU General Public License for more details. */ +#include "disk_cache.h" +#include "sdcard.h" + #include -#include "opentx.h" #if defined(SIMU) && !defined(SIMU_DISKIO) #define __disk_read(...) (RES_OK) #define __disk_write(...) (RES_OK) #endif -#if 0 // set to 1 to enable traces +#if 0 // set to 1 to enable traces + #include "debug.h" #define TRACE_DISK_CACHE(...) TRACE(__VA_ARGS__) #else #define TRACE_DISK_CACHE(...) #endif +#if FF_MAX_SS != FF_MIN_SS +#error "Variable sector size is not supported" +#endif + +#define BLOCK_SIZE FF_MAX_SS +#define DISK_CACHE_BLOCK_SIZE (DISK_CACHE_BLOCK_SECTORS * BLOCK_SIZE) + DiskCache diskCache; +class DiskCacheBlock +{ +public: + DiskCacheBlock(); + bool read(BYTE* buff, DWORD sector, UINT count); + DRESULT fill(BYTE drv, BYTE* buff, DWORD sector, UINT count); + void free(DWORD sector, UINT count); + void free(); + bool empty() const; + +private: + uint8_t data[DISK_CACHE_BLOCK_SIZE]; + DWORD startSector; + DWORD endSector; +}; + DiskCacheBlock::DiskCacheBlock(): startSector(0), endSector(0) @@ -97,7 +123,7 @@ void DiskCache::clear() stats.noHits = 0; stats.noMisses = 0; stats.noWrites = 0; - for (int n=0; n= sdGetNoSectors()) { + if (sector + DISK_CACHE_BLOCK_SECTORS >= sdGetNoSectors()) { TRACE_DISK_CACHE("\t\t cache would be beyond end of disk %u (%u)", (uint32_t)sector, sdGetNoSectors()); return __disk_read(drv, buff, sector, count); } - for (int n=0; n #include + #include "opentx.h" #include "diskio.h" @@ -30,6 +31,12 @@ #include "libopenui/src/libopenui_file.h" #endif +#if FF_MAX_SS != FF_MIN_SS +#error "Variable sector size is not supported" +#endif + +#define BLOCK_SIZE FF_MAX_SS + #define SDCARD_MIN_FREE_SPACE_MB 50 // Maintain a 50MB free space buffer to prevent crashes const char * sdCheckAndCreateDirectory(const char * path) @@ -451,6 +458,13 @@ uint32_t sdGetFreeSectors() return nofree * fat->csize; } +uint32_t sdGetFreeKB() +{ + return sdGetFreeSectors() * (1024 / BLOCK_SIZE); +} + +bool sdIsFull() { return sdGetFreeKB() < SDCARD_MIN_FREE_SPACE_MB * 1024; } + #else // #if !defined(SIMU) || defined(SIMU_DISKIO) uint32_t sdGetNoSectors() @@ -468,4 +482,130 @@ uint32_t sdGetFreeSectors() return ((SDCARD_MIN_FREE_SPACE_MB*1024*1024)/BLOCK_SIZE)+1; // SIMU SD card is always above threshold } +uint32_t sdGetFreeKB() { return SDCARD_MIN_FREE_SPACE_MB * 1024 + 1; } +bool sdIsFull() { return false; } + #endif // #if !defined(SIMU) || defined(SIMU_DISKIO) + + +static bool _g_FATFS_init = false; +static FATFS g_FATFS_Obj __DMA; // this is in uninitialised section !!! + +#if defined(LOG_TELEMETRY) +FIL g_telemetryFile = {}; +#endif + +#if defined(LOG_BLUETOOTH) +FIL g_bluetoothFile = {}; +#endif + +#include "audio.h" +#include "sdcard.h" +#include "disk_cache.h" + +/*-----------------------------------------------------------------------*/ +/* Lock / unlock functions */ +/*-----------------------------------------------------------------------*/ +static RTOS_MUTEX_HANDLE ioMutex; +uint32_t ioMutexReq = 0, ioMutexRel = 0; +int ff_cre_syncobj (BYTE vol, FF_SYNC_t * mutex) +{ + *mutex = ioMutex; + return 1; +} + +int ff_req_grant (FF_SYNC_t mutex) +{ + ioMutexReq += 1; + RTOS_LOCK_MUTEX(mutex); + return 1; +} + +void ff_rel_grant (FF_SYNC_t mutex) +{ + ioMutexRel += 1; + RTOS_UNLOCK_MUTEX(mutex); +} + +int ff_del_syncobj (FF_SYNC_t mutex) +{ + return 1; +} + +void sdInit() +{ + TRACE("sdInit"); + RTOS_CREATE_MUTEX(ioMutex); + sdMount(); +} + +void sdMount() +{ + TRACE("sdMount"); + +#if defined(DISK_CACHE) + diskCache.clear(); +#endif + + if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { + // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called + _g_FATFS_init = true; + sdGetFreeSectors(); + +#if defined(LOG_TELEMETRY) + f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); + if (f_size(&g_telemetryFile) > 0) { + f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append + } +#endif + +#if defined(LOG_BLUETOOTH) + f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE); + if (f_size(&g_bluetoothFile) > 0) { + f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append + } +#endif + } + else { + TRACE("f_mount() failed"); + } +} + +void sdDone() +{ + TRACE("sdDone"); + + if (sdMounted()) { + audioQueue.stopSD(); + +#if defined(LOG_TELEMETRY) + f_close(&g_telemetryFile); +#endif + +#if defined(LOG_BLUETOOTH) + f_close(&g_bluetoothFile); +#endif + + f_mount(nullptr, "", 0); // unmount SD + } +} + +uint32_t sdMounted() +{ + return _g_FATFS_init && (g_FATFS_Obj.fs_type != 0); +} + + +uint32_t sdIsHC() +{ + // defined in diskio + #define CT_BLOCK 0x08 + extern uint32_t SD_GetCardType(); + + return SD_GetCardType() & CT_BLOCK; +} + +uint32_t sdGetSpeed() +{ + return 330000; +} diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index ad777092e4d..4a83cfe7948 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -24,7 +24,6 @@ #include "ff.h" -extern FATFS g_FATFS_Obj; extern FIL g_oLogFile; #include "translations.h" @@ -124,9 +123,32 @@ void logsInit(); void logsClose(); void logsWrite(); +void sdInit(); +void sdMount(); +void sdDone(); +uint32_t sdMounted(); + uint32_t sdGetNoSectors(); uint32_t sdGetSize(); uint32_t sdGetFreeSectors(); +uint32_t sdGetFreeKB(); +bool sdIsFull(); + +#if defined(PCBTARANIS) +void sdPoll10ms(); +#endif + +#if !defined(SIMU) || defined(SIMU_DISKIO) + uint32_t sdIsHC(); + uint32_t sdGetSpeed(); + #define SD_IS_HC() (sdIsHC()) + #define SD_GET_SPEED() (sdGetSpeed()) + #define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) +#else + #define SD_IS_HC() (0) + #define SD_GET_SPEED() (0) +#endif + const char * sdCheckAndCreateDirectory(const char * path); #if !defined(BOOT) diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt index 1695eccfd4d..449bbcd2789 100644 --- a/radio/src/targets/common/arm/CMakeLists.txt +++ b/radio/src/targets/common/arm/CMakeLists.txt @@ -308,7 +308,6 @@ set(SRC set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} # keys_driver.cpp - diskio.cpp # telemetry_driver.cpp ) diff --git a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt index 82e67992974..77df75fa3f9 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/bootloader/CMakeLists.txt @@ -25,7 +25,6 @@ set(BOOTLOADER_SRC ../../../../../${FATFS_DIR}/ffunicode.c ../../../../../targets/${TARGET_DIR}/${LCD_DRIVER} ../../../../../targets/${TARGET_DIR}/backlight_driver.cpp - ../../../../../targets/${TARGET_DIR}/diskio.cpp ../../../../../targets/${TARGET_DIR}/board.cpp ../../../../../targets/${TARGET_DIR}/bootloader/boot_menu.cpp ${CMAKE_CURRENT_BINARY_DIR}/hal_keys.inc @@ -42,6 +41,7 @@ set(BOOTLOADER_SRC ../stm32_serial_driver.cpp ../stm32_usart_driver.cpp ../stm32_gpio_driver.cpp + ../stm32_dma.cpp init.c boot.cpp bin_files.cpp @@ -77,7 +77,8 @@ if(PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14) ../../../../../fonts/lvgl/lv_font_roboto_bl_16.c ../../../../../thirdparty/libopenui/src/bitmapbuffer.cpp ../../../../../thirdparty/libopenui/thirdparty/lz4/lz4.c - ../../../../../targets/common/arm/stm32/sdio_sd.c + ../../../../../targets/common/arm/stm32/sdio_sd.cpp + ../../../../../targets/common/arm/stm32/diskio_sdio.cpp ../../../../../targets/common/arm/stm32/rtc_driver.cpp ../../../../../targets/${TARGET_DIR}/sdram_driver.c ../../../../../targets/${TARGET_DIR}/haptic_driver.cpp @@ -119,6 +120,7 @@ else() ../../../../../gui/common/stdlcd/fonts.cpp ../../../../../gui/common/stdlcd/utf8.cpp ../../../../../targets/${TARGET_DIR}/eeprom_driver.cpp + ../../../../../targets/${TARGET_DIR}/diskio.cpp ) remove_definitions(-DDEBUG) endif() diff --git a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp index 29811154897..f909d2f8b2f 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/bin_files.cpp @@ -38,6 +38,14 @@ BinFileInfo binFiles[MAX_BIN_FILES]; uint8_t Block_buffer[BLOCK_LEN]; UINT BlockCount; +void sdInit(void) +{ + static FATFS fatFS __DMA; + + if (f_mount(&fatFS, "", 1) == FR_OK) { + f_chdir("/"); + } +} FRESULT openBinDir(MemoryType mt) { diff --git a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp index e836e0c9578..0839e8d7f4b 100644 --- a/radio/src/targets/common/arm/stm32/bootloader/boot.cpp +++ b/radio/src/targets/common/arm/stm32/bootloader/boot.cpp @@ -94,9 +94,12 @@ uint32_t eepromWritten = 0; FlashCheckRes valid; MemoryType memoryType; uint32_t unlocked = 0; +uint32_t timer10MsCount; + void interrupt10ms() { + timer10MsCount++; tenms |= 1u; // 10 mS has passed g_tmr10ms++; @@ -116,6 +119,7 @@ void interrupt10ms() void init10msTimer() { + timer10MsCount = 0; INTERRUPT_xMS_TIMER->ARR = 9999; // 10mS in uS INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS INTERRUPT_xMS_TIMER->CCER = 0; @@ -126,6 +130,11 @@ void init10msTimer() NVIC_EnableIRQ(INTERRUPT_xMS_IRQn); } +extern "C" uint32_t HAL_GetTick(void) +{ + return timer10MsCount*10; +} + #if !defined(SIMU) extern "C" void INTERRUPT_xMS_IRQHandler() { @@ -188,8 +197,6 @@ int menuFlashFile(uint32_t index, event_t event) return -1; } -static uint32_t PowerUpDelay; - void flashWriteBlock() { uint32_t blockOffset = 0; @@ -571,12 +578,16 @@ int bootloaderMain() lcdRefresh(); +#if defined(SDCARD) && defined(PCBTARANIS) + static uint32_t PowerUpDelay = 0; + if (PowerUpDelay < 20) { // 200 mS PowerUpDelay += 1; } else { sdPoll10ms(); } +#endif } if (state != ST_FLASHING && state != ST_USB) { diff --git a/radio/src/targets/nv14/diskio.cpp b/radio/src/targets/common/arm/stm32/diskio_sdio.cpp similarity index 55% rename from radio/src/targets/nv14/diskio.cpp rename to radio/src/targets/common/arm/stm32/diskio_sdio.cpp index e28f0b5c3ce..a156849a13e 100644 --- a/radio/src/targets/nv14/diskio.cpp +++ b/radio/src/targets/common/arm/stm32/diskio_sdio.cpp @@ -25,45 +25,24 @@ /* disk I/O modules and attach it to FatFs module with common interface. */ /*-----------------------------------------------------------------------*/ -#include "diskio.h" -#include "debug.h" -#include "targets/common/arm/stm32/sdio_sd.h" - -#include - -// TODO share this with Horus (and perhaps other STM32) - -/*-----------------------------------------------------------------------*/ -/* Lock / unlock functions */ -/*-----------------------------------------------------------------------*/ -#if !defined(BOOT) -static RTOS_MUTEX_HANDLE ioMutex; -uint32_t ioMutexReq = 0, ioMutexRel = 0; -int ff_cre_syncobj (BYTE vol, FF_SYNC_t *mutex) -{ - *mutex = ioMutex; - return 1; -} +#include "stm32_hal.h" +#include "sdio_sd.h" -int ff_req_grant (FF_SYNC_t mutex) -{ - ioMutexReq += 1; - RTOS_LOCK_MUTEX(mutex); - return 1; -} +#include "FatFs/diskio.h" -void ff_rel_grant (FF_SYNC_t mutex) -{ - ioMutexRel += 1; - RTOS_UNLOCK_MUTEX(mutex); -} +#include +#include "debug.h" -int ff_del_syncobj (FF_SYNC_t mutex) -{ - return 1; -} +#if FF_MAX_SS != FF_MIN_SS +#error "Variable sector size is not supported" #endif +#define BLOCK_SIZE FF_MAX_SS +#define SD_TIMEOUT 300 /* 300ms */ + +// Disk status +extern volatile uint32_t WriteStatus; +extern volatile uint32_t ReadStatus; /*-----------------------------------------------------------------------*/ /* Inidialize a Drive */ @@ -89,11 +68,11 @@ DSTATUS disk_initialize ( } TRACE("SD card info:"); - TRACE("sectors: %u", (uint32_t)(SDCardInfo.CardCapacity / 512)); - TRACE("type: %u", (uint32_t)(SDCardInfo.CardType)); - TRACE("EraseGrSize: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrSize)); - TRACE("EraseGrMul: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrMul)); - TRACE("ManufacturerID: %u", (uint32_t)(SDCardInfo.SD_cid.ManufacturerID)); + TRACE("type: %u", (uint32_t)(SD_GetCardType())); + TRACE("class: %u", (uint32_t)(SD_GetCardClass())); + TRACE("sectors: %u", (uint32_t)(SD_GetSectorCount())); + TRACE("sector size: %u", (uint32_t)(SD_GetSectorSize())); + TRACE("block size: %u", (uint32_t)(SD_GetBlockSize())); return(stat); } @@ -124,39 +103,52 @@ uint32_t sdReadRetries = 0; /* Read Sector(s) */ +// Please note: +// this functions assumes that buff is properly aligned +// and in the right RAM segment for DMA +// DRESULT disk_read_dma(BYTE drv, BYTE * buff, DWORD sector, UINT count) { - // this functions assumes that buff is properly aligned and in the right RAM segment for DMA - DRESULT res; - SD_Error Status; - SDTransferState State; - for (int retry=0; retry<3; retry++) { - res = RES_OK; - if (count == 1) { - Status = SD_ReadBlock(buff, sector, BLOCK_SIZE); // 4GB Compliant + DRESULT res = RES_ERROR; + + for (int retry = 0; retry < 3; retry++) { + + ReadStatus = 0; + SD_Error Status = SD_ReadBlocks(buff, sector, BLOCK_SIZE, count); + if (Status != SD_OK) { + TRACE("SD ReadBlocks=%d, s:%u c: %u", Status, sector, (uint32_t)count); + ++sdReadRetries; + continue; } - else { - Status = SD_ReadMultiBlocks(buff, sector, BLOCK_SIZE, count); // 4GB Compliant + + // Wait that the reading process is completed or a timeout occurs + uint32_t timeout = HAL_GetTick(); + while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)); + + if (ReadStatus == 0) { + TRACE("SD read timeout, s:%u c:%u", sector, (uint32_t)count); + ++sdReadRetries; + continue; } - if (Status == SD_OK) { - Status = SD_WaitReadOperation(200*count); // Check if the Transfer is finished - while ((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) - if (State == SD_TRANSFER_ERROR) { - TRACE("State=SD_TRANSFER_ERROR, c: %u", sector, (uint32_t)count); - res = RES_ERROR; - } - else if (Status != SD_OK) { - TRACE("Status(WaitRead)=%d, s:%u c: %u", Status, sector, (uint32_t)count); - res = RES_ERROR; + + ReadStatus = 0; + timeout = HAL_GetTick(); + + while((HAL_GetTick() - timeout) < SD_TIMEOUT) { + if (SD_GetStatus() == SD_TRANSFER_OK) { + res = RES_OK; + break; } } - else { - TRACE("Status(ReadBlock)=%d, s:%u c: %u", Status, sector, (uint32_t)count); - res = RES_ERROR; + + if (res == RES_OK) { + // exit retry loop + break; } - if (res == RES_OK) break; - sdReadRetries += 1; + + TRACE("SD getstatus timeout, s:%u c:%u", sector, (uint32_t)count); } + return res; } @@ -174,6 +166,10 @@ DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count) return RES_NOTRDY; } + if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { + return RES_ERROR; + } + DRESULT res = RES_OK; if (count == 0) return res; @@ -199,6 +195,7 @@ DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count) buff += BLOCK_SIZE; } } + return res; } @@ -213,13 +210,16 @@ DRESULT __disk_write( UINT count /* Number of sectors to write (1..255) */ ) { - SD_Error Status; DRESULT res = RES_OK; // TRACE("disk_write %d %p %10d %d", drv, buff, sector, count); if (SD_Detect() != SD_PRESENT) - return(RES_NOTRDY); + return RES_NOTRDY; + + if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { + return RES_ERROR; + } if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) { //TRACE("disk_write bad alignment (%p)", buff); @@ -236,30 +236,37 @@ DRESULT __disk_write( return(res); } - if (count == 1) { - Status = SD_WriteBlock((uint8_t *)buff, sector, BLOCK_SIZE); // 4GB Compliant - } - else { - Status = SD_WriteMultiBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count); // 4GB Compliant + SD_Error Status = SD_WriteBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count); + if (Status != SD_OK) { + TRACE("SD WriteBlocks=%d, s:%u c: %u", Status, sector, (uint32_t)count); + return RES_ERROR; } - if (Status == SD_OK) { - SDTransferState State; + // Wait that the reading process is completed or a timeout occurs + uint32_t timeout = HAL_GetTick(); + while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT)); - Status = SD_WaitWriteOperation(500*count); // Check if the Transfer is finished + if (WriteStatus == 0) { + TRACE("SD write timeout, s:%u c:%u", sector, (uint32_t)count); + return RES_ERROR; + } - while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) + WriteStatus = 0; + res = RES_ERROR; + timeout = HAL_GetTick(); - if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) { - TRACE("__disk_write() err, st:%d,%d, s:%u c: %u", Status, State, sector, (uint32_t)count); - res = RES_ERROR; + while((HAL_GetTick() - timeout) < SD_TIMEOUT) { + if (SD_GetStatus() == SD_TRANSFER_OK) { + res = RES_OK; + break; } } - else { + + if (res != RES_OK) { + TRACE("SD getstatus timeout, s:%u c: %u", sector, (uint32_t)count); res = RES_ERROR; } - // TRACE("result=%d", res); return res; } #endif /* _READONLY */ @@ -274,6 +281,7 @@ DRESULT disk_ioctl ( ) { DRESULT res; + uint32_t tmp; if (drv) return RES_PARERR; @@ -281,24 +289,44 @@ DRESULT disk_ioctl ( switch (ctrl) { case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ - // use 512 for sector size, SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!! - *(DWORD*)buff = SDCardInfo.CardCapacity / BLOCK_SIZE; + tmp = SD_GetSectorCount(); + + if(tmp == 0) { + res = RES_ERROR; + break; + } + + *(DWORD*)buff = tmp; res = RES_OK; break; case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */ - *(WORD*)buff = BLOCK_SIZE; // force sector size. SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!! + tmp = SD_GetSectorSize(); + + if(tmp == 0) { + res = RES_ERROR; + break; + } + + *(WORD*)buff = tmp; res = RES_OK; break; case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ - // TODO verify that this is the correct value - *(DWORD*)buff = (uint32_t)SDCardInfo.SD_csd.EraseGrSize * (uint32_t)SDCardInfo.SD_csd.EraseGrMul; + tmp = SD_GetBlockSize() / BLOCK_SIZE; + + if(tmp == 0) { + res = RES_ERROR; + break; + } + + *(DWORD*)buff = tmp; res = RES_OK; break; case CTRL_SYNC: - while (SD_GetStatus() == SD_TRANSFER_BUSY); /* Complete pending write process (needed at _FS_READONLY == 0) */ + /* Complete pending write process (needed at _FS_READONLY == 0) */ + while (SD_GetStatus() == SD_TRANSFER_BUSY); res = RES_OK; break; @@ -310,86 +338,3 @@ DRESULT disk_ioctl ( return res; } - -// TODO everything here should not be in the driver layer ... - -bool _g_FATFS_init = false; -FATFS g_FATFS_Obj __DMA; // initialized in boardInit() - -#if defined(LOG_TELEMETRY) -FIL g_telemetryFile = {}; -#endif - -#if defined(BOOT) -void sdInit(void) -{ - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - f_chdir("/"); - } -} -#else - -#include "audio.h" -#include "sdcard.h" -#include "disk_cache.h" - -void sdInit() -{ - TRACE("sdInit"); - RTOS_CREATE_MUTEX(ioMutex); - sdMount(); -} - -void sdMount() -{ - TRACE("sdMount"); - -#if defined(DISK_CACHE) - diskCache.clear(); -#endif - - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called - _g_FATFS_init = true; - sdGetFreeSectors(); - -#if defined(LOG_TELEMETRY) - f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_telemetryFile) > 0) { - f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append - } -#endif - } - else { - TRACE("f_mount() failed"); - } -} - -void sdDone() -{ - TRACE("sdDone"); - - if (sdMounted()) { - audioQueue.stopSD(); -#if defined(LOG_TELEMETRY) - f_close(&g_telemetryFile); -#endif - f_mount(NULL, "", 0); // unmount SD - } -} -#endif - -uint32_t sdMounted() -{ - return _g_FATFS_init && g_FATFS_Obj.fs_type != 0; -} - -uint32_t sdIsHC() -{ - return true; // TODO (CardType & CT_BLOCK); -} - -uint32_t sdGetSpeed() -{ - return 330000; -} diff --git a/radio/src/targets/common/arm/stm32/f4/CMakeLists.txt b/radio/src/targets/common/arm/stm32/f4/CMakeLists.txt index af79251ce08..de78096c176 100644 --- a/radio/src/targets/common/arm/stm32/f4/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/f4/CMakeLists.txt @@ -15,6 +15,7 @@ if(NOT NATIVE_BUILD) ${STM32CUBE_DIR}/Src/stm32f4xx_ll_usart.c ${STM32CUBE_DIR}/Src/stm32f4xx_ll_rcc.c ${STM32CUBE_DIR}/Src/stm32f4xx_ll_exti.c + ${STM32CUBE_DIR}/Src/stm32f4xx_ll_sdmmc.c ${STM32CUBE_DIR}/Src/stm32f4xx_ll_adc.c ${STM32CUBE_DIR}/Src/stm32f4xx_ll_spi.c # HAL drivers @@ -25,6 +26,8 @@ if(NOT NATIVE_BUILD) ${STM32CUBE_DIR}/Src/stm32f4xx_hal_rtc.c ${STM32CUBE_DIR}/Src/stm32f4xx_hal_i2c.c ${STM32CUBE_DIR}/Src/stm32f4xx_hal_i2c_ex.c + ${STM32CUBE_DIR}/Src/stm32f4xx_hal_sd.c + ${STM32CUBE_DIR}/Src/stm32f4xx_hal_dma.c ) target_compile_options(stm32cube_ll PRIVATE -DUSE_FULL_LL_DRIVER) @@ -64,7 +67,6 @@ if(CPU_TYPE_FULL STREQUAL STM32F429xI) ${STM32_STDPERIPH_DIR}/src/stm32f4xx_ltdc.c ${STM32_STDPERIPH_DIR}/src/stm32f4xx_dma.c ${STM32_STDPERIPH_DIR}/src/stm32f4xx_dma2d.c - ${STM32_STDPERIPH_DIR}/src/stm32f4xx_sdio.c ) elseif (CPU_TYPE_FULL STREQUAL STM32F413xG) set(STM32_STDPERIPH_SRC ${STM32_STDPERIPH_SRC} diff --git a/radio/src/targets/common/arm/stm32/sdio_sd.c b/radio/src/targets/common/arm/stm32/sdio_sd.c deleted file mode 100644 index 66464a3027a..00000000000 --- a/radio/src/targets/common/arm/stm32/sdio_sd.c +++ /dev/null @@ -1,2036 +0,0 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include "sdio_sd.h" -#include "debug.h" - -#if defined(STM32F4) - #include "stm32f4xx_sdio.h" -#elif defined(STM32F2) - #include "stm32f2xx_sdio.h" -#endif - -#define SDIO_STATIC_FLAGS ((uint32_t)0x000005FF) -#define SDIO_CMD0TIMEOUT ((uint32_t)0x00010000) - -#define SD_OCR_ADDR_OUT_OF_RANGE ((uint32_t)0x80000000) -#define SD_OCR_ADDR_MISALIGNED ((uint32_t)0x40000000) -#define SD_OCR_BLOCK_LEN_ERR ((uint32_t)0x20000000) -#define SD_OCR_ERASE_SEQ_ERR ((uint32_t)0x10000000) -#define SD_OCR_BAD_ERASE_PARAM ((uint32_t)0x08000000) -#define SD_OCR_WRITE_PROT_VIOLATION ((uint32_t)0x04000000) -#define SD_OCR_LOCK_UNLOCK_FAILED ((uint32_t)0x01000000) -#define SD_OCR_COM_CRC_FAILED ((uint32_t)0x00800000) -#define SD_OCR_ILLEGAL_CMD ((uint32_t)0x00400000) -#define SD_OCR_CARD_ECC_FAILED ((uint32_t)0x00200000) -#define SD_OCR_CC_ERROR ((uint32_t)0x00100000) -#define SD_OCR_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00080000) -#define SD_OCR_STREAM_READ_UNDERRUN ((uint32_t)0x00040000) -#define SD_OCR_STREAM_WRITE_OVERRUN ((uint32_t)0x00020000) -#define SD_OCR_CID_CSD_OVERWRIETE ((uint32_t)0x00010000) -#define SD_OCR_WP_ERASE_SKIP ((uint32_t)0x00008000) -#define SD_OCR_CARD_ECC_DISABLED ((uint32_t)0x00004000) -#define SD_OCR_ERASE_RESET ((uint32_t)0x00002000) -#define SD_OCR_AKE_SEQ_ERROR ((uint32_t)0x00000008) -#define SD_OCR_ERRORBITS ((uint32_t)0xFDFFE008) - -#define SD_R6_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00002000) -#define SD_R6_ILLEGAL_CMD ((uint32_t)0x00004000) -#define SD_R6_COM_CRC_FAILED ((uint32_t)0x00008000) - -#define SD_VOLTAGE_WINDOW_SD ((uint32_t)0x80100000) -#define SD_HIGH_CAPACITY ((uint32_t)0x40000000) -#define SD_STD_CAPACITY ((uint32_t)0x00000000) -#define SD_CHECK_PATTERN ((uint32_t)0x000001AA) - -#if defined(RADIO_TX16S) - #define SD_MAX_VOLT_TRIAL ((uint32_t)0x00000834) -#else - #define SD_MAX_VOLT_TRIAL ((uint32_t)0x0000FFFF) -#endif - -#define SD_ALLZERO ((uint32_t)0x00000000) - -#define SD_WIDE_BUS_SUPPORT ((uint32_t)0x00040000) -#define SD_SINGLE_BUS_SUPPORT ((uint32_t)0x00010000) -#define SD_CARD_LOCKED ((uint32_t)0x02000000) - -#define SD_DATATIMEOUT ((uint32_t)1000000) -#define SD_0TO7BITS ((uint32_t)0x000000FF) -#define SD_8TO15BITS ((uint32_t)0x0000FF00) -#define SD_16TO23BITS ((uint32_t)0x00FF0000) -#define SD_24TO31BITS ((uint32_t)0xFF000000) - -#define SDIO_SEND_IF_COND ((uint32_t)0x00000008) - - -#define SD_CMD_GO_IDLE_STATE ((uint8_t)0) -#define SD_CMD_SEND_OP_COND ((uint8_t)1) -#define SD_CMD_ALL_SEND_CID ((uint8_t)2) -#define SD_CMD_SET_REL_ADDR ((uint8_t)3) /*!< SDIO_SEND_REL_ADDR for SD Card */ -#define SD_CMD_SET_DSR ((uint8_t)4) -#define SD_CMD_SDIO_SEN_OP_COND ((uint8_t)5) -#define SD_CMD_HS_SWITCH ((uint8_t)6) -#define SD_CMD_SEL_DESEL_CARD ((uint8_t)7) -#define SD_CMD_HS_SEND_EXT_CSD ((uint8_t)8) -#define SD_CMD_SEND_CSD ((uint8_t)9) -#define SD_CMD_SEND_CID ((uint8_t)10) -#define SD_CMD_READ_DAT_UNTIL_STOP ((uint8_t)11) /*!< SD Card doesn't support it */ -#define SD_CMD_STOP_TRANSMISSION ((uint8_t)12) -#define SD_CMD_SEND_STATUS ((uint8_t)13) -#define SD_CMD_HS_BUSTEST_READ ((uint8_t)14) -#define SD_CMD_GO_INACTIVE_STATE ((uint8_t)15) -#define SD_CMD_SET_BLOCKLEN ((uint8_t)16) -#define SD_CMD_READ_SINGLE_BLOCK ((uint8_t)17) -#define SD_CMD_READ_MULT_BLOCK ((uint8_t)18) -#define SD_CMD_HS_BUSTEST_WRITE ((uint8_t)19) -#define SD_CMD_WRITE_DAT_UNTIL_STOP ((uint8_t)20) /*!< SD Card doesn't support it */ -#define SD_CMD_SET_BLOCK_COUNT ((uint8_t)23) /*!< SD Card doesn't support it */ -#define SD_CMD_WRITE_SINGLE_BLOCK ((uint8_t)24) -#define SD_CMD_WRITE_MULT_BLOCK ((uint8_t)25) -#define SD_CMD_PROG_CID ((uint8_t)26) /*!< reserved for manufacturers */ -#define SD_CMD_PROG_CSD ((uint8_t)27) -#define SD_CMD_SET_WRITE_PROT ((uint8_t)28) -#define SD_CMD_CLR_WRITE_PROT ((uint8_t)29) -#define SD_CMD_SEND_WRITE_PROT ((uint8_t)30) -#define SD_CMD_SD_ERASE_GRP_START ((uint8_t)32) /*!< To set the address of the first write - block to be erased. (For SD card only) */ -#define SD_CMD_SD_ERASE_GRP_END ((uint8_t)33) /*!< To set the address of the last write block of the - continuous range to be erased. (For SD card only) */ -#define SD_CMD_ERASE_GRP_START ((uint8_t)35) /*!< To set the address of the first write block to be erased. - (For MMC card only spec 3.31) */ - -#define SD_CMD_ERASE_GRP_END ((uint8_t)36) /*!< To set the address of the last write block of the - continuous range to be erased. (For MMC card only spec 3.31) */ - -#define SD_CMD_ERASE ((uint8_t)38) -#define SD_CMD_FAST_IO ((uint8_t)39) /*!< SD Card doesn't support it */ -#define SD_CMD_GO_IRQ_STATE ((uint8_t)40) /*!< SD Card doesn't support it */ -#define SD_CMD_LOCK_UNLOCK ((uint8_t)42) -#define SD_CMD_APP_CMD ((uint8_t)55) -#define SD_CMD_GEN_CMD ((uint8_t)56) -#define SD_CMD_NO_CMD ((uint8_t)64) - -#define SD_CMD_APP_SD_SET_BUSWIDTH ((uint8_t)6) /*!< For SD Card only */ -#define SD_CMD_SD_APP_STAUS ((uint8_t)13) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS ((uint8_t)22) /*!< For SD Card only */ -#define SD_CMD_SD_APP_OP_COND ((uint8_t)41) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SET_CLR_CARD_DETECT ((uint8_t)42) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SEND_SCR ((uint8_t)51) /*!< For SD Card only */ -#define SD_CMD_SDIO_RW_DIRECT ((uint8_t)52) /*!< For SD I/O Card only */ -#define SD_CMD_SDIO_RW_EXTENDED ((uint8_t)53) /*!< For SD I/O Card only */ - -#define SD_CMD_SD_APP_GET_MKB ((uint8_t)43) /*!< For SD Card only */ -#define SD_CMD_SD_APP_GET_MID ((uint8_t)44) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SET_CER_RN1 ((uint8_t)45) /*!< For SD Card only */ -#define SD_CMD_SD_APP_GET_CER_RN2 ((uint8_t)46) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SET_CER_RES2 ((uint8_t)47) /*!< For SD Card only */ -#define SD_CMD_SD_APP_GET_CER_RES1 ((uint8_t)48) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK ((uint8_t)18) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK ((uint8_t)25) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SECURE_ERASE ((uint8_t)38) /*!< For SD Card only */ -#define SD_CMD_SD_APP_CHANGE_SECURE_AREA ((uint8_t)49) /*!< For SD Card only */ -#define SD_CMD_SD_APP_SECURE_WRITE_MKB ((uint8_t)48) /*!< For SD Card only */ - -#define SDIO_STD_CAPACITY_SD_CARD_V1_1 ((uint32_t)0x00000000) -#define SDIO_STD_CAPACITY_SD_CARD_V2_0 ((uint32_t)0x00000001) -#define SDIO_HIGH_CAPACITY_SD_CARD ((uint32_t)0x00000002) -#define SDIO_MULTIMEDIA_CARD ((uint32_t)0x00000003) -#define SDIO_SECURE_DIGITAL_IO_CARD ((uint32_t)0x00000004) -#define SDIO_HIGH_SPEED_MULTIMEDIA_CARD ((uint32_t)0x00000005) -#define SDIO_SECURE_DIGITAL_IO_COMBO_CARD ((uint32_t)0x00000006) -#define SDIO_HIGH_CAPACITY_MMC_CARD ((uint32_t)0x00000007) - - -typedef enum -{ - SD_CARD_READY = ((uint32_t)0x00000001), - SD_CARD_IDENTIFICATION = ((uint32_t)0x00000002), - SD_CARD_STANDBY = ((uint32_t)0x00000003), - SD_CARD_TRANSFER = ((uint32_t)0x00000004), - SD_CARD_SENDING = ((uint32_t)0x00000005), - SD_CARD_RECEIVING = ((uint32_t)0x00000006), - SD_CARD_PROGRAMMING = ((uint32_t)0x00000007), - SD_CARD_DISCONNECTED = ((uint32_t)0x00000008), - SD_CARD_ERROR = ((uint32_t)0x000000FF) -} SDCardState; - - -static uint32_t CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; -static uint32_t CSD_Tab[4], CID_Tab[4], RCA = 0; -__IO uint8_t StopCondition = 0; -__IO SD_Error TransferError = SD_OK; -__IO uint8_t TransferEnd = 0, DMAEndOfTransfer = 0; -SD_CardInfo SDCardInfo; - -SDIO_InitTypeDef SDIO_InitStructure; -SDIO_CmdInitTypeDef SDIO_CmdInitStructure; -SDIO_DataInitTypeDef SDIO_DataInitStructure; - -static SD_Error CmdError(void); -static SD_Error CmdResp1Error(uint8_t cmd); -static SD_Error CmdResp7Error(void); -static SD_Error CmdResp3Error(void); -static SD_Error CmdResp2Error(void); -static SD_Error CmdResp6Error(uint8_t cmd, uint16_t *prca); -static SD_Error SDEnWideBus(FunctionalState NewState); -static SD_Error FindSCR(uint16_t rca, uint32_t *pscr); - -SD_Error SD_PowerON(void); -SDCardState SD_GetState(void); -SD_Error SD_InitializeCards(void); -SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo); -SD_Error SD_EnableWideBusOperation(uint32_t WideMode); -SD_Error SD_SelectDeselect(uint32_t addr); -SD_Error SD_StopTransfer(void); -SD_Error SD_SendStatus(uint32_t *pcardstatus); - -void SD_LowLevel_Init(void) -{ - GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_SDIO); - GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_SDIO); - GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_SDIO); - GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_SDIO); - GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_SDIO); - GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_SDIO); - - /* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PD.02 CMD line */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; - GPIO_Init(GPIOD, &GPIO_InitStructure); - - /* Configure PC.12 pin: CLK pin */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Enable the SDIO APB2 Clock */ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SDIO, ENABLE); - - // SDIO Interrupt ENABLE - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); - // DMA2 STREAMx Interrupt ENABLE - NVIC_InitStructure.NVIC_IRQChannel = SD_SDIO_DMA_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_Init(&NVIC_InitStructure); -} - -void SD_LowLevel_DMA_TxConfig(uint32_t * BufferSRC, uint32_t BufferSize) -{ - DMA_InitTypeDef SDDMA_InitStructure; - - DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF); - - /* DMA2 Stream3 or Stream6 disable */ - DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE); - - /* DMA2 Stream3 or Stream6 Config */ - DMA_DeInit(SD_SDIO_DMA_STREAM); - - SDDMA_InitStructure.DMA_Channel = SD_SDIO_DMA_CHANNEL; - SDDMA_InitStructure.DMA_PeripheralBaseAddr = SD_SDIO_FIFO_ADDRESS; - SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferSRC; - SDDMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; - SDDMA_InitStructure.DMA_BufferSize = 1; - SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; - SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; - SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal; - SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; - SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; - SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; - SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4; - SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; - DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure); - DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE); - DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral); - - /* DMA2 Stream3 or Stream6 enable */ - DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE); - -} - -void SD_LowLevel_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize) -{ - DMA_InitTypeDef SDDMA_InitStructure; - - DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF); - - /* DMA2 Stream3 or Stream6 disable */ - DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE); - - /* DMA2 Stream3 or Stream6 Config */ - DMA_DeInit(SD_SDIO_DMA_STREAM); - - SDDMA_InitStructure.DMA_Channel = SD_SDIO_DMA_CHANNEL; - SDDMA_InitStructure.DMA_PeripheralBaseAddr = SD_SDIO_FIFO_ADDRESS; - SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferDST; - SDDMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; - SDDMA_InitStructure.DMA_BufferSize = 1; - SDDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - SDDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - SDDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; - SDDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; - SDDMA_InitStructure.DMA_Mode = DMA_Mode_Normal; - SDDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; - SDDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; - SDDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; - SDDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4; - SDDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_INC4; - DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure); - DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE); - DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral); - - /* DMA2 Stream3 or Stream6 enable */ - DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE); -} - -SD_Error SD_Init(void) -{ - __IO SD_Error errorstatus = SD_OK; - - /* SDIO Peripheral Low Level Init */ - SD_LowLevel_Init(); - - SDIO_DeInit(); - - errorstatus = SD_PowerON(); - if (errorstatus != SD_OK) { - TRACE("SD_PowerON() status=%d", errorstatus); - /*!< CMD Response TimeOut (wait for CMDSENT flag) */ - return errorstatus; - } - - errorstatus = SD_InitializeCards(); - if (errorstatus != SD_OK) { - TRACE("SD_InitializeCards() status=%d", errorstatus); - /*!< CMD Response TimeOut (wait for CMDSENT flag) */ - return errorstatus; - } - - /*!< Configure the SDIO peripheral */ - /*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */ - /*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */ - SDIO_InitStructure.SDIO_ClockDiv = SD_SDIO_TRANSFER_CLK_DIV; - SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; - SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; - SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; - SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b; - SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; - SDIO_Init(&SDIO_InitStructure); - - /*----------------- Read CSD/CID MSD registers ------------------*/ - errorstatus = SD_GetCardInfo(&SDCardInfo); - - if (errorstatus == SD_OK) { - /*----------------- Select Card --------------------------------*/ - errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16)); - } - - if (errorstatus == SD_OK) { - errorstatus = SD_EnableWideBusOperation(SDIO_BusWide_4b); - } - - return errorstatus; -} - -/** - * @brief Gets the cuurent sd card data transfer status. - * @param None - * @retval SDTransferState: Data Transfer state. - * This value can be: - * - SD_TRANSFER_OK: No data transfer is acting - * - SD_TRANSFER_BUSY: Data transfer is acting - */ -SDTransferState SD_GetStatus(void) -{ - SDCardState cardstate = SD_GetState(); - - if (cardstate == SD_CARD_TRANSFER) { - return SD_TRANSFER_OK; - } - else if (cardstate == SD_CARD_ERROR) { - return SD_TRANSFER_ERROR; - } - else { - return SD_TRANSFER_BUSY; - } -} - -/** - * @brief Returns the current card's state. - * @param None - * @retval SDCardState: SD Card Error or SD Card Current State. - */ -SDCardState SD_GetState(void) -{ - uint32_t resp1 = 0; - - if (SD_Detect()== SD_PRESENT) { - if (SD_SendStatus(&resp1) != SD_OK) { - return SD_CARD_ERROR; - } - else { - return (SDCardState)((resp1 >> 9) & 0x0F); - } - } - else { - return SD_CARD_ERROR; - } -} - -/** - * @brief Detect if SD card is correctly plugged in the memory slot. - * @param None - * @retval Return if SD is detected or not - */ -uint8_t SD_Detect(void) -{ - __IO uint8_t status = SD_PRESENT; - -#if 0 // TODO - /*!< Check GPIO to detect SD */ - if (GPIO_ReadInputDataBit(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) != Bit_RESET) { - status = SD_NOT_PRESENT; - } -#endif - - return status; -} - -//--------------------------------------------------------------------------------------- -//disable optimize -#define OPTIMIZE(level) __attribute__((optimize(level))) - -/** - * @brief Enquires cards about their operating voltage and configures - * clock controls. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_PowerON(void) -{ - __IO SD_Error errorstatus = SD_OK; - uint32_t response = 0, count = 0, validvoltage = 0; - uint32_t SDType = SD_STD_CAPACITY; - - /*!< Power ON Sequence -----------------------------------------------------*/ - /*!< Configure the SDIO peripheral */ - /*!< SDIO_CK = SDIOCLK / (SDIO_INIT_CLK_DIV + 2) */ - /*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */ - /*!< SDIO_CK for initialization should not exceed 400 KHz */ - SDIO_InitStructure.SDIO_ClockDiv = SD_SDIO_INIT_CLK_DIV; - SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; - SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; - SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; - SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b; - SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; - SDIO_Init(&SDIO_InitStructure); - - /*!< Set Power State to ON */ - SDIO_SetPowerState(SDIO_PowerState_ON); - - /*!< Enable SDIO Clock */ - SDIO_ClockCmd(ENABLE); - - /*!< CMD0: GO_IDLE_STATE ---------------------------------------------------*/ - /*!< No CMD response required */ - SDIO_CmdInitStructure.SDIO_Argument = 0x0; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_GO_IDLE_STATE; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_No; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdError(); - - if (errorstatus != SD_OK) { - TRACE("SD_CMD_GO_IDLE_STATE status=%d", errorstatus); - /*!< CMD Response TimeOut (wait for CMDSENT flag) */ - return errorstatus; - } - - /*!< CMD8: SEND_IF_COND ----------------------------------------------------*/ - /*!< Send CMD8 to verify SD card interface operating condition */ - /*!< Argument: - [31:12]: Reserved (shall be set to '0') - - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) - - [7:0]: Check Pattern (recommended 0xAA) */ - /*!< CMD Response: R7 */ - SDIO_CmdInitStructure.SDIO_Argument = SD_CHECK_PATTERN; - SDIO_CmdInitStructure.SDIO_CmdIndex = SDIO_SEND_IF_COND; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp7Error(); - - if (errorstatus == SD_OK) { - CardType = SDIO_STD_CAPACITY_SD_CARD_V2_0; /*!< SD Card 2.0 */ - SDType = SD_HIGH_CAPACITY; - } - else { - /*!< CMD55 */ - SDIO_CmdInitStructure.SDIO_Argument = 0x00; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - } - /*!< CMD55 */ - SDIO_CmdInitStructure.SDIO_Argument = 0x00; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - /*!< If errorstatus is Command TimeOut, it is a MMC card */ - /*!< If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch) - or SD card 1.x */ - if (errorstatus == SD_OK) { - /*!< SD CARD */ - /*!< Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */ - while ((!validvoltage) && (count < SD_MAX_VOLT_TRIAL)) { - - /*!< SEND CMD55 APP_CMD with RCA as 0 */ - SDIO_CmdInitStructure.SDIO_Argument = 0x00; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - if (errorstatus != SD_OK) { - TRACE("SD_CMD_APP_CMD status=%d", errorstatus); - return errorstatus; - } - SDIO_CmdInitStructure.SDIO_Argument = SD_VOLTAGE_WINDOW_SD | SDType; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_OP_COND; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp3Error(); - if (errorstatus != SD_OK) { - TRACE("SD_CMD_SD_APP_OP_COND status=%d", errorstatus); - return errorstatus; - } - - response = SDIO_GetResponse(SDIO_RESP1); - validvoltage = (((response >> 31) == 1) ? 1 : 0); - count++; - SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL); - } - if (count >= SD_MAX_VOLT_TRIAL) { - errorstatus = SD_INVALID_VOLTRANGE; - return errorstatus; - } - - if (response &= SD_HIGH_CAPACITY) { - CardType = SDIO_HIGH_CAPACITY_SD_CARD; - } - - } - - return errorstatus; -} - -/** - * @brief Turns the SDIO output signals off. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_PowerOFF(void) -{ - SD_Error errorstatus = SD_OK; - - /*!< Set Power State to OFF */ - SDIO_SetPowerState(SDIO_PowerState_OFF); - - return errorstatus; -} - -/** - * @brief Intialises all cards or single card as the case may be Card(s) come - * into standby state. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_InitializeCards(void) -{ - SD_Error errorstatus = SD_OK; - uint16_t rca = 0x01; - - if (SDIO_GetPowerState() == SDIO_PowerState_OFF) { - errorstatus = SD_REQUEST_NOT_APPLICABLE; - return errorstatus; - } - - if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) { - /*!< Send CMD2 ALL_SEND_CID */ - SDIO_CmdInitStructure.SDIO_Argument = 0x0; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_ALL_SEND_CID; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp2Error(); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - CID_Tab[0] = SDIO_GetResponse(SDIO_RESP1); - CID_Tab[1] = SDIO_GetResponse(SDIO_RESP2); - CID_Tab[2] = SDIO_GetResponse(SDIO_RESP3); - CID_Tab[3] = SDIO_GetResponse(SDIO_RESP4); - } - - if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_SECURE_DIGITAL_IO_COMBO_CARD == CardType) - || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) { - /*!< Send CMD3 SET_REL_ADDR with argument 0 */ - /*!< SD Card publishes its RCA. */ - SDIO_CmdInitStructure.SDIO_Argument = 0x00; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_REL_ADDR; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp6Error(SD_CMD_SET_REL_ADDR, &rca); - - if (SD_OK != errorstatus) { - return errorstatus; - } - } - - if (SDIO_SECURE_DIGITAL_IO_CARD != CardType) { - RCA = rca; - - /*!< Send CMD9 SEND_CSD with argument as card's RCA */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)(rca << 16); - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_CSD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Long; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp2Error(); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - CSD_Tab[0] = SDIO_GetResponse(SDIO_RESP1); - CSD_Tab[1] = SDIO_GetResponse(SDIO_RESP2); - CSD_Tab[2] = SDIO_GetResponse(SDIO_RESP3); - CSD_Tab[3] = SDIO_GetResponse(SDIO_RESP4); - } - - errorstatus = SD_OK; /*!< All cards get intialized */ - - return errorstatus; -} - -/** - * @brief Returns information about specific card. - * @param cardinfo: pointer to a SD_CardInfo structure that contains all SD card - * information. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_GetCardInfo(SD_CardInfo *cardinfo) -{ - SD_Error errorstatus = SD_OK; - uint8_t tmp = 0; - - cardinfo->CardType = (uint8_t)CardType; - cardinfo->RCA = (uint16_t)RCA; - - /*!< Byte 0 */ - tmp = (uint8_t)((CSD_Tab[0] & 0xFF000000) >> 24); - cardinfo->SD_csd.CSDStruct = (tmp & 0xC0) >> 6; - cardinfo->SD_csd.SysSpecVersion = (tmp & 0x3C) >> 2; - cardinfo->SD_csd.Reserved1 = tmp & 0x03; - - /*!< Byte 1 */ - tmp = (uint8_t)((CSD_Tab[0] & 0x00FF0000) >> 16); - cardinfo->SD_csd.TAAC = tmp; - - /*!< Byte 2 */ - tmp = (uint8_t)((CSD_Tab[0] & 0x0000FF00) >> 8); - cardinfo->SD_csd.NSAC = tmp; - - /*!< Byte 3 */ - tmp = (uint8_t)(CSD_Tab[0] & 0x000000FF); - cardinfo->SD_csd.MaxBusClkFrec = tmp; - - /*!< Byte 4 */ - tmp = (uint8_t)((CSD_Tab[1] & 0xFF000000) >> 24); - cardinfo->SD_csd.CardComdClasses = tmp << 4; - - /*!< Byte 5 */ - tmp = (uint8_t)((CSD_Tab[1] & 0x00FF0000) >> 16); - cardinfo->SD_csd.CardComdClasses |= (tmp & 0xF0) >> 4; - cardinfo->SD_csd.RdBlockLen = tmp & 0x0F; - - /*!< Byte 6 */ - tmp = (uint8_t)((CSD_Tab[1] & 0x0000FF00) >> 8); - cardinfo->SD_csd.PartBlockRead = (tmp & 0x80) >> 7; - cardinfo->SD_csd.WrBlockMisalign = (tmp & 0x40) >> 6; - cardinfo->SD_csd.RdBlockMisalign = (tmp & 0x20) >> 5; - cardinfo->SD_csd.DSRImpl = (tmp & 0x10) >> 4; - cardinfo->SD_csd.Reserved2 = 0; /*!< Reserved */ - - if ((CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1) || (CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0)) { - cardinfo->SD_csd.DeviceSize = (tmp & 0x03) << 10; - - /*!< Byte 7 */ - tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); - cardinfo->SD_csd.DeviceSize |= (tmp) << 2; - - /*!< Byte 8 */ - tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); - cardinfo->SD_csd.DeviceSize |= (tmp & 0xC0) >> 6; - - cardinfo->SD_csd.MaxRdCurrentVDDMin = (tmp & 0x38) >> 3; - cardinfo->SD_csd.MaxRdCurrentVDDMax = (tmp & 0x07); - - /*!< Byte 9 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); - cardinfo->SD_csd.MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5; - cardinfo->SD_csd.MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2; - cardinfo->SD_csd.DeviceSizeMul = (tmp & 0x03) << 1; - /*!< Byte 10 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); - cardinfo->SD_csd.DeviceSizeMul |= (tmp & 0x80) >> 7; - - cardinfo->CardCapacity = (cardinfo->SD_csd.DeviceSize + 1) ; - cardinfo->CardCapacity *= (1 << (cardinfo->SD_csd.DeviceSizeMul + 2)); - cardinfo->CardBlockSize = 1 << (cardinfo->SD_csd.RdBlockLen); - cardinfo->CardCapacity *= cardinfo->CardBlockSize; - } - else if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) { - /*!< Byte 7 */ - tmp = (uint8_t)(CSD_Tab[1] & 0x000000FF); - cardinfo->SD_csd.DeviceSize = (tmp & 0x3F) << 16; - - /*!< Byte 8 */ - tmp = (uint8_t)((CSD_Tab[2] & 0xFF000000) >> 24); - - cardinfo->SD_csd.DeviceSize |= (tmp << 8); - - /*!< Byte 9 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x00FF0000) >> 16); - - cardinfo->SD_csd.DeviceSize |= (tmp); - - /*!< Byte 10 */ - tmp = (uint8_t)((CSD_Tab[2] & 0x0000FF00) >> 8); - - cardinfo->CardCapacity = ((uint64_t)cardinfo->SD_csd.DeviceSize + 1) * 512 * 1024; - cardinfo->CardBlockSize = 512; - } - - - cardinfo->SD_csd.EraseGrSize = (tmp & 0x40) >> 6; - cardinfo->SD_csd.EraseGrMul = (tmp & 0x3F) << 1; - - /*!< Byte 11 */ - tmp = (uint8_t)(CSD_Tab[2] & 0x000000FF); - cardinfo->SD_csd.EraseGrMul |= (tmp & 0x80) >> 7; - cardinfo->SD_csd.WrProtectGrSize = (tmp & 0x7F); - - /*!< Byte 12 */ - tmp = (uint8_t)((CSD_Tab[3] & 0xFF000000) >> 24); - cardinfo->SD_csd.WrProtectGrEnable = (tmp & 0x80) >> 7; - cardinfo->SD_csd.ManDeflECC = (tmp & 0x60) >> 5; - cardinfo->SD_csd.WrSpeedFact = (tmp & 0x1C) >> 2; - cardinfo->SD_csd.MaxWrBlockLen = (tmp & 0x03) << 2; - - /*!< Byte 13 */ - tmp = (uint8_t)((CSD_Tab[3] & 0x00FF0000) >> 16); - cardinfo->SD_csd.MaxWrBlockLen |= (tmp & 0xC0) >> 6; - cardinfo->SD_csd.WriteBlockPaPartial = (tmp & 0x20) >> 5; - cardinfo->SD_csd.Reserved3 = 0; - cardinfo->SD_csd.ContentProtectAppli = (tmp & 0x01); - - /*!< Byte 14 */ - tmp = (uint8_t)((CSD_Tab[3] & 0x0000FF00) >> 8); - cardinfo->SD_csd.FileFormatGrouop = (tmp & 0x80) >> 7; - cardinfo->SD_csd.CopyFlag = (tmp & 0x40) >> 6; - cardinfo->SD_csd.PermWrProtect = (tmp & 0x20) >> 5; - cardinfo->SD_csd.TempWrProtect = (tmp & 0x10) >> 4; - cardinfo->SD_csd.FileFormat = (tmp & 0x0C) >> 2; - cardinfo->SD_csd.ECC = (tmp & 0x03); - - /*!< Byte 15 */ - tmp = (uint8_t)(CSD_Tab[3] & 0x000000FF); - cardinfo->SD_csd.CSD_CRC = (tmp & 0xFE) >> 1; - cardinfo->SD_csd.Reserved4 = 1; - - - /*!< Byte 0 */ - tmp = (uint8_t)((CID_Tab[0] & 0xFF000000) >> 24); - cardinfo->SD_cid.ManufacturerID = tmp; - - /*!< Byte 1 */ - tmp = (uint8_t)((CID_Tab[0] & 0x00FF0000) >> 16); - cardinfo->SD_cid.OEM_AppliID = tmp << 8; - - /*!< Byte 2 */ - tmp = (uint8_t)((CID_Tab[0] & 0x000000FF00) >> 8); - cardinfo->SD_cid.OEM_AppliID |= tmp; - - /*!< Byte 3 */ - tmp = (uint8_t)(CID_Tab[0] & 0x000000FF); - cardinfo->SD_cid.ProdName1 = tmp << 24; - - /*!< Byte 4 */ - tmp = (uint8_t)((CID_Tab[1] & 0xFF000000) >> 24); - cardinfo->SD_cid.ProdName1 |= tmp << 16; - - /*!< Byte 5 */ - tmp = (uint8_t)((CID_Tab[1] & 0x00FF0000) >> 16); - cardinfo->SD_cid.ProdName1 |= tmp << 8; - - /*!< Byte 6 */ - tmp = (uint8_t)((CID_Tab[1] & 0x0000FF00) >> 8); - cardinfo->SD_cid.ProdName1 |= tmp; - - /*!< Byte 7 */ - tmp = (uint8_t)(CID_Tab[1] & 0x000000FF); - cardinfo->SD_cid.ProdName2 = tmp; - - /*!< Byte 8 */ - tmp = (uint8_t)((CID_Tab[2] & 0xFF000000) >> 24); - cardinfo->SD_cid.ProdRev = tmp; - - /*!< Byte 9 */ - tmp = (uint8_t)((CID_Tab[2] & 0x00FF0000) >> 16); - cardinfo->SD_cid.ProdSN = tmp << 24; - - /*!< Byte 10 */ - tmp = (uint8_t)((CID_Tab[2] & 0x0000FF00) >> 8); - cardinfo->SD_cid.ProdSN |= tmp << 16; - - /*!< Byte 11 */ - tmp = (uint8_t)(CID_Tab[2] & 0x000000FF); - cardinfo->SD_cid.ProdSN |= tmp << 8; - - /*!< Byte 12 */ - tmp = (uint8_t)((CID_Tab[3] & 0xFF000000) >> 24); - cardinfo->SD_cid.ProdSN |= tmp; - - /*!< Byte 13 */ - tmp = (uint8_t)((CID_Tab[3] & 0x00FF0000) >> 16); - cardinfo->SD_cid.Reserved1 |= (tmp & 0xF0) >> 4; - cardinfo->SD_cid.ManufactDate = (tmp & 0x0F) << 8; - - /*!< Byte 14 */ - tmp = (uint8_t)((CID_Tab[3] & 0x0000FF00) >> 8); - cardinfo->SD_cid.ManufactDate |= tmp; - - /*!< Byte 15 */ - tmp = (uint8_t)(CID_Tab[3] & 0x000000FF); - cardinfo->SD_cid.CID_CRC = (tmp & 0xFE) >> 1; - cardinfo->SD_cid.Reserved2 = 1; - - return errorstatus; -} - -/** - * @brief Enables wide bus opeartion for the requeseted card if supported by - * card. - * @param WideMode: Specifies the SD card wide bus mode. - * This parameter can be one of the following values: - * @arg SDIO_BusWide_8b: 8-bit data transfer (Only for MMC) - * @arg SDIO_BusWide_4b: 4-bit data transfer - * @arg SDIO_BusWide_1b: 1-bit data transfer - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_EnableWideBusOperation(uint32_t WideMode) -{ - SD_Error errorstatus = SD_OK; - - /*!< MMC Card doesn't support this feature */ - if (SDIO_MULTIMEDIA_CARD == CardType) { - errorstatus = SD_UNSUPPORTED_FEATURE; - return errorstatus; - } - else if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType)) { - if (SDIO_BusWide_8b == WideMode) { - errorstatus = SD_UNSUPPORTED_FEATURE; - return errorstatus; - } - else if (SDIO_BusWide_4b == WideMode) { - errorstatus = SDEnWideBus(ENABLE); - - if (SD_OK == errorstatus) { - /*!< Configure the SDIO peripheral */ - SDIO_InitStructure.SDIO_ClockDiv = SD_SDIO_TRANSFER_CLK_DIV; - SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; - SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; - SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; - SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_4b; - SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; - SDIO_Init(&SDIO_InitStructure); - } - } - else { - errorstatus = SDEnWideBus(DISABLE); - - if (SD_OK == errorstatus) { - /*!< Configure the SDIO peripheral */ - SDIO_InitStructure.SDIO_ClockDiv = SD_SDIO_TRANSFER_CLK_DIV; - SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; - SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; - SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; - SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b; - SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; - SDIO_Init(&SDIO_InitStructure); - } - } - } - - return errorstatus; -} - -/** - * @brief Selects od Deselects the corresponding card. - * @param addr: Address of the Card to be selected. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_SelectDeselect(uint32_t addr) -{ - SD_Error errorstatus; - - /*!< Send CMD7 SDIO_SEL_DESEL_CARD */ - SDIO_CmdInitStructure.SDIO_Argument = addr; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEL_DESEL_CARD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SEL_DESEL_CARD); - - return errorstatus; -} - -/** - * @brief Allows to read one block from a specified address in a card. The Data - * transfer can be managed by DMA mode or Polling mode. - * @note This operation should be followed by two functions to check if the - * DMA Controller and SD Card status. - * - SD_ReadWaitOperation(): this function insure that the DMA - * controller has finished all data transfer. - * - SD_GetStatus(): to check that the SD Card has finished the - * data transfer and it is ready for data. - * @param readbuff: pointer to the buffer that will contain the received data - * @param ReadAddr: Address from where data are to be read. - * @param BlockSize: the SD card Data block size. The Block size should be 512. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize) -{ - SD_Error errorstatus = SD_OK; - - TransferError = SD_OK; - TransferEnd = 0; - StopCondition = 0; - DMAEndOfTransfer = 0; - - SDIO->DCTRL = 0x0; - - SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE); - SDIO_DMACmd(ENABLE); - SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize); - - if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) - BlockSize = 512; - else - ReadAddr *= 512; - - /* Set Block Size for Card */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; - SDIO_DataInitStructure.SDIO_DataLength = BlockSize; - SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_512b; - SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO; - SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; - SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; - SDIO_DataConfig(&SDIO_DataInitStructure); - - /*!< Send CMD17 READ_SINGLE_BLOCK */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_SINGLE_BLOCK; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_READ_SINGLE_BLOCK); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - return errorstatus; -} - -/** - * @brief Allows to read blocks from a specified address in a card. The Data - * transfer can be managed by DMA mode or Polling mode. - * @note This operation should be followed by two functions to check if the - * DMA Controller and SD Card status. - * - SD_ReadWaitOperation(): this function insure that the DMA - * controller has finished all data transfer. - * - SD_GetStatus(): to check that the SD Card has finished the - * data transfer and it is ready for data. - * @param readbuff: pointer to the buffer that will contain the received data. - * @param ReadAddr: Address from where data are to be read. - * @param BlockSize: the SD card Data block size. The Block size should be 512. - * @param NumberOfBlocks: number of blocks to be read. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) -{ - SD_Error errorstatus = SD_OK; - TransferError = SD_OK; - TransferEnd = 0; - StopCondition = 1; - DMAEndOfTransfer = 0; - - SDIO->DCTRL = 0x0; - - SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE); - SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, (NumberOfBlocks * BlockSize)); - SDIO_DMACmd(ENABLE); - - if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) - BlockSize = 512; - else - ReadAddr *= 512; - - /*!< Set Block Size for Card */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT * NumberOfBlocks; - SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize; - SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_512b; - SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO; - SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; - SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; - SDIO_DataConfig(&SDIO_DataInitStructure); - - /*!< Send CMD18 READ_MULT_BLOCK with argument data address */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_MULT_BLOCK; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_READ_MULT_BLOCK); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - return errorstatus; -} - -/** - * @brief This function waits until the SDIO DMA data transfer is finished. - * This function should be called after SDIO_ReadMultiBlocks() function - * to insure that all data sent by the card are already transferred by - * the DMA controller. - * @param None. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_WaitReadOperation(uint32_t timeout) -{ - SD_Error errorstatus = SD_OK; - - while (!DMAEndOfTransfer && !TransferEnd && (TransferError == SD_OK) && (timeout > 0)) { - delay_ms(1); - timeout--; - } -#if !defined(BOOT) - TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_read, (TransferError << 8) + (DMAEndOfTransfer << 1) + TransferEnd); -#endif - - DMAEndOfTransfer = 0; - - timeout = 100; - - while(((SDIO->STA & SDIO_FLAG_RXACT)) && (timeout > 0)) { - delay_ms(1); - timeout--; - } -#if !defined(BOOT) - TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_read, -1); -#endif - - if (StopCondition == 1) { - errorstatus = SD_StopTransfer(); - StopCondition = 0; - } - - if ((timeout == 0) && (errorstatus == SD_OK)) { - errorstatus = SD_DATA_TIMEOUT; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - if (TransferError != SD_OK) { - return TransferError; - } - else { - return errorstatus; - } -} - -/** - * @brief Allows to write one block starting from a specified address in a card. - * The Data transfer can be managed by DMA mode or Polling mode. - * @note This operation should be followed by two functions to check if the - * DMA Controller and SD Card status. - * - SD_ReadWaitOperation(): this function insure that the DMA - * controller has finished all data transfer. - * - SD_GetStatus(): to check that the SD Card has finished the - * data transfer and it is ready for data. - * @param writebuff: pointer to the buffer that contain the data to be transferred. - * @param WriteAddr: Address from where data are to be read. - * @param BlockSize: the SD card Data block size. The Block size should be 512. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize) -{ - SD_Error errorstatus = SD_OK; - - TransferError = SD_OK; - TransferEnd = 0; - StopCondition = 0; - - SDIO->DCTRL = 0x0; - - SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE); - SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, BlockSize); - SDIO_DMACmd(ENABLE); - - if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) - BlockSize = 512; - else - WriteAddr *= 512; - - /* Set Block Size for Card */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - /*!< Send CMD24 WRITE_SINGLE_BLOCK */ - SDIO_CmdInitStructure.SDIO_Argument = WriteAddr; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_WRITE_SINGLE_BLOCK); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; - SDIO_DataInitStructure.SDIO_DataLength = BlockSize; - SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_512b; - SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard; - SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; - SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; - SDIO_DataConfig(&SDIO_DataInitStructure); - - return errorstatus; -} - -/** - * @brief Allows to write blocks starting from a specified address in a card. - * The Data transfer can be managed by DMA mode only. - * @note This operation should be followed by two functions to check if the - * DMA Controller and SD Card status. - * - SD_ReadWaitOperation(): this function insure that the DMA - * controller has finished all data transfer. - * - SD_GetStatus(): to check that the SD Card has finished the - * data transfer and it is ready for data. - * @param WriteAddr: Address from where data are to be read. - * @param writebuff: pointer to the buffer that contain the data to be transferred. - * @param BlockSize: the SD card Data block size. The Block size should be 512. - * @param NumberOfBlocks: number of blocks to be written. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) -{ - SD_Error errorstatus = SD_OK; - - TransferError = SD_OK; - TransferEnd = 0; - StopCondition = 1; - - SDIO->DCTRL = 0x0; - - SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR, ENABLE); - SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, (NumberOfBlocks * BlockSize)); - SDIO_DMACmd(ENABLE); - - if (CardType == SDIO_HIGH_CAPACITY_SD_CARD) { - BlockSize = 512; - } - else { - WriteAddr *= 512; - } - - /* Set Block Size for Card */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - /*!< To improve performance */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16); - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - if (errorstatus != SD_OK) { - return errorstatus; - } - /*!< To improve performance */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)NumberOfBlocks; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCK_COUNT; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCK_COUNT); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - - /*!< Send CMD25 WRITE_MULT_BLOCK with argument data address */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)WriteAddr; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_MULT_BLOCK; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_WRITE_MULT_BLOCK); - - if (SD_OK != errorstatus) { - return errorstatus; - } - - SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT * NumberOfBlocks; - SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize; - SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_512b; - SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToCard; - SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; - SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; - SDIO_DataConfig(&SDIO_DataInitStructure); - - return errorstatus; -} - - -/** - * @brief This function waits until the SDIO DMA data transfer is finished. - * This function should be called after SDIO_WriteBlock() and - * SDIO_WriteMultiBlocks() function to insure that all data sent by the - * card are already transferred by the DMA controller. - * @param None. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_WaitWriteOperation(uint32_t timeout) -{ - SD_Error errorstatus = SD_OK; - - while (!DMAEndOfTransfer && !TransferEnd && (TransferError == SD_OK) && (timeout > 0)) { - delay_ms(1); - timeout--; - } -#if !defined(BOOT) - TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_write, (TransferError << 8) + (DMAEndOfTransfer << 1) + TransferEnd); -#endif - - DMAEndOfTransfer = 0; - - timeout = 100; - - while(((SDIO->STA & SDIO_FLAG_TXACT)) && (timeout > 0)) { - delay_ms(1); - timeout--; - } -#if !defined(BOOT) - TRACE_SD_CARD_EVENT((timeout == 0), sd_wait_write, -1); -#endif - - if (StopCondition == 1) { - errorstatus = SD_StopTransfer(); - StopCondition = 0; - } - - if ((timeout == 0) && (errorstatus == SD_OK)) { - errorstatus = SD_DATA_TIMEOUT; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - if (TransferError != SD_OK) { - return TransferError; - } - else { - return errorstatus; - } -} - -/** - * @brief Gets the cuurent data transfer state. - * @param None - * @retval SDTransferState: Data Transfer state. - * This value can be: - * - SD_TRANSFER_OK: No data transfer is acting - * - SD_TRANSFER_BUSY: Data transfer is acting - */ -OPTIMIZE("O0") SDTransferState SD_GetTransferState(void) -{ - if (SDIO->STA & (SDIO_FLAG_TXACT | SDIO_FLAG_RXACT)) { - return SD_TRANSFER_BUSY; - } - else { - return SD_TRANSFER_OK; - } -} - -/** - * @brief Aborts an ongoing data transfer. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_StopTransfer(void) -{ - SD_Error errorstatus = SD_OK; - - /*!< Send CMD12 STOP_TRANSMISSION */ - SDIO_CmdInitStructure.SDIO_Argument = 0x0; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_STOP_TRANSMISSION; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_STOP_TRANSMISSION); - - return errorstatus; -} - -/** - * @brief Returns the current card's status. - * @param pcardstatus: pointer to the buffer that will contain the SD card - * status (Card Status register). - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") SD_Error SD_SendStatus(uint32_t *pcardstatus) -{ - SD_Error errorstatus = SD_OK; - - if (pcardstatus == NULL) { - errorstatus = SD_INVALID_PARAMETER; - return errorstatus; - } - - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SEND_STATUS; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SEND_STATUS); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - *pcardstatus = SDIO_GetResponse(SDIO_RESP1); - - return errorstatus; -} - -/** - * @brief Allows to process all the interrupts that are high. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") void SD_ProcessIRQ(void) -{ - if (SDIO_GetITStatus(SDIO_IT_DATAEND) != RESET) { - TransferError = SD_OK; - SDIO_ClearITPendingBit(SDIO_IT_DATAEND); - TransferEnd = 1; - } - else if (SDIO_GetITStatus(SDIO_IT_DCRCFAIL) != RESET) { - SDIO_ClearITPendingBit(SDIO_IT_DCRCFAIL); - TransferError = SD_DATA_CRC_FAIL; - } - else if (SDIO_GetITStatus(SDIO_IT_DTIMEOUT) != RESET) { - SDIO_ClearITPendingBit(SDIO_IT_DTIMEOUT); - TransferError = SD_DATA_TIMEOUT; - } - else if (SDIO_GetITStatus(SDIO_IT_RXOVERR) != RESET) { - SDIO_ClearITPendingBit(SDIO_IT_RXOVERR); - TransferError = SD_RX_OVERRUN; - } - else if (SDIO_GetITStatus(SDIO_IT_TXUNDERR) != RESET) { - SDIO_ClearITPendingBit(SDIO_IT_TXUNDERR); - TransferError = SD_TX_UNDERRUN; - } - else if (SDIO_GetITStatus(SDIO_IT_STBITERR) != RESET) { - SDIO_ClearITPendingBit(SDIO_IT_STBITERR); - TransferError = SD_START_BIT_ERR; - } - - SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | - SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR | - SDIO_IT_RXOVERR | SDIO_IT_STBITERR, DISABLE); - -#if !defined(BOOT) - TRACE_SD_CARD_EVENT((TransferError != SD_OK), sd_irq, TransferError); -#endif -} - -/** - * @brief This function waits until the SDIO DMA data transfer is finished. - * @param None. - * @retval None. - */ -OPTIMIZE("O0") void SD_ProcessDMAIRQ(void) -{ - if (DMA2->LISR & SD_SDIO_DMA_FLAG_TCIF) { - DMAEndOfTransfer = 1; - DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_TCIF|SD_SDIO_DMA_FLAG_FEIF); - } -} - -/** - * @brief Checks for error conditions for CMD0. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdError(void) -{ - SD_Error errorstatus = SD_OK; - uint32_t timeout; - - timeout = SDIO_CMD0TIMEOUT; /*!< 10000 */ - - while ((timeout > 0) && (SDIO_GetFlagStatus(SDIO_FLAG_CMDSENT) == RESET)) { - timeout--; - } - - if (timeout == 0) { - errorstatus = SD_CMD_RSP_TIMEOUT; - return errorstatus; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - return errorstatus; -} - -/** - * @brief Checks for error conditions for R7 response. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdResp7Error(void) -{ - SD_Error errorstatus = SD_OK; - uint32_t status; - uint32_t timeout = SDIO_CMD0TIMEOUT; - - status = SDIO->STA; - - while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) && (timeout > 0)) { - timeout--; - status = SDIO->STA; - } - - if ((timeout == 0) || (status & SDIO_FLAG_CTIMEOUT)) { - /*!< Card is not V2.0 complient or card does not support the set voltage range */ - errorstatus = SD_CMD_RSP_TIMEOUT; - SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); - return errorstatus; - } - - if (status & SDIO_FLAG_CMDREND) { - /*!< Card is SD V2.0 compliant */ - errorstatus = SD_OK; - SDIO_ClearFlag(SDIO_FLAG_CMDREND); - return errorstatus; - } - return errorstatus; -} - -/** - * @brief Checks for error conditions for R1 response. - * @param cmd: The sent command index. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdResp1Error(uint8_t cmd) -{ - SD_Error errorstatus = SD_OK; - uint32_t status; - uint32_t response_r1; - - status = SDIO->STA; - - while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))) { - status = SDIO->STA; - } - - if (status & SDIO_FLAG_CTIMEOUT) { - errorstatus = SD_CMD_RSP_TIMEOUT; - SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); - return errorstatus; - } - else if (status & SDIO_FLAG_CCRCFAIL) { - errorstatus = SD_CMD_CRC_FAIL; - SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL); - return errorstatus; - } - - /*!< Check response received is of desired command */ - if (SDIO_GetCommandResponse() != cmd) { - errorstatus = SD_ILLEGAL_CMD; - return errorstatus; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - /*!< We have received response, retrieve it for analysis */ - response_r1 = SDIO_GetResponse(SDIO_RESP1); - - if ((response_r1 & SD_OCR_ERRORBITS) == SD_ALLZERO) { - return errorstatus; - } - - if (response_r1 & SD_OCR_ADDR_OUT_OF_RANGE) { - return SD_ADDR_OUT_OF_RANGE; - } - - if (response_r1 & SD_OCR_ADDR_MISALIGNED) { - return SD_ADDR_MISALIGNED; - } - - if (response_r1 & SD_OCR_BLOCK_LEN_ERR) { - return SD_BLOCK_LEN_ERR; - } - - if (response_r1 & SD_OCR_ERASE_SEQ_ERR) { - return SD_ERASE_SEQ_ERR; - } - - if (response_r1 & SD_OCR_BAD_ERASE_PARAM) { - return SD_BAD_ERASE_PARAM; - } - - if (response_r1 & SD_OCR_WRITE_PROT_VIOLATION) { - return SD_WRITE_PROT_VIOLATION; - } - - if (response_r1 & SD_OCR_LOCK_UNLOCK_FAILED) { - return SD_LOCK_UNLOCK_FAILED; - } - - if (response_r1 & SD_OCR_COM_CRC_FAILED) { - return SD_COM_CRC_FAILED; - } - - if (response_r1 & SD_OCR_ILLEGAL_CMD) { - return SD_ILLEGAL_CMD; - } - - if (response_r1 & SD_OCR_CARD_ECC_FAILED) { - return SD_CARD_ECC_FAILED; - } - - if (response_r1 & SD_OCR_CC_ERROR) { - return SD_CC_ERROR; - } - - if (response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR) { - return SD_GENERAL_UNKNOWN_ERROR; - } - - if (response_r1 & SD_OCR_STREAM_READ_UNDERRUN) { - return SD_STREAM_READ_UNDERRUN; - } - - if (response_r1 & SD_OCR_STREAM_WRITE_OVERRUN) { - return SD_STREAM_WRITE_OVERRUN; - } - - if (response_r1 & SD_OCR_CID_CSD_OVERWRIETE) { - return SD_CID_CSD_OVERWRITE; - } - - if (response_r1 & SD_OCR_WP_ERASE_SKIP) { - return SD_WP_ERASE_SKIP; - } - - if (response_r1 & SD_OCR_CARD_ECC_DISABLED) { - return SD_CARD_ECC_DISABLED; - } - - if (response_r1 & SD_OCR_ERASE_RESET) { - return SD_ERASE_RESET; - } - - if (response_r1 & SD_OCR_AKE_SEQ_ERROR) { - return SD_AKE_SEQ_ERROR; - } - - return errorstatus; -} - -/** - * @brief Checks for error conditions for R3 (OCR) response. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdResp3Error(void) -{ - SD_Error errorstatus = SD_OK; - uint32_t status; - - status = SDIO->STA; - - while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT))) { - status = SDIO->STA; - } - - if (status & SDIO_FLAG_CTIMEOUT) { - errorstatus = SD_CMD_RSP_TIMEOUT; - SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); - return errorstatus; - } - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - return errorstatus; -} - -/** - * @brief Checks for error conditions for R2 (CID or CSD) response. - * @param None - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdResp2Error(void) -{ - SD_Error errorstatus = SD_OK; - uint32_t status; - - status = SDIO->STA; - - while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND))) { - status = SDIO->STA; - } - - if (status & SDIO_FLAG_CTIMEOUT) { - errorstatus = SD_CMD_RSP_TIMEOUT; - SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); - return errorstatus; - } - else if (status & SDIO_FLAG_CCRCFAIL) { - errorstatus = SD_CMD_CRC_FAIL; - SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL); - return errorstatus; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - return errorstatus; -} - -/** - * @brief Checks for error conditions for R6 (RCA) response. - * @param cmd: The sent command index. - * @param prca: pointer to the variable that will contain the SD card relative - * address RCA. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error CmdResp6Error(uint8_t cmd, uint16_t *prca) -{ - SD_Error errorstatus = SD_OK; - uint32_t status; - uint32_t response_r1; - - status = SDIO->STA; - - while (!(status & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND))) { - status = SDIO->STA; - } - - if (status & SDIO_FLAG_CTIMEOUT) { - errorstatus = SD_CMD_RSP_TIMEOUT; - SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT); - return errorstatus; - } - else if (status & SDIO_FLAG_CCRCFAIL) { - errorstatus = SD_CMD_CRC_FAIL; - SDIO_ClearFlag(SDIO_FLAG_CCRCFAIL); - return errorstatus; - } - - /*!< Check response received is of desired command */ - if (SDIO_GetCommandResponse() != cmd) { - errorstatus = SD_ILLEGAL_CMD; - return errorstatus; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - /*!< We have received response, retrieve it. */ - response_r1 = SDIO_GetResponse(SDIO_RESP1); - - if (SD_ALLZERO == (response_r1 & (SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED))) { - *prca = (uint16_t) (response_r1 >> 16); - return errorstatus; - } - - if (response_r1 & SD_R6_GENERAL_UNKNOWN_ERROR) { - return SD_GENERAL_UNKNOWN_ERROR; - } - - if (response_r1 & SD_R6_ILLEGAL_CMD) { - return SD_ILLEGAL_CMD; - } - - if (response_r1 & SD_R6_COM_CRC_FAILED) { - return SD_COM_CRC_FAILED; - } - - return errorstatus; -} - -/** - * @brief Enables or disables the SDIO wide bus mode. - * @param NewState: new state of the SDIO wide bus mode. - * This parameter can be: ENABLE or DISABLE. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error SDEnWideBus(FunctionalState NewState) -{ - SD_Error errorstatus = SD_OK; - - uint32_t scr[2] = {0, 0}; - - if (SDIO_GetResponse(SDIO_RESP1) & SD_CARD_LOCKED) { - errorstatus = SD_LOCK_UNLOCK_FAILED; - return errorstatus; - } - - /*!< Get SCR Register */ - errorstatus = FindSCR(RCA, scr); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - /*!< If wide bus operation to be enabled */ - if (NewState == ENABLE) { - /*!< If requested card supports wide bus operation */ - if ((scr[1] & SD_WIDE_BUS_SUPPORT) != SD_ALLZERO) { - /*!< Send CMD55 APP_CMD with argument as card's RCA.*/ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - /*!< Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ - SDIO_CmdInitStructure.SDIO_Argument = 0x2; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH); - - if (errorstatus != SD_OK) { - return errorstatus; - } - return errorstatus; - } - else { - errorstatus = SD_REQUEST_NOT_APPLICABLE; - return errorstatus; - } - } /*!< If wide bus operation to be disabled */ - else { - /*!< If requested card supports 1 bit mode operation */ - if ((scr[1] & SD_SINGLE_BUS_SUPPORT) != SD_ALLZERO) { - /*!< Send CMD55 APP_CMD with argument as card's RCA.*/ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - /*!< Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ - SDIO_CmdInitStructure.SDIO_Argument = 0x00; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_APP_SD_SET_BUSWIDTH); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - return errorstatus; - } - else { - errorstatus = SD_REQUEST_NOT_APPLICABLE; - return errorstatus; - } - } -} - -/** - * @brief Find the SD card SCR register value. - * @param rca: selected card address. - * @param pscr: pointer to the buffer that will contain the SCR value. - * @retval SD_Error: SD Card Error code. - */ -OPTIMIZE("O0") static SD_Error FindSCR(uint16_t rca, uint32_t *pscr) -{ - uint32_t index = 0; - SD_Error errorstatus = SD_OK; - uint32_t tempscr[2] = {0, 0}; - - /*!< Set Block Size To 8 Bytes */ - /*!< Send CMD55 APP_CMD with argument as card's RCA */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)8; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SET_BLOCKLEN); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - /*!< Send CMD55 APP_CMD with argument as card's RCA */ - SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_APP_CMD); - - if (errorstatus != SD_OK) { - return errorstatus; - } - SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT; - SDIO_DataInitStructure.SDIO_DataLength = 8; - SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_8b; - SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO; - SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block; - SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable; - SDIO_DataConfig(&SDIO_DataInitStructure); - - - /*!< Send ACMD51 SD_APP_SEND_SCR with argument as 0 */ - SDIO_CmdInitStructure.SDIO_Argument = 0x0; - SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_SEND_SCR; - SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; - SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No; - SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable; - SDIO_SendCommand(&SDIO_CmdInitStructure); - - errorstatus = CmdResp1Error(SD_CMD_SD_APP_SEND_SCR); - - if (errorstatus != SD_OK) { - return errorstatus; - } - - while (!(SDIO->STA & (SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR))) { - if (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET) { - *(tempscr + index) = SDIO_ReadData(); - index++; - } - } - - if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET) { - SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT); - errorstatus = SD_DATA_TIMEOUT; - return errorstatus; - } - else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET) { - SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL); - errorstatus = SD_DATA_CRC_FAIL; - return errorstatus; - } - else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET) { - SDIO_ClearFlag(SDIO_FLAG_RXOVERR); - errorstatus = SD_RX_OVERRUN; - return errorstatus; - } - else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET) { - SDIO_ClearFlag(SDIO_FLAG_STBITERR); - errorstatus = SD_START_BIT_ERR; - return errorstatus; - } - - /*!< Clear all the static flags */ - SDIO_ClearFlag(SDIO_STATIC_FLAGS); - - *(pscr + 1) = ((tempscr[0] & SD_0TO7BITS) << 24) | ((tempscr[0] & SD_8TO15BITS) << 8) | ((tempscr[0] & SD_16TO23BITS) >> 8) | ((tempscr[0] & SD_24TO31BITS) >> 24); - - *(pscr) = ((tempscr[1] & SD_0TO7BITS) << 24) | ((tempscr[1] & SD_8TO15BITS) << 8) | ((tempscr[1] & SD_16TO23BITS) >> 8) | ((tempscr[1] & SD_24TO31BITS) >> 24); - - return errorstatus; -} - -void SDIO_IRQHandler(void) -{ - DEBUG_INTERRUPT(INT_SDIO); - SD_ProcessIRQ(); -} - -void SD_SDIO_DMA_IRQHANDLER(void) -{ - DEBUG_INTERRUPT(INT_SDIO_DMA); - SD_ProcessDMAIRQ(); -} - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/radio/src/targets/common/arm/stm32/sdio_sd.cpp b/radio/src/targets/common/arm/stm32/sdio_sd.cpp new file mode 100644 index 00000000000..dc2d9d20484 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/sdio_sd.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sdio_sd.h" +#include "stm32_dma.h" +#include "stm32_gpio_driver.h" + +#include "stm32_hal_ll.h" +#include "stm32_hal.h" + +#include "hal.h" + +#include "delays_driver.h" +#include "debug.h" + +/* Configure PC.08, PC.09, PC.10, PC.11 pins: D0, D1, D2, D3 pins */ +#if !defined(SD_SDIO_DATA_GPIO) && !defined(SD_SDIO_DATA_GPIO_PINS) +#define SD_SDIO_DATA_GPIO GPIOC +#define SD_SDIO_DATA_GPIO_PINS \ + (LL_GPIO_PIN_8 | LL_GPIO_PIN_9 | LL_GPIO_PIN_10 | LL_GPIO_PIN_11) +#endif + +/* Configure PD.02 CMD line */ +#if !defined(SD_SDIO_CMD_GPIO) && !defined(SD_SDIO_CMD_GPIO_PIN) +#define SD_SDIO_CMD_GPIO GPIOD +#define SD_SDIO_CMD_GPIO_PIN LL_GPIO_PIN_2 +#endif + +#if !defined(SD_SDIO_CLK_GPIO) && !defined(SD_SDIO_CLK_GPIO_PIN) +#define SD_SDIO_CLK_GPIO GPIOC +#define SD_SDIO_CLK_GPIO_PIN LL_GPIO_PIN_12 +#endif + +static SD_HandleTypeDef sdio; +static DMA_HandleTypeDef sdioTxDma; + +// Disk status +volatile uint32_t WriteStatus = 0; +volatile uint32_t ReadStatus = 0; + +static void SD_LowLevel_Init(void) +{ + /* Enable the SDIO APB2 Clock */ + __HAL_RCC_SDIO_CLK_ENABLE(); + + LL_GPIO_InitTypeDef GPIO_InitStructure; + LL_GPIO_StructInit(&GPIO_InitStructure); + + stm32_gpio_enable_clock(SD_SDIO_DATA_GPIO); + stm32_gpio_enable_clock(SD_SDIO_CMD_GPIO); + stm32_gpio_enable_clock(SD_SDIO_CLK_GPIO); + + GPIO_InitStructure.Pin = SD_SDIO_DATA_GPIO_PINS; + GPIO_InitStructure.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStructure.Mode = LL_GPIO_MODE_ALTERNATE; + GPIO_InitStructure.OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStructure.Pull = LL_GPIO_PULL_UP; + GPIO_InitStructure.Alternate = LL_GPIO_AF_12; // SDIO + LL_GPIO_Init(SD_SDIO_DATA_GPIO, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = SD_SDIO_CMD_GPIO_PIN; + LL_GPIO_Init(SD_SDIO_CMD_GPIO, &GPIO_InitStructure); + + /* Configure PC.12 pin: CLK pin */ + GPIO_InitStructure.Pin = SD_SDIO_CLK_GPIO_PIN; + GPIO_InitStructure.Pull = LL_GPIO_PULL_NO; + LL_GPIO_Init(SD_SDIO_CLK_GPIO, &GPIO_InitStructure); + + // SDIO Interrupt ENABLE + NVIC_SetPriority(SDIO_IRQn, 0); + NVIC_EnableIRQ(SDIO_IRQn); + + // Init SDIO DMA instance + sdioTxDma.Instance = SD_SDIO_DMA_STREAM; + sdioTxDma.Init.Channel = SD_SDIO_DMA_CHANNEL; + sdioTxDma.Init.PeriphInc = DMA_PINC_DISABLE; + sdioTxDma.Init.MemInc = DMA_MINC_ENABLE; + sdioTxDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + sdioTxDma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + sdioTxDma.Init.Mode = DMA_PFCTRL; + sdioTxDma.Init.Priority = DMA_PRIORITY_VERY_HIGH; + sdioTxDma.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + sdioTxDma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + sdioTxDma.Init.MemBurst = DMA_MBURST_INC4; + sdioTxDma.Init.PeriphBurst = DMA_PBURST_INC4; + + stm32_dma_enable_clock(SD_SDIO_DMA); + HAL_DMA_Init(&sdioTxDma); + + __HAL_LINKDMA(&sdio, hdmatx, sdioTxDma); + __HAL_LINKDMA(&sdio, hdmarx, sdioTxDma); + + // DMA2 STREAMx Interrupt ENABLE + NVIC_SetPriority(SD_SDIO_DMA_IRQn, 0); + NVIC_EnableIRQ(SD_SDIO_DMA_IRQn); +} + +SD_Error SD_Init(void) +{ + static bool _sdio_init = false; + + if(_sdio_init) return SD_OK; + _sdio_init = true; + + __IO SD_Error errorstatus = SD_OK; + + /* SDIO Peripheral Low Level Init */ + SD_LowLevel_Init(); + + /*!< Configure the SDIO peripheral */ + /*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */ + /*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */ + sdio.Instance = SDIO; + sdio.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + sdio.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + sdio.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + sdio.Init.BusWide = SDIO_BUS_WIDE_1B; + sdio.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + sdio.Init.ClockDiv = SD_SDIO_TRANSFER_CLK_DIV; + HAL_SD_DeInit(&sdio); + + HAL_StatusTypeDef halStatus = HAL_SD_Init(&sdio); + if (halStatus != HAL_OK) { + TRACE("SD_PowerON() status=%d", halStatus); + /*!< CMD Response TimeOut (wait for CMDSENT flag) */ + return SD_ERROR; + } + + HAL_SD_CardInfoTypeDef cardInfo; + HAL_StatusTypeDef es = HAL_SD_GetCardInfo(&sdio, &cardInfo); + if(es != HAL_OK) + return SD_ERROR; + + HAL_SD_ConfigWideBusOperation(&sdio, SDIO_BUS_WIDE_4B); + + return errorstatus; +} + +/** + * @brief Gets the cuurent sd card data transfer status. + * @param None + * @retval SDTransferState: Data Transfer state. + * This value can be: + * - SD_TRANSFER_OK: No data transfer is acting + * - SD_TRANSFER_BUSY: Data transfer is acting + */ +SDTransferState SD_GetStatus(void) +{ + HAL_SD_CardStateTypeDef cardstate = HAL_SD_GetCardState(&sdio); + + if (cardstate == HAL_SD_CARD_TRANSFER) { + return SD_TRANSFER_OK; + } + else if (cardstate == HAL_SD_CARD_ERROR) { + return SD_TRANSFER_ERROR; + } + + // auto err = HAL_SD_GetError(&sdio); + // if (err != HAL_SD_ERROR_NONE) { + // return SD_TRANSFER_ERROR; + // } + + return SD_TRANSFER_BUSY; +} + +int SD_CheckStatusWithTimeout(uint32_t timeout) +{ + uint32_t timer = HAL_GetTick(); + /* block until SDIO IP is ready again or a timeout occur */ + while(HAL_GetTick() - timer < timeout) { + auto state = SD_GetStatus(); + if (state != SD_TRANSFER_BUSY) { + return state == SD_TRANSFER_OK ? 0 : -1; + } + } + + return -1; +} + +/** + * @brief Detect if SD card is correctly plugged in the memory slot. + * @param None + * @retval Return if SD is detected or not + */ +uint8_t SD_Detect(void) +{ + __IO uint8_t status = SD_PRESENT; + + /*!< Check GPIO to detect SD */ + if ((LL_GPIO_ReadInputPort(SD_PRESENT_GPIO) & SD_PRESENT_LL_GPIO_PIN) != 0) { + status = SD_NOT_PRESENT; + } + + return status; +} + +/** + * @brief Returns information about specific card. + * @param cardinfo: pointer to a SD_CardInfo structure that contains all SD card + * information. + * @retval SD_Error: SD Card Error code. + */ +SD_Error SD_GetCardInfo(HAL_SD_CardInfoTypeDef *cardinfo) +{ + if(HAL_SD_GetCardInfo(&sdio, cardinfo) != HAL_OK) + return SD_ERROR; + + return SD_OK; +} + +/** + * @brief Allows to read blocks from a specified address in a card. The Data + * transfer can be managed by DMA mode or Polling mode. + * @note This operation should be followed by two functions to check if the + * DMA Controller and SD Card status. + * - SD_ReadWaitOperation(): this function insure that the DMA + * controller has finished all data transfer. + * - SD_GetStatus(): to check that the SD Card has finished the + * data transfer and it is ready for data. + * @param readbuff: pointer to the buffer that will contain the received data. + * @param ReadAddr: Address from where data are to be read. + * @param BlockSize: the SD card Data block size. The Block size should be 512. + * @param NumberOfBlocks: number of blocks to be read. + * @retval SD_Error: SD Card Error code. + */ +SD_Error SD_ReadBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) +{ + HAL_StatusTypeDef res = HAL_SD_ReadBlocks_DMA(&sdio, readbuff, ReadAddr, NumberOfBlocks); + if(res == HAL_OK) + return SD_OK; + + return SD_ERROR; +} + +// /** +// * @brief This function waits until the SDIO DMA data transfer is finished. +// * This function should be called after SDIO_ReadMultiBlocks() function +// * to insure that all data sent by the card are already transferred by +// * the DMA controller. +// * @param None. +// * @retval SD_Error: SD Card Error code. +// */ +// SD_Error SD_WaitReadOperation(uint32_t timeout) +// { +// volatile HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&sdio); +// if(state == HAL_SD_CARD_READY || state == HAL_SD_CARD_TRANSFER) +// return SD_OK; +// timeout = 100; + +// while((HAL_SD_GetCardState(&sdio) == HAL_SD_CARD_SENDING) && (timeout > 0)) { +// delay_ms(1); +// timeout--; +// } + +// state = HAL_SD_GetCardState(&sdio); +// if(timeout > 0 && state == HAL_SD_CARD_TRANSFER) +// return SD_OK; + +// return SD_ERROR; +// } + +/** + * @brief Allows to write blocks starting from a specified address in a card. + * The Data transfer can be managed by DMA mode only. + * @note This operation should be followed by two functions to check if the + * DMA Controller and SD Card status. + * - SD_ReadWaitOperation(): this function insure that the DMA + * controller has finished all data transfer. + * - SD_GetStatus(): to check that the SD Card has finished the + * data transfer and it is ready for data. + * @param WriteAddr: Address from where data are to be read. + * @param writebuff: pointer to the buffer that contain the data to be transferred. + * @param BlockSize: the SD card Data block size. The Block size should be 512. + * @param NumberOfBlocks: number of blocks to be written. + * @retval SD_Error: SD Card Error code. + */ +SD_Error SD_WriteBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks) +{ + HAL_StatusTypeDef res = HAL_SD_WriteBlocks_DMA(&sdio, writebuff, WriteAddr, NumberOfBlocks); + if(res == HAL_OK) + return SD_OK; + return SD_ERROR; +} + +// /** +// * @brief This function waits until the SDIO DMA data transfer is finished. +// * This function should be called after SDIO_WriteBlock() and +// * SDIO_WriteMultiBlocks() function to insure that all data sent by the +// * card are already transferred by the DMA controller. +// * @param None. +// * @retval SD_Error: SD Card Error code. +// */ +// OPTIMIZE("O0") SD_Error SD_WaitWriteOperation(uint32_t timeout) +// { +// HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&sdio); +// if(state == HAL_SD_CARD_READY || state == HAL_SD_CARD_TRANSFER) +// return SD_OK; + +// timeout = 1000; + +// state = HAL_SD_GetCardState(&sdio); +// while((state == HAL_SD_CARD_RECEIVING || state == HAL_SD_CARD_PROGRAMMING) && (timeout > 0)) { +// delay_ms(1); +// timeout--; +// state = HAL_SD_GetCardState(&sdio); +// } + +// state = HAL_SD_GetCardState(&sdio); +// if(timeout > 0 && state == HAL_SD_CARD_TRANSFER) +// return SD_OK; + +// return SD_ERROR; +// } + +uint32_t SD_GetSectorCount() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.LogBlockNbr; +} + +uint32_t SD_GetSectorSize() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.LogBlockSize; +} + +uint32_t SD_GetBlockSize() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.LogBlockSize; +} + +uint32_t SD_GetCardType() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.CardType; +} + +uint32_t SD_GetCardVersion() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.CardVersion; +} + +uint32_t SD_GetCardClass() +{ + HAL_SD_CardInfoTypeDef cardInfo; + + if(SD_GetCardInfo(&cardInfo) != SD_OK) + return 0; + + return cardInfo.Class; +} + +/** +* @brief Tx Transfer completed callbacks +* @param hsd: SD handle +* @retval None +*/ + +extern "C" void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + WriteStatus = 1; +} + +/** +* @brief Rx Transfer completed callbacks +* @param hsd: SD handle +* @retval None +*/ + +extern "C" void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) +{ + UNUSED(hsd); + ReadStatus = 1; +} + +extern "C" void SDIO_IRQHandler(void) +{ + DEBUG_INTERRUPT(INT_SDIO); + HAL_SD_IRQHandler(&sdio); +} +extern "C" void SD_SDIO_DMA_IRQHANDLER(void) +{ + DEBUG_INTERRUPT(INT_SDIO_DMA); + HAL_DMA_IRQHandler(&sdioTxDma); +} diff --git a/radio/src/targets/common/arm/stm32/sdio_sd.h b/radio/src/targets/common/arm/stm32/sdio_sd.h index ff45e9ff34a..7e87224efc1 100644 --- a/radio/src/targets/common/arm/stm32/sdio_sd.h +++ b/radio/src/targets/common/arm/stm32/sdio_sd.h @@ -23,62 +23,11 @@ #ifndef _SDIO_SD_H_ #define _SDIO_SD_H_ -#include "board.h" - -#ifdef __cplusplus - extern "C" { -#endif +#include /* Includes ------------------------------------------------------------------*/ typedef enum { -/** - * @brief SDIO specific error defines - */ - SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */ - SD_DATA_CRC_FAIL = (2), /*!< Data bock sent/received (CRC check Failed) */ - SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */ - SD_DATA_TIMEOUT = (4), /*!< Data time out */ - SD_TX_UNDERRUN = (5), /*!< Transmit FIFO under-run */ - SD_RX_OVERRUN = (6), /*!< Receive FIFO over-run */ - SD_START_BIT_ERR = (7), /*!< Start bit not detected on all data signals in widE bus mode */ - SD_CMD_OUT_OF_RANGE = (8), /*!< CMD's argument was out of range.*/ - SD_ADDR_MISALIGNED = (9), /*!< Misaligned address */ - SD_BLOCK_LEN_ERR = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */ - SD_ERASE_SEQ_ERR = (11), /*!< An error in the sequence of erase command occurs.*/ - SD_BAD_ERASE_PARAM = (12), /*!< An Invalid selection for erase groups */ - SD_WRITE_PROT_VIOLATION = (13), /*!< Attempt to program a write protect block */ - SD_LOCK_UNLOCK_FAILED = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */ - SD_COM_CRC_FAILED = (15), /*!< CRC check of the previous command failed */ - SD_ILLEGAL_CMD = (16), /*!< Command is not legal for the card state */ - SD_CARD_ECC_FAILED = (17), /*!< Card internal ECC was applied but failed to correct the data */ - SD_CC_ERROR = (18), /*!< Internal card controller error */ - SD_GENERAL_UNKNOWN_ERROR = (19), /*!< General or Unknown error */ - SD_STREAM_READ_UNDERRUN = (20), /*!< The card could not sustain data transfer in stream read operation. */ - SD_STREAM_WRITE_OVERRUN = (21), /*!< The card could not sustain data programming in stream mode */ - SD_CID_CSD_OVERWRITE = (22), /*!< CID/CSD overwrite error */ - SD_WP_ERASE_SKIP = (23), /*!< only partial address space was erased */ - SD_CARD_ECC_DISABLED = (24), /*!< Command has been executed without using internal ECC */ - SD_ERASE_RESET = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */ - SD_AKE_SEQ_ERROR = (26), /*!< Error in sequence of authentication. */ - SD_INVALID_VOLTRANGE = (27), - SD_ADDR_OUT_OF_RANGE = (28), - SD_SWITCH_ERROR = (29), - SD_SDIO_DISABLED = (30), - SD_SDIO_FUNCTION_BUSY = (31), - SD_SDIO_FUNCTION_FAILED = (32), - SD_SDIO_UNKNOWN_FUNCTION = (33), - -/** - * @brief Standard error defines - */ - SD_INTERNAL_ERROR, - SD_NOT_CONFIGURED, - SD_REQUEST_PENDING, - SD_REQUEST_NOT_APPLICABLE, - SD_INVALID_PARAMETER, - SD_UNSUPPORTED_FEATURE, - SD_UNSUPPORTED_HW, SD_ERROR, SD_OK = 0 } SD_Error; @@ -93,106 +42,29 @@ typedef enum SD_TRANSFER_ERROR } SDTransferState; - - -/** - * @brief Card Specific Data: CSD Register - */ -typedef struct -{ - __IO uint8_t CSDStruct; /*!< CSD structure */ - __IO uint8_t SysSpecVersion; /*!< System specification version */ - __IO uint8_t Reserved1; /*!< Reserved */ - __IO uint8_t TAAC; /*!< Data read access-time 1 */ - __IO uint8_t NSAC; /*!< Data read access-time 2 in CLK cycles */ - __IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */ - __IO uint16_t CardComdClasses; /*!< Card command classes */ - __IO uint8_t RdBlockLen; /*!< Max. read data block length */ - __IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */ - __IO uint8_t WrBlockMisalign; /*!< Write block misalignment */ - __IO uint8_t RdBlockMisalign; /*!< Read block misalignment */ - __IO uint8_t DSRImpl; /*!< DSR implemented */ - __IO uint8_t Reserved2; /*!< Reserved */ - __IO uint32_t DeviceSize; /*!< Device Size */ - __IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */ - __IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */ - __IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */ - __IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */ - __IO uint8_t DeviceSizeMul; /*!< Device size multiplier */ - __IO uint8_t EraseGrSize; /*!< Erase group size */ - __IO uint8_t EraseGrMul; /*!< Erase group size multiplier */ - __IO uint8_t WrProtectGrSize; /*!< Write protect group size */ - __IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */ - __IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */ - __IO uint8_t WrSpeedFact; /*!< Write speed factor */ - __IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */ - __IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */ - __IO uint8_t Reserved3; /*!< Reserded */ - __IO uint8_t ContentProtectAppli; /*!< Content protection application */ - __IO uint8_t FileFormatGrouop; /*!< File format group */ - __IO uint8_t CopyFlag; /*!< Copy flag (OTP) */ - __IO uint8_t PermWrProtect; /*!< Permanent write protection */ - __IO uint8_t TempWrProtect; /*!< Temporary write protection */ - __IO uint8_t FileFormat; /*!< File Format */ - __IO uint8_t ECC; /*!< ECC code */ - __IO uint8_t CSD_CRC; /*!< CSD CRC */ - __IO uint8_t Reserved4; /*!< 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 */ -} SD_CID; - -/** - * @brief SD Card information - */ -typedef struct -{ - SD_CSD SD_csd; - SD_CID SD_cid; - uint64_t CardCapacity; /*!< Card Capacity */ - uint32_t CardBlockSize; /*!< Card Block Size */ - uint16_t RCA; - uint8_t CardType; -} SD_CardInfo; - /** * @brief SD detection on its memory slot */ #define SD_PRESENT ((uint8_t)0x01) #define SD_NOT_PRESENT ((uint8_t)0x00) -// void SD_DeInit(void); SD_Error SD_Init(void); SDTransferState SD_GetStatus(void); +int SD_CheckStatusWithTimeout(uint32_t timeout); uint8_t SD_Detect(void); SD_Error SD_PowerOFF(void); -SD_Error SD_ReadBlock(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize); -SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); -SD_Error SD_WriteBlock(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize); -SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); +SD_Error SD_ReadBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); +SD_Error SD_WriteBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks); SDTransferState SD_GetTransferState(void); SD_Error SD_WaitReadOperation(uint32_t timeout); SD_Error SD_WaitWriteOperation(uint32_t timeout); -#ifdef __cplusplus -} -#endif - -extern SD_CardInfo SDCardInfo; +uint32_t SD_GetSectorCount(); +uint32_t SD_GetSectorSize(); +uint32_t SD_GetBlockSize(); +uint32_t SD_GetCardType(); +uint32_t SD_GetCardVersion(); +uint32_t SD_GetCardClass(); #endif // _SDIO_SD_H_ diff --git a/radio/src/targets/common/arm/stm32/stm32f4xx_hal_conf.h b/radio/src/targets/common/arm/stm32/stm32f4xx_hal_conf.h index c457c731e6c..9d25a1eb119 100644 --- a/radio/src/targets/common/arm/stm32/stm32f4xx_hal_conf.h +++ b/radio/src/targets/common/arm/stm32/stm32f4xx_hal_conf.h @@ -70,7 +70,7 @@ // #define HAL_RNG_MODULE_ENABLED #define HAL_RTC_MODULE_ENABLED // #define HAL_SAI_MODULE_ENABLED -// #define HAL_SD_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED // #define HAL_SPI_MODULE_ENABLED // #define HAL_TIM_MODULE_ENABLED // #define HAL_UART_MODULE_ENABLED diff --git a/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp b/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp index fb5963e8cc8..8d7152fc431 100644 --- a/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp +++ b/radio/src/targets/common/arm/stm32/usbd_storage_msd.cpp @@ -28,6 +28,13 @@ #include + +#if FF_MAX_SS != FF_MIN_SS +#error "Variable sector size is not supported" +#endif + +#define BLOCK_SIZE FF_MAX_SS + #if !defined(BOOT) #include "timers_driver.h" #define WATCHDOG_SUSPEND(x) watchdogSuspend(x) diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt index 72b94f274c0..47a5e49f8a3 100644 --- a/radio/src/targets/horus/CMakeLists.txt +++ b/radio/src/targets/horus/CMakeLists.txt @@ -273,7 +273,8 @@ set(FIRMWARE_SRC targets/common/arm/stm32/heartbeat_driver.cpp targets/common/arm/stm32/trainer_driver.cpp targets/common/arm/stm32/ads79xx.cpp - targets/common/arm/stm32/sdio_sd.c + targets/common/arm/stm32/sdio_sd.cpp + targets/common/arm/stm32/diskio_sdio.cpp ) if(BOOTLOADER) diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 3ce7eeb280c..459c480b19c 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -261,4 +261,3 @@ bool isBacklightEnabled() if (globalData.unexpectedShutdown) return true; return boardBacklightOn; } - diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index 4dcbab1c12f..42f7e1c2098 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -92,27 +92,10 @@ enum { #endif #endif -// SD driver -#define BLOCK_SIZE 512 /* Block Size in Bytes */ -#if !defined(SIMU) || defined(SIMU_DISKIO) -uint32_t sdIsHC(); -uint32_t sdGetSpeed(); -#define SD_IS_HC() (sdIsHC()) -#define SD_GET_SPEED() (sdGetSpeed()) -#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) -#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) -void sdInit(); -void sdMount(); -void sdDone(); -#define sdPoll10ms() -uint32_t sdMounted(); +#if defined(SIMU) + #define SD_CARD_PRESENT() true #else -#define SD_IS_HC() (0) -#define SD_GET_SPEED() (0) -#define sdInit() -#define sdMount() -#define sdDone() -#define SD_CARD_PRESENT() true + #define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) #endif // Flash Write driver diff --git a/radio/src/targets/horus/diskio.cpp b/radio/src/targets/horus/diskio.cpp deleted file mode 100644 index ac9be846a1a..00000000000 --- a/radio/src/targets/horus/diskio.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) EdgeTX - * - * Based on code named - * opentx - https://github.com/opentx/opentx - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */ -/*-----------------------------------------------------------------------*/ -/* This is a stub disk I/O module that acts as front end of the existing */ -/* disk I/O modules and attach it to FatFs module with common interface. */ -/*-----------------------------------------------------------------------*/ - -#include "diskio.h" -#include "debug.h" -#include "targets/common/arm/stm32/sdio_sd.h" - -#include - -/*-----------------------------------------------------------------------*/ -/* Lock / unlock functions */ -/*-----------------------------------------------------------------------*/ -#if !defined(BOOT) -static RTOS_MUTEX_HANDLE ioMutex; -uint32_t ioMutexReq = 0, ioMutexRel = 0; -int ff_cre_syncobj (BYTE vol, FF_SYNC_t * mutex) -{ - *mutex = ioMutex; - return 1; -} - -int ff_req_grant (FF_SYNC_t mutex) -{ - ioMutexReq += 1; - RTOS_LOCK_MUTEX(mutex); - return 1; -} - -void ff_rel_grant (FF_SYNC_t mutex) -{ - ioMutexRel += 1; - RTOS_UNLOCK_MUTEX(mutex); -} - -int ff_del_syncobj (FF_SYNC_t mutex) -{ - return 1; -} -#endif - - -/*-----------------------------------------------------------------------*/ -/* Inidialize a Drive */ - -DSTATUS disk_initialize ( - BYTE drv /* Physical drive nmuber (0..) */ -) -{ - DSTATUS stat = 0; - - /* Supports only single drive */ - if (drv) - { - stat |= STA_NOINIT; - } - - /*-------------------------- SD Init ----------------------------- */ - SD_Error res = SD_Init(); - if (res != SD_OK) - { - TRACE("SD_Init() failed: %d", res); - stat |= STA_NOINIT; - } - - TRACE("SD card info:"); - TRACE("sectors: %u", (uint32_t)(SDCardInfo.CardCapacity / 512)); - TRACE("type: %u", (uint32_t)(SDCardInfo.CardType)); - TRACE("EraseGrSize: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrSize)); - TRACE("EraseGrMul: %u", (uint32_t)(SDCardInfo.SD_csd.EraseGrMul)); - TRACE("ManufacturerID: %u", (uint32_t)(SDCardInfo.SD_cid.ManufacturerID)); - - return(stat); -} - -DWORD scratch[BLOCK_SIZE / 4] __DMA; - -/*-----------------------------------------------------------------------*/ -/* Return Disk Status */ - -DSTATUS disk_status ( - BYTE drv /* Physical drive nmuber (0..) */ -) -{ - DSTATUS stat = 0; - - if (SD_Detect() != SD_PRESENT) - stat |= STA_NODISK; - - // STA_NOTINIT - Subsystem not initailized - // STA_PROTECTED - Write protected, MMC/SD switch if available - - return(stat); -} - -uint32_t sdReadRetries = 0; - -/*-----------------------------------------------------------------------*/ -/* Read Sector(s) */ - - -DRESULT disk_read_dma(BYTE drv, BYTE * buff, DWORD sector, UINT count) -{ - // this functions assumes that buff is properly aligned and in the right RAM segment for DMA - DRESULT res; - SD_Error Status; - SDTransferState State; - for (int retry=0; retry<3; retry++) { - res = RES_OK; - if (count == 1) { - Status = SD_ReadBlock(buff, sector, BLOCK_SIZE); // 4GB Compliant - } - else { - Status = SD_ReadMultiBlocks(buff, sector, BLOCK_SIZE, count); // 4GB Compliant - } - if (Status == SD_OK) { - Status = SD_WaitReadOperation(200*count); // Check if the Transfer is finished - while ((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) - if (State == SD_TRANSFER_ERROR) { - TRACE("State=SD_TRANSFER_ERROR, c: %u", sector, (uint32_t)count); - res = RES_ERROR; - } - else if (Status != SD_OK) { - TRACE("Status(WaitRead)=%d, s:%u c: %u", Status, sector, (uint32_t)count); - res = RES_ERROR; - } - } - else { - TRACE("Status(ReadBlock)=%d, s:%u c: %u", Status, sector, (uint32_t)count); - res = RES_ERROR; - } - if (res == RES_OK) break; - sdReadRetries += 1; - } - return res; -} - -DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count) -{ - // If unaligned, do the single block reads with a scratch buffer. - // If aligned and single sector, do a single block read. - // If aligned and multiple sectors, try multi block read. - // If multi block read fails, try single block reads without - // an intermediate buffer (move trough the provided buffer) - - // TRACE("disk_read %d %p %10d %d", drv, buff, sector, count); - if (SD_Detect() != SD_PRESENT) { - TRACE("SD_Detect() != SD_PRESENT"); - return RES_NOTRDY; - } - - DRESULT res = RES_OK; - if (count == 0) return res; - - if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) { - // buffer is not aligned, use scratch buffer that is aligned - TRACE("disk_read bad alignment (%p)", buff); - while (count--) { - res = disk_read_dma(drv, (BYTE *)scratch, sector++, 1); - if (res != RES_OK) break; - memcpy(buff, scratch, BLOCK_SIZE); - buff += BLOCK_SIZE; - } - return res; - } - - res = disk_read_dma(drv, buff, sector, count); - if (res != RES_OK && count > 1) { - // multi-read failed, try reading same sectors, one by one - TRACE("disk_read() multi-block failed, trying single block reads..."); - while (count--) { - res = disk_read_dma(drv, buff, sector++, 1); - if (res != RES_OK) break; - buff += BLOCK_SIZE; - } - } - return res; -} - -/*-----------------------------------------------------------------------*/ -/* Write Sector(s) */ - -#if _READONLY == 0 -DRESULT __disk_write( - BYTE drv, /* Physical drive nmuber (0..) */ - const BYTE *buff, /* Data to be written */ - DWORD sector, /* Sector address (LBA) */ - UINT count /* Number of sectors to write (1..255) */ -) -{ - SD_Error Status; - DRESULT res = RES_OK; - - // TRACE("disk_write %d %p %10d %d", drv, buff, sector, count); - - if (SD_Detect() != SD_PRESENT) - return(RES_NOTRDY); - - if ((DWORD)buff < 0x20000000 || ((DWORD)buff & 3)) { - //TRACE("disk_write bad alignment (%p)", buff); - while(count--) { - memcpy(scratch, buff, BLOCK_SIZE); - - res = __disk_write(drv, (BYTE *)scratch, sector++, 1); - - if (res != RES_OK) - break; - - buff += BLOCK_SIZE; - } - return(res); - } - - if (count == 1) { - Status = SD_WriteBlock((uint8_t *)buff, sector, BLOCK_SIZE); // 4GB Compliant - } - else { - Status = SD_WriteMultiBlocks((uint8_t *)buff, sector, BLOCK_SIZE, count); // 4GB Compliant - } - - if (Status == SD_OK) { - SDTransferState State; - - Status = SD_WaitWriteOperation(500*count); // Check if the Transfer is finished - - while((State = SD_GetStatus()) == SD_TRANSFER_BUSY); // BUSY, OK (DONE), ERROR (FAIL) - - if ((State == SD_TRANSFER_ERROR) || (Status != SD_OK)) { - TRACE("__disk_write() err, st:%d,%d, s:%u c: %u", Status, State, sector, (uint32_t)count); - res = RES_ERROR; - } - } - else { - res = RES_ERROR; - } - - // TRACE("result=%d", res); - return res; -} -#endif /* _READONLY */ - -/*-----------------------------------------------------------------------*/ -/* Miscellaneous Functions */ - -DRESULT disk_ioctl ( - BYTE drv, /* Physical drive nmuber (0..) */ - BYTE ctrl, /* Control code */ - void *buff /* Buffer to send/receive control data */ -) -{ - DRESULT res; - - if (drv) return RES_PARERR; - - res = RES_ERROR; - - switch (ctrl) { - case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */ - // use 512 for sector size, SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!! - *(DWORD*)buff = SDCardInfo.CardCapacity / BLOCK_SIZE; - res = RES_OK; - break; - - case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */ - *(WORD*)buff = BLOCK_SIZE; // force sector size. SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!! - res = RES_OK; - break; - - case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */ - // TODO verify that this is the correct value - *(DWORD*)buff = (uint32_t)SDCardInfo.SD_csd.EraseGrSize * (uint32_t)SDCardInfo.SD_csd.EraseGrMul; - res = RES_OK; - break; - - case CTRL_SYNC: - while (SD_GetStatus() == SD_TRANSFER_BUSY); /* Complete pending write process (needed at _FS_READONLY == 0) */ - res = RES_OK; - break; - - default: - res = RES_OK; - break; - - } - - return res; -} - -// TODO everything here should not be in the driver layer ... - -bool _g_FATFS_init = false; -FATFS g_FATFS_Obj __DMA; // this is in uninitialised section !!! - -#if defined(LOG_TELEMETRY) -FIL g_telemetryFile = {}; -#endif - -#if defined(LOG_BLUETOOTH) -FIL g_bluetoothFile = {}; -#endif - -#if defined(BOOT) -void sdInit(void) -{ - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - f_chdir("/"); - } -} -#else - -#include "audio.h" -#include "sdcard.h" -#include "disk_cache.h" - -void sdInit() -{ - TRACE("sdInit"); - RTOS_CREATE_MUTEX(ioMutex); - sdMount(); -} - -void sdMount() -{ - TRACE("sdMount"); - - diskCache.clear(); - - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called - _g_FATFS_init = true; - sdGetFreeSectors(); - -#if defined(LOG_TELEMETRY) - f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_telemetryFile) > 0) { - f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append - } -#endif - -#if defined(LOG_BLUETOOTH) - f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_bluetoothFile) > 0) { - f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append - } -#endif - } - else { - TRACE("f_mount() failed"); - } -} - -void sdDone() -{ - TRACE("sdDone"); - - if (sdMounted()) { - audioQueue.stopSD(); - -#if defined(LOG_TELEMETRY) - f_close(&g_telemetryFile); -#endif - -#if defined(LOG_BLUETOOTH) - f_close(&g_bluetoothFile); -#endif - - f_mount(nullptr, "", 0); // unmount SD - } -} -#endif - -uint32_t sdMounted() -{ - return _g_FATFS_init && (g_FATFS_Obj.fs_type != 0); -} - -uint32_t sdIsHC() -{ - return true; // TODO (CardType & CT_BLOCK); -} - -uint32_t sdGetSpeed() -{ - return 330000; -} diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 6ce0bbdfd41..c62e2eb7738 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -620,16 +620,12 @@ #define SD_RCC_APB1Periph 0 #define SD_PRESENT_GPIO GPIOC #define SD_PRESENT_GPIO_PIN GPIO_Pin_5 // PC.05 +#define SD_PRESENT_LL_GPIO_PIN LL_GPIO_PIN_5 // PC.05 +#define SD_SDIO_DMA DMA2 #define SD_SDIO_DMA_STREAM DMA2_Stream3 -#define SD_SDIO_DMA_CHANNEL DMA_Channel_4 -#define SD_SDIO_DMA_FLAG_FEIF DMA_FLAG_FEIF3 -#define SD_SDIO_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3 -#define SD_SDIO_DMA_FLAG_TEIF DMA_FLAG_TEIF3 -#define SD_SDIO_DMA_FLAG_HTIF DMA_FLAG_HTIF3 -#define SD_SDIO_DMA_FLAG_TCIF DMA_FLAG_TCIF3 +#define SD_SDIO_DMA_CHANNEL LL_DMA_CHANNEL_4 #define SD_SDIO_DMA_IRQn DMA2_Stream3_IRQn #define SD_SDIO_DMA_IRQHANDLER DMA2_Stream3_IRQHandler -#define SD_SDIO_FIFO_ADDRESS ((uint32_t)0x40012C80) #define SD_SDIO_CLK_DIV(fq) ((48000000 / (fq)) - 2) #define SD_SDIO_INIT_CLK_DIV SD_SDIO_CLK_DIV(400000) #define SD_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(24000000) diff --git a/radio/src/targets/nv14/CMakeLists.txt b/radio/src/targets/nv14/CMakeLists.txt index 8f8914a6f13..74f4c28b060 100644 --- a/radio/src/targets/nv14/CMakeLists.txt +++ b/radio/src/targets/nv14/CMakeLists.txt @@ -147,7 +147,8 @@ set(FIRMWARE_SRC targets/common/arm/stm32/stm32_usart_driver.cpp targets/common/arm/stm32/trainer_driver.cpp targets/common/arm/stm32/pwr_driver.cpp - targets/common/arm/stm32/sdio_sd.c + targets/common/arm/stm32/sdio_sd.cpp + targets/common/arm/stm32/diskio_sdio.cpp ) # Make malloc() thread-safe diff --git a/radio/src/targets/nv14/board.cpp b/radio/src/targets/nv14/board.cpp index edc2d24a3af..c3db55d84c1 100644 --- a/radio/src/targets/nv14/board.cpp +++ b/radio/src/targets/nv14/board.cpp @@ -273,9 +273,6 @@ void boardInit() keysInit(); switchInit(); audioInit(); - // we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access) - // and this section is un-initialized - memset(&g_FATFS_Obj, 0, sizeof(g_FATFS_Obj)); monitorInit(); adcInit(&_adc_driver); hapticInit(); diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h index 4aa91e7fdde..971d6819a27 100644 --- a/radio/src/targets/nv14/board.h +++ b/radio/src/targets/nv14/board.h @@ -53,27 +53,10 @@ void boardOff(); #define LEN_CPU_UID (3*8+2) void getCPUUniqueID(char * s); -// SD driver -#define BLOCK_SIZE 512 /* Block Size in Bytes */ -#if !defined(SIMU) || defined(SIMU_DISKIO) -uint32_t sdIsHC(); -uint32_t sdGetSpeed(); -#define SD_IS_HC() (sdIsHC()) -#define SD_GET_SPEED() (sdGetSpeed()) -#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) -#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) -void sdInit(); -void sdMount(); -void sdDone(); -#define sdPoll10ms() -uint32_t sdMounted(); +#if defined(SIMU) + #define SD_CARD_PRESENT() true #else -#define SD_IS_HC() (0) -#define SD_GET_SPEED() (0) -#define sdInit() -#define sdMount() -#define sdDone() -#define SD_CARD_PRESENT() true + #define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) #endif // Flash Write driver diff --git a/radio/src/targets/nv14/hal.h b/radio/src/targets/nv14/hal.h index b7672ab708a..8b50df5a51d 100644 --- a/radio/src/targets/nv14/hal.h +++ b/radio/src/targets/nv14/hal.h @@ -296,16 +296,12 @@ #define SD_RCC_APB1Periph 0 #define SD_PRESENT_GPIO GPIOH #define SD_PRESENT_GPIO_PIN GPIO_Pin_10 // PH.10 +#define SD_PRESENT_LL_GPIO_PIN LL_GPIO_PIN_10 // PH.10 +#define SD_SDIO_DMA DMA2 #define SD_SDIO_DMA_STREAM DMA2_Stream3 -#define SD_SDIO_DMA_CHANNEL DMA_Channel_4 -#define SD_SDIO_DMA_FLAG_FEIF DMA_FLAG_FEIF3 -#define SD_SDIO_DMA_FLAG_DMEIF DMA_FLAG_DMEIF3 -#define SD_SDIO_DMA_FLAG_TEIF DMA_FLAG_TEIF3 -#define SD_SDIO_DMA_FLAG_HTIF DMA_FLAG_HTIF3 -#define SD_SDIO_DMA_FLAG_TCIF DMA_FLAG_TCIF3 +#define SD_SDIO_DMA_CHANNEL LL_DMA_CHANNEL_4 #define SD_SDIO_DMA_IRQn DMA2_Stream3_IRQn #define SD_SDIO_DMA_IRQHANDLER DMA2_Stream3_IRQHandler -#define SD_SDIO_FIFO_ADDRESS ((uint32_t)0x40012C80) #define SD_SDIO_CLK_DIV(fq) ((48000000 / (fq)) - 2) #define SD_SDIO_INIT_CLK_DIV SD_SDIO_CLK_DIV(400000) #define SD_SDIO_TRANSFER_CLK_DIV SD_SDIO_CLK_DIV(24000000) diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index af0be75e710..01720aa5145 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -19,6 +19,7 @@ * GNU General Public License for more details. */ +#include "board.h" #define SIMPGMSPC_USE_QT 0 #if defined(SIMU_AUDIO) @@ -65,8 +66,6 @@ extern const etx_hal_adc_driver_t simu_adc_driver; void lcdCopy(void * dest, void * src); -FATFS g_FATFS_Obj; - uint64_t simuTimerMicros(void) { #if SIMPGMSPC_USE_QT @@ -588,6 +587,12 @@ void rtcSetTime(const struct gtm * t) { } +#if defined(PCBTARANIS) +void sdPoll10ms() {} +#endif + +uint32_t SD_GetCardType() { return 0; } + #if defined(USB_SERIAL) const etx_serial_port_t UsbSerialPort = { "USB-VCP", nullptr, nullptr }; #endif diff --git a/radio/src/targets/simu/simpgmspace.h b/radio/src/targets/simu/simpgmspace.h index 4ab1aeb5584..7793948bd0f 100644 --- a/radio/src/targets/simu/simpgmspace.h +++ b/radio/src/targets/simu/simpgmspace.h @@ -80,17 +80,6 @@ void simuMain(); #define SIMU_USE_SDCARD #endif -#if defined(SIMU_DISKIO) - uint32_t sdMounted(); - #define sdPoll10ms() - void sdInit(void); - void sdDone(void); -#else - #define sdPoll10ms() - uint32_t sdMounted(void); - #define sdMounted() (true) -#endif - #if defined(SIMU_USE_SDCARD) void simuFatfsSetPaths(const char * sdPath, const char * settingsPath); #else diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index 59cad3b421d..fbc90422600 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -559,6 +559,7 @@ set(FIRMWARE_TARGET_SRC volume_i2c.cpp eeprom_driver.cpp backlight_driver.cpp + diskio.cpp ) if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCBREV STREQUAL COMMANDO8) diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 111ac60b538..aaad5a82dca 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -65,37 +65,13 @@ enum { }; // SD driver -#define BLOCK_SIZE 512 /* Block Size in Bytes */ -#if !defined(SIMU) || defined(SIMU_DISKIO) -uint32_t sdIsHC(); -uint32_t sdGetSpeed(); -#define SD_IS_HC() (sdIsHC()) -#define SD_GET_SPEED() (sdGetSpeed()) -#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors()) -#else -#define SD_IS_HC() (0) -#define SD_GET_SPEED() (0) -#endif #define __disk_read disk_read #define __disk_write disk_write -#if defined(SIMU) - #if !defined(SIMU_DISKIO) - #define sdInit() - #define sdDone() - #endif - #define sdMount() - #define SD_CARD_PRESENT() true -#else -void sdInit(); -void sdMount(); -void sdDone(); -void sdPoll10ms(); -uint32_t sdMounted(); -#if defined(SD_PRESENT_GPIO) -#define SD_CARD_PRESENT() ((SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) == 0) + +#if defined(SIMU) || !defined(SD_PRESENT_GPIO) + #define SD_CARD_PRESENT() true #else -#define SD_CARD_PRESENT() (true) -#endif + #define SD_CARD_PRESENT() ((SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN) == 0) #endif // Flash Write driver diff --git a/radio/src/targets/taranis/diskio.cpp b/radio/src/targets/taranis/diskio.cpp index 80417b0e3c5..08bb8617f31 100644 --- a/radio/src/targets/taranis/diskio.cpp +++ b/radio/src/targets/taranis/diskio.cpp @@ -63,45 +63,17 @@ #define CT_SDC (CT_SD1|CT_SD2) #define CT_BLOCK 0x08 -/*-----------------------------------------------------------------------*/ -/* Lock / unlock functions */ -/*-----------------------------------------------------------------------*/ -#if !defined(BOOT) -static RTOS_MUTEX_HANDLE ioMutex; - -int ff_cre_syncobj (BYTE vol, FF_SYNC_t *mutex) -{ - *mutex = ioMutex; - return 1; -} - -int ff_req_grant (FF_SYNC_t mutex) -{ - RTOS_LOCK_MUTEX(mutex); - return 1; -} - -void ff_rel_grant (FF_SYNC_t mutex) -{ - RTOS_UNLOCK_MUTEX(mutex); -} - -int ff_del_syncobj (FF_SYNC_t mutex) -{ - return 1; -} -#endif - static const DWORD socket_state_mask_cp = (1 << 0); static const DWORD socket_state_mask_wp = (1 << 1); -static volatile -DSTATUS Stat = STA_NOINIT; /* Disk status */ +/* Disk status */ +static volatile DSTATUS Stat = STA_NOINIT; -static volatile -DWORD Timer1, Timer2; /* 100Hz decrement timers */ +/* 100Hz decrement timers */ +static volatile DWORD Timer1, Timer2; -BYTE CardType; /* Card type flags */ +/* Card type flags */ +BYTE CardType; enum speed_setting { INTERFACE_SLOW, INTERFACE_FAST }; @@ -955,85 +927,7 @@ void sdPoll10ms() } } -// TODO everything here should not be in the driver layer ... - -bool _g_FATFS_init = false; -FATFS g_FATFS_Obj __DMA; // this is in uninitialised section !!! - -#if defined(LOG_TELEMETRY) -FIL g_telemetryFile = {}; -#endif - -#if defined(LOG_BLUETOOTH) -FIL g_bluetoothFile = {}; -#endif - -#if defined(BOOT) -void sdInit(void) -{ - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - f_chdir("/"); - } -} -#else -// TODO shouldn't be there! -void sdInit(void) -{ - TRACE("sdInit"); - RTOS_CREATE_MUTEX(ioMutex); - sdMount(); -} - -void sdMount() -{ - TRACE("sdMount"); - if (f_mount(&g_FATFS_Obj, "", 1) == FR_OK) { - // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called - _g_FATFS_init = true; - sdGetFreeSectors(); - -#if defined(LOG_TELEMETRY) - f_open(&g_telemetryFile, LOGS_PATH "/telemetry.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_telemetryFile) > 0) { - f_lseek(&g_telemetryFile, f_size(&g_telemetryFile)); // append - } -#endif - -#if defined(LOG_BLUETOOTH) - f_open(&g_bluetoothFile, LOGS_PATH "/bluetooth.log", FA_OPEN_ALWAYS | FA_WRITE); - if (f_size(&g_bluetoothFile) > 0) { - f_lseek(&g_bluetoothFile, f_size(&g_bluetoothFile)); // append - } -#endif - } -} - -void sdDone() -{ - if (sdMounted()) { - audioQueue.stopSD(); -#if defined(LOG_TELEMETRY) - f_close(&g_telemetryFile); -#endif -#if defined(LOG_BLUETOOTH) - f_close(&g_bluetoothFile); -#endif - f_mount(nullptr, "", 0); // unmount SD - } -} -#endif - -uint32_t sdMounted() -{ - return _g_FATFS_init && (g_FATFS_Obj.fs_type != 0); -} - -uint32_t sdIsHC() -{ - return (CardType & CT_BLOCK); -} - -uint32_t sdGetSpeed() +uint32_t SD_GetCardType() { - return 330000; + return CardType; } diff --git a/radio/src/thirdparty/FatFs/diskio.h b/radio/src/thirdparty/FatFs/diskio.h index 871d0a0b9cd..1c8bba0425c 100644 --- a/radio/src/thirdparty/FatFs/diskio.h +++ b/radio/src/thirdparty/FatFs/diskio.h @@ -35,7 +35,6 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); #if defined(DISK_CACHE) -// #include "FatFs/diskio.h" DRESULT __disk_read(BYTE drv, BYTE * buff, DWORD sector, UINT count); DRESULT __disk_write(BYTE drv, const BYTE * buff, DWORD sector, UINT count); #else