2 FreeRTOS.org V4.0.2 - Copyright (C) 2003-2006 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 See http://www.FreeRTOS.org for documentation, latest information, license
\r
28 and contact details. Please ensure to read the configuration and relevant
\r
29 port sections of the online documentation.
\r
30 ***************************************************************************
\r
38 typedef xQueueHandle xSemaphoreHandle;
\r
40 #define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( unsigned portCHAR ) 1 )
\r
41 #define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( unsigned portCHAR ) 0 )
\r
42 #define semGIVE_BLOCK_TIME ( ( portTickType ) 0 )
\r
47 * <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre>
\r
49 * <i>Macro</i> that implements a semaphore by using the existing queue mechanism.
\r
50 * The queue length is 1 as this is a binary semaphore. The data size is 0
\r
51 * as we don't want to actually store any data - we just want to know if the
\r
52 * queue is empty or full.
\r
54 * @param xSemaphore Handle to the created semaphore. Should be of type xSemaphoreHandle.
\r
58 xSemaphoreHandle xSemaphore;
\r
60 void vATask( void * pvParameters )
\r
62 // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
\r
63 // This is a macro so pass the variable in directly.
\r
64 vSemaphoreCreateBinary( xSemaphore );
\r
66 if( xSemaphore != NULL )
\r
68 // The semaphore was created successfully.
\r
69 // The semaphore can now be used.
\r
73 * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary
\r
74 * \ingroup Semaphores
\r
76 #define vSemaphoreCreateBinary( xSemaphore ) { \
\r
77 xSemaphore = xQueueCreate( ( unsigned portCHAR ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH ); \
\r
78 if( xSemaphore != NULL ) \
\r
80 xSemaphoreGive( xSemaphore ); \
\r
87 * xSemaphoreHandle xSemaphore,
\r
88 * portTickType xBlockTime
\r
91 * <i>Macro</i> to obtain a semaphore. The semaphore must of been created using
\r
92 * vSemaphoreCreateBinary ().
\r
94 * @param xSemaphore A handle to the semaphore being obtained. This is the
\r
95 * handle returned by vSemaphoreCreateBinary ();
\r
97 * @param xBlockTime The time in ticks to wait for the semaphore to become
\r
98 * available. The macro portTICK_RATE_MS can be used to convert this to a
\r
99 * real time. A block time of zero can be used to poll the semaphore.
\r
101 * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime
\r
102 * expired without the semaphore becoming available.
\r
106 xSemaphoreHandle xSemaphore = NULL;
\r
108 // A task that creates a semaphore.
\r
109 void vATask( void * pvParameters )
\r
111 // Create the semaphore to guard a shared resource.
\r
112 vSemaphoreCreateBinary( xSemaphore );
\r
115 // A task that uses the semaphore.
\r
116 void vAnotherTask( void * pvParameters )
\r
118 // ... Do other things.
\r
120 if( xSemaphore != NULL )
\r
122 // See if we can obtain the semaphore. If the semaphore is not available
\r
123 // wait 10 ticks to see if it becomes free.
\r
124 if( xSemaphoreTake( xSemaphore, ( portTickType ) 10 ) == pdTRUE )
\r
126 // We were able to obtain the semaphore and can now access the
\r
127 // shared resource.
\r
131 // We have finished accessing the shared resource. Release the
\r
133 xSemaphoreGive( xSemaphore );
\r
137 // We could not obtain the semaphore and can therefore not access
\r
138 // the shared resource safely.
\r
143 * \defgroup xSemaphoreTake xSemaphoreTake
\r
144 * \ingroup Semaphores
\r
146 #define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime )
\r
150 * <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>
\r
152 * <i>Macro</i> to release a semaphore. The semaphore must of been created using
\r
153 * vSemaphoreCreateBinary (), and obtained using sSemaphoreTake ().
\r
155 * This must not be used from an ISR. See xSemaphoreGiveFromISR () for
\r
156 * an alternative which can be used from an ISR.
\r
158 * @param xSemaphore A handle to the semaphore being released. This is the
\r
159 * handle returned by vSemaphoreCreateBinary ();
\r
161 * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred.
\r
162 * Semaphores are implemented using queues. An error can occur if there is
\r
163 * no space on the queue to post a message - indicating that the
\r
164 * semaphore was not first obtained correctly.
\r
168 xSemaphoreHandle xSemaphore = NULL;
\r
170 void vATask( void * pvParameters )
\r
172 // Create the semaphore to guard a shared resource.
\r
173 vSemaphoreCreateBinary( xSemaphore );
\r
175 if( xSemaphore != NULL )
\r
177 if( xSemaphoreGive( xSemaphore ) != pdTRUE )
\r
179 // We would expect this call to fail because we cannot give
\r
180 // a semaphore without first "taking" it!
\r
183 // Obtain the semaphore - don't block if the semaphore is not
\r
184 // immediately available.
\r
185 if( xSemaphoreTake( xSemaphore, ( portTickType ) 0 ) )
\r
187 // We now have the semaphore and can access the shared resource.
\r
191 // We have finished accessing the shared resource so can free the
\r
193 if( xSemaphoreGive( xSemaphore ) != pdTRUE )
\r
195 // We would not expect this call to fail because we must have
\r
196 // obtained the semaphore to get here.
\r
202 * \defgroup xSemaphoreGive xSemaphoreGive
\r
203 * \ingroup Semaphores
\r
205 #define xSemaphoreGive( xSemaphore ) xQueueSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME )
\r
210 xSemaphoreGiveFromISR(
\r
211 xSemaphoreHandle xSemaphore,
\r
212 portSHORT sTaskPreviouslyWoken
\r
215 * <i>Macro</i> to release a semaphore. The semaphore must of been created using
\r
216 * vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().
\r
218 * This macro can be used from an ISR.
\r
220 * @param xSemaphore A handle to the semaphore being released. This is the
\r
221 * handle returned by vSemaphoreCreateBinary ();
\r
223 * @param sTaskPreviouslyWoken This is included so an ISR can make multiple calls
\r
224 * to xSemaphoreGiveFromISR () from a single interrupt. The first call
\r
225 * should always pass in pdFALSE. Subsequent calls should pass in
\r
226 * the value returned from the previous call. See the file serial .c in the
\r
227 * PC port for a good example of using xSemaphoreGiveFromISR ().
\r
229 * @return pdTRUE if a task was woken by releasing the semaphore. This is
\r
230 * used by the ISR to determine if a context switch may be required following
\r
235 #define LONG_TIME 0xffff
\r
236 #define TICKS_TO_WAIT 10
\r
237 xSemaphoreHandle xSemaphore = NULL;
\r
239 // Repetitive task.
\r
240 void vATask( void * pvParameters )
\r
244 // We want this task to run every 10 ticks or a timer. The semaphore
\r
245 // was created before this task was started
\r
247 // Block waiting for the semaphore to become available.
\r
248 if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
\r
250 // It is time to execute.
\r
254 // We have finished our task. Return to the top of the loop where
\r
255 // we will block on the semaphore until it is time to execute
\r
262 void vTimerISR( void * pvParameters )
\r
264 static unsigned portCHAR ucLocalTickCount = 0;
\r
266 // A timer tick has occurred.
\r
268 // ... Do other time functions.
\r
270 // Is it time for vATask () to run?
\r
271 ucLocalTickCount++;
\r
272 if( ucLocalTickCount >= TICKS_TO_WAIT )
\r
274 // Unblock the task by releasing the semaphore.
\r
275 xSemaphoreGive( xSemaphore );
\r
277 // Reset the count so we release the semaphore again in 10 ticks time.
\r
278 ucLocalTickCount = 0;
\r
282 * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
\r
283 * \ingroup Semaphores
\r
285 #define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken ) xQueueSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken )
\r