 839e52ac32
			
		
	
	
		839e52ac32
		
			
		
	
	
	
	
		
			
			* Furi: remove CMSIS thread api, migrate to FuriThread, remove unused CMSIS APIs * Furi: magic thread catcher validating thread completion; backtrace improver * Furi: allow furi_thread_get_current_id outside of thread context * Furi: use IRQ instead of ISR for core primitives
		
			
				
	
	
		
			223 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "event_flags.h"
 | |
| #include "common_defines.h"
 | |
| 
 | |
| #include <event_groups.h>
 | |
| 
 | |
| #define MAX_BITS_EVENT_GROUPS 24U
 | |
| #define EVENT_FLAGS_INVALID_BITS (~((1UL << MAX_BITS_EVENT_GROUPS) - 1U))
 | |
| 
 | |
| osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t* attr) {
 | |
|     EventGroupHandle_t hEventGroup;
 | |
|     int32_t mem;
 | |
| 
 | |
|     hEventGroup = NULL;
 | |
| 
 | |
|     if(FURI_IS_IRQ_MODE() == 0U) {
 | |
|         mem = -1;
 | |
| 
 | |
|         if(attr != NULL) {
 | |
|             if((attr->cb_mem != NULL) && (attr->cb_size >= sizeof(StaticEventGroup_t))) {
 | |
|                 /* The memory for control block is provided, use static object */
 | |
|                 mem = 1;
 | |
|             } else {
 | |
|                 if((attr->cb_mem == NULL) && (attr->cb_size == 0U)) {
 | |
|                     /* Control block will be allocated from the dynamic pool */
 | |
|                     mem = 0;
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             mem = 0;
 | |
|         }
 | |
| 
 | |
|         if(mem == 1) {
 | |
| #if(configSUPPORT_STATIC_ALLOCATION == 1)
 | |
|             hEventGroup = xEventGroupCreateStatic(attr->cb_mem);
 | |
| #endif
 | |
|         } else {
 | |
|             if(mem == 0) {
 | |
| #if(configSUPPORT_DYNAMIC_ALLOCATION == 1)
 | |
|                 hEventGroup = xEventGroupCreate();
 | |
| #endif
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Return event flags ID */
 | |
|     return ((osEventFlagsId_t)hEventGroup);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Set the specified Event Flags.
 | |
| 
 | |
|   Limitations:
 | |
|   - Event flags are limited to 24 bits.
 | |
| */
 | |
| uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags) {
 | |
|     EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
 | |
|     uint32_t rflags;
 | |
|     BaseType_t yield;
 | |
| 
 | |
|     if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
 | |
|         rflags = (uint32_t)osErrorParameter;
 | |
|     } else if(FURI_IS_IRQ_MODE() != 0U) {
 | |
| #if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
 | |
|         (void)yield;
 | |
|         /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
 | |
|         rflags = (uint32_t)osErrorResource;
 | |
| #else
 | |
|         yield = pdFALSE;
 | |
| 
 | |
|         if(xEventGroupSetBitsFromISR(hEventGroup, (EventBits_t)flags, &yield) == pdFAIL) {
 | |
|             rflags = (uint32_t)osErrorResource;
 | |
|         } else {
 | |
|             rflags = flags;
 | |
|             portYIELD_FROM_ISR(yield);
 | |
|         }
 | |
| #endif
 | |
|     } else {
 | |
|         rflags = xEventGroupSetBits(hEventGroup, (EventBits_t)flags);
 | |
|     }
 | |
| 
 | |
|     /* Return event flags after setting */
 | |
|     return (rflags);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Clear the specified Event Flags.
 | |
| 
 | |
|   Limitations:
 | |
|   - Event flags are limited to 24 bits.
 | |
| */
 | |
| uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags) {
 | |
|     EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
 | |
|     uint32_t rflags;
 | |
| 
 | |
|     if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
 | |
|         rflags = (uint32_t)osErrorParameter;
 | |
|     } else if(FURI_IS_IRQ_MODE() != 0U) {
 | |
| #if(configUSE_OS2_EVENTFLAGS_FROM_ISR == 0)
 | |
|         /* Enable timers and xTimerPendFunctionCall function to support osEventFlagsSet from ISR */
 | |
|         rflags = (uint32_t)osErrorResource;
 | |
| #else
 | |
|         rflags = xEventGroupGetBitsFromISR(hEventGroup);
 | |
| 
 | |
|         if(xEventGroupClearBitsFromISR(hEventGroup, (EventBits_t)flags) == pdFAIL) {
 | |
|             rflags = (uint32_t)osErrorResource;
 | |
|         } else {
 | |
|             /* xEventGroupClearBitsFromISR only registers clear operation in the timer command queue. */
 | |
|             /* Yield is required here otherwise clear operation might not execute in the right order. */
 | |
|             /* See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/93 for more info.               */
 | |
|             portYIELD_FROM_ISR(pdTRUE);
 | |
|         }
 | |
| #endif
 | |
|     } else {
 | |
|         rflags = xEventGroupClearBits(hEventGroup, (EventBits_t)flags);
 | |
|     }
 | |
| 
 | |
|     /* Return event flags before clearing */
 | |
|     return (rflags);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Get the current Event Flags.
 | |
| 
 | |
|   Limitations:
 | |
|   - Event flags are limited to 24 bits.
 | |
| */
 | |
| uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) {
 | |
|     EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
 | |
|     uint32_t rflags;
 | |
| 
 | |
|     if(ef_id == NULL) {
 | |
|         rflags = 0U;
 | |
|     } else if(FURI_IS_IRQ_MODE() != 0U) {
 | |
|         rflags = xEventGroupGetBitsFromISR(hEventGroup);
 | |
|     } else {
 | |
|         rflags = xEventGroupGetBits(hEventGroup);
 | |
|     }
 | |
| 
 | |
|     /* Return current event flags */
 | |
|     return (rflags);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Wait for one or more Event Flags to become signaled.
 | |
| 
 | |
|   Limitations:
 | |
|   - Event flags are limited to 24 bits.
 | |
|   - osEventFlagsWait cannot be called from an ISR.
 | |
| */
 | |
| uint32_t
 | |
|     osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
 | |
|     EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
 | |
|     BaseType_t wait_all;
 | |
|     BaseType_t exit_clr;
 | |
|     uint32_t rflags;
 | |
| 
 | |
|     if((hEventGroup == NULL) || ((flags & EVENT_FLAGS_INVALID_BITS) != 0U)) {
 | |
|         rflags = (uint32_t)osErrorParameter;
 | |
|     } else if(FURI_IS_IRQ_MODE() != 0U) {
 | |
|         rflags = (uint32_t)osErrorISR;
 | |
|     } else {
 | |
|         if(options & osFlagsWaitAll) {
 | |
|             wait_all = pdTRUE;
 | |
|         } else {
 | |
|             wait_all = pdFAIL;
 | |
|         }
 | |
| 
 | |
|         if(options & osFlagsNoClear) {
 | |
|             exit_clr = pdFAIL;
 | |
|         } else {
 | |
|             exit_clr = pdTRUE;
 | |
|         }
 | |
| 
 | |
|         rflags = xEventGroupWaitBits(
 | |
|             hEventGroup, (EventBits_t)flags, exit_clr, wait_all, (TickType_t)timeout);
 | |
| 
 | |
|         if(options & osFlagsWaitAll) {
 | |
|             if((flags & rflags) != flags) {
 | |
|                 if(timeout > 0U) {
 | |
|                     rflags = (uint32_t)osErrorTimeout;
 | |
|                 } else {
 | |
|                     rflags = (uint32_t)osErrorResource;
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             if((flags & rflags) == 0U) {
 | |
|                 if(timeout > 0U) {
 | |
|                     rflags = (uint32_t)osErrorTimeout;
 | |
|                 } else {
 | |
|                     rflags = (uint32_t)osErrorResource;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Return event flags before clearing */
 | |
|     return (rflags);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Delete an Event Flags object.
 | |
| */
 | |
| osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) {
 | |
|     EventGroupHandle_t hEventGroup = (EventGroupHandle_t)ef_id;
 | |
|     osStatus_t stat;
 | |
| 
 | |
| #ifndef USE_FreeRTOS_HEAP_1
 | |
|     if(FURI_IS_IRQ_MODE() != 0U) {
 | |
|         stat = osErrorISR;
 | |
|     } else if(hEventGroup == NULL) {
 | |
|         stat = osErrorParameter;
 | |
|     } else {
 | |
|         stat = osOK;
 | |
|         vEventGroupDelete(hEventGroup);
 | |
|     }
 | |
| #else
 | |
|     stat = osError;
 | |
| #endif
 | |
| 
 | |
|     /* Return execution status */
 | |
|     return (stat);
 | |
| }
 |