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