static void prvExerciseSemaphoreAPI( void ) { SemaphoreHandle_t xSemaphore; const UBaseType_t uxMaxCount = 5, uxInitialCount = 0; /* Most of the semaphore API is common to the queue API and is already being used. This function uses a few semaphore functions that are unique to the RTOS objects, rather than generic and used by queues also. First create and use a counting semaphore. */ xSemaphore = xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ); configASSERT( xSemaphore ); /* Give the semaphore a couple of times and ensure the count is returned correctly. */ xSemaphoreGive( xSemaphore ); xSemaphoreGive( xSemaphore ); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 2 ); vSemaphoreDelete( xSemaphore ); /* Create a recursive mutex, and ensure the mutex holder and count are returned returned correctly. */ xSemaphore = xSemaphoreCreateRecursiveMutex(); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); configASSERT( xSemaphore ); xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK ); xSemaphoreTakeRecursive( xSemaphore, mainDONT_BLOCK ); configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() ); configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetHandle( mainTASK_TO_DELETE_NAME ) ); xSemaphoreGiveRecursive( xSemaphore ); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); xSemaphoreGiveRecursive( xSemaphore ); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL ); vSemaphoreDelete( xSemaphore ); /* Create a normal mutex, and sure the mutex holder and count are returned returned correctly. */ xSemaphore = xSemaphoreCreateMutex(); configASSERT( xSemaphore ); xSemaphoreTake( xSemaphore, mainDONT_BLOCK ); xSemaphoreTake( xSemaphore, mainDONT_BLOCK ); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 0 ); /* Not recursive so can only be 1. */ configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == xTaskGetCurrentTaskHandle() ); xSemaphoreGive( xSemaphore ); configASSERT( uxSemaphoreGetCount( xSemaphore ) == 1 ); configASSERT( xSemaphoreGetMutexHolder( xSemaphore ) == NULL ); vSemaphoreDelete( xSemaphore ); }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexLock * Description : This function checks the mutex's status, if it is unlocked, * lock it and returns kStatus_OSA_Success, otherwise, timeout will be used for * wait. The parameter timeout indicates how long should wait in milliseconds. * Pass OSA_WAIT_FOREVER to wait indefinitely, pass 0 will return the value * kStatus_OSA_Timeout immediately if mutex is locked. * This function returns kStatus_OSA_Success if the mutex is obtained, returns * kStatus_OSA_Timeout if the mutex is not obtained within the specified * 'timeout', returns kStatus_OSA_Error if any errors occur during waiting. * *END**************************************************************************/ osa_status_t OSA_MutexLock(mutex_t *pMutex, uint32_t timeout) { uint32_t timeoutTicks; assert(pMutex); /* If pMutex has been locked by current task, return error. */ if (xSemaphoreGetMutexHolder(*pMutex) == xTaskGetCurrentTaskHandle()) { return kStatus_OSA_Error; } /* Convert timeout from millisecond to tick. */ if (timeout == OSA_WAIT_FOREVER) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(timeout); } if (xSemaphoreTake(*pMutex, timeoutTicks)==pdFALSE) { return kStatus_OSA_Timeout; /* timeout */ } else { return kStatus_OSA_Success; /* semaphore taken */ } }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexUnlock * Description : This function is used to unlock a mutex. * *END**************************************************************************/ osaStatus_t OSA_MutexUnlock(osaMutexId_t mutexId) { #if osNumberOfMutexes mutex_t mutex = (mutex_t)mutexId; if(mutexId == NULL) { return osaStatus_Error; } /* If pMutex is not locked by current task, return error. */ if (xSemaphoreGetMutexHolder(mutex) != xTaskGetCurrentTaskHandle()) { return osaStatus_Error; } if (xSemaphoreGive(mutex)==pdPASS) { return osaStatus_Success; } else { return osaStatus_Error; } #else (void)mutexId; return osaStatus_Error; #endif }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexUnlock * Description : This function is used to unlock a mutex. * *END**************************************************************************/ osa_status_t OSA_MutexUnlock(mutex_t *pMutex) { assert(pMutex); /* If pMutex is not locked by current task, return error. */ if (xSemaphoreGetMutexHolder(*pMutex) != xTaskGetCurrentTaskHandle()) { return kStatus_OSA_Error; } if (xSemaphoreGive(*pMutex)==pdPASS) { return kStatus_OSA_Success; } else { return kStatus_OSA_Error; } }
/*FUNCTION********************************************************************** * * Function Name : OSA_MutexLock * Description : This function checks the mutex's status, if it is unlocked, * lock it and returns osaStatus_Success, otherwise, wait for the mutex. * This function returns osaStatus_Success if the mutex is obtained, returns * osaStatus_Error if any errors occur during waiting. If the mutex has been * locked, pass 0 as timeout will return osaStatus_Timeout immediately. * *END**************************************************************************/ osaStatus_t OSA_MutexLock(osaMutexId_t mutexId, uint32_t millisec) { #if osNumberOfMutexes uint32_t timeoutTicks; mutex_t mutex = (mutex_t)mutexId; if(mutexId == NULL) { return osaStatus_Error; } /* If pMutex has been locked by current task, return error. */ if (xSemaphoreGetMutexHolder(mutex) == xTaskGetCurrentTaskHandle()) { return osaStatus_Error; } /* Convert timeout from millisecond to tick. */ if (millisec == osaWaitForever_c) { timeoutTicks = portMAX_DELAY; } else { timeoutTicks = MSEC_TO_TICK(millisec); } if (xSemaphoreTake(mutex, timeoutTicks)==pdFALSE) { return osaStatus_Timeout; /* timeout */ } else { return osaStatus_Success; /* semaphore taken */ } #else (void)mutexId; (void)millisec; return osaStatus_Error; #endif }
/** * @brief mmem_check checks the memory system for consistency */ void mmem_check(void) { if (mutex == NULL) { /* initalization not done, * so data could be wrong */ return; } /* In ISR the mutex state could not be checked, * therefore cancle when called from ISR. */ const uint16_t irq_nr = (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk); if (irq_nr > 0) { return; } /* mutex check is only needed, if the scheduler is running */ if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { /* do not check, if any function is in the critical region */ if (xSemaphoreGetMutexHolder(mutex) != NULL) { return; } /* enter the critical section */ if ( !xSemaphoreTake(mutex, portMAX_DELAY) ) { return; } } else { return; } if (avail_memory > MMEM_SIZE) { /* only last two entries needed. * On first check was successfully and on * second entry check fails */ print_stack_trace_part(2); } const struct mmem* const first = list_head(mmemlist); if (first != NULL) { /* only check the list, if there is an element */ const struct mmem* m = first; for (; m->next != NULL; m = m->next) { if (m->real_size < m->size) { /* only last two entries needed. * On first check was successfully and on * second entry check fails */ print_stack_trace_part(2); } const size_t offset = m->next->ptr - m->ptr; if (offset != m->real_size) { /* only last two entries needed. * On first check was successfully and on * second entry check fails */ print_stack_trace_part(2); } } /* last element uses different checks */ if (m->real_size < m->size) { /* only last two entries needed. * On first check was successfully and on * second entry check fails */ print_stack_trace_part(2); } const size_t offset = &memory[MMEM_SIZE - avail_memory] - (char*)m->ptr; if (offset != m->real_size) { /* only last two entries needed. * On first check was successfully and on * second entry check fails */ print_stack_trace_part(2); } } xSemaphoreGive(mutex); }