1 /*
2 * Copyright (c) 2016-2018, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdbool.h>
34 #include <stdint.h>
35 #include <stdlib.h>
36
37 /*
38 * By default disable both asserts and log for this module.
39 * This must be done before DebugP.h is included.
40 */
41 #ifndef DebugP_ASSERT_ENABLED
42 #define DebugP_ASSERT_ENABLED 0
43 #endif
44 #ifndef DebugP_LOG_ENABLED
45 #define DebugP_LOG_ENABLED 0
46 #endif
47
48 #include <ti/drivers/dpl/DebugP.h>
49 #include <ti/drivers/dpl/HwiP.h>
50 #include <ti/drivers/SD.h>
51 #include <ti/drivers/SDFatFS.h>
52
53 #include <third_party/fatfs/ff.h>
54
55 /* SDFatFS Specific Defines */
56 #define DRIVE_NOT_MOUNTED (~(0U))
57
58 extern const SDFatFS_Config SDFatFS_config[];
59 extern const uint_least8_t SDFatFS_count;
60
61 static bool isInitialized = false;
62
63 /*
64 * Array of SDFatFS_Handles to determine the association of the
65 * FatFs drive number with a SDFatFS_Handle.
66 * FF_VOLUMES is defined in <third_party/fatfs/ffconf.h>.
67 */
68 static SDFatFS_Handle sdFatFSHandles[FF_VOLUMES];
69
70 /* FatFS function prototypes */
71 DSTATUS SDFatFS_diskInitialize(BYTE drive);
72 DRESULT SDFatFS_diskIOctrl(BYTE drive, BYTE ctrl, void *buffer);
73 DRESULT SDFatFS_diskRead(BYTE drive, BYTE *buffer,
74 DWORD sector, UINT secCount);
75 DSTATUS SDFatFS_diskStatus(BYTE drive);
76 DRESULT SDFatFS_diskWrite(BYTE drive, const BYTE *buffer,
77 DWORD sector, UINT secCount);
78
79 /*
80 * ======== SDFatFS_close ========
81 */
SDFatFS_close(SDFatFS_Handle handle)82 void SDFatFS_close(SDFatFS_Handle handle)
83 {
84 TCHAR path[3];
85 DRESULT dresult;
86 FRESULT fresult;
87 SDFatFS_Object *obj = handle->object;
88
89 /* Construct base directory path */
90 path[0] = (TCHAR)'0' + obj->driveNum;
91 path[1] = (TCHAR)':';
92 path[2] = (TCHAR)'\0';
93
94 /* Close the SD driver */
95 SD_close(obj->sdHandle);
96
97 /* Unmount the FatFs drive */
98 fresult = f_mount(NULL, path, 0);
99 if (fresult != FR_OK) {
100 DebugP_log1("SDFatFS: Could not unmount FatFs volume @ drive"
101 " number %d", obj->driveNum);
102 }
103
104 /* Unregister the disk_*() functions */
105 dresult = disk_unregister(obj->driveNum);
106 if (dresult != RES_OK) {
107 DebugP_log1("SDFatFS: Error unregistering disk"
108 " functions @ drive number %d", obj->driveNum);
109 }
110
111 obj->driveNum = DRIVE_NOT_MOUNTED;
112 DebugP_log0("SDFatFS closed");
113 }
114
115 /*
116 * ======== SDFatFS_diskInitialize ========
117 */
SDFatFS_diskInitialize(BYTE drive)118 DSTATUS SDFatFS_diskInitialize(BYTE drive)
119 {
120 int_fast8_t result;
121 SDFatFS_Object *obj = sdFatFSHandles[drive]->object;
122
123 result = SD_initialize(obj->sdHandle);
124
125 /* Convert lower level driver status code */
126 if (result == SD_STATUS_SUCCESS) {
127 obj->diskState = ((DSTATUS) obj->diskState) & ~((DSTATUS)STA_NOINIT);
128 }
129
130 return (obj->diskState);
131 }
132
133 /*
134 * ======== SDFatFS_diskIOctrl ========
135 * Function to perform specified disk operations. This function is called by the
136 * FatFs module and must not be called by the application!
137 */
SDFatFS_diskIOctrl(BYTE drive,BYTE ctrl,void * buffer)138 DRESULT SDFatFS_diskIOctrl(BYTE drive, BYTE ctrl, void *buffer)
139 {
140 SDFatFS_Object *obj = sdFatFSHandles[drive]->object;
141 DRESULT fatfsRes = RES_ERROR;
142
143 switch (ctrl) {
144 case CTRL_SYNC:
145 fatfsRes = RES_OK;
146 break;
147
148 case (BYTE)GET_SECTOR_COUNT:
149 *(uint32_t*)buffer = (uint32_t)SD_getNumSectors(obj->sdHandle);
150
151 DebugP_log1("SDFatFS: Disk IO control: sector count: %d",
152 *(uint32_t*)buffer);
153 fatfsRes = RES_OK;
154 break;
155
156 case (BYTE)GET_SECTOR_SIZE:
157 *(WORD*)buffer = (WORD)SD_getSectorSize(obj->sdHandle);
158 DebugP_log1("SDFatFS: Disk IO control: sector size: %d",
159 *(WORD*)buffer);
160 fatfsRes = RES_OK;
161 break;
162
163 case (BYTE)GET_BLOCK_SIZE:
164 *(WORD*)buffer = (WORD)SD_getSectorSize(obj->sdHandle);
165 DebugP_log1("SDFatFS: Disk IO control: block size: %d",
166 *(WORD*)buffer);
167 fatfsRes = RES_OK;
168 break;
169
170 default:
171 DebugP_log0("SDFatFS: Disk IO control parameter error");
172 fatfsRes = RES_PARERR;
173 break;
174 }
175 return (fatfsRes);
176 }
177
178 /*
179 * ======== SDFatFS_diskRead ========
180 * Function to perform a disk read from the SDCard. This function is called by
181 * the FatFs module and must not be called by the application!
182 */
SDFatFS_diskRead(BYTE drive,BYTE * buffer,DWORD sector,UINT secCount)183 DRESULT SDFatFS_diskRead(BYTE drive, BYTE *buffer,
184 DWORD sector, UINT secCount)
185 {
186 int_fast32_t result;
187 DRESULT fatfsRes = RES_ERROR;
188 SDFatFS_Object *obj = sdFatFSHandles[drive]->object;
189
190 /* Return if disk not initialized */
191 if ((obj->diskState & (DSTATUS)STA_NOINIT) != 0) {
192 fatfsRes = RES_PARERR;
193 }
194 else {
195 result = SD_read(obj->sdHandle, (uint_least8_t *)buffer,
196 (int_least32_t)sector, (uint_least32_t)secCount);
197
198 /* Convert lower level driver status code */
199 if (result == SD_STATUS_SUCCESS) {
200 fatfsRes = RES_OK;
201 }
202 }
203
204 return (fatfsRes);
205 }
206
207 /*
208 * ======== SDFatFS_diskStatus ========
209 * Function to return the current disk status. This function is called by
210 * the FatFs module and must not be called by the application!
211 */
SDFatFS_diskStatus(BYTE drive)212 DSTATUS SDFatFS_diskStatus(BYTE drive)
213 {
214 return (((SDFatFS_Object *)sdFatFSHandles[drive]->object)->diskState);
215 }
216
217
218 #if (_READONLY == 0)
219 /*
220 * ======== SDFatFS_diskWrite ========
221 * Function to perform a write to the SDCard. This function is called by
222 * the FatFs module and must not be called by the application!
223 */
SDFatFS_diskWrite(BYTE drive,const BYTE * buffer,DWORD sector,UINT secCount)224 DRESULT SDFatFS_diskWrite(BYTE drive, const BYTE *buffer, DWORD sector,
225 UINT secCount)
226 {
227 int_fast32_t result;
228 DRESULT fatfsRes = RES_ERROR;
229 SDFatFS_Object *obj = sdFatFSHandles[drive]->object;
230
231 /* Return if disk not initialized */
232 if ((obj->diskState & (DSTATUS)STA_NOINIT) != 0) {
233 fatfsRes = RES_PARERR;
234 }
235 else {
236 result = SD_write(obj->sdHandle, (const uint_least8_t *)buffer,
237 (int_least32_t)sector, (uint_least32_t)secCount);
238
239 /* Convert lower level driver status code */
240 if (result == SD_STATUS_SUCCESS) {
241 fatfsRes = RES_OK;
242 }
243 }
244
245 return (fatfsRes);
246 }
247 #endif
248
249 /*
250 * ======== SDFatFS_init ========
251 */
SDFatFS_init(void)252 void SDFatFS_init(void)
253 {
254 uint_least8_t i;
255 uint_fast32_t key;
256 SDFatFS_Object *obj;
257
258 key = HwiP_disable();
259
260 if (!isInitialized) {
261 isInitialized = (bool) true;
262
263 /* Initialize each SDFatFS object */
264 for (i = 0; i < SDFatFS_count; i++) {
265 obj = ((SDFatFS_Handle)&(SDFatFS_config[i]))->object;
266
267 obj->diskState = STA_NOINIT;
268 obj->driveNum = DRIVE_NOT_MOUNTED;
269 }
270
271 /* Initialize the SD Driver */
272 SD_init();
273 }
274
275 HwiP_restore(key);
276 }
277
278
279 /*
280 * ======== SDFatFS_open ========
281 * Note: The index passed into this function must correspond directly
282 * to the SD driver index.
283 */
SDFatFS_open(uint_least8_t idx,uint_least8_t drive)284 SDFatFS_Handle SDFatFS_open(uint_least8_t idx, uint_least8_t drive)
285 {
286 uintptr_t key;
287 DRESULT dresult;
288 FRESULT fresult;
289 TCHAR path[3];
290 SDFatFS_Handle handle = NULL;
291 SDFatFS_Object *obj;
292
293 /* Verify driver index and state */
294 if (isInitialized && (idx < SDFatFS_count)) {
295 /* Get handle for this driver instance */
296 handle = (SDFatFS_Handle)&(SDFatFS_config[idx]);
297 obj = handle->object;
298
299 /* Determine if the device was already opened */
300 key = HwiP_disable();
301 if (obj->driveNum != DRIVE_NOT_MOUNTED) {
302 HwiP_restore(key);
303 DebugP_log1("SDFatFS Drive %d already in use!", obj->driveNum);
304 handle = NULL;
305 }
306 else {
307 obj->driveNum = drive;
308
309 /* Open SD Driver */
310 obj->sdHandle = SD_open(idx, NULL);
311
312 HwiP_restore(key);
313
314 if (obj->sdHandle == NULL) {
315 obj->driveNum = DRIVE_NOT_MOUNTED;
316 /* Error occurred in lower level driver */
317 handle = NULL;
318 }
319 else {
320
321 /* Register FATFS Functions */
322 dresult = disk_register(obj->driveNum,
323 SDFatFS_diskInitialize,
324 SDFatFS_diskStatus,
325 SDFatFS_diskRead,
326 SDFatFS_diskWrite,
327 SDFatFS_diskIOctrl);
328
329 /* Check for drive errors */
330 if (dresult != RES_OK) {
331 DebugP_log0("SDFatFS: Disk functions not registered");
332 SDFatFS_close(handle);
333 handle = NULL;
334 }
335 else {
336
337 /* Construct base directory path */
338 path[0] = (TCHAR)'0' + obj->driveNum;
339 path[1] = (TCHAR)':';
340 path[2] = (TCHAR)'\0';
341
342 /*
343 * Register the filesystem with FatFs. This operation does
344 * not access the SDCard yet.
345 */
346 fresult = f_mount(&(obj->filesystem), path, 0);
347 if (fresult != FR_OK) {
348 DebugP_log1("SDFatFS: Drive %d not mounted",
349 obj->driveNum);
350
351 SDFatFS_close(handle);
352 handle = NULL;
353 }
354 else {
355
356 /*
357 * Store the new sdfatfs handle for the input drive
358 * number
359 */
360 sdFatFSHandles[obj->driveNum] = handle;
361
362 DebugP_log0("SDFatFS: opened");
363 }
364 }
365 }
366 }
367 }
368
369 return (handle);
370 }
371