OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [HCS12_CodeWarrior_small/] [main.c] - Blame information for rev 675

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 588 jeremybenn
/*
2
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
3
 
4
    ***************************************************************************
5
    *                                                                         *
6
    * If you are:                                                             *
7
    *                                                                         *
8
    *    + New to FreeRTOS,                                                   *
9
    *    + Wanting to learn FreeRTOS or multitasking in general quickly       *
10
    *    + Looking for basic training,                                        *
11
    *    + Wanting to improve your FreeRTOS skills and productivity           *
12
    *                                                                         *
13
    * then take a look at the FreeRTOS books - available as PDF or paperback  *
14
    *                                                                         *
15
    *        "Using the FreeRTOS Real Time Kernel - a Practical Guide"        *
16
    *                  http://www.FreeRTOS.org/Documentation                  *
17
    *                                                                         *
18
    * A pdf reference manual is also available.  Both are usually delivered   *
19
    * to your inbox within 20 minutes to two hours when purchased between 8am *
20
    * and 8pm GMT (although please allow up to 24 hours in case of            *
21
    * exceptional circumstances).  Thank you for your support!                *
22
    *                                                                         *
23
    ***************************************************************************
24
 
25
    This file is part of the FreeRTOS distribution.
26
 
27
    FreeRTOS is free software; you can redistribute it and/or modify it under
28
    the terms of the GNU General Public License (version 2) as published by the
29
    Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
30
    ***NOTE*** The exception to the GPL is included to allow you to distribute
31
    a combined work that includes FreeRTOS without being obliged to provide the
32
    source code for proprietary components outside of the FreeRTOS kernel.
33
    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
34
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
36
    more details. You should have received a copy of the GNU General Public
37
    License and the FreeRTOS license exception along with FreeRTOS; if not it
38
    can be viewed here: http://www.freertos.org/a00114.html and also obtained
39
    by writing to Richard Barry, contact details for whom are available on the
40
    FreeRTOS WEB site.
41
 
42
    1 tab == 4 spaces!
43
 
44
    http://www.FreeRTOS.org - Documentation, latest information, license and
45
    contact details.
46
 
47
    http://www.SafeRTOS.com - A version that is certified for use in safety
48
    critical systems.
49
 
50
    http://www.OpenRTOS.com - Commercial support, development, porting,
51
    licensing and training services.
52
*/
53
 
54
 
55
/*
56
 *
57
 * vMain() is effectively the demo application entry point.  It is called by
58
 * the main() function generated by the Processor Expert application.
59
 *
60
 * vMain() creates all the demo application tasks, then starts the scheduler.
61
 * The WEB      documentation provides more details of the demo application tasks.
62
 *
63
 * Main.c also creates a task called "Check".  This only executes every three
64
 * seconds but has the highest priority so is guaranteed to get processor time.
65
 * Its main function is to check that all the other tasks are still operational.
66
 * Each task (other than the "flash" tasks) maintains a unique count that is
67
 * incremented each time the task successfully completes its function.  Should
68
 * any error occur within such a task the count is permanently halted.  The
69
 * check task inspects the count of each task to ensure it has changed since
70
 * the last time the check task executed.  If all the count variables have
71
 * changed all the tasks are still executing error free, and the check task
72
 * toggles the onboard LED.  Should any task contain an error at any time
73
 * the LED toggle rate will change from 3 seconds to 500ms.
74
 *
75
 * This file also includes the functionality normally implemented within the
76
 * standard demo application file integer.c.  Due to the limited memory
77
 * available on the microcontroller the functionality has been included within
78
 * the idle task hook [vApplicationIdleHook()] - instead of within the usual
79
 * separate task.  See the documentation within integer.c for the rationale
80
 * of the integer task functionality.
81
 *
82
 *
83
 *
84
 * The demo applications included with other FreeRTOS ports make use of the
85
 * standard ComTest tasks.  These use a loopback connector to transmit and
86
 * receive RS232 characters between two tasks.  The test is important for two
87
 * reasons:
88
 *
89
 *      1) It tests the mechanism of context switching from within an application
90
 *         ISR.
91
 *
92
 *      2) It generates some randomised timing.
93
 *
94
 * The demo board used to develop this port does not include an RS232 interface
95
 * so the ComTest tasks could not easily be included.  Instead these two tests
96
 * are created using a 'Button Push' task.
97
 *
98
 * The 'Button Push' task blocks on a queue, waiting for data to arrive.  A
99
 * simple interrupt routine connected to the PP0 input on the demo board places
100
 * data in the queue each time the PP0 button is pushed (this button is built
101
 * onto the demo board).  As the 'Button Push' task is created with a
102
 * relatively high priority it will unblock and want to execute as soon as data
103
 * arrives in the queue - resulting in a context switch within the PP0 input
104
 * ISR.  If the data retrieved from the queue is that expected the 'Button Push'
105
 * task toggles LED 5.  Therefore correct operation is indicated by the LED
106
 * toggling each time the PP0 button is pressed.
107
 *
108
 * This test is not as satisfactory as the ComTest method - but the simple
109
 * nature of the port makes is just about adequate.
110
 *
111
 */
112
 
113
/* Kernel includes. */
114
#include "FreeRTOS.h"
115
#include "task.h"
116
#include "queue.h"
117
 
118
/* Demo application includes. */
119
#include "flash.h"
120
#include "PollQ.h"
121
#include "dynamic.h"
122
#include "partest.h"
123
 
124
/* Processor expert includes. */
125
#include "ButtonInterrupt.h"
126
 
127
/*-----------------------------------------------------------
128
        Definitions.
129
-----------------------------------------------------------*/
130
 
131
/* Priorities assigned to demo application tasks. */
132
#define mainFLASH_PRIORITY                      ( tskIDLE_PRIORITY + 2 )
133
#define mainCHECK_TASK_PRIORITY         ( tskIDLE_PRIORITY + 3 )
134
#define mainBUTTON_TASK_PRIORITY        ( tskIDLE_PRIORITY + 3 )
135
#define mainQUEUE_POLL_PRIORITY         ( tskIDLE_PRIORITY + 2 )
136
 
137
/* LED that is toggled by the check task.  The check task periodically checks
138
that all the other tasks are operating without error.  If no errors are found
139
the LED is toggled with mainCHECK_PERIOD frequency.  If an error is found
140
then the toggle rate increases to mainERROR_CHECK_PERIOD. */
141
#define mainCHECK_TASK_LED                      ( 7 )
142
#define mainCHECK_PERIOD                        ( ( portTickType ) 3000 / portTICK_RATE_MS  )
143
#define mainERROR_CHECK_PERIOD          ( ( portTickType ) 500 / portTICK_RATE_MS )
144
 
145
/* LED that is toggled by the button push interrupt. */
146
#define mainBUTTON_PUSH_LED                     ( 5 )
147
 
148
/* The constants used in the idle task calculation. */
149
#define intgCONST1                              ( ( long ) 123 )
150
#define intgCONST2                              ( ( long ) 234567 )
151
#define intgCONST3                              ( ( long ) -3 )
152
#define intgCONST4                              ( ( long ) 7 )
153
#define intgEXPECTED_ANSWER             ( ( ( intgCONST1 + intgCONST2 ) * intgCONST3 ) / intgCONST4 )
154
 
155
/* The length of the queue between is button push ISR and the Button Push task
156
is greater than 1 to account for switch bounces generating multiple inputs. */
157
#define mainBUTTON_QUEUE_SIZE 6
158
 
159
/*-----------------------------------------------------------
160
        Local functions prototypes.
161
-----------------------------------------------------------*/
162
 
163
/*
164
 * The 'Check' task function.  See the explanation at the top of the file.
165
 */
166
static void vErrorChecks( void* pvParameters );
167
 
168
/*
169
 * The 'Button Push' task.  See the explanation at the top of the file.
170
 */
171
static void vButtonTask( void *pvParameters );
172
 
173
/*
174
 * The idle task hook - in which the integer task is implemented.  See the
175
 * explanation at the top of the file.
176
 */
177
void vApplicationIdleHook( void );
178
 
179
/*
180
 * Checks the unique counts of other tasks to ensure they are still operational.
181
 */
182
static long prvCheckOtherTasksAreStillRunning( void );
183
 
184
 
185
 
186
/*-----------------------------------------------------------
187
        Local variables.
188
-----------------------------------------------------------*/
189
 
190
/* A few tasks are defined within this file.  This flag is used to indicate
191
their status.  If an error is detected in one of the locally defined tasks then
192
this flag is set to pdTRUE. */
193
portBASE_TYPE xLocalError = pdFALSE;
194
 
195
/* The queue used to send data from the button push ISR to the Button Push
196
task. */
197
static xQueueHandle xButtonQueue;
198
 
199
 
200
/*-----------------------------------------------------------*/
201
 
202
/*
203
 * This is called from the main() function generated by the Processor Expert.
204
 */
205
void vMain( void )
206
{
207
        /* Start some of the standard demo tasks. */
208
        vStartLEDFlashTasks( mainFLASH_PRIORITY );
209
        vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
210
        vStartDynamicPriorityTasks();
211
 
212
        /* Start the locally defined tasks.  There is also a task implemented as
213
        the idle hook. */
214
        xTaskCreate( vErrorChecks, "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );
215
        xTaskCreate( vButtonTask, "Button", configMINIMAL_STACK_SIZE, NULL, mainBUTTON_TASK_PRIORITY, NULL );
216
 
217
        /* All the tasks have been created - start the scheduler. */
218
        vTaskStartScheduler();
219
 
220
        /* Should not reach here! */
221
        for( ;; );
222
}
223
/*-----------------------------------------------------------*/
224
 
225
static void vErrorChecks( void *pvParameters )
226
{
227
portTickType xDelayPeriod = mainCHECK_PERIOD;
228
portTickType xLastWakeTime;
229
 
230
        /* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil()
231
        functions correctly. */
232
        xLastWakeTime = xTaskGetTickCount();
233
 
234
        for( ;; )
235
        {
236
                /* Delay until it is time to execute again.  The delay period is
237
                shorter following an error. */
238
                vTaskDelayUntil( &xLastWakeTime, xDelayPeriod );
239
 
240
                /* Check all the demo application tasks are executing without
241
                error. If an error is found the delay period is shortened - this
242
                has the effect of increasing the flash rate of the 'check' task
243
                LED. */
244
                if( prvCheckOtherTasksAreStillRunning() == pdFAIL )
245
                {
246
                        /* An error has been detected in one of the tasks - flash faster. */
247
                        xDelayPeriod = mainERROR_CHECK_PERIOD;
248
                }
249
 
250
                /* Toggle the LED each cycle round. */
251
                vParTestToggleLED( mainCHECK_TASK_LED );
252
        }
253
}
254
/*-----------------------------------------------------------*/
255
 
256
static long prvCheckOtherTasksAreStillRunning( void )
257
{
258
portBASE_TYPE xAllTasksPassed = pdPASS;
259
 
260
        if( xArePollingQueuesStillRunning() != pdTRUE )
261
        {
262
                xAllTasksPassed = pdFAIL;
263
        }
264
 
265
        if( xAreDynamicPriorityTasksStillRunning() != pdTRUE )
266
        {
267
                xAllTasksPassed = pdFAIL;
268
        }
269
 
270
        /* Also check the status flag for the tasks defined within this function. */
271
        if( xLocalError != pdFALSE )
272
        {
273
                xAllTasksPassed = pdFAIL;
274
        }
275
 
276
        return xAllTasksPassed;
277
}
278
/*-----------------------------------------------------------*/
279
 
280
void vApplicationIdleHook( void )
281
{
282
/* This variable is effectively set to a constant so it is made volatile to
283
ensure the compiler does not just get rid of it. */
284
volatile long lValue;
285
 
286
        /* Keep performing a calculation and checking the result against a constant. */
287
        for( ;; )
288
        {
289
                /* Perform the calculation.  This will store partial value in
290
                registers, resulting in a good test of the context switch mechanism. */
291
                lValue = intgCONST1;
292
                lValue += intgCONST2;
293
                lValue *= intgCONST3;
294
                lValue /= intgCONST4;
295
 
296
                /* Did we perform the calculation correctly with no corruption? */
297
                if( lValue != intgEXPECTED_ANSWER )
298
                {
299
                        /* Error! */
300
                        portENTER_CRITICAL();
301
                                xLocalError = pdTRUE;
302
                        portEXIT_CRITICAL();
303
                }
304
 
305
                /* Yield in case cooperative scheduling is being used. */
306
                #if configUSE_PREEMPTION == 0
307
                {
308
                        taskYIELD();
309
                }
310
                #endif          
311
        }
312
}
313
/*-----------------------------------------------------------*/
314
 
315
static void vButtonTask( void *pvParameters )
316
{
317
unsigned portBASE_TYPE uxExpected = 1, uxReceived;
318
 
319
        /* Create the queue used by the producer and consumer. */
320
        xButtonQueue = xQueueCreate( mainBUTTON_QUEUE_SIZE, ( unsigned portBASE_TYPE ) sizeof( unsigned portBASE_TYPE ) );
321
 
322
        if( xButtonQueue )
323
        {
324
                /* Now the queue is created it is safe to enable the button interrupt. */
325
                ButtonInterrupt_Enable();
326
 
327
                for( ;; )
328
                {
329
                        /* Simply wait for data to arrive from the button push interrupt. */
330
                        if( xQueueReceive( xButtonQueue, &uxReceived, portMAX_DELAY ) == pdPASS )
331
                        {
332
                                /* Was the data we received that expected? */
333
                                if( uxReceived != uxExpected )
334
                                {
335
                                        /* Error! */
336
                                        portENTER_CRITICAL();
337
                                                xLocalError = pdTRUE;
338
                                        portEXIT_CRITICAL();
339
                                }
340
                                else
341
                                {
342
                                        /* Toggle the LED for every successful push. */
343
                                        vParTestToggleLED( mainBUTTON_PUSH_LED );
344
                                }
345
 
346
                                uxExpected++;
347
                        }
348
                }
349
        }
350
 
351
        /* Will only get here if the queue could not be created. */
352
        for( ;; );
353
}
354
/*-----------------------------------------------------------*/
355
 
356
#pragma CODE_SEG __NEAR_SEG NON_BANKED
357
 
358
        /* Button push ISR. */
359
        void interrupt vButtonPush( void )
360
        {
361
                static unsigned portBASE_TYPE uxValToSend = 0;
362
                static unsigned long xHigherPriorityTaskWoken;
363
 
364
                xHigherPriorityTaskWoken = pdFALSE;
365
 
366
                /* Send an incrementing value to the button push task each run. */
367
                uxValToSend++;
368
 
369
                /* Clear the interrupt flag. */
370
                PIFP = 1;
371
 
372
                /* Send the incremented value down the queue.  The button push task is
373
                blocked waiting for the data.  As the button push task is high priority
374
                it will wake and a context switch should be performed before leaving
375
                the ISR. */
376
                xQueueSendFromISR( xButtonQueue, &uxValToSend, &xHigherPriorityTaskWoken );
377
 
378
                if( xHigherPriorityTaskWoken )
379
                {
380
                        /* NOTE: This macro can only be used if there are no local
381
                        variables defined.  This function uses a static variable so it's
382
                        use is permitted.  If the variable were not static portYIELD()
383
                        would have to be used in it's place. */
384
                        portTASK_SWITCH_FROM_ISR();
385
                }
386
        }
387
 
388
#pragma CODE_SEG DEFAULT
389
 
390
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.