2 * FreeRTOS+FAT build 191128 - Note: FreeRTOS+FAT is still in the lab!
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
4 * Authors include James Walmsley, Hein Tibosch and Richard Barry
\r
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
7 * this software and associated documentation files (the "Software"), to deal in
\r
8 * the Software without restriction, including without limitation the rights to
\r
9 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
10 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
11 * subject to the following conditions:
\r
13 * The above copyright notice and this permission notice shall be included in all
\r
14 * copies or substantial portions of the Software.
\r
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
18 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
19 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
23 * https://www.FreeRTOS.org
\r
31 /* Scheduler include files. */
\r
32 #include "FreeRTOS.h"
\r
35 #include "ff_headers.h"
\r
36 #include "event_groups.h"
\r
38 #ifndef configUSE_RECURSIVE_MUTEXES
\r
39 #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
\r
41 #if( configUSE_RECURSIVE_MUTEXES != 1 )
\r
42 #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h
\r
44 #endif /* configUSE_RECURSIVE_MUTEXES */
\r
46 #if ( INCLUDE_vTaskDelay != 1 )
\r
47 #error Missing some FreeRTOS define
\r
50 /* There are two areas which are protected with a semaphore:
\r
51 Directories and the FAT area.
\r
52 The masks below are used when calling Group Event functions. */
\r
53 #define FF_FAT_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_FAT_LOCK )
\r
54 #define FF_DIR_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_DIR_LOCK )
\r
56 /* This is not a real lock: it is a bit (or semaphore) will will be given
\r
57 each time when a sector buffer is released. */
\r
58 #define FF_BUF_LOCK_EVENT_BITS ( ( const EventBits_t ) FF_BUF_LOCK )
\r
60 /*-----------------------------------------------------------*/
\r
62 BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms )
\r
66 /* HT: Actually FF_TrySemaphore is never used. */
\r
67 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
71 configASSERT( pxSemaphore );
\r
72 xReturn = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, pdMS_TO_TICKS( ulTime_ms ) );
\r
75 /*-----------------------------------------------------------*/
\r
77 void FF_PendSemaphore( void *pxSemaphore )
\r
79 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
81 /* No need to take the semaphore. */
\r
84 configASSERT( pxSemaphore );
\r
85 xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, portMAX_DELAY );
\r
87 /*-----------------------------------------------------------*/
\r
89 void FF_ReleaseSemaphore( void *pxSemaphore )
\r
91 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
93 /* Scheduler not yet active. */
\r
96 configASSERT( pxSemaphore );
\r
97 xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) pxSemaphore );
\r
99 /*-----------------------------------------------------------*/
\r
101 void FF_Sleep( uint32_t ulTime_ms )
\r
103 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
105 /* This sleep is used as a kind of yield.
\r
106 Not necessary while the Scheduler does not run. */
\r
109 vTaskDelay( pdMS_TO_TICKS( ulTime_ms ) );
\r
111 /*-----------------------------------------------------------*/
\r
113 void FF_DeleteEvents( FF_IOManager_t *pxIOManager )
\r
115 if( pxIOManager->xEventGroup != NULL )
\r
117 vEventGroupDelete( pxIOManager->xEventGroup );
\r
120 /*-----------------------------------------------------------*/
\r
122 BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )
\r
124 BaseType_t xResult;
\r
126 pxIOManager->xEventGroup = xEventGroupCreate();
\r
127 if( pxIOManager->xEventGroup != NULL )
\r
129 xEventGroupSetBits( pxIOManager->xEventGroup,
\r
130 FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );
\r
140 /*-----------------------------------------------------------*/
\r
142 void FF_LockDirectory( FF_IOManager_t *pxIOManager )
\r
146 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
148 /* Scheduler not yet active. */
\r
153 /* Called when a task want to make changes to a directory.
\r
154 First it waits for the desired bit to come high. */
\r
155 xEventGroupWaitBits( pxIOManager->xEventGroup,
\r
156 FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
\r
157 ( EventBits_t )0, /* xClearOnExit */
\r
158 pdFALSE, /* xWaitForAllBits n.a. */
\r
159 pdMS_TO_TICKS( 10000UL ) );
\r
161 /* The next operation will only succeed for 1 task at a time,
\r
162 because it is an atomary test & set operation: */
\r
163 xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
\r
165 if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )
\r
167 /* This task has cleared the desired bit.
\r
168 It now 'owns' the resource. */
\r
173 /*-----------------------------------------------------------*/
\r
175 void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )
\r
177 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
179 /* Scheduler not yet active. */
\r
182 configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );
\r
183 xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );
\r
185 /*-----------------------------------------------------------*/
\r
187 int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
\r
191 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
193 /* Scheduler not yet active. */
\r
196 void *handle = xTaskGetCurrentTaskHandle();
\r
197 if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
\r
199 if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )
\r
215 void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )
\r
219 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
221 /* Scheduler not yet active. */
\r
224 handle = xTaskGetCurrentTaskHandle();
\r
226 if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
\r
228 configASSERT( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) );
\r
230 /* In case configASSERT() is not defined. */
\r
231 ( void ) pxIOManager;
\r
236 void FF_LockFAT( FF_IOManager_t *pxIOManager )
\r
240 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
242 /* Scheduler not yet active. */
\r
245 configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );
\r
249 /* Called when a task want to make changes to the FAT area.
\r
250 First it waits for the desired bit to come high. */
\r
251 xEventGroupWaitBits( pxIOManager->xEventGroup,
\r
252 FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
\r
253 ( EventBits_t )0, /* xClearOnExit */
\r
254 pdFALSE, /* xWaitForAllBits n.a. */
\r
255 pdMS_TO_TICKS( 10000UL ) );
\r
257 /* The next operation will only succeed for 1 task at a time,
\r
258 because it is an atomary test & set operation: */
\r
259 xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
\r
261 if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )
\r
263 /* This task has cleared the desired bit.
\r
264 It now 'owns' the resource. */
\r
265 pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();
\r
270 /*-----------------------------------------------------------*/
\r
272 void FF_UnlockFAT( FF_IOManager_t *pxIOManager )
\r
274 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
276 /* Scheduler not yet active. */
\r
279 configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );
\r
280 pxIOManager->pvFATLockHandle = NULL;
\r
281 xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );
\r
283 /*-----------------------------------------------------------*/
\r
285 BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )
\r
288 BaseType_t xReturn;
\r
290 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
292 /* Scheduler not yet active. */
\r
295 /* This function is called when a task is waiting for a sector buffer
\r
296 to become available. */
\r
297 xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,
\r
298 FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */
\r
299 FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */
\r
300 pdFALSE, /* xWaitForAllBits n.a. */
\r
301 pdMS_TO_TICKS( xWaitMS ) );
\r
302 if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )
\r
313 /*-----------------------------------------------------------*/
\r
315 void FF_BufferProceed( FF_IOManager_t *pxIOManager )
\r
317 if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )
\r
319 /* Scheduler not yet active. */
\r
322 /* Wake-up all tasks that are waiting for a sector buffer to become available. */
\r
323 xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );
\r
325 /*-----------------------------------------------------------*/
\r