]> begriffs open source - cmsis-freertos/blob - Demo/Common/Minimal/StreamBufferInterrupt.c
Updated pack to FreeRTOS 10.4.6
[cmsis-freertos] / Demo / Common / Minimal / StreamBufferInterrupt.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  * A simple example that shows a stream buffer being used to pass data from an
30  * interrupt to a task.
31  *
32  * There are two strings, pcStringToSend and pcStringToReceive, where
33  * pcStringToReceive is a substring of pcStringToSend.  The interrupt sends
34  * a few bytes of pcStringToSend to a stream buffer ever few times that it
35  * executes.  A task reads the bytes from the stream buffer, looking for the
36  * substring, and flagging an error if the received data is invalid.
37  */
38
39 /* Standard includes. */
40 #include "stdio.h"
41 #include "string.h"
42
43 /* FreeRTOS includes. */
44 #include "FreeRTOS.h"
45 #include "task.h"
46 #include "stream_buffer.h"
47
48 /* Demo app includes. */
49 #include "StreamBufferInterrupt.h"
50
51 #define sbiSTREAM_BUFFER_LENGTH_BYTES        ( ( size_t ) 100 )
52 #define sbiSTREAM_BUFFER_TRIGGER_LEVEL_10    ( ( BaseType_t ) 10 )
53
54 /*-----------------------------------------------------------*/
55
56 /* Implements the task that receives a stream of bytes from the interrupt. */
57 static void prvReceivingTask( void * pvParameters );
58
59 /*-----------------------------------------------------------*/
60
61 /* The stream buffer that is used to send data from an interrupt to the task. */
62 static StreamBufferHandle_t xStreamBuffer = NULL;
63
64 /* The string that is sent from the interrupt to the task four bytes at a
65  * time.  Must be multiple of 4 bytes long as the ISR sends 4 bytes at a time*/
66 static const char * pcStringToSend = "_____Hello FreeRTOS_____";
67
68 /* The string to task is looking for, which must be a substring of
69  * pcStringToSend. */
70 static const char * pcStringToReceive = "Hello FreeRTOS";
71
72 /* Set to pdFAIL if anything unexpected happens. */
73 static BaseType_t xDemoStatus = pdPASS;
74
75 /* Incremented each time pcStringToReceive is correctly received, provided no
76  * errors have occurred.  Used so the check task can check this task is still
77  * running as expected. */
78 static uint32_t ulCycleCount = 0;
79
80 /*-----------------------------------------------------------*/
81
82 void vStartStreamBufferInterruptDemo( void )
83 {
84     /* Create the stream buffer that sends data from the interrupt to the
85      * task, and create the task. */
86     xStreamBuffer = xStreamBufferCreate( /* The buffer length in bytes. */
87         sbiSTREAM_BUFFER_LENGTH_BYTES,
88         /* The stream buffer's trigger level. */
89         sbiSTREAM_BUFFER_TRIGGER_LEVEL_10 );
90
91     xTaskCreate( prvReceivingTask,         /* The function that implements the task. */
92                  "StrIntRx",               /* Human readable name for the task. */
93                  configMINIMAL_STACK_SIZE, /* Stack size (in words!). */
94                  NULL,                     /* Task parameter is not used. */
95                  tskIDLE_PRIORITY + 2,     /* The priority at which the task is created. */
96                  NULL );                   /* No use for the task handle. */
97 }
98 /*-----------------------------------------------------------*/
99
100 static void prvReceivingTask( void * pvParameters )
101 {
102     char cRxBuffer[ 20 ];
103     BaseType_t xNextByte = 0;
104
105     /* Remove warning about unused parameters. */
106     ( void ) pvParameters;
107
108     /* Make sure the string will fit in the Rx buffer, including the NULL
109      * terminator. */
110     configASSERT( sizeof( cRxBuffer ) > strlen( pcStringToReceive ) );
111
112     /* Make sure the stream buffer has been created. */
113     configASSERT( xStreamBuffer != NULL );
114
115     /* Start with the Rx buffer in a known state. */
116     memset( cRxBuffer, 0x00, sizeof( cRxBuffer ) );
117
118     for( ; ; )
119     {
120         /* Keep receiving characters until the end of the string is received.
121          * Note:  An infinite block time is used to simplify the example.  Infinite
122          * block times are not recommended in production code as they do not allow
123          * for error recovery. */
124         xStreamBufferReceive( /* The stream buffer data is being received from. */
125             xStreamBuffer,
126             /* Where to place received data. */
127             ( void * ) &( cRxBuffer[ xNextByte ] ),
128             /* The number of bytes to receive. */
129             sizeof( char ),
130
131             /* The time to wait for the next data if the buffer
132              * is empty. */
133             portMAX_DELAY );
134
135         /* If xNextByte is 0 then this task is looking for the start of the
136          * string, which is 'H'. */
137         if( xNextByte == 0 )
138         {
139             if( cRxBuffer[ xNextByte ] == 'H' )
140             {
141                 /* The start of the string has been found.  Now receive
142                  * characters until the end of the string is found. */
143                 xNextByte++;
144             }
145         }
146         else
147         {
148             /* Receiving characters while looking for the end of the string,
149              * which is an 'S'. */
150             if( cRxBuffer[ xNextByte ] == 'S' )
151             {
152                 /* The string has now been received.  Check its validity. */
153                 if( strcmp( cRxBuffer, pcStringToReceive ) != 0 )
154                 {
155                     xDemoStatus = pdFAIL;
156                 }
157
158                 /* Return to start looking for the beginning of the string
159                  * again. */
160                 memset( cRxBuffer, 0x00, sizeof( cRxBuffer ) );
161                 xNextByte = 0;
162
163                 /* Increment the cycle count as an indication to the check task
164                  * that this demo is still running. */
165                 if( xDemoStatus == pdPASS )
166                 {
167                     ulCycleCount++;
168                 }
169             }
170             else
171             {
172                 /* Receive the next character the next time around, while
173                  * continuing to look for the end of the string. */
174                 xNextByte++;
175
176                 configASSERT( ( size_t ) xNextByte < sizeof( cRxBuffer ) );
177             }
178         }
179     }
180 }
181 /*-----------------------------------------------------------*/
182
183 void vBasicStreamBufferSendFromISR( void )
184 {
185     static size_t xNextByteToSend = 0;
186     const BaseType_t xCallsBetweenSends = 100, xBytesToSend = 4;
187     static BaseType_t xCallCount = 0;
188
189     /* Is it time to write to the stream buffer again? */
190     xCallCount++;
191
192     if( xCallCount > xCallsBetweenSends )
193     {
194         xCallCount = 0;
195
196         /* Send the next four bytes to the stream buffer. */
197         xStreamBufferSendFromISR( xStreamBuffer,
198                                   ( const void * ) ( pcStringToSend + xNextByteToSend ),
199                                   xBytesToSend,
200                                   NULL );
201
202         /* Send the next four bytes the next time around, wrapping to the start
203          * of the string if necessary. */
204         xNextByteToSend += xBytesToSend;
205
206         if( xNextByteToSend >= strlen( pcStringToSend ) )
207         {
208             xNextByteToSend = 0;
209         }
210     }
211 }
212 /*-----------------------------------------------------------*/
213
214 BaseType_t xIsInterruptStreamBufferDemoStillRunning( void )
215 {
216     uint32_t ulLastCycleCount = 0;
217
218     /* Check the demo is still running. */
219     if( ulLastCycleCount == ulCycleCount )
220     {
221         xDemoStatus = pdFAIL;
222     }
223     else
224     {
225         ulLastCycleCount = ulCycleCount;
226     }
227
228     return xDemoStatus;
229 }