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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Source/] [portable/] [RVDS/] [ARM7_LPC21xx/] [port.c] - Blame information for rev 857

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

Line No. Rev Author Line
1 572 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
/* Standard includes. */
56
#include <stdlib.h>
57
 
58
/* Scheduler includes. */
59
#include "FreeRTOS.h"
60
#include "task.h"
61
 
62
/* Constants required to setup the initial task context. */
63
#define portINITIAL_SPSR                                ( ( portSTACK_TYPE ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
64
#define portTHUMB_MODE_BIT                              ( ( portSTACK_TYPE ) 0x20 )
65
#define portINSTRUCTION_SIZE                    ( ( portSTACK_TYPE ) 4 )
66
#define portNO_CRITICAL_SECTION_NESTING ( ( portSTACK_TYPE ) 0 )
67
 
68
/* Constants required to setup the tick ISR. */
69
#define portENABLE_TIMER                        ( ( unsigned portCHAR ) 0x01 )
70
#define portPRESCALE_VALUE                      0x00
71
#define portINTERRUPT_ON_MATCH          ( ( unsigned portLONG ) 0x01 )
72
#define portRESET_COUNT_ON_MATCH        ( ( unsigned portLONG ) 0x02 )
73
 
74
/* Constants required to setup the VIC for the tick ISR. */
75
#define portTIMER_VIC_CHANNEL           ( ( unsigned portLONG ) 0x0004 )
76
#define portTIMER_VIC_CHANNEL_BIT       ( ( unsigned portLONG ) 0x0010 )
77
#define portTIMER_VIC_ENABLE            ( ( unsigned portLONG ) 0x0020 )
78
 
79
/* Constants required to handle interrupts. */
80
#define portTIMER_MATCH_ISR_BIT         ( ( unsigned portCHAR ) 0x01 )
81
#define portCLEAR_VIC_INTERRUPT         ( ( unsigned portLONG ) 0 )
82
 
83
/*-----------------------------------------------------------*/
84
 
85
/* The code generated by the Keil compiler does not maintain separate
86
stack and frame pointers. The portENTER_CRITICAL macro cannot therefore
87
use the stack as per other ports.  Instead a variable is used to keep
88
track of the critical section nesting.  This variable has to be stored
89
as part of the task context and must be initialised to a non zero value. */
90
 
91
#define portNO_CRITICAL_NESTING         ( ( unsigned portLONG ) 0 )
92
volatile unsigned portLONG ulCriticalNesting = 9999UL;
93
 
94
/*-----------------------------------------------------------*/
95
 
96
/* Setup the timer to generate the tick interrupts. */
97
static void prvSetupTimerInterrupt( void );
98
 
99
/*
100
 * The scheduler can only be started from ARM mode, so
101
 * vPortStartFirstSTask() is defined in portISR.c.
102
 */
103
extern __asm void vPortStartFirstTask( void );
104
 
105
/*-----------------------------------------------------------*/
106
 
107
/*
108
 * See header file for description.
109
 */
110
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
111
{
112
portSTACK_TYPE *pxOriginalTOS;
113
 
114
        /* Setup the initial stack of the task.  The stack is set exactly as
115
        expected by the portRESTORE_CONTEXT() macro.
116
 
117
        Remember where the top of the (simulated) stack is before we place
118
        anything on it. */
119
        pxOriginalTOS = pxTopOfStack;
120
 
121
        /* First on the stack is the return address - which in this case is the
122
        start of the task.  The offset is added to make the return address appear
123
        as it would within an IRQ ISR. */
124
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;
125
        pxTopOfStack--;
126
 
127
        *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaaaaaa;  /* R14 */
128
        pxTopOfStack--;
129
        *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
130
        pxTopOfStack--;
131
        *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212;  /* R12 */
132
        pxTopOfStack--;
133
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;  /* R11 */
134
        pxTopOfStack--;
135
        *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010;  /* R10 */
136
        pxTopOfStack--;
137
        *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909;  /* R9 */
138
        pxTopOfStack--;
139
        *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808;  /* R8 */
140
        pxTopOfStack--;
141
        *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707;  /* R7 */
142
        pxTopOfStack--;
143
        *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606;  /* R6 */
144
        pxTopOfStack--;
145
        *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505;  /* R5 */
146
        pxTopOfStack--;
147
        *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404;  /* R4 */
148
        pxTopOfStack--;
149
        *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303;  /* R3 */
150
        pxTopOfStack--;
151
        *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202;  /* R2 */
152
        pxTopOfStack--;
153
        *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101;  /* R1 */
154
        pxTopOfStack--;
155
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
156
        pxTopOfStack--;
157
 
158
        /* The last thing onto the stack is the status register, which is set for
159
        system mode, with interrupts enabled. */
160
        *pxTopOfStack = ( portSTACK_TYPE ) portINITIAL_SPSR;
161
 
162
        if( ( ( unsigned long ) pxCode & 0x01UL ) != 0x00UL )
163
        {
164
                /* We want the task to start in thumb mode. */
165
                *pxTopOfStack |= portTHUMB_MODE_BIT;
166
        }
167
 
168
        pxTopOfStack--;
169
 
170
        /* The code generated by the Keil compiler does not maintain separate
171
        stack and frame pointers. The portENTER_CRITICAL macro cannot therefore
172
        use the stack as per other ports.  Instead a variable is used to keep
173
        track of the critical section nesting.  This variable has to be stored
174
        as part of the task context and is initially set to zero. */
175
        *pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
176
 
177
        return pxTopOfStack;
178
}
179
/*-----------------------------------------------------------*/
180
 
181
portBASE_TYPE xPortStartScheduler( void )
182
{
183
        /* Start the timer that generates the tick ISR. */
184
        prvSetupTimerInterrupt();
185
 
186
        /* Start the first task.  This is done from portISR.c as ARM mode must be
187
        used. */
188
        vPortStartFirstTask();
189
 
190
        /* Should not get here! */
191
        return 0;
192
}
193
/*-----------------------------------------------------------*/
194
 
195
void vPortEndScheduler( void )
196
{
197
        /* It is unlikely that the ARM port will require this function as there
198
        is nothing to return to.  If this is required - stop the tick ISR then
199
        return back to main. */
200
}
201
/*-----------------------------------------------------------*/
202
 
203
#if configUSE_PREEMPTION == 0
204
 
205
        /*
206
         * The cooperative scheduler requires a normal IRQ service routine to
207
         * simply increment the system tick.
208
         */
209
        void vNonPreemptiveTick( void ) __irq;
210
        void vNonPreemptiveTick( void ) __irq
211
        {
212
                /* Increment the tick count - this may make a delaying task ready
213
                to run - but a context switch is not performed. */
214
                vTaskIncrementTick();
215
 
216
                T0IR = portTIMER_MATCH_ISR_BIT;                         /* Clear the timer event */
217
                VICVectAddr = portCLEAR_VIC_INTERRUPT;          /* Acknowledge the Interrupt */
218
        }
219
 
220
 #else
221
 
222
        /*
223
         **************************************************************************
224
         * The preemptive scheduler ISR is written in assembler and can be found
225
         * in the portASM.s file. This will only get used if portUSE_PREEMPTION
226
         * is set to 1 in portmacro.h
227
         **************************************************************************
228
         */
229
 
230
          void vPreemptiveTick( void );
231
 
232
#endif
233
/*-----------------------------------------------------------*/
234
 
235
static void prvSetupTimerInterrupt( void )
236
{
237
unsigned portLONG ulCompareMatch;
238
 
239
        /* A 1ms tick does not require the use of the timer prescale.  This is
240
        defaulted to zero but can be used if necessary. */
241
        T0PR = portPRESCALE_VALUE;
242
 
243
        /* Calculate the match value required for our wanted tick rate. */
244
        ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
245
 
246
        /* Protect against divide by zero.  Using an if() statement still results
247
        in a warning - hence the #if. */
248
        #if portPRESCALE_VALUE != 0
249
        {
250
                ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
251
        }
252
        #endif
253
 
254
        T0MR0 = ulCompareMatch;
255
 
256
        /* Generate tick with timer 0 compare match. */
257
        T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
258
 
259
        /* Setup the VIC for the timer. */
260
        VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
261
        VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
262
 
263
        /* The ISR installed depends on whether the preemptive or cooperative
264
        scheduler is being used. */
265
        #if configUSE_PREEMPTION == 1
266
        {
267
                VICVectAddr0 = ( unsigned portLONG ) vPreemptiveTick;
268
        }
269
        #else
270
        {
271
                VICVectAddr0 = ( unsigned portLONG ) vNonPreemptiveTick;
272
        }
273
        #endif
274
 
275
        VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
276
 
277
        /* Start the timer - interrupts are disabled when this function is called
278
        so it is okay to do this here. */
279
        T0TCR = portENABLE_TIMER;
280
}
281
/*-----------------------------------------------------------*/
282
 
283
void vPortEnterCritical( void )
284
{
285
        /* Disable interrupts as per portDISABLE_INTERRUPTS();                                                  */
286
        __disable_irq();
287
 
288
        /* Now interrupts are disabled ulCriticalNesting can be accessed
289
        directly.  Increment ulCriticalNesting to keep a count of how many times
290
        portENTER_CRITICAL() has been called. */
291
        ulCriticalNesting++;
292
}
293
/*-----------------------------------------------------------*/
294
 
295
void vPortExitCritical( void )
296
{
297
        if( ulCriticalNesting > portNO_CRITICAL_NESTING )
298
        {
299
                /* Decrement the nesting count as we are leaving a critical section. */
300
                ulCriticalNesting--;
301
 
302
                /* If the nesting level has reached zero then interrupts should be
303
                re-enabled. */
304
                if( ulCriticalNesting == portNO_CRITICAL_NESTING )
305
                {
306
                        /* Enable interrupts as per portEXIT_CRITICAL(). */
307
                        __enable_irq();
308
                }
309
        }
310
}
311
/*-----------------------------------------------------------*/
312
 
313
 

powered by: WebSVN 2.1.0

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