]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/avr32_uc3/ff_locking.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / FreeRTOS-Plus-FAT / portable / avr32_uc3 / ff_locking.c
diff --git a/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/avr32_uc3/ff_locking.c b/FreeRTOS-Labs/Source/FreeRTOS-Plus-FAT/portable/avr32_uc3/ff_locking.c
new file mode 100644 (file)
index 0000000..5def6eb
--- /dev/null
@@ -0,0 +1,343 @@
+/*\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 "ff_headers.h"\r
+#include "event_groups.h"\r
+\r
+\r
+/* Scheduler include files. */\r
+#ifdef __WIN32__\r
+       #include "MyMalloc.h"\r
+#else\r
+       #include "FreeRTOS.h"\r
+       #include "task.h"\r
+       #include "semphr.h"\r
+       #include "tcpLogging.h"\r
+#endif\r
+\r
+#include "logbuf.h"\r
+#include <string.h>\r
+#include "bitops.h"\r
+#if USE_SOFT_WDT\r
+       #include "softWdt.h"\r
+#endif\r
+\r
+#include "thread_mutex.h"\r
+\r
+#include "event_groups.h"\r
+\r
+#if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       #include "eventLogging.h"\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
+extern void myTaskDelay (unsigned aTime);\r
+\r
+static char cMutexWasCreated = 0;\r
+static pthread_mutex_t xFATMutex;\r
+\r
+static void vCreateFATMutex ()\r
+{\r
+       cMutexWasCreated = 1;\r
+       pthread_mutex_init ("FreeRTOS+FAT", &xFATMutex, 0);\r
+}\r
+\r
+BaseType_t FF_HasSemaphore (void *pxSemaphore)\r
+{\r
+       // Return pdTRUE if the calling task owns the semaphore\r
+       if (!cMutexWasCreated) vCreateFATMutex ();\r
+       return pthread_has_mutex (&xFATMutex);\r
+}\r
+\r
+\r
+BaseType_t FF_SemaphoreTaken (void *pxSemaphore)\r
+{\r
+       // Return pdTRUE if the calling task owns the semaphore\r
+       if (!cMutexWasCreated) vCreateFATMutex ();\r
+       return pthread_mutex_islocked (&xFATMutex);\r
+}\r
+\r
+\r
+#if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+static char mutex_owner[32];\r
+#endif\r
+\r
+BaseType_t FF_TrySemaphore( void *pxSemaphore, uint32_t ulTime_ms)\r
+{\r
+BaseType_t rc;\r
+       #if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       {\r
+               eventLogAdd("Pend_%s\n", pcName);\r
+       }\r
+       #endif /* FF_DO_TRACE_SEMAPHORE */\r
+       if (!cMutexWasCreated) vCreateFATMutex ();\r
+       rc = pthread_mutex_lock (&xFATMutex, ulTime_ms);\r
+       #if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       if (rc > 0) {\r
+               if(mutex_owner[0] != 0) {\r
+                       logPrintf("Pend Try: %s overruled\n", mutex_owner);\r
+               }\r
+               snprintf(mutex_owner, sizeof mutex_owner, pcName);\r
+       }\r
+       #endif /* FF_DO_TRACE_SEMAPHORE */\r
+       return rc;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_PendSemaphore( void *pxSemaphore )\r
+{\r
+       #if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       {\r
+               eventLogAdd("Pend_%s\n", pcName);\r
+       }\r
+       #endif /* FF_DO_TRACE_SEMAPHORE */\r
+\r
+       if (!cMutexWasCreated) vCreateFATMutex ();\r
+       pthread_mutex_lock (&xFATMutex, 120000);\r
+       #if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       {\r
+               if(mutex_owner[0] != 0) {\r
+                       logPrintf("Pend Enter: %s overruled by %s\n", mutex_owner, pcName);\r
+               }\r
+               snprintf(mutex_owner, sizeof mutex_owner, pcName);\r
+       }\r
+       #endif /* FF_DO_TRACE_SEMAPHORE */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_ReleaseSemaphore( void *pxSemaphore )\r
+{\r
+       #if( FF_DO_TRACE_SEMAPHORE != 0 )\r
+       {\r
+               if(strcmp (pcName, mutex_owner) != 0) {\r
+                       // FF_GetBuffer2 != FF_GetBuffer\r
+                       logPrintf("Pend Exit: %s owned by %s\n", pcName, mutex_owner);\r
+               }\r
+               eventLogAdd("Exit_%s\n", pcName);\r
+               mutex_owner[0] = '\0';\r
+       }\r
+       #endif /* FF_DO_TRACE_SEMAPHORE */\r
+\r
+       if (cMutexWasCreated)  {\r
+               pthread_mutex_unlock (&xFATMutex);\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void FF_Sleep( uint32_t ulTime_ms )\r
+{\r
+       myTaskDelay (ulTime_ms);\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
+       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
+       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
+       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 = 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
+       configASSERT( FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) == pdFALSE );\r
+       if (FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) != pdFALSE )\r
+       {\r
+               return;\r
+       }\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
+       configASSERT( ( xEventGroupGetBits( pxIOManager->xEventGroup ) & FF_FAT_LOCK_EVENT_BITS ) == 0 );\r
+       if (FF_Has_Lock( pxIOManager, FF_FAT_LOCK ) != pdFALSE )\r
+       {\r
+               pxIOManager->pvFATLockHandle = NULL;\r
+               xEventGroupSetBits( pxIOManager->xEventGroup, FF_FAT_LOCK_EVENT_BITS );\r
+       }\r
+       else\r
+       {\r
+               FF_PRINTF("FF_UnlockFAT: wasn't locked by me\n");\r
+       }\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
+       /* 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
+       /* 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