]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/ff_locking.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / ff_locking.c
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/ff_locking.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/ff_locking.c
new file mode 100644 (file)
index 0000000..41db9ba
--- /dev/null
@@ -0,0 +1,325 @@
+/*\r
+ * FreeRTOS+FAT build 191128 - Note:  FreeRTOS+FAT is still in the lab!\r
+ * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ * Authors include James Walmsley, Hein Tibosch and Richard Barry\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * https://www.FreeRTOS.org\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+/* Scheduler include files. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+#include "semphr.h"\r
+#include "ff_headers.h"\r
+#include "event_groups.h"\r
+\r
+#ifndef configUSE_RECURSIVE_MUTEXES\r
+       #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h\r
+#else\r
+       #if( configUSE_RECURSIVE_MUTEXES != 1 )\r
+               #error configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h\r
+       #endif\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+\r
+#if ( INCLUDE_vTaskDelay != 1 )\r
+       #error Missing some FreeRTOS define\r
+#endif\r
+\r
+/* There are two areas which are protected with a semaphore:\r
+Directories and the FAT area.\r
+The masks below are used when calling Group Event functions. */\r
+#define FF_FAT_LOCK_EVENT_BITS    ( ( const EventBits_t ) FF_FAT_LOCK )\r
+#define FF_DIR_LOCK_EVENT_BITS    ( ( const EventBits_t ) FF_DIR_LOCK )\r
+\r
+/* This is not a real lock: it is a bit (or semaphore) will will be given\r
+each time when a sector buffer is released. */\r
+#define FF_BUF_LOCK_EVENT_BITS    ( ( const EventBits_t ) FF_BUF_LOCK )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms )\r
+{\r
+BaseType_t xReturn;\r
+\r
+       /* HT: Actually FF_TrySemaphore is never used. */\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               return 0;\r
+       }\r
+       configASSERT( pxSemaphore );\r
+       xReturn = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, pdMS_TO_TICKS( ulTime_ms ) );\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_PendSemaphore( void *pxSemaphore )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* No need to take the semaphore. */\r
+               return;\r
+       }\r
+       configASSERT( pxSemaphore );\r
+       xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) pxSemaphore, portMAX_DELAY );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_ReleaseSemaphore( void *pxSemaphore )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       configASSERT( pxSemaphore );\r
+       xSemaphoreGiveRecursive( ( SemaphoreHandle_t ) pxSemaphore );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_Sleep( uint32_t ulTime_ms )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* This sleep is used as a kind of yield.\r
+               Not necessary while the Scheduler does not run. */\r
+               return;\r
+       }\r
+       vTaskDelay( pdMS_TO_TICKS( ulTime_ms ) );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_DeleteEvents( FF_IOManager_t *pxIOManager )\r
+{\r
+       if( pxIOManager->xEventGroup != NULL )\r
+       {\r
+               vEventGroupDelete( pxIOManager->xEventGroup );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FF_CreateEvents( FF_IOManager_t *pxIOManager )\r
+{\r
+BaseType_t xResult;\r
+\r
+       pxIOManager->xEventGroup = xEventGroupCreate();\r
+       if( pxIOManager->xEventGroup != NULL )\r
+       {\r
+               xEventGroupSetBits( pxIOManager->xEventGroup,\r
+                       FF_FAT_LOCK_EVENT_BITS | FF_DIR_LOCK_EVENT_BITS | FF_BUF_LOCK_EVENT_BITS );\r
+               xResult = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xResult = pdFALSE;\r
+       }\r
+\r
+       return xResult;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_LockDirectory( FF_IOManager_t *pxIOManager )\r
+{\r
+       EventBits_t xBits;\r
+\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       for( ;; )\r
+       {\r
+               /* Called when a task want to make changes to a directory.\r
+               First it waits for the desired bit to come high. */\r
+               xEventGroupWaitBits( pxIOManager->xEventGroup,\r
+                       FF_DIR_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
+                       ( EventBits_t )0,       /* xClearOnExit */\r
+                       pdFALSE,                /* xWaitForAllBits n.a. */\r
+                       pdMS_TO_TICKS( 10000UL ) );\r
+\r
+               /* The next operation will only succeed for 1 task at a time,\r
+               because it is an atomary test & set operation: */\r
+               xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );\r
+\r
+               if( ( xBits & FF_DIR_LOCK_EVENT_BITS ) != 0 )\r
+               {\r
+                       /* This task has cleared the desired bit.\r
+                       It now 'owns' the resource. */\r
+                       break;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_UnlockDirectory( FF_IOManager_t *pxIOManager )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_DIR_LOCK_EVENT_BITS ) == 0 );\r
+       xEventGroupSetBits( pxIOManager->xEventGroup, FF_DIR_LOCK_EVENT_BITS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+int FF_Has_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )\r
+{\r
+int iReturn;\r
+\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return 0;\r
+       }\r
+       void *handle = xTaskGetCurrentTaskHandle();\r
+       if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
+       {\r
+               if( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) )\r
+               {\r
+                       iReturn = pdTRUE;\r
+               }\r
+               else\r
+               {\r
+                       iReturn = pdFALSE;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               iReturn = pdFALSE;\r
+       }\r
+       return iReturn;\r
+}\r
+\r
+void FF_Assert_Lock( FF_IOManager_t *pxIOManager, uint32_t aBits )\r
+{\r
+       void *handle;\r
+\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       handle = xTaskGetCurrentTaskHandle();\r
+\r
+       if( ( aBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
+       {\r
+               configASSERT( ( pxIOManager->pvFATLockHandle != NULL ) && ( pxIOManager->pvFATLockHandle == handle ) );\r
+\r
+               /* In case configASSERT() is not defined. */\r
+               ( void ) pxIOManager;\r
+               ( void ) handle;\r
+       }\r
+}\r
+\r
+void FF_LockFAT( FF_IOManager_t *pxIOManager )\r
+{\r
+EventBits_t xBits;\r
+\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Called when a task want to make changes to the FAT area.\r
+               First it waits for the desired bit to come high. */\r
+               xEventGroupWaitBits( pxIOManager->xEventGroup,\r
+                       FF_FAT_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
+                       ( EventBits_t )0,       /* xClearOnExit */\r
+                       pdFALSE,                /* xWaitForAllBits n.a. */\r
+                       pdMS_TO_TICKS( 10000UL ) );\r
+\r
+               /* The next operation will only succeed for 1 task at a time,\r
+               because it is an atomary test & set operation: */\r
+               xBits = xEventGroupClearBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );\r
+\r
+               if( ( xBits & FF_FAT_LOCK_EVENT_BITS ) != 0 )\r
+               {\r
+                       /* This task has cleared the desired bit.\r
+                       It now 'owns' the resource. */\r
+                       pxIOManager->pvFATLockHandle = xTaskGetCurrentTaskHandle();\r
+                       break;\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_UnlockFAT( FF_IOManager_t *pxIOManager )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );\r
+       pxIOManager->pvFATLockHandle = NULL;\r
+       xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+BaseType_t FF_BufferWait( FF_IOManager_t *pxIOManager, uint32_t xWaitMS )\r
+{\r
+EventBits_t xBits;\r
+BaseType_t xReturn;\r
+\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return pdTRUE;\r
+       }\r
+       /* This function is called when a task is waiting for a sector buffer\r
+       to become available. */\r
+       xBits = xEventGroupWaitBits( pxIOManager->xEventGroup,\r
+               FF_BUF_LOCK_EVENT_BITS, /* uxBitsToWaitFor */\r
+               FF_BUF_LOCK_EVENT_BITS, /* xClearOnExit */\r
+               pdFALSE,                /* xWaitForAllBits n.a. */\r
+               pdMS_TO_TICKS( xWaitMS ) );\r
+       if( ( xBits & FF_BUF_LOCK_EVENT_BITS ) != 0 )\r
+       {\r
+               xReturn = pdTRUE;\r
+       }\r
+       else\r
+       {\r
+               xReturn = pdFALSE;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_BufferProceed( FF_IOManager_t *pxIOManager )\r
+{\r
+       if( xTaskGetSchedulerState() != taskSCHEDULER_RUNNING )\r
+       {\r
+               /* Scheduler not yet active. */\r
+               return;\r
+       }\r
+       /* Wake-up all tasks that are waiting for a sector buffer to become available. */\r
+       xEventGroupSetBits( pxIOManager->xEventGroup, FF_BUF_LOCK_EVENT_BITS );\r
+}\r
+/*-----------------------------------------------------------*/\r