]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/Minimal/QueueOverwrite.c
5b1dea541803e80e8d8e8f21070e40f6e8af62bd
[freertos] / FreeRTOS / Demo / Common / Minimal / QueueOverwrite.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /*\r
29  * Basic task to demonstrate the xQueueOverwrite() function.  See the comments\r
30  * in the function itself.\r
31  */\r
32 \r
33 /* Scheduler include files. */\r
34 #include "FreeRTOS.h"\r
35 #include "task.h"\r
36 #include "queue.h"\r
37 \r
38 /* Demo program include files. */\r
39 #include "QueueOverwrite.h"\r
40 \r
41 /* A block time of 0 just means "don't block". */\r
42 #define qoDONT_BLOCK            0\r
43 \r
44 /* Number of times to overwrite the value in the queue. */\r
45 #define qoLOOPS                 5\r
46 \r
47 /* The task that uses the queue. */\r
48 static void prvQueueOverwriteTask( void *pvParameters );\r
49 \r
50 /* Variable that is incremented on each loop of prvQueueOverwriteTask() provided\r
51 prvQueueOverwriteTask() has not found any errors. */\r
52 static uint32_t ulLoopCounter = 0;\r
53 \r
54 /* Set to pdFALSE if an error is discovered by the\r
55 vQueueOverwritePeriodicISRDemo() function. */\r
56 static BaseType_t xISRTestStatus = pdPASS;\r
57 \r
58 /* The queue that is accessed from the ISR.  The queue accessed by the task is\r
59 created inside the task itself. */\r
60 static QueueHandle_t xISRQueue = NULL;\r
61 \r
62 /*-----------------------------------------------------------*/\r
63 \r
64 void vStartQueueOverwriteTask( UBaseType_t uxPriority )\r
65 {\r
66 const UBaseType_t uxQueueLength = 1;\r
67 \r
68         /* Create the queue used by the ISR.  xQueueOverwriteFromISR() should only\r
69         be used on queues that have a length of 1. */\r
70         xISRQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );\r
71 \r
72         /* Create the test task.  The queue used by the test task is created inside\r
73         the task itself. */\r
74         xTaskCreate( prvQueueOverwriteTask, "QOver", configMINIMAL_STACK_SIZE, NULL, uxPriority, ( TaskHandle_t * ) NULL );\r
75 }\r
76 /*-----------------------------------------------------------*/\r
77 \r
78 static void prvQueueOverwriteTask( void *pvParameters )\r
79 {\r
80 QueueHandle_t xTaskQueue;\r
81 const UBaseType_t uxQueueLength = 1;\r
82 uint32_t ulValue, ulStatus = pdPASS, x;\r
83 \r
84         /* The parameter is not used. */\r
85         ( void ) pvParameters;\r
86 \r
87         /* Create the queue.  xQueueOverwrite() should only be used on queues that\r
88         have a length of 1. */\r
89         xTaskQueue = xQueueCreate( uxQueueLength, ( UBaseType_t ) sizeof( uint32_t ) );\r
90         configASSERT( xTaskQueue );\r
91 \r
92         for( ;; )\r
93         {\r
94                 /* The queue is empty.  Writing to the queue then reading from the queue\r
95                 should return the item written. */\r
96                 ulValue = 10;\r
97                 xQueueOverwrite( xTaskQueue, &ulValue );\r
98 \r
99                 ulValue = 0;\r
100                 xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
101 \r
102                 if( ulValue != 10 )\r
103                 {\r
104                         ulStatus = pdFAIL;\r
105                 }\r
106 \r
107                 /* Now try writing to the queue several times.  Each time the value\r
108                 in the queue should get overwritten. */\r
109                 for( x = 0; x < qoLOOPS; x++ )\r
110                 {\r
111                         /* Write to the queue. */\r
112                         xQueueOverwrite( xTaskQueue, &x );\r
113 \r
114                         /* Check the value in the queue is that written, even though the\r
115                         queue was not necessarily empty. */\r
116                         xQueuePeek( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
117                         if( ulValue != x )\r
118                         {\r
119                                 ulStatus = pdFAIL;\r
120                         }\r
121 \r
122                         /* There should always be one item in the queue. */\r
123                         if( uxQueueMessagesWaiting( xTaskQueue ) != uxQueueLength )\r
124                         {\r
125                                 ulStatus = pdFAIL;\r
126                         }\r
127                 }\r
128 \r
129                 /* Empty the queue again. */\r
130                 xQueueReceive( xTaskQueue, &ulValue, qoDONT_BLOCK );\r
131 \r
132                 if( uxQueueMessagesWaiting( xTaskQueue ) != 0 )\r
133                 {\r
134                         ulStatus = pdFAIL;\r
135                 }\r
136 \r
137                 if( ulStatus != pdFAIL )\r
138                 {\r
139                         /* Increment a counter to show this task is still running without\r
140                         error. */\r
141                         ulLoopCounter++;\r
142                 }\r
143 \r
144                 #if( configUSE_PREEMPTION == 0 )\r
145                         taskYIELD();\r
146                 #endif\r
147         }\r
148 }\r
149 /*-----------------------------------------------------------*/\r
150 \r
151 BaseType_t xIsQueueOverwriteTaskStillRunning( void )\r
152 {\r
153 BaseType_t xReturn;\r
154 \r
155         if( xISRTestStatus != pdPASS )\r
156         {\r
157                 xReturn = pdFAIL;\r
158         }\r
159         else if( ulLoopCounter > 0 )\r
160         {\r
161                 xReturn = pdPASS;\r
162         }\r
163         else\r
164         {\r
165                 /* The task has either stalled of discovered an error. */\r
166                 xReturn = pdFAIL;\r
167         }\r
168 \r
169         ulLoopCounter = 0;\r
170 \r
171         return xReturn;\r
172 }\r
173 /*-----------------------------------------------------------*/\r
174 \r
175 void vQueueOverwritePeriodicISRDemo( void )\r
176 {\r
177 static uint32_t ulCallCount = 0;\r
178 const uint32_t ulTx1 = 10UL, ulTx2 = 20UL, ulNumberOfSwitchCases = 3UL;\r
179 uint32_t ulRx;\r
180 \r
181         /* This function should be called from an interrupt, such as the tick hook\r
182         function vApplicationTickHook(). */\r
183 \r
184         configASSERT( xISRQueue );\r
185 \r
186         switch( ulCallCount )\r
187         {\r
188                 case 0:\r
189                         /* The queue is empty.  Write ulTx1 to the queue.  In this demo the\r
190                         last parameter is not used because there are no tasks blocked on\r
191                         this queue. */\r
192                         xQueueOverwriteFromISR( xISRQueue, &ulTx1, NULL );\r
193 \r
194                         /* Peek the queue to check it holds the expected value. */\r
195                         xQueuePeekFromISR( xISRQueue, &ulRx );\r
196                         if( ulRx != ulTx1 )\r
197                         {\r
198                                 xISRTestStatus = pdFAIL;\r
199                         }\r
200                         break;\r
201 \r
202                 case 1:\r
203                         /* The queue already holds ulTx1.  Overwrite the value in the queue\r
204                         with ulTx2. */\r
205                         xQueueOverwriteFromISR( xISRQueue, &ulTx2, NULL );\r
206                         break;\r
207 \r
208                 case 2:\r
209                         /* Read from the queue to empty the queue again.  The value read\r
210                         should be ulTx2. */\r
211                         xQueueReceiveFromISR( xISRQueue, &ulRx, NULL );\r
212 \r
213                         if( ulRx != ulTx2 )\r
214                         {\r
215                                 xISRTestStatus = pdFAIL;\r
216                         }\r
217                         break;\r
218         }\r
219 \r
220         /* Run the next case in the switch statement above next time this function\r
221         is called. */\r
222         ulCallCount++;\r
223 \r
224         if( ulCallCount >= ulNumberOfSwitchCases )\r
225         {\r
226                 /* Go back to the start. */\r
227                 ulCallCount = 0;\r
228         }\r
229 }\r
230 \r