1
+ /*
2
+ * FreeRTOS V202212.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
+ * https://www.FreeRTOS.org
23
+ * https://github.com/FreeRTOS
24
+ *
25
+ */
26
+
27
+ /* Scheduler includes. */
28
+ #include "FreeRTOS.h"
29
+ #include "task.h"
30
+
31
+ /* Reg test includes. */
32
+ #include "reg_tests.h"
33
+
34
+ /* Hardware includes. */
35
+ #include "main.h"
36
+
37
+ /*
38
+ * Functions that implement reg test tasks.
39
+ */
40
+ static void prvRegTest1Task ( void * pvParameters );
41
+ static void prvRegTest2Task ( void * pvParameters );
42
+ static void prvRegTest3Task ( void * pvParameters );
43
+ static void prvRegTest4Task ( void * pvParameters );
44
+
45
+ /*
46
+ * Check task periodically checks that reg tests tasks
47
+ * are running fine.
48
+ */
49
+ static void prvCheckTask ( void * pvParameters );
50
+
51
+ /*
52
+ * Functions implemented in assembly.
53
+ */
54
+ extern void vRegTest1Asm ( void ) __attribute__( ( naked ) );
55
+ extern void vRegTest2Asm ( void ) __attribute__( ( naked ) );
56
+ extern void vRegTest3Asm ( void ) __attribute__( ( naked ) );
57
+ extern void vRegTest4Asm ( void ) __attribute__( ( naked ) );
58
+ /*-----------------------------------------------------------*/
59
+
60
+ /*
61
+ * Priority of the check task.
62
+ */
63
+ #define CHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )
64
+
65
+ /*
66
+ * Frequency of check task.
67
+ */
68
+ #define NO_ERROR_CHECK_TASK_PERIOD ( pdMS_TO_TICKS( 5000UL ) )
69
+ #define ERROR_CHECK_TASK_PERIOD ( pdMS_TO_TICKS( 200UL ) )
70
+
71
+ /*
72
+ * Parameters passed to reg test tasks.
73
+ */
74
+ #define REG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 )
75
+ #define REG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 )
76
+ #define REG_TEST_TASK_3_PARAMETER ( ( void * ) 0x12348765 )
77
+ #define REG_TEST_TASK_4_PARAMETER ( ( void * ) 0x43215678 )
78
+ /*-----------------------------------------------------------*/
79
+
80
+ /*
81
+ * The following variables are used to communicate the status of the register
82
+ * test tasks to the check task. If the variables keep incrementing, then the
83
+ * register test tasks have not discovered any errors. If a variable stops
84
+ * incrementing, then an error has been found.
85
+ */
86
+ volatile unsigned long ulRegTest1LoopCounter = 0UL , ulRegTest2LoopCounter = 0UL ;
87
+ volatile unsigned long ulRegTest3LoopCounter = 0UL , ulRegTest4LoopCounter = 0UL ;
88
+
89
+ /**
90
+ * Counter to keep a count of how may times the check task loop has detected
91
+ * error.
92
+ */
93
+ volatile unsigned long ulCheckTaskLoops = 0UL ;
94
+ /*-----------------------------------------------------------*/
95
+
96
+ void vStartRegTests ( void )
97
+ {
98
+ static StackType_t xRegTest1TaskStack [ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned ( configMINIMAL_STACK_SIZE * sizeof ( StackType_t ) ) ) );
99
+ static StackType_t xRegTest2TaskStack [ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned ( configMINIMAL_STACK_SIZE * sizeof ( StackType_t ) ) ) );
100
+ static StackType_t xRegTest3TaskStack [ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned ( configMINIMAL_STACK_SIZE * sizeof ( StackType_t ) ) ) );
101
+ static StackType_t xRegTest4TaskStack [ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned ( configMINIMAL_STACK_SIZE * sizeof ( StackType_t ) ) ) );
102
+ static StackType_t xCheckTaskStack [ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned ( configMINIMAL_STACK_SIZE * sizeof ( StackType_t ) ) ) );
103
+
104
+ TaskParameters_t xRegTest1TaskParameters =
105
+ {
106
+ .pvTaskCode = prvRegTest1Task ,
107
+ .pcName = "RegTest1" ,
108
+ .usStackDepth = configMINIMAL_STACK_SIZE ,
109
+ .pvParameters = REG_TEST_TASK_1_PARAMETER ,
110
+ .uxPriority = tskIDLE_PRIORITY | portPRIVILEGE_BIT ,
111
+ .puxStackBuffer = xRegTest1TaskStack ,
112
+ .xRegions = {
113
+ { 0 , 0 , 0 },
114
+ { 0 , 0 , 0 },
115
+ { 0 , 0 , 0 },
116
+ { 0 , 0 , 0 },
117
+ { 0 , 0 , 0 },
118
+ { 0 , 0 , 0 },
119
+ { 0 , 0 , 0 },
120
+ { 0 , 0 , 0 },
121
+ { 0 , 0 , 0 },
122
+ { 0 , 0 , 0 },
123
+ { 0 , 0 , 0 }
124
+ }
125
+ };
126
+ TaskParameters_t xRegTest2TaskParameters =
127
+ {
128
+ .pvTaskCode = prvRegTest2Task ,
129
+ .pcName = "RegTest2" ,
130
+ .usStackDepth = configMINIMAL_STACK_SIZE ,
131
+ .pvParameters = REG_TEST_TASK_2_PARAMETER ,
132
+ .uxPriority = tskIDLE_PRIORITY | portPRIVILEGE_BIT ,
133
+ .puxStackBuffer = xRegTest2TaskStack ,
134
+ .xRegions = {
135
+ { 0 , 0 , 0 },
136
+ { 0 , 0 , 0 },
137
+ { 0 , 0 , 0 },
138
+ { 0 , 0 , 0 },
139
+ { 0 , 0 , 0 },
140
+ { 0 , 0 , 0 },
141
+ { 0 , 0 , 0 },
142
+ { 0 , 0 , 0 },
143
+ { 0 , 0 , 0 },
144
+ { 0 , 0 , 0 },
145
+ { 0 , 0 , 0 }
146
+ }
147
+ };
148
+ TaskParameters_t xRegTest3TaskParameters =
149
+ {
150
+ .pvTaskCode = prvRegTest3Task ,
151
+ .pcName = "RegTest3" ,
152
+ .usStackDepth = configMINIMAL_STACK_SIZE ,
153
+ .pvParameters = REG_TEST_TASK_3_PARAMETER ,
154
+ .uxPriority = tskIDLE_PRIORITY | portPRIVILEGE_BIT ,
155
+ .puxStackBuffer = xRegTest3TaskStack ,
156
+ .xRegions = {
157
+ { 0 , 0 , 0 },
158
+ { 0 , 0 , 0 },
159
+ { 0 , 0 , 0 },
160
+ { 0 , 0 , 0 },
161
+ { 0 , 0 , 0 },
162
+ { 0 , 0 , 0 },
163
+ { 0 , 0 , 0 },
164
+ { 0 , 0 , 0 },
165
+ { 0 , 0 , 0 },
166
+ { 0 , 0 , 0 },
167
+ { 0 , 0 , 0 }
168
+ }
169
+ };
170
+ TaskParameters_t xRegTest4TaskParameters =
171
+ {
172
+ .pvTaskCode = prvRegTest4Task ,
173
+ .pcName = "RegTest4" ,
174
+ .usStackDepth = configMINIMAL_STACK_SIZE ,
175
+ .pvParameters = REG_TEST_TASK_4_PARAMETER ,
176
+ .uxPriority = tskIDLE_PRIORITY | portPRIVILEGE_BIT ,
177
+ .puxStackBuffer = xRegTest4TaskStack ,
178
+ .xRegions = {
179
+ { 0 , 0 , 0 },
180
+ { 0 , 0 , 0 },
181
+ { 0 , 0 , 0 },
182
+ { 0 , 0 , 0 },
183
+ { 0 , 0 , 0 },
184
+ { 0 , 0 , 0 },
185
+ { 0 , 0 , 0 },
186
+ { 0 , 0 , 0 },
187
+ { 0 , 0 , 0 },
188
+ { 0 , 0 , 0 },
189
+ { 0 , 0 , 0 }
190
+ }
191
+ };
192
+
193
+ TaskParameters_t xCheckTaskParameters =
194
+ {
195
+ .pvTaskCode = prvCheckTask ,
196
+ .pcName = "Check" ,
197
+ .usStackDepth = configMINIMAL_STACK_SIZE ,
198
+ .pvParameters = NULL ,
199
+ .uxPriority = ( CHECK_TASK_PRIORITY | portPRIVILEGE_BIT ),
200
+ .puxStackBuffer = xCheckTaskStack ,
201
+ .xRegions = {
202
+ { 0 , 0 , 0 },
203
+ { 0 , 0 , 0 },
204
+ { 0 , 0 , 0 },
205
+ { 0 , 0 , 0 },
206
+ { 0 , 0 , 0 },
207
+ { 0 , 0 , 0 },
208
+ { 0 , 0 , 0 },
209
+ { 0 , 0 , 0 },
210
+ { 0 , 0 , 0 },
211
+ { 0 , 0 , 0 },
212
+ { 0 , 0 , 0 }
213
+ }
214
+ };
215
+
216
+ xTaskCreateRestricted ( & ( xRegTest1TaskParameters ), NULL );
217
+ xTaskCreateRestricted ( & ( xRegTest2TaskParameters ), NULL );
218
+ xTaskCreateRestricted ( & ( xRegTest3TaskParameters ), NULL );
219
+ xTaskCreateRestricted ( & ( xRegTest4TaskParameters ), NULL );
220
+ xTaskCreateRestricted ( & ( xCheckTaskParameters ), NULL );
221
+ }
222
+ /*-----------------------------------------------------------*/
223
+
224
+ static void prvRegTest1Task ( void * pvParameters )
225
+ {
226
+ /* Although the reg tests are written in assembly, its entry
227
+ * point is written in C for convenience of checking that the
228
+ * task parameter is being passed in correctly. */
229
+ if ( pvParameters == REG_TEST_TASK_1_PARAMETER )
230
+ {
231
+ /* Start the part of the test that is written in assembler. */
232
+ vRegTest1Asm ();
233
+ }
234
+
235
+ /* The following line will only execute if the task parameter
236
+ * is found to be incorrect. The check task will detect that
237
+ * the reg test loop counter is not being incremented and flag
238
+ * an error. */
239
+ vTaskDelete ( NULL );
240
+ }
241
+ /*-----------------------------------------------------------*/
242
+
243
+ static void prvRegTest2Task ( void * pvParameters )
244
+ {
245
+ /* Although the reg tests are written in assembly, its entry
246
+ * point is written in C for convenience of checking that the
247
+ * task parameter is being passed in correctly. */
248
+ if ( pvParameters == REG_TEST_TASK_2_PARAMETER )
249
+ {
250
+ /* Start the part of the test that is written in assembler. */
251
+ vRegTest2Asm ();
252
+ }
253
+
254
+ /* The following line will only execute if the task parameter
255
+ * is found to be incorrect. The check task will detect that
256
+ * the reg test loop counter is not being incremented and flag
257
+ * an error. */
258
+ vTaskDelete ( NULL );
259
+ }
260
+ /*-----------------------------------------------------------*/
261
+
262
+ static void prvRegTest3Task ( void * pvParameters )
263
+ {
264
+ /* Although the reg tests are written in assembly, its entry
265
+ * point is written in C for convenience of checking that the
266
+ * task parameter is being passed in correctly. */
267
+ if ( pvParameters == REG_TEST_TASK_3_PARAMETER )
268
+ {
269
+ /* Start the part of the test that is written in assembler. */
270
+ vRegTest3Asm ();
271
+ }
272
+
273
+ /* The following line will only execute if the task parameter
274
+ * is found to be incorrect. The check task will detect that
275
+ * the reg test loop counter is not being incremented and flag
276
+ * an error. */
277
+ vTaskDelete ( NULL );
278
+ }
279
+ /*-----------------------------------------------------------*/
280
+
281
+ static void prvRegTest4Task ( void * pvParameters )
282
+ {
283
+ /* Although the reg tests are written in assembly, its entry
284
+ * point is written in C for convenience of checking that the
285
+ * task parameter is being passed in correctly. */
286
+ if ( pvParameters == REG_TEST_TASK_4_PARAMETER )
287
+ {
288
+ /* Start the part of the test that is written in assembler. */
289
+ vRegTest4Asm ();
290
+ }
291
+
292
+ /* The following line will only execute if the task parameter
293
+ * is found to be incorrect. The check task will detect that
294
+ * the reg test loop counter is not being incremented and flag
295
+ * an error. */
296
+ vTaskDelete ( NULL );
297
+ }
298
+ /*-----------------------------------------------------------*/
299
+
300
+ static void prvCheckTask ( void * pvParameters )
301
+ {
302
+ TickType_t xDelayPeriod = NO_ERROR_CHECK_TASK_PERIOD ;
303
+ TickType_t xLastExecutionTime ;
304
+ unsigned long ulErrorFound = pdFALSE ;
305
+ static unsigned long ulLastRegTest1Value = 0 , ulLastRegTest2Value = 0 ;
306
+ static unsigned long ulLastRegTest3Value = 0 , ulLastRegTest4Value = 0 ;
307
+
308
+ /* Just to stop compiler warnings. */
309
+ ( void ) pvParameters ;
310
+
311
+ /* Initialize xLastExecutionTime so the first call to vTaskDelayUntil()
312
+ * works correctly. */
313
+ xLastExecutionTime = xTaskGetTickCount ();
314
+
315
+ /* Cycle for ever, delaying then checking all the other tasks are still
316
+ * operating without error. The onboard LED is toggled on each iteration.
317
+ * If an error is detected then the delay period is decreased from
318
+ * mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has
319
+ * the effect of increasing the rate at which the onboard LED toggles, and
320
+ * in so doing gives visual feedback of the system status. */
321
+ for ( ;; )
322
+ {
323
+ /* Delay until it is time to execute again. */
324
+ vTaskDelayUntil ( & xLastExecutionTime , xDelayPeriod );
325
+
326
+ /* Check that the register test 1 task is still running. */
327
+ if ( ulLastRegTest1Value == ulRegTest1LoopCounter )
328
+ {
329
+ ulErrorFound |= 1UL << 0UL ;
330
+ }
331
+ ulLastRegTest1Value = ulRegTest1LoopCounter ;
332
+
333
+ /* Check that the register test 2 task is still running. */
334
+ if ( ulLastRegTest2Value == ulRegTest2LoopCounter )
335
+ {
336
+ ulErrorFound |= 1UL << 1UL ;
337
+ }
338
+ ulLastRegTest2Value = ulRegTest2LoopCounter ;
339
+
340
+ /* Check that the register test 3 task is still running. */
341
+ if ( ulLastRegTest3Value == ulRegTest3LoopCounter )
342
+ {
343
+ ulErrorFound |= 1UL << 2UL ;
344
+ }
345
+ ulLastRegTest3Value = ulRegTest3LoopCounter ;
346
+
347
+ /* Check that the register test 4 task is still running. */
348
+ if ( ulLastRegTest4Value == ulRegTest4LoopCounter )
349
+ {
350
+ ulErrorFound |= 1UL << 3UL ;
351
+ }
352
+ ulLastRegTest4Value = ulRegTest4LoopCounter ;
353
+
354
+
355
+ /* Toggle the green LED to give an indication of the system status.
356
+ * If the LED toggles every NO_ERROR_CHECK_TASK_PERIOD milliseconds
357
+ * then everything is ok. A faster toggle indicates an error. */
358
+ HAL_GPIO_TogglePin ( LD1_GPIO_Port , LD1_Pin );
359
+
360
+ if ( ulErrorFound != pdFALSE )
361
+ {
362
+ /* An error has been detected in one of the tasks - flash the LED
363
+ * at a higher frequency to give visible feedback that something has
364
+ * gone wrong (it might just be that the loop back connector required
365
+ * by the comtest tasks has not been fitted). */
366
+ xDelayPeriod = ERROR_CHECK_TASK_PERIOD ;
367
+
368
+ /* Turn on Red LED to indicate error. */
369
+ HAL_GPIO_WritePin ( LD3_GPIO_Port , LD3_Pin , GPIO_PIN_SET );
370
+
371
+ /* Increment error detection count. */
372
+ ulCheckTaskLoops ++ ;
373
+ }
374
+ }
375
+ }
376
+ /*-----------------------------------------------------------*/
0 commit comments