5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
22 /*-----------------------------------------------------------------------*/
23 /* This is a stub disk I/O module that acts as front end of the existing */
24 /* disk I/O modules and attach it to FatFs module with common interface. */
25 /*-----------------------------------------------------------------------*/
30 #include "targets/common/arm/stm32/sdio_sd.h"
32 /*-----------------------------------------------------------------------*/
33 /* Lock / unlock functions */
34 /*-----------------------------------------------------------------------*/
36 static RTOS_MUTEX_HANDLE ioMutex
;
37 uint32_t ioMutexReq
= 0, ioMutexRel
= 0;
38 int ff_cre_syncobj (BYTE vol
, _SYNC_t
*mutex
)
44 int ff_req_grant (_SYNC_t mutex
)
47 RTOS_LOCK_MUTEX(mutex
);
51 void ff_rel_grant (_SYNC_t mutex
)
54 RTOS_UNLOCK_MUTEX(mutex
);
57 int ff_del_syncobj (_SYNC_t mutex
)
64 /*-----------------------------------------------------------------------*/
65 /* Inidialize a Drive */
67 DSTATUS
disk_initialize (
68 BYTE drv
/* Physical drive nmuber (0..) */
73 /* Supports only single drive */
79 /*-------------------------- SD Init ----------------------------- */
80 SD_Error res
= SD_Init();
83 TRACE("SD_Init() failed: %d", res
);
87 TRACE("SD card info:");
88 TRACE("sectors: %u", (uint32_t)(SDCardInfo
.CardCapacity
/ 512));
89 TRACE("type: %u", (uint32_t)(SDCardInfo
.CardType
));
90 TRACE("EraseGrSize: %u", (uint32_t)(SDCardInfo
.SD_csd
.EraseGrSize
));
91 TRACE("EraseGrMul: %u", (uint32_t)(SDCardInfo
.SD_csd
.EraseGrMul
));
92 TRACE("ManufacturerID: %u", (uint32_t)(SDCardInfo
.SD_cid
.ManufacturerID
));
97 DWORD scratch
[BLOCK_SIZE
/ 4] __DMA
;
99 /*-----------------------------------------------------------------------*/
100 /* Return Disk Status */
102 DSTATUS
disk_status (
103 BYTE drv
/* Physical drive nmuber (0..) */
108 if (SD_Detect() != SD_PRESENT
)
111 // STA_NOTINIT - Subsystem not initailized
112 // STA_PROTECTED - Write protected, MMC/SD switch if available
117 uint32_t sdReadRetries
= 0;
119 /*-----------------------------------------------------------------------*/
123 DRESULT
disk_read_dma(BYTE drv
, BYTE
* buff
, DWORD sector
, UINT count
)
125 // this functions assumes that buff is properly aligned and in the right RAM segment for DMA
128 SDTransferState State
;
129 for (int retry
=0; retry
<3; retry
++) {
132 Status
= SD_ReadBlock(buff
, sector
, BLOCK_SIZE
); // 4GB Compliant
135 Status
= SD_ReadMultiBlocks(buff
, sector
, BLOCK_SIZE
, count
); // 4GB Compliant
137 if (Status
== SD_OK
) {
138 Status
= SD_WaitReadOperation(200*count
); // Check if the Transfer is finished
139 while ((State
= SD_GetStatus()) == SD_TRANSFER_BUSY
); // BUSY, OK (DONE), ERROR (FAIL)
140 if (State
== SD_TRANSFER_ERROR
) {
141 TRACE("State=SD_TRANSFER_ERROR, c: %u", sector
, (uint32_t)count
);
144 else if (Status
!= SD_OK
) {
145 TRACE("Status(WaitRead)=%d, s:%u c: %u", Status
, sector
, (uint32_t)count
);
150 TRACE("Status(ReadBlock)=%d, s:%u c: %u", Status
, sector
, (uint32_t)count
);
153 if (res
== RES_OK
) break;
159 DRESULT
__disk_read(BYTE drv
, BYTE
* buff
, DWORD sector
, UINT count
)
161 // If unaligned, do the single block reads with a scratch buffer.
162 // If aligned and single sector, do a single block read.
163 // If aligned and multiple sectors, try multi block read.
164 // If multi block read fails, try single block reads without
165 // an intermediate buffer (move trough the provided buffer)
167 // TRACE("disk_read %d %p %10d %d", drv, buff, sector, count);
168 if (SD_Detect() != SD_PRESENT
) {
169 TRACE("SD_Detect() != SD_PRESENT");
173 DRESULT res
= RES_OK
;
174 if (count
== 0) return res
;
176 if ((DWORD
)buff
< 0x20000000 || ((DWORD
)buff
& 3)) {
177 // buffer is not aligned, use scratch buffer that is aligned
178 TRACE("disk_read bad alignment (%p)", buff
);
180 res
= disk_read_dma(drv
, (BYTE
*)scratch
, sector
++, 1);
181 if (res
!= RES_OK
) break;
182 memcpy(buff
, scratch
, BLOCK_SIZE
);
188 res
= disk_read_dma(drv
, buff
, sector
, count
);
189 if (res
!= RES_OK
&& count
> 1) {
190 // multi-read failed, try reading same sectors, one by one
191 TRACE("disk_read() multi-block failed, trying single block reads...");
193 res
= disk_read_dma(drv
, buff
, sector
++, 1);
194 if (res
!= RES_OK
) break;
201 /*-----------------------------------------------------------------------*/
202 /* Write Sector(s) */
205 DRESULT
__disk_write(
206 BYTE drv
, /* Physical drive nmuber (0..) */
207 const BYTE
*buff
, /* Data to be written */
208 DWORD sector
, /* Sector address (LBA) */
209 UINT count
/* Number of sectors to write (1..255) */
213 DRESULT res
= RES_OK
;
215 // TRACE("disk_write %d %p %10d %d", drv, buff, sector, count);
217 if (SD_Detect() != SD_PRESENT
)
220 if ((DWORD
)buff
< 0x20000000 || ((DWORD
)buff
& 3)) {
221 TRACE("disk_write bad alignment (%p)", buff
);
223 memcpy(scratch
, buff
, BLOCK_SIZE
);
225 res
= __disk_write(drv
, (BYTE
*)scratch
, sector
++, 1);
236 Status
= SD_WriteBlock((uint8_t *)buff
, sector
, BLOCK_SIZE
); // 4GB Compliant
239 Status
= SD_WriteMultiBlocks((uint8_t *)buff
, sector
, BLOCK_SIZE
, count
); // 4GB Compliant
242 if (Status
== SD_OK
) {
243 SDTransferState State
;
245 Status
= SD_WaitWriteOperation(500*count
); // Check if the Transfer is finished
247 while((State
= SD_GetStatus()) == SD_TRANSFER_BUSY
); // BUSY, OK (DONE), ERROR (FAIL)
249 if ((State
== SD_TRANSFER_ERROR
) || (Status
!= SD_OK
)) {
250 TRACE("__disk_write() err, st:%d,%d, s:%u c: %u", Status
, State
, sector
, (uint32_t)count
);
258 // TRACE("result=%d", res);
261 #endif /* _READONLY */
263 /*-----------------------------------------------------------------------*/
264 /* Miscellaneous Functions */
267 BYTE drv
, /* Physical drive nmuber (0..) */
268 BYTE ctrl
, /* Control code */
269 void *buff
/* Buffer to send/receive control data */
274 if (drv
) return RES_PARERR
;
279 case GET_SECTOR_COUNT
: /* Get number of sectors on the disk (DWORD) */
280 // use 512 for sector size, SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
281 *(DWORD
*)buff
= SDCardInfo
.CardCapacity
/ BLOCK_SIZE
;
285 case GET_SECTOR_SIZE
: /* Get R/W sector size (WORD) */
286 *(WORD
*)buff
= BLOCK_SIZE
; // force sector size. SDCardInfo.CardBlockSize is not sector size and can be 1024 for 2G SD cards!!!!
290 case GET_BLOCK_SIZE
: /* Get erase block size in unit of sector (DWORD) */
291 // TODO verify that this is the correct value
292 *(DWORD
*)buff
= (uint32_t)SDCardInfo
.SD_csd
.EraseGrSize
* (uint32_t)SDCardInfo
.SD_csd
.EraseGrMul
;
297 while (SD_GetStatus() == SD_TRANSFER_BUSY
); /* Complete pending write process (needed at _FS_READONLY == 0) */
310 // TODO everything here should not be in the driver layer ...
312 FATFS g_FATFS_Obj __DMA
; // initialized in boardInit()
313 #if defined(LOG_TELEMETRY)
314 FIL g_telemetryFile
= {};
320 if (f_mount(&g_FATFS_Obj
, "", 1) == FR_OK
) {
329 ioMutex
= CoCreateMutex();
330 if (ioMutex
>= CFG_MAX_MUTEX
) {
343 if (f_mount(&g_FATFS_Obj
, "", 1) == FR_OK
) {
344 // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called
347 #if defined(LOG_TELEMETRY)
348 f_open(&g_telemetryFile
, LOGS_PATH
"/telemetry.log", FA_OPEN_ALWAYS
| FA_WRITE
);
349 if (f_size(&g_telemetryFile
) > 0) {
350 f_lseek(&g_telemetryFile
, f_size(&g_telemetryFile
)); // append
355 TRACE("f_mount() failed");
365 #if defined(LOG_TELEMETRY)
366 f_close(&g_telemetryFile
);
368 f_mount(nullptr, "", 0); // unmount SD
375 return g_FATFS_Obj
.fs_type
!= 0;
380 return true; // TODO (CardType & CT_BLOCK);
383 uint32_t sdGetSpeed()