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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Source/] [portable/] [GCC/] [MicroBlaze/] [port.c] - Blame information for rev 593

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
 * Implementation of functions defined in portable.h for the MicroBlaze port.
56
 *----------------------------------------------------------*/
57
 
58
 
59
/* Scheduler includes. */
60
#include "FreeRTOS.h"
61
#include "task.h"
62
 
63
/* Standard includes. */
64
#include <string.h>
65
 
66
/* Hardware includes. */
67
#include <xintc.h>
68
#include <xintc_i.h>
69
#include <xtmrctr.h>
70
 
71
/* Tasks are started with interrupts enabled. */
72
#define portINITIAL_MSR_STATE           ( ( portSTACK_TYPE ) 0x02 )
73
 
74
/* Tasks are started with a critical section nesting of 0 - however prior
75
to the scheduler being commenced we don't want the critical nesting level
76
to reach zero, so it is initialised to a high value. */
77
#define portINITIAL_NESTING_VALUE       ( 0xff )
78
 
79
/* Our hardware setup only uses one counter. */
80
#define portCOUNTER_0                           0
81
 
82
/* The stack used by the ISR is filled with a known value to assist in
83
debugging. */
84
#define portISR_STACK_FILL_VALUE        0x55555555
85
 
86
/* Counts the nesting depth of calls to portENTER_CRITICAL().  Each task
87
maintains it's own count, so this variable is saved as part of the task
88
context. */
89
volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE;
90
 
91
/* To limit the amount of stack required by each task, this port uses a
92
separate stack for interrupts. */
93
unsigned long *pulISRStack;
94
 
95
/*-----------------------------------------------------------*/
96
 
97
/*
98
 * Sets up the periodic ISR used for the RTOS tick.  This uses timer 0, but
99
 * could have alternatively used the watchdog timer or timer 1.
100
 */
101
static void prvSetupTimerInterrupt( void );
102
/*-----------------------------------------------------------*/
103
 
104
/*
105
 * Initialise the stack of a task to look exactly as if a call to
106
 * portSAVE_CONTEXT had been made.
107
 *
108
 * See the header file portable.h.
109
 */
110
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
111
{
112
extern void *_SDA2_BASE_, *_SDA_BASE_;
113
const unsigned long ulR2 = ( unsigned long ) &_SDA2_BASE_;
114
const unsigned long ulR13 = ( unsigned long ) &_SDA_BASE_;
115
 
116
        /* Place a few bytes of known values on the bottom of the stack.
117
        This is essential for the Microblaze port and these lines must
118
        not be omitted.  The parameter value will overwrite the
119
        0x22222222 value during the function prologue. */
120
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;
121
        pxTopOfStack--;
122
        *pxTopOfStack = ( portSTACK_TYPE ) 0x22222222;
123
        pxTopOfStack--;
124
        *pxTopOfStack = ( portSTACK_TYPE ) 0x33333333;
125
        pxTopOfStack--;
126
 
127
        /* First stack an initial value for the critical section nesting.  This
128
        is initialised to zero as tasks are started with interrupts enabled. */
129
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00;        /* R0. */
130
 
131
        /* Place an initial value for all the general purpose registers. */
132
        pxTopOfStack--;
133
        *pxTopOfStack = ( portSTACK_TYPE ) ulR2;        /* R2 - small data area. */
134
        pxTopOfStack--;
135
        *pxTopOfStack = ( portSTACK_TYPE ) 0x03;        /* R3. */
136
        pxTopOfStack--;
137
        *pxTopOfStack = ( portSTACK_TYPE ) 0x04;        /* R4. */
138
        pxTopOfStack--;
139
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;/* R5 contains the function call parameters. */
140
        pxTopOfStack--;
141
        *pxTopOfStack = ( portSTACK_TYPE ) 0x06;        /* R6. */
142
        pxTopOfStack--;
143
        *pxTopOfStack = ( portSTACK_TYPE ) 0x07;        /* R7. */
144
        pxTopOfStack--;
145
        *pxTopOfStack = ( portSTACK_TYPE ) 0x08;        /* R8. */
146
        pxTopOfStack--;
147
        *pxTopOfStack = ( portSTACK_TYPE ) 0x09;        /* R9. */
148
        pxTopOfStack--;
149
        *pxTopOfStack = ( portSTACK_TYPE ) 0x0a;        /* R10. */
150
        pxTopOfStack--;
151
        *pxTopOfStack = ( portSTACK_TYPE ) 0x0b;        /* R11. */
152
        pxTopOfStack--;
153
        *pxTopOfStack = ( portSTACK_TYPE ) 0x0c;        /* R12. */
154
        pxTopOfStack--;
155
        *pxTopOfStack = ( portSTACK_TYPE ) ulR13;       /* R13 - small data read write area. */
156
        pxTopOfStack--;
157
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode;      /* R14. */
158
        pxTopOfStack--;
159
        *pxTopOfStack = ( portSTACK_TYPE ) 0x0f;        /* R15. */
160
        pxTopOfStack--;
161
        *pxTopOfStack = ( portSTACK_TYPE ) 0x10;        /* R16. */
162
        pxTopOfStack--;
163
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11;        /* R17. */
164
        pxTopOfStack--;
165
        *pxTopOfStack = ( portSTACK_TYPE ) 0x12;        /* R18. */
166
        pxTopOfStack--;
167
        *pxTopOfStack = ( portSTACK_TYPE ) 0x13;        /* R19. */
168
        pxTopOfStack--;
169
        *pxTopOfStack = ( portSTACK_TYPE ) 0x14;        /* R20. */
170
        pxTopOfStack--;
171
        *pxTopOfStack = ( portSTACK_TYPE ) 0x15;        /* R21. */
172
        pxTopOfStack--;
173
        *pxTopOfStack = ( portSTACK_TYPE ) 0x16;        /* R22. */
174
        pxTopOfStack--;
175
        *pxTopOfStack = ( portSTACK_TYPE ) 0x17;        /* R23. */
176
        pxTopOfStack--;
177
        *pxTopOfStack = ( portSTACK_TYPE ) 0x18;        /* R24. */
178
        pxTopOfStack--;
179
        *pxTopOfStack = ( portSTACK_TYPE ) 0x19;        /* R25. */
180
        pxTopOfStack--;
181
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1a;        /* R26. */
182
        pxTopOfStack--;
183
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1b;        /* R27. */
184
        pxTopOfStack--;
185
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1c;        /* R28. */
186
        pxTopOfStack--;
187
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1d;        /* R29. */
188
        pxTopOfStack--;
189
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1e;        /* R30. */
190
        pxTopOfStack--;
191
 
192
        /* The MSR is stacked between R30 and R31. */
193
        *pxTopOfStack = portINITIAL_MSR_STATE;
194
        pxTopOfStack--;
195
 
196
        *pxTopOfStack = ( portSTACK_TYPE ) 0x1f;        /* R31. */
197
        pxTopOfStack--;
198
 
199
        /* Return a pointer to the top of the stack we have generated so this can
200
        be stored in the task control block for the task. */
201
        return pxTopOfStack;
202
}
203
/*-----------------------------------------------------------*/
204
 
205
portBASE_TYPE xPortStartScheduler( void )
206
{
207
extern void ( __FreeRTOS_interrupt_Handler )( void );
208
extern void ( vStartFirstTask )( void );
209
 
210
 
211
        /* Setup the FreeRTOS interrupt handler.  Code copied from crt0.s. */
212
        asm volatile (  "la     r6, r0, __FreeRTOS_interrupt_handler            \n\t" \
213
                                        "sw     r6, r1, r0                                                                      \n\t" \
214
                                        "lhu r7, r1, r0                                                                 \n\t" \
215
                                        "shi r7, r0, 0x12                                                               \n\t" \
216
                                        "shi r6, r0, 0x16 " );
217
 
218
        /* Setup the hardware to generate the tick.  Interrupts are disabled when
219
        this function is called. */
220
        prvSetupTimerInterrupt();
221
 
222
        /* Allocate the stack to be used by the interrupt handler. */
223
        pulISRStack = ( unsigned long * ) pvPortMalloc( configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ) );
224
 
225
        /* Restore the context of the first task that is going to run. */
226
        if( pulISRStack != NULL )
227
        {
228
                /* Fill the ISR stack with a known value to facilitate debugging. */
229
                memset( pulISRStack, portISR_STACK_FILL_VALUE, configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ) );
230
                pulISRStack += ( configMINIMAL_STACK_SIZE - 1 );
231
 
232
                /* Kick off the first task. */
233
                vStartFirstTask();
234
        }
235
 
236
        /* Should not get here as the tasks are now running! */
237
        return pdFALSE;
238
}
239
/*-----------------------------------------------------------*/
240
 
241
void vPortEndScheduler( void )
242
{
243
        /* Not implemented. */
244
}
245
/*-----------------------------------------------------------*/
246
 
247
/*
248
 * Manual context switch called by portYIELD or taskYIELD.
249
 */
250
void vPortYield( void )
251
{
252
extern void VPortYieldASM( void );
253
 
254
        /* Perform the context switch in a critical section to assure it is
255
        not interrupted by the tick ISR.  It is not a problem to do this as
256
        each task maintains it's own interrupt status. */
257
        portENTER_CRITICAL();
258
                /* Jump directly to the yield function to ensure there is no
259
                compiler generated prologue code. */
260
                asm volatile (  "bralid r14, VPortYieldASM              \n\t" \
261
                                                "or r0, r0, r0                                  \n\t" );
262
        portEXIT_CRITICAL();
263
}
264
/*-----------------------------------------------------------*/
265
 
266
/*
267
 * Hardware initialisation to generate the RTOS tick.
268
 */
269
static void prvSetupTimerInterrupt( void )
270
{
271
XTmrCtr xTimer;
272
const unsigned long ulCounterValue = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
273
unsigned portBASE_TYPE uxMask;
274
 
275
        /* The OPB timer1 is used to generate the tick.  Use the provided library
276
        functions to enable the timer and set the tick frequency. */
277
        XTmrCtr_mDisable( XPAR_OPB_TIMER_1_BASEADDR, XPAR_OPB_TIMER_1_DEVICE_ID );
278
        XTmrCtr_Initialize( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
279
        XTmrCtr_mSetLoadReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCounterValue );
280
        XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_LOAD_MASK | XTC_CSR_INT_OCCURED_MASK );
281
 
282
        /* Set the timer interrupt enable bit while maintaining the other bit
283
        states. */
284
        uxMask = XIntc_In32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ) );
285
        uxMask |= XPAR_OPB_TIMER_1_INTERRUPT_MASK;
286
        XIntc_Out32( ( XPAR_OPB_INTC_0_BASEADDR + XIN_IER_OFFSET ), ( uxMask ) );
287
 
288
        XTmrCtr_Start( &xTimer, XPAR_OPB_TIMER_1_DEVICE_ID );
289
        XTmrCtr_mSetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK | XTC_CSR_INT_OCCURED_MASK );
290
        XIntc_mAckIntr( XPAR_INTC_SINGLE_BASEADDR, 1 );
291
}
292
/*-----------------------------------------------------------*/
293
 
294
/*
295
 * The interrupt handler placed in the interrupt vector when the scheduler is
296
 * started.  The task context has already been saved when this is called.
297
 * This handler determines the interrupt source and calls the relevant
298
 * peripheral handler.
299
 */
300
void vTaskISRHandler( void )
301
{
302
static unsigned long ulPending;
303
 
304
        /* Which interrupts are pending? */
305
        ulPending = XIntc_In32( ( XPAR_INTC_SINGLE_BASEADDR + XIN_IVR_OFFSET ) );
306
 
307
        if( ulPending < XPAR_INTC_MAX_NUM_INTR_INPUTS )
308
        {
309
                static XIntc_VectorTableEntry *pxTablePtr;
310
                static XIntc_Config *pxConfig;
311
                static unsigned long ulInterruptMask;
312
 
313
                ulInterruptMask = ( unsigned long ) 1 << ulPending;
314
 
315
                /* Get the configuration data using the device ID */
316
                pxConfig = &XIntc_ConfigTable[ ( unsigned long ) XPAR_INTC_SINGLE_DEVICE_ID ];
317
 
318
                pxTablePtr = &( pxConfig->HandlerTable[ ulPending ] );
319
                if( pxConfig->AckBeforeService & ( ulInterruptMask  ) )
320
                {
321
                        XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
322
                        pxTablePtr->Handler( pxTablePtr->CallBackRef );
323
                }
324
                else
325
                {
326
                        pxTablePtr->Handler( pxTablePtr->CallBackRef );
327
                        XIntc_mAckIntr( pxConfig->BaseAddress, ulInterruptMask );
328
                }
329
        }
330
}
331
/*-----------------------------------------------------------*/
332
 
333
/*
334
 * Handler for the timer interrupt.
335
 */
336
void vTickISR( void *pvBaseAddress )
337
{
338
unsigned long ulCSR;
339
 
340
        /* Increment the RTOS tick - this might cause a task to unblock. */
341
        vTaskIncrementTick();
342
 
343
        /* Clear the timer interrupt */
344
        ulCSR = XTmrCtr_mGetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0);
345
        XTmrCtr_mSetControlStatusReg( XPAR_OPB_TIMER_1_BASEADDR, portCOUNTER_0, ulCSR );
346
 
347
        /* If we are using the preemptive scheduler then we also need to determine
348
        if this tick should cause a context switch. */
349
        #if configUSE_PREEMPTION == 1
350
                vTaskSwitchContext();
351
        #endif
352
}
353
/*-----------------------------------------------------------*/
354
 
355
 
356
 
357
 
358
 

powered by: WebSVN 2.1.0

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