]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/ff_locking.org.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / ff_locking.org.c
1 /*\r
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
5  *\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
12  *\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
15  *\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
22  *\r
23  * https://www.FreeRTOS.org\r
24  *\r
25  */\r
26 \r
27 #include <stdio.h>\r
28 #include <stdlib.h>\r
29 #include <string.h>\r
30 \r
31 /* Scheduler include files. */\r
32 #include "FreeRTOS.h"\r
33 #include "task.h"\r
34 #include "semphr.h"\r
35 #include "ff_headers.h"\r
36 #include "event_groups.h"\r
37 \r
38 #ifndef configUSE_RECURSIVE_MUTEXES\r
39         #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h\r
40 #else\r
41         #if( configUSE_RECURSIVE_MUTEXES != 1 )\r
42                 #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h\r
43         #endif\r
44 #endif /* configUSE_RECURSIVE_MUTEXES */\r
45 \r
46 #if ( INCLUDE_vTaskDelay != 1 )\r
47         #error Missing some FreeRTOS define\r
48 #endif\r
49 \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
55 \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
59 \r
60 /*-----------------------------------------------------------*/\r
61 \r
62 BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms )\r
63 {\r
64 BaseType_t xReturn;\r
65 \r
66         configASSERT( pxSemaphore );\r
67         xReturn = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, pdMS_TO_TICKS( ulTime_ms ) );\r
68         return xReturn;\r
69 }\r
70 /*-----------------------------------------------------------*/\r
71 \r
72 void FF_PendSemaphore( void *pxSemaphore )\r
73 {\r
74         configASSERT( pxSemaphore );\r
75         xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, portMAX_DELAY );\r
76 }\r
77 /*-----------------------------------------------------------*/\r
78 \r
79 void FF_ReleaseSemaphore( void *pxSemaphore )\r
80 {\r
81         configASSERT( pxSemaphore );\r
82         xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) pxSemaphore );\r
83 }\r
84 /*-----------------------------------------------------------*/\r
85 \r
86 void FF_Sleep( uint32_t ulTime_ms )\r
87 {\r
88         vTaskDelay( pdMS_TO_TICKS( ulTime_ms ) );\r
89 }\r
90 /*-----------------------------------------------------------*/\r
91 \r
92 void FF_DeleteEvents( FF_IOManager_t *pxIOManager )\r
93 {\r
94         if( pxIOManager->xEventGroup != NULL )\r
95         {\r
96                 vEventGroupDelete( pxIOManager->xEventGroup );\r
97         }\r
98 }\r
99 /*-----------------------------------------------------------*/\r
100 \r
101 BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )\r
102 {\r
103 BaseType_t xResult;\r
104 \r
105         pxIOManager->xEventGroup = xEventGroupCreate();\r
106         if( pxIOManager->xEventGroup != NULL )\r
107         {\r
108                 xEventGroupSetBits( pxIOManager->xEventGroup,\r
109                         FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );\r
110                 xResult = pdTRUE;\r
111         }\r
112         else\r
113         {\r
114                 xResult = pdFALSE;\r
115         }\r
116 \r
117         return xResult;\r
118 }\r
119 /*-----------------------------------------------------------*/\r
120 \r
121 void FF_LockDirectory( FF_IOManager_t *pxIOManager )\r
122 {\r
123         EventBits_t xBits;\r
124 \r
125         for( ;; )\r
126         {\r
127                 /* Called when a task want to make changes to a directory.\r
128                 First it waits for the desired bit to come high. */\r
129                 xEventGroupWaitBits( pxIOManager->xEventGroup,\r
130                         FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
131                         ( EventBits_t )0,       /* xClearOnExit */\r
132                         pdFALSE,                /* xWaitForAllBits n.a. */\r
133                         pdMS_TO_TICKS( 10000UL ) );\r
134 \r
135                 /* The next operation will only succeed for 1 task at a time,\r
136                 because it is an atomary test & set operation: */\r
137                 xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );\r
138 \r
139                 if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )\r
140                 {\r
141                         /* This task has cleared the desired bit.\r
142                         It now 'owns' the resource. */\r
143                         break;\r
144                 }\r
145         }\r
146 }\r
147 /*-----------------------------------------------------------*/\r
148 \r
149 void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )\r
150 {\r
151         configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );\r
152         xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );\r
153 }\r
154 /*-----------------------------------------------------------*/\r
155 \r
156 int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )\r
157 {\r
158 int iReturn;\r
159 \r
160         void *handle = xTaskGetCurrentTaskHandle();\r
161         if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
162         {\r
163                 if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )\r
164                 {\r
165                         iReturn = pdTRUE;\r
166                 }\r
167                 else\r
168                 {\r
169                         iReturn = pdFALSE;\r
170                 }\r
171         }\r
172         else\r
173         {\r
174                 iReturn = pdFALSE;\r
175         }\r
176         return iReturn;\r
177 }\r
178 \r
179 void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )\r
180 {\r
181         void *handle = xTaskGetCurrentTaskHandle();\r
182 \r
183         if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
184         {\r
185                 configASSERT( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) );\r
186 \r
187                 /* In case configASSERT() is not defined. */\r
188                 ( void ) pxIOManager;\r
189                 ( void ) handle;\r
190         }\r
191 }\r
192 \r
193 void FF_LockFAT( FF_IOManager_t *pxIOManager )\r
194 {\r
195 EventBits_t xBits;\r
196 \r
197         configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );\r
198 \r
199         for( ;; )\r
200         {\r
201                 /* Called when a task want to make changes to the FAT area.\r
202                 First it waits for the desired bit to come high. */\r
203                 xEventGroupWaitBits( pxIOManager->xEventGroup,\r
204                         FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
205                         ( EventBits_t )0,       /* xClearOnExit */\r
206                         pdFALSE,                /* xWaitForAllBits n.a. */\r
207                         pdMS_TO_TICKS( 10000UL ) );\r
208 \r
209                 /* The next operation will only succeed for 1 task at a time,\r
210                 because it is an atomary test & set operation: */\r
211                 xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );\r
212 \r
213                 if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
214                 {\r
215                         /* This task has cleared the desired bit.\r
216                         It now 'owns' the resource. */\r
217                         pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();\r
218                         break;\r
219                 }\r
220         }\r
221 }\r
222 /*-----------------------------------------------------------*/\r
223 \r
224 void FF_UnlockFAT( FF_IOManager_t *pxIOManager )\r
225 {\r
226         configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );\r
227         pxIOManager->pvFATLockHandle = NULL;\r
228         xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );\r
229 }\r
230 /*-----------------------------------------------------------*/\r
231 \r
232 BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )\r
233 {\r
234 EventBits_t xBits;\r
235 BaseType_t xReturn;\r
236 \r
237         /* This function is called when a task is waiting for a sector buffer\r
238         to become available. */\r
239         xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,\r
240                 FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
241                 FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */\r
242                 pdFALSE,                /* xWaitForAllBits n.a. */\r
243                 pdMS_TO_TICKS( xWaitMS ) );\r
244         if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )\r
245         {\r
246                 xReturn = pdTRUE;\r
247         }\r
248         else\r
249         {\r
250                 xReturn = pdFALSE;\r
251         }\r
252 \r
253         return xReturn;\r
254 }\r
255 /*-----------------------------------------------------------*/\r
256 \r
257 void FF_BufferProceed( FF_IOManager_t *pxIOManager )\r
258 {\r
259         /* Wake-up all tasks that are waiting for a sector buffer to become available. */\r
260         xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );\r
261 }\r
262 /*-----------------------------------------------------------*/\r