Martin
typedef struct INVCNT_SEMAPHORE {
xSemaphoreHandle mutex;
xQueueHandle msgQueue;
} INVCNT_SEMAPHORE;
portBASE_TYPE invCntCreate(INVCNT_SEMAPHORE * b) {
b->mutex = xSemaphoreCreateMutex();
return ((NULL == b->mutex) ? pdFALSE : pdTRUE);
}
portBASE_TYPE invCntTake(INVCNT_SEMAPHORE * b,
unsigned portBASE_TYPE uxMaxCount, portTickType xTicksToWait) {
unsigned portCHAR dummy;
portBASE_TYPE err;
portTickType timeout;
// Lock resource to protect from taking by task with higher priority.
err = xSemaphoreTake( b->mutex , (portTickType)0);
if (pdTRUE != err) {
// Taken failed. Maybe was taken before.
return err;
}
// Delete message queue.
if (NULL != b->msgQueue) {
// Protect this deletion to avoid sending to null queue in condGive.
portENTER_CRITICAL();
// Delete queue.
vQueueDelete(b->msgQueue);
b->msgQueue = NULL;
// Exit critical section.
portEXIT_CRITICAL();
}
// Create message queue based on uxMaxCount value.
// How many times can be condVar given.
b->msgQueue = xQueueCreate(uxMaxCount, sizeof(unsigned portCHAR));
// Process only if queue was created.
if (NULL != b->msgQueue) {
// Iterate thought uxMaxCount(until n*given or timeout).
while (uxMaxCount != 0) {
// Compute the timeout value.
timeout = xTaskGetTickCount();
// Receive item from queue.
err = xQueueReceive(b->msgQueue, &(dummy), xTicksToWait);
// Check for xQueueReceive return value.
if (pdTRUE != err) {
break;
}
#if BARRIER_DUMMY_VAL_CHECK // Something wrong?
// Check the value.
if (BARRIER_DUMMY_VAL != dummy) {
err = pdFALSE;
break;
}
#endif
// If time is infinite, do not edit xTicksToWait.
if (portMAX_DELAY != xTicksToWait) {
// Get current tick time. To save function calling.
portTickType timeElapsed = xTaskGetTickCount() - timeout;
// Get current tick time and count how many ticks we should wait before the total timeout.
// Probably xTicksToWait > timeElapsed should be always true.
xTicksToWait = (xTicksToWait > timeElapsed) ? (xTicksToWait
- timeElapsed) : 0;
}
// Decrement number of given's.
uxMaxCount--;
}//while (uxMaxCount != 0)
}
// Release protecting mutex.
xSemaphoreGive( b->mutex );
// Return last error.
return err;
}
portBASE_TYPE invCntGive(INVCNT_SEMAPHORE * b) {
unsigned portCHAR dummy = BARRIER_DUMMY_VAL;
portBASE_TYPE err;
// Send to the cond var iff message queue is not NULL.
if (NULL != b->msgQueue) {
err = xQueueSend(b->msgQueue, &(dummy), (portTickType)0);
} else {
err = pdFALSE;
}
return err;
}
portBASE_TYPE invCntGiveFromISR(INVCNT_SEMAPHORE * b,
portBASE_TYPE * pxHigherPriorityTaskWoken) {
unsigned portCHAR dummy = BARRIER_DUMMY_VAL;
if (NULL != b->msgQueue) {
return xQueueSendFromISR(b->msgQueue, &(dummy), pxHigherPriorityTaskWoken);
} else {
return pdFALSE;
}
}