]> git.sur5r.net Git - freertos/blob - Source/include/semphr.h
Implement xTaskResumeFromISR.
[freertos] / Source / include / semphr.h
1 /*\r
2         FreeRTOS.org V4.0.4 - Copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \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
10 \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
15 \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
19 \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
24         can be applied.\r
25 \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
31 */\r
32 \r
33 #include "queue.h"\r
34 \r
35 #ifndef SEMAPHORE_H\r
36 #define SEMAPHORE_H\r
37 \r
38 typedef xQueueHandle xSemaphoreHandle;\r
39 \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
43 \r
44 \r
45 /**\r
46  * semphr. h\r
47  * <pre>vSemaphoreCreateBinary( xSemaphoreHandle xSemaphore )</pre>\r
48  *\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
53  *\r
54  * @param xSemaphore Handle to the created semaphore.  Should be of type xSemaphoreHandle.\r
55  *\r
56  * Example usage:\r
57  <pre>\r
58  xSemaphoreHandle xSemaphore;\r
59 \r
60  void vATask( void * pvParameters )\r
61  {\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
65 \r
66     if( xSemaphore != NULL )\r
67     {\r
68         // The semaphore was created successfully.\r
69         // The semaphore can now be used.  \r
70     }\r
71  }\r
72  </pre>\r
73  * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary\r
74  * \ingroup Semaphores\r
75  */\r
76 #define vSemaphoreCreateBinary( xSemaphore )            {                                                                                                                                                                                       \\r
77                                                                                                                 xSemaphore = xQueueCreate( ( unsigned portCHAR ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH );   \\r
78                                                                                                                 if( xSemaphore != NULL )                                                                                                                                \\r
79                                                                                                                 {                                                                                                                                                                               \\r
80                                                                                                                         xSemaphoreGive( xSemaphore );                                                                                                           \\r
81                                                                                                                 }                                                                                                                                                                               \\r
82                                                                                                         }\r
83 \r
84 /**\r
85  * semphr. h\r
86  * xSemaphoreTake( \r
87  *                   xSemaphoreHandle xSemaphore, \r
88  *                   portTickType xBlockTime \r
89  *               )</pre>\r
90  *\r
91  * <i>Macro</i> to obtain a semaphore.  The semaphore must of been created using \r
92  * vSemaphoreCreateBinary ().\r
93  *\r
94  * @param xSemaphore A handle to the semaphore being obtained.  This is the\r
95  * handle returned by vSemaphoreCreateBinary ();\r
96  *\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
100  *\r
101  * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime\r
102  * expired without the semaphore becoming available.\r
103  *\r
104  * Example usage:\r
105  <pre>\r
106  xSemaphoreHandle xSemaphore = NULL;\r
107 \r
108  // A task that creates a semaphore.\r
109  void vATask( void * pvParameters )\r
110  {\r
111     // Create the semaphore to guard a shared resource.\r
112     vSemaphoreCreateBinary( xSemaphore );\r
113  }\r
114 \r
115  // A task that uses the semaphore.\r
116  void vAnotherTask( void * pvParameters )\r
117  {\r
118     // ... Do other things.\r
119 \r
120     if( xSemaphore != NULL )\r
121     {\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
125         {\r
126             // We were able to obtain the semaphore and can now access the\r
127             // shared resource.\r
128 \r
129             // ...\r
130 \r
131             // We have finished accessing the shared resource.  Release the \r
132             // semaphore.\r
133             xSemaphoreGive( xSemaphore );\r
134         }\r
135         else\r
136         {\r
137             // We could not obtain the semaphore and can therefore not access\r
138             // the shared resource safely.\r
139         }\r
140     }\r
141  }\r
142  </pre>\r
143  * \defgroup xSemaphoreTake xSemaphoreTake\r
144  * \ingroup Semaphores\r
145  */\r
146 #define xSemaphoreTake( xSemaphore, xBlockTime )        xQueueReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime )\r
147 \r
148 /**\r
149  * semphr. h\r
150  * <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>\r
151  *\r
152  * <i>Macro</i> to release a semaphore.  The semaphore must of been created using \r
153  * vSemaphoreCreateBinary (), and obtained using sSemaphoreTake ().\r
154  *\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
157  *\r
158  * @param xSemaphore A handle to the semaphore being released.  This is the\r
159  * handle returned by vSemaphoreCreateBinary ();\r
160  *\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
165  *\r
166  * Example usage:\r
167  <pre>\r
168  xSemaphoreHandle xSemaphore = NULL;\r
169 \r
170  void vATask( void * pvParameters )\r
171  {\r
172     // Create the semaphore to guard a shared resource.\r
173     vSemaphoreCreateBinary( xSemaphore );\r
174 \r
175     if( xSemaphore != NULL )\r
176     {\r
177         if( xSemaphoreGive( xSemaphore ) != pdTRUE )\r
178         {\r
179             // We would expect this call to fail because we cannot give\r
180             // a semaphore without first "taking" it!\r
181         }\r
182 \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
186         {\r
187             // We now have the semaphore and can access the shared resource.\r
188 \r
189             // ...\r
190 \r
191             // We have finished accessing the shared resource so can free the\r
192             // semaphore.\r
193             if( xSemaphoreGive( xSemaphore ) != pdTRUE )\r
194             {\r
195                 // We would not expect this call to fail because we must have\r
196                 // obtained the semaphore to get here.\r
197             }\r
198         }\r
199     }\r
200  }\r
201  </pre>\r
202  * \defgroup xSemaphoreGive xSemaphoreGive\r
203  * \ingroup Semaphores\r
204  */\r
205 #define xSemaphoreGive( xSemaphore )                            xQueueSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME )\r
206 \r
207 /**\r
208  * semphr. h\r
209  * <pre>\r
210  xSemaphoreGiveFromISR( \r
211                           xSemaphoreHandle xSemaphore, \r
212                           portSHORT sTaskPreviouslyWoken \r
213                       )</pre>\r
214  *\r
215  * <i>Macro</i> to  release a semaphore.  The semaphore must of been created using \r
216  * vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().\r
217  *\r
218  * This macro can be used from an ISR.\r
219  *\r
220  * @param xSemaphore A handle to the semaphore being released.  This is the\r
221  * handle returned by vSemaphoreCreateBinary ();\r
222  *\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
228  *\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
231  * the ISR.\r
232  *\r
233  * Example usage:\r
234  <pre>\r
235  #define LONG_TIME 0xffff\r
236  #define TICKS_TO_WAIT  10\r
237  xSemaphoreHandle xSemaphore = NULL;\r
238 \r
239  // Repetitive task.\r
240  void vATask( void * pvParameters )\r
241  {\r
242     for( ;; )\r
243     {\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
246 \r
247         // Block waiting for the semaphore to become available.\r
248         if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )\r
249         {\r
250             // It is time to execute.\r
251 \r
252             // ...\r
253 \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
256             // again.\r
257         }\r
258     }\r
259  }\r
260 \r
261  // Timer ISR\r
262  void vTimerISR( void * pvParameters )\r
263  {\r
264  static unsigned portCHAR ucLocalTickCount = 0;\r
265 \r
266     // A timer tick has occurred.\r
267 \r
268     // ... Do other time functions.\r
269 \r
270     // Is it time for vATask () to run?\r
271     ucLocalTickCount++;\r
272     if( ucLocalTickCount >= TICKS_TO_WAIT )\r
273     {\r
274         // Unblock the task by releasing the semaphore.\r
275         xSemaphoreGive( xSemaphore );\r
276 \r
277         // Reset the count so we release the semaphore again in 10 ticks time.\r
278         ucLocalTickCount = 0;\r
279     }\r
280  }\r
281  </pre>\r
282  * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR\r
283  * \ingroup Semaphores\r
284  */\r
285 #define xSemaphoreGiveFromISR( xSemaphore, xTaskPreviouslyWoken )                       xQueueSendFromISR( ( xQueueHandle ) xSemaphore, NULL, xTaskPreviouslyWoken )\r
286 \r
287 \r
288 #endif\r
289 \r