version 2.8
gfile_fatfs_diskio_chibios.c
1 /*-----------------------------------------------------------------------*/
2 /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
3 /*-----------------------------------------------------------------------*/
4 /* This is a stub disk I/O module that acts as front end of the existing */
5 /* disk I/O modules and attach it to FatFs module with common interface. */
6 /*-----------------------------------------------------------------------*/
7 
8 #include "../../gfx.h"
9 
10 #if GFX_USE_GFILE && GFILE_NEED_FATFS && GFX_USE_OS_CHIBIOS && !GFILE_FATFS_EXTERNAL_LIB
11 
12 #include "gfile_fatfs_wrapper.h"
13 
14 #if HAL_USE_MMC_SPI && HAL_USE_SDC
15  #error "cannot specify both MMC_SPI and SDC drivers"
16 #endif
17 
18 #if HAL_USE_MMC_SPI
19  extern MMCDriver MMCD1;
20 #elif HAL_USE_SDC
21  extern SDCDriver SDCD1;
22 #else
23  #error "MMC_SPI or SDC driver must be specified"
24 #endif
25 
26 /*-----------------------------------------------------------------------*/
27 /* Correspondence between physical drive number and physical drive. */
28 #define MMC 0
29 #define SDC 0
30 /*-----------------------------------------------------------------------*/
31 
32 // WOW - Bugs galore!!! (in ChibiOS)
33 // Bugs:
34 // 1. ChibiOS DMA operations do not do the appropriate cache flushing or invalidating
35 // on cpu's that require it eg STM32F7 series.
36 // Instead they provide explicit dmaBufferInvalidate and dmaBufferFlush calls
37 // and rely on the user to explicitly flush the cache.
38 // Solution: We explicitly flush the cache after any possible DMA operation.
39 // 2. Unfortunately these explicit routines also have a bug. They assume that the
40 // specified data structure is aligned on a cache line boundary - not a good assumption.
41 // Solution: We increase the size provided to ChibiOS so that it does it properly.
42 // This assumes of course that we know the size of the cpu cache line.
43 #if CH_KERNEL_MAJOR > 2
44  #define CPU_CACHE_LINE_SIZE 32
45  #define CACHE_FLUSH(buf, sz) dmaBufferFlush((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
46  #define CACHE_INVALIDATE(buf, sz) dmaBufferInvalidate((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
47 #else
48  #define CACHE_FLUSH(buf, sz)
49  #define CACHE_INVALIDATE(buf, sz)
50 #endif
51 
52 /* Initialize a Drive */
53 DSTATUS disk_initialize (
54  BYTE drv /* Physical drive nmuber (0..) */
55 )
56 {
57  DSTATUS stat;
58 
59  switch (drv) {
60 #if HAL_USE_MMC_SPI
61  case MMC:
62  stat = 0;
63  /* It is initialized externally, just reads the status.*/
64  if (blkGetDriverState(&MMCD1) != BLK_READY)
65  stat |= STA_NOINIT;
66  if (mmcIsWriteProtected(&MMCD1))
67  stat |= STA_PROTECT;
68  return stat;
69 #else
70  case SDC:
71  stat = 0;
72  /* It is initialized externally, just reads the status.*/
73  if (blkGetDriverState(&SDCD1) != BLK_READY)
74  stat |= STA_NOINIT;
75  if (sdcIsWriteProtected(&SDCD1))
76  stat |= STA_PROTECT;
77  return stat;
78 #endif
79  }
80  return STA_NODISK;
81 }
82 
83 
84 
85 /*-----------------------------------------------------------------------*/
86 /* Return Disk Status */
87 
88 DSTATUS disk_status (
89  BYTE drv /* Physical drive nmuber (0..) */
90 )
91 {
92  DSTATUS stat;
93 
94  switch (drv) {
95 #if HAL_USE_MMC_SPI
96  case MMC:
97  stat = 0;
98  /* It is initialized externally, just reads the status.*/
99  if (blkGetDriverState(&MMCD1) != BLK_READY)
100  stat |= STA_NOINIT;
101  if (mmcIsWriteProtected(&MMCD1))
102  stat |= STA_PROTECT;
103  return stat;
104 #else
105  case SDC:
106  stat = 0;
107  /* It is initialized externally, just reads the status.*/
108  if (blkGetDriverState(&SDCD1) != BLK_READY)
109  stat |= STA_NOINIT;
110  if (sdcIsWriteProtected(&SDCD1))
111  stat |= STA_PROTECT;
112  return stat;
113 #endif
114  }
115  return STA_NODISK;
116 }
117 
118 
119 
120 /*-----------------------------------------------------------------------*/
121 /* Read Sector(s) */
122 
123 DRESULT disk_read (
124  BYTE drv, /* Physical drive nmuber (0..) */
125  BYTE *buff, /* Data buffer to store read data */
126  DWORD sector, /* Sector address (LBA) */
127  UINT count /* Number of sectors to read (1..255) */
128 )
129 {
130  switch (drv) {
131 #if HAL_USE_MMC_SPI
132  case MMC:
133  if (blkGetDriverState(&MMCD1) != BLK_READY)
134  return RES_NOTRDY;
135  if (mmcStartSequentialRead(&MMCD1, sector))
136  return RES_ERROR;
137  CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
138  while (count > 0) {
139  if (mmcSequentialRead(&MMCD1, buff))
140  return RES_ERROR;
141  buff += MMCSD_BLOCK_SIZE;
142  count--;
143  }
144  if (mmcStopSequentialRead(&MMCD1))
145  return RES_ERROR;
146  CACHE_INVALIDATE(buff, MMCSD_BLOCK_SIZE*count);
147  return RES_OK;
148 #else
149  case SDC:
150  if (blkGetDriverState(&SDCD1) != BLK_READY)
151  return RES_NOTRDY;
152  CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
153  if (sdcRead(&SDCD1, sector, buff, count))
154  return RES_ERROR;
155  CACHE_INVALIDATE(buff, MMCSD_BLOCK_SIZE*count);
156  return RES_OK;
157 #endif
158  }
159  return RES_PARERR;
160 }
161 
162 
163 
164 /*-----------------------------------------------------------------------*/
165 /* Write Sector(s) */
166 
167 #if _READONLY == 0
168 DRESULT disk_write (
169  BYTE drv, /* Physical drive nmuber (0..) */
170  const BYTE *buff, /* Data to be written */
171  DWORD sector, /* Sector address (LBA) */
172  UINT count /* Number of sectors to write (1..255) */
173 )
174 {
175  switch (drv) {
176 #if HAL_USE_MMC_SPI
177  case MMC:
178  if (blkGetDriverState(&MMCD1) != BLK_READY)
179  return RES_NOTRDY;
180  if (mmcIsWriteProtected(&MMCD1))
181  return RES_WRPRT;
182  if (mmcStartSequentialWrite(&MMCD1, sector))
183  return RES_ERROR;
184  CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
185  while (count > 0) {
186  if (mmcSequentialWrite(&MMCD1, buff))
187  return RES_ERROR;
188  buff += MMCSD_BLOCK_SIZE;
189  count--;
190  }
191  if (mmcStopSequentialWrite(&MMCD1))
192  return RES_ERROR;
193  return RES_OK;
194 #else
195  case SDC:
196  if (blkGetDriverState(&SDCD1) != BLK_READY)
197  return RES_NOTRDY;
198  CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
199  if (sdcWrite(&SDCD1, sector, buff, count))
200  return RES_ERROR;
201  return RES_OK;
202 #endif
203  }
204  return RES_PARERR;
205 }
206 #endif /* _READONLY */
207 
208 
209 
210 /*-----------------------------------------------------------------------*/
211 /* Miscellaneous Functions */
212 
213 DRESULT disk_ioctl (
214  BYTE drv, /* Physical drive nmuber (0..) */
215  BYTE ctrl, /* Control code */
216  void *buff /* Buffer to send/receive control data */
217 )
218 {
219  switch (drv) {
220 #if HAL_USE_MMC_SPI
221  case MMC:
222  switch (ctrl) {
223  case CTRL_SYNC:
224  return RES_OK;
225  case GET_SECTOR_SIZE:
226  *((WORD *)buff) = MMCSD_BLOCK_SIZE;
227  return RES_OK;
228 #if _USE_ERASE
229  case CTRL_ERASE_SECTOR:
230  mmcErase(&MMCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
231  return RES_OK;
232 #endif
233  default:
234  return RES_PARERR;
235  }
236 #else
237  case SDC:
238  switch (ctrl) {
239  case CTRL_SYNC:
240  return RES_OK;
241  case GET_SECTOR_COUNT:
242  *((DWORD *)buff) = mmcsdGetCardCapacity(&SDCD1);
243  return RES_OK;
244  case GET_SECTOR_SIZE:
245  *((WORD *)buff) = MMCSD_BLOCK_SIZE;
246  return RES_OK;
247  case GET_BLOCK_SIZE:
248  *((DWORD *)buff) = 256; /* 512b blocks in one erase block */
249  return RES_OK;
250 #if _USE_ERASE
251  case CTRL_ERASE_SECTOR:
252  sdcErase(&SDCD1, *((DWORD *)buff), *((DWORD *)buff + 1));
253  return RES_OK;
254 #endif
255  default:
256  return RES_PARERR;
257  }
258 #endif
259  }
260  return RES_PARERR;
261 }
262 
263 #if HAL_USE_RTC
264  extern RTCDriver RTCD1;
265 
266  DWORD get_fattime(void) {
267  RTCDateTime timespec;
268 
269  rtcGetTime(&RTCD1, &timespec);
270  return rtcConvertDateTimeToFAT(&timespec);
271  }
272 #else
273  DWORD get_fattime(void) {
274  return ((uint32_t)0 | (1 << 16)) | (1 << 21); /* wrong but valid time */
275  }
276 #endif
277 
278 #endif // GFX_USE_GFILE && GFILE_NEED_FATFS && GFX_USE_OS_CHIBIOS && !GFILE_FATFS_EXTERNAL_LIB
GFILE FATFS wrapper.