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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Source/] [portable/] [GCC/] [RX600/] [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
 * Implementation of functions defined in portable.h for the SH2A port.
56
 *----------------------------------------------------------*/
57
 
58
/* Scheduler includes. */
59
#include "FreeRTOS.h"
60
#include "task.h"
61
 
62
/* Library includes. */
63
#include "string.h"
64
 
65
/* Hardware specifics. */
66
#include "iodefine.h"
67
 
68
/*-----------------------------------------------------------*/
69
 
70
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore
71
PSW is set with U and I set, and PM and IPL clear. */
72
#define portINITIAL_PSW     ( ( portSTACK_TYPE ) 0x00030000 )
73
#define portINITIAL_FPSW    ( ( portSTACK_TYPE ) 0x00000100 )
74
 
75
/* These macros allow a critical section to be added around the call to
76
vTaskIncrementTick(), which is only ever called from interrupts at the kernel
77
priority - ie a known priority.  Therefore these local macros are a slight
78
optimisation compared to calling the global SET/CLEAR_INTERRUPT_MASK macros,
79
which would require the old IPL to be read first and stored in a local variable. */
80
#define portDISABLE_INTERRUPTS_FROM_KERNEL_ISR()        __asm volatile ( "MVTIPL        %0" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) )
81
#define portENABLE_INTERRUPTS_FROM_KERNEL_ISR()         __asm volatile ( "MVTIPL        %0" ::"i"(configKERNEL_INTERRUPT_PRIORITY) )
82
 
83
/*-----------------------------------------------------------*/
84
 
85
/*
86
 * Function to start the first task executing - written in asm code as direct
87
 * access to registers is required.
88
 */
89
static void prvStartFirstTask( void ) __attribute__((naked));
90
 
91
/*
92
 * Software interrupt handler.  Performs the actual context switch (saving and
93
 * restoring of registers).  Written in asm code as direct register access is
94
 * required.
95
 */
96
void vSoftwareInterruptISR( void ) __attribute__((naked));
97
 
98
/*
99
 * The tick interrupt handler.
100
 */
101
void vTickISR( void ) __attribute__((interrupt));
102
 
103
/*-----------------------------------------------------------*/
104
 
105
extern void *pxCurrentTCB;
106
 
107
/*-----------------------------------------------------------*/
108
 
109
/*
110
 * See header file for description.
111
 */
112
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
113
{
114
        /* R0 is not included as it is the stack pointer. */
115
 
116
        *pxTopOfStack = 0xdeadbeef;
117
        pxTopOfStack--;
118
        *pxTopOfStack = portINITIAL_PSW;
119
        pxTopOfStack--;
120
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode;
121
 
122
        /* When debugging it can be useful if every register is set to a known
123
        value.  Otherwise code space can be saved by just setting the registers
124
        that need to be set. */
125
        #ifdef USE_FULL_REGISTER_INITIALISATION
126
        {
127
                pxTopOfStack--;
128
                *pxTopOfStack = 0xffffffff;     /* r15. */
129
                pxTopOfStack--;
130
                *pxTopOfStack = 0xeeeeeeee;
131
                pxTopOfStack--;
132
                *pxTopOfStack = 0xdddddddd;
133
                pxTopOfStack--;
134
                *pxTopOfStack = 0xcccccccc;
135
                pxTopOfStack--;
136
                *pxTopOfStack = 0xbbbbbbbb;
137
                pxTopOfStack--;
138
                *pxTopOfStack = 0xaaaaaaaa;
139
                pxTopOfStack--;
140
                *pxTopOfStack = 0x99999999;
141
                pxTopOfStack--;
142
                *pxTopOfStack = 0x88888888;
143
                pxTopOfStack--;
144
                *pxTopOfStack = 0x77777777;
145
                pxTopOfStack--;
146
                *pxTopOfStack = 0x66666666;
147
                pxTopOfStack--;
148
                *pxTopOfStack = 0x55555555;
149
                pxTopOfStack--;
150
                *pxTopOfStack = 0x44444444;
151
                pxTopOfStack--;
152
                *pxTopOfStack = 0x33333333;
153
                pxTopOfStack--;
154
                *pxTopOfStack = 0x22222222;
155
                pxTopOfStack--;
156
        }
157
        #else
158
        {
159
                pxTopOfStack -= 15;
160
        }
161
        #endif
162
 
163
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R1 */
164
        pxTopOfStack--;
165
        *pxTopOfStack = portINITIAL_FPSW;
166
        pxTopOfStack--;
167
        *pxTopOfStack = 0x12345678; /* Accumulator. */
168
        pxTopOfStack--;
169
        *pxTopOfStack = 0x87654321; /* Accumulator. */
170
 
171
        return pxTopOfStack;
172
}
173
/*-----------------------------------------------------------*/
174
 
175
portBASE_TYPE xPortStartScheduler( void )
176
{
177
extern void vApplicationSetupTimerInterrupt( void );
178
 
179
        /* Use pxCurrentTCB just so it does not get optimised away. */
180
        if( pxCurrentTCB != NULL )
181
        {
182
                /* Call an application function to set up the timer that will generate the
183
                tick interrupt.  This way the application can decide which peripheral to
184
                use.  A demo application is provided to show a suitable example. */
185
                vApplicationSetupTimerInterrupt();
186
 
187
                /* Enable the software interrupt. */
188
                _IEN( _ICU_SWINT ) = 1;
189
 
190
                /* Ensure the software interrupt is clear. */
191
                _IR( _ICU_SWINT ) = 0;
192
 
193
                /* Ensure the software interrupt is set to the kernel priority. */
194
                _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
195
 
196
                /* Start the first task. */
197
                prvStartFirstTask();
198
        }
199
 
200
        /* Should not get here. */
201
        return pdFAIL;
202
}
203
/*-----------------------------------------------------------*/
204
 
205
void vPortEndScheduler( void )
206
{
207
        /* Not implemented as there is nothing to return to. */
208
}
209
/*-----------------------------------------------------------*/
210
 
211
static void prvStartFirstTask( void )
212
{
213
        __asm volatile
214
        (
215
                /* When starting the scheduler there is nothing that needs moving to the
216
                interrupt stack because the function is not called from an interrupt.
217
                Just ensure the current stack is the user stack. */
218
                "SETPSW         U                                               \n" \
219
 
220
                /* Obtain the location of the stack associated with which ever task
221
                pxCurrentTCB is currently pointing to. */
222
                "MOV.L          #_pxCurrentTCB, R15             \n" \
223
                "MOV.L          [R15], R15                              \n" \
224
                "MOV.L          [R15], R0                               \n" \
225
 
226
                /* Restore the registers from the stack of the task pointed to by
227
                pxCurrentTCB. */
228
            "POP                R15                                             \n" \
229
 
230
                /* Accumulator low 32 bits. */
231
            "MVTACLO    R15                                     \n" \
232
            "POP                R15                                             \n" \
233
 
234
                /* Accumulator high 32 bits. */
235
            "MVTACHI    R15                                     \n" \
236
            "POP                R15                                             \n" \
237
 
238
                /* Floating point status word. */
239
            "MVTC               R15, FPSW                               \n" \
240
 
241
                /* R1 to R15 - R0 is not included as it is the SP. */
242
            "POPM               R1-R15                                  \n" \
243
 
244
                /* This pops the remaining registers. */
245
            "RTE                                                                \n" \
246
            "NOP                                                                \n" \
247
            "NOP                                                                \n"
248
        );
249
}
250
/*-----------------------------------------------------------*/
251
 
252
void vSoftwareInterruptISR( void )
253
{
254
        __asm volatile
255
        (
256
                /* Re-enable interrupts. */
257
                "SETPSW         I                                                       \n" \
258
 
259
                /* Move the data that was automatically pushed onto the interrupt stack when
260
                the interrupt occurred from the interrupt stack to the user stack.
261
 
262
                R15 is saved before it is clobbered. */
263
                "PUSH.L         R15                                                     \n" \
264
 
265
                /* Read the user stack pointer. */
266
                "MVFC           USP, R15                                        \n" \
267
 
268
                /* Move the address down to the data being moved. */
269
                "SUB            #12, R15                                        \n" \
270
                "MVTC           R15, USP                                        \n" \
271
 
272
                /* Copy the data across, R15, then PC, then PSW. */
273
                "MOV.L          [ R0 ], [ R15 ]                         \n" \
274
                "MOV.L          4[ R0 ], 4[ R15 ]                       \n" \
275
                "MOV.L          8[ R0 ], 8[ R15 ]                       \n" \
276
 
277
                /* Move the interrupt stack pointer to its new correct position. */
278
                "ADD            #12, R0                                         \n" \
279
 
280
                /* All the rest of the registers are saved directly to the user stack. */
281
                "SETPSW         U                                                       \n" \
282
 
283
                /* Save the rest of the general registers (R15 has been saved already). */
284
                "PUSHM          R1-R14                                          \n" \
285
 
286
                /* Save the FPSW and accumulator. */
287
                "MVFC           FPSW, R15                                       \n" \
288
                "PUSH.L         R15                                                     \n" \
289
                "MVFACHI        R15                                                     \n" \
290
                "PUSH.L         R15                                                     \n" \
291
 
292
                /* Middle word. */
293
                "MVFACMI        R15                                                     \n" \
294
 
295
                /* Shifted left as it is restored to the low order word. */
296
                "SHLL           #16, R15                                        \n" \
297
                "PUSH.L         R15                                                     \n" \
298
 
299
                /* Save the stack pointer to the TCB. */
300
                "MOV.L          #_pxCurrentTCB, R15                     \n" \
301
                "MOV.L          [ R15 ], R15                            \n" \
302
                "MOV.L          R0, [ R15 ]                                     \n" \
303
 
304
                /* Ensure the interrupt mask is set to the syscall priority while the kernel
305
                structures are being accessed. */
306
                "MVTIPL         %0                                                      \n" \
307
 
308
                /* Select the next task to run. */
309
                "BSR.A          _vTaskSwitchContext                     \n" \
310
 
311
                /* Reset the interrupt mask as no more data structure access is required. */
312
                "MVTIPL         %1                                                      \n" \
313
 
314
                /* Load the stack pointer of the task that is now selected as the Running
315
                state task from its TCB. */
316
                "MOV.L          #_pxCurrentTCB,R15                      \n" \
317
                "MOV.L          [ R15 ], R15                            \n" \
318
                "MOV.L          [ R15 ], R0                                     \n" \
319
 
320
                /* Restore the context of the new task.  The PSW (Program Status Word) and
321
                PC will be popped by the RTE instruction. */
322
                "POP            R15                                                     \n" \
323
                "MVTACLO        R15                                                     \n" \
324
                "POP            R15                                                     \n" \
325
                "MVTACHI        R15                                                     \n" \
326
                "POP            R15                                                     \n" \
327
                "MVTC           R15, FPSW                                       \n" \
328
                "POPM           R1-R15                                          \n" \
329
                "RTE                                                                    \n" \
330
                "NOP                                                                    \n" \
331
                "NOP                                                                      "
332
                :: "i"(configMAX_SYSCALL_INTERRUPT_PRIORITY), "i"(configKERNEL_INTERRUPT_PRIORITY)
333
        );
334
}
335
/*-----------------------------------------------------------*/
336
 
337
void vTickISR( void )
338
{
339
        /* Re-enabled interrupts. */
340
        __asm volatile( "SETPSW I" );
341
 
342
        /* Increment the tick, and perform any processing the new tick value
343
        necessitates.  Ensure IPL is at the max syscall value first. */
344
        portDISABLE_INTERRUPTS_FROM_KERNEL_ISR();
345
        {
346
                vTaskIncrementTick();
347
        }
348
        portENABLE_INTERRUPTS_FROM_KERNEL_ISR();
349
 
350
        /* Only select a new task if the preemptive scheduler is being used. */
351
        #if( configUSE_PREEMPTION == 1 )
352
                taskYIELD();
353
        #endif
354
}
355
/*-----------------------------------------------------------*/
356
 
357
unsigned long ulPortGetIPL( void )
358
{
359
        __asm volatile
360
        (
361
                "MVFC   PSW, R1                 \n"     \
362
                "SHLR   #24, R1                 \n"     \
363
                "RTS                                      "
364
        );
365
 
366
        /* This will never get executed, but keeps the compiler from complaining. */
367
        return 0;
368
}
369
/*-----------------------------------------------------------*/
370
 
371
void vPortSetIPL( unsigned long ulNewIPL )
372
{
373
        __asm volatile
374
        (
375
                "PUSH   R5                              \n" \
376
                "MVFC   PSW, R5                 \n"     \
377
                "SHLL   #24, R1                 \n" \
378
                "AND    #-0F000001H, R5 \n" \
379
                "OR             R1, R5                  \n" \
380
                "MVTC   R5, PSW                 \n" \
381
                "POP    R5                              \n" \
382
                "RTS                                      "
383
         );
384
}

powered by: WebSVN 2.1.0

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