FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [January 2007 Threads] Proper use of a semaphorePosted by Scott Nortman on January 8, 2007 Is this the correct use of a semaphore to sync with an ISR:
void aTask( void *pv ){
____for(;;){ ________xSemaphoreTake( aSemaphore, 10 ); ________<cause ISR in a few ms > ________xSemaphoreTake( aSemaphore, 10 ); ________<rest of code> ____} }
ISR( INT0_vect ) { ____xSemaphoreGiveFromISR( aSemaphore ); }
Comments?
Thanks, Scott
RE: Proper use of a semaphorePosted by Nobody/Anonymous on January 8, 2007 This is the way it is done in some applications included in the download, and the way I do it.
The semaphore can be used to wake a high priority task to process the data obtained by the interrupt removing the need for the data to be processed in the interrupt itself.
In your example I presume the interrupt is guaranteed to occur within 10 ticks, or that you handle the case when this does not happen?
RE: Proper use of a semaphorePosted by Scott Nortman on January 8, 2007 How can a task be suspended indefinitly until a semaphore is given?
RE: Proper use of a semaphorePosted by Richard on January 8, 2007 When calling xSemaphoreTake() a block time is specified. The maximum block time that can be specified depends on the data type used for portTickType. If portTickType is 32 bits, and the tick is set to 1KHz (too fast for most applications) then the maximum block period is 0xffffffff or equivalent to approximately 40 days.
In FreeRTOS.org versions prior to V4.1.3 blocking for longer periods than this required the return value to be checked in a loop. For example:
while( xSemaphoreTake( aSemaphore, portMAX_DELAY ) != pdPASS );
would block the task indefinitely (pseudo indefinitely).
From V4.1.3 the behaviour can be changed depending on the value of configINCLUDE_vTaskSuspend. If configINCLUDE_vTaskSuspend is 0 then the behaviour is as per described above. If configINCLUDE_vTaskSuspend is 1 then a delay period of portMAX_DEALY is taken to mean that the task should block indefinitely and the while loop is not necessary.
This has not made it into the docs yet, other than the change history - sorry :-(
Regards.
RE: Proper use of a semaphorePosted by Scott Nortman on January 19, 2007 Thanks for the suggestions. So, just to confirm, assuming that I am using v4.1.3, I expect the following code to perform the following:
1. Take the semaphore 2. Cause an ISR to occur later in time 3. Start waiting for the semaphore 4. ISR gives the semaphore after a period of time 5. Calling task processes the data 6. Give the semaphore 7. Go to 1
/* Start of file */
static xSemaphoreHandle aTaskSemaphore;
void aTask( void * pv ) {
____vSemaphoreCreateBinary( aTaskSemaphore );
____for(;;){
________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ){
____________Trigger_ISR_Soon();
____________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ){
________________ProcessDataFromISR();
________________xSemaphoreGive( aTaskSemaphore );
____________}
________}
____}
} /* end aTask */
/* This is the ISR that will trigger and give the semaphore */ ISR( INT0_vect ) { ____portBASE_TYPE xTaskWoken = pdFALSE;
____if( xSemaphoreGiveFromISR( aTaskSemaphore, xTaskWoken ){
________taskYEILD();
____}
}
RE: Proper use of a semaphorePosted by Richard on January 20, 2007 Which port are you using? Some ports do not permit taskYELD() to be called directly in an ISR, and a different macro is provided for this purpose. If this is how it is done in the demo serial port driver that came with the port then it will be ok.
I'm not sure of the structure of your task, because I'm not sure what it is you are trying to do exactly. I understand steps 2 to 5, but not the bit around it. You seem to be synchronising with the ISR in two places. Is this correct? I'm also not sure about the call to xSemaphoreGive() in the task.
In its simplest for, where a task wants to execute each time an ISR executes, the code would take the following structure:
void vTask( void *pvParameters ) { ____for( ;; ) ____{ ________if( xSemaphoreTake( aTaskSemaphore, portMAX_DELAY ) == pdTRUE ) ________{ ____________/* Got the semaphore, the ISR must have fired. Do the work ____________here. */ ____________ ____________/* We do not have to give the semaphore back. The semaphore ____________is 'empty' because of our call to xSemaphoreTake(). We go ____________back to block again waiting for it to be given again by the ____________ISR. The task takes it, the ISR gives it. */ ________} ____} }
void vISR( void ) { portBASE_TYPE xYieldRequired = pdFALSE;
____/* ISR fired. Wake the task. */ ____if( xSemaphoreGiveFromISR( aTaskSemaphore, FALSE ) ) ____{ ________xYieldRequired = true; ____} ____ ____/* Clear the interrupt. */ ____ ____if( xYieldRequired ) ____{ ________/* Yield here using whatever macro is required by the port ________being used. */ ____} }
Regards.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|