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

Subversion Repositories openrisc

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

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
 
56
Changes from V2.6.0
57
 
58
        + AVR port - Replaced the inb() and outb() functions with direct memory
59
          access.  This allows the port to be built with the 20050414 build of
60
          WinAVR.
61
*/
62
 
63
#include <stdlib.h>
64
#include <avr/interrupt.h>
65
 
66
#include "FreeRTOS.h"
67
#include "task.h"
68
 
69
/*-----------------------------------------------------------
70
 * Implementation of functions defined in portable.h for the AVR port.
71
 *----------------------------------------------------------*/
72
 
73
/* Start tasks with interrupts enables. */
74
#define portFLAGS_INT_ENABLED                                   ( ( portSTACK_TYPE ) 0x80 )
75
 
76
/* Hardware constants for timer 1. */
77
#define portCLEAR_COUNTER_ON_MATCH                              ( ( unsigned char ) 0x08 )
78
#define portPRESCALE_64                                                 ( ( unsigned char ) 0x03 )
79
#define portCLOCK_PRESCALER                                             ( ( unsigned long ) 64 )
80
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE    ( ( unsigned char ) 0x10 )
81
 
82
/*-----------------------------------------------------------*/
83
 
84
/* We require the address of the pxCurrentTCB variable, but don't want to know
85
any details of its type. */
86
typedef void tskTCB;
87
extern volatile tskTCB * volatile pxCurrentTCB;
88
 
89
/*-----------------------------------------------------------*/
90
 
91
/*
92
 * Macro to save all the general purpose registers, the save the stack pointer
93
 * into the TCB.
94
 *
95
 * The first thing we do is save the flags then disable interrupts.  This is to
96
 * guard our stack against having a context switch interrupt after we have already
97
 * pushed the registers onto the stack - causing the 32 registers to be on the
98
 * stack twice.
99
 *
100
 * r1 is set to zero as the compiler expects it to be thus, however some
101
 * of the math routines make use of R1.
102
 *
103
 * The interrupts will have been disabled during the call to portSAVE_CONTEXT()
104
 * so we need not worry about reading/writing to the stack pointer.
105
 */
106
 
107
#define portSAVE_CONTEXT()                                                                      \
108
        asm volatile (  "push   r0                                              \n\t"   \
109
                                        "in             r0, __SREG__                    \n\t"   \
110
                                        "cli                                                    \n\t"   \
111
                                        "push   r0                                              \n\t"   \
112
                                        "push   r1                                              \n\t"   \
113
                                        "clr    r1                                              \n\t"   \
114
                                        "push   r2                                              \n\t"   \
115
                                        "push   r3                                              \n\t"   \
116
                                        "push   r4                                              \n\t"   \
117
                                        "push   r5                                              \n\t"   \
118
                                        "push   r6                                              \n\t"   \
119
                                        "push   r7                                              \n\t"   \
120
                                        "push   r8                                              \n\t"   \
121
                                        "push   r9                                              \n\t"   \
122
                                        "push   r10                                             \n\t"   \
123
                                        "push   r11                                             \n\t"   \
124
                                        "push   r12                                             \n\t"   \
125
                                        "push   r13                                             \n\t"   \
126
                                        "push   r14                                             \n\t"   \
127
                                        "push   r15                                             \n\t"   \
128
                                        "push   r16                                             \n\t"   \
129
                                        "push   r17                                             \n\t"   \
130
                                        "push   r18                                             \n\t"   \
131
                                        "push   r19                                             \n\t"   \
132
                                        "push   r20                                             \n\t"   \
133
                                        "push   r21                                             \n\t"   \
134
                                        "push   r22                                             \n\t"   \
135
                                        "push   r23                                             \n\t"   \
136
                                        "push   r24                                             \n\t"   \
137
                                        "push   r25                                             \n\t"   \
138
                                        "push   r26                                             \n\t"   \
139
                                        "push   r27                                             \n\t"   \
140
                                        "push   r28                                             \n\t"   \
141
                                        "push   r29                                             \n\t"   \
142
                                        "push   r30                                             \n\t"   \
143
                                        "push   r31                                             \n\t"   \
144
                                        "lds    r26, pxCurrentTCB               \n\t"   \
145
                                        "lds    r27, pxCurrentTCB + 1   \n\t"   \
146
                                        "in             r0, 0x3d                                \n\t"   \
147
                                        "st             x+, r0                                  \n\t"   \
148
                                        "in             r0, 0x3e                                \n\t"   \
149
                                        "st             x+, r0                                  \n\t"   \
150
                                );
151
 
152
/*
153
 * Opposite to portSAVE_CONTEXT().  Interrupts will have been disabled during
154
 * the context save so we can write to the stack pointer.
155
 */
156
 
157
#define portRESTORE_CONTEXT()                                                           \
158
        asm volatile (  "lds    r26, pxCurrentTCB               \n\t"   \
159
                                        "lds    r27, pxCurrentTCB + 1   \n\t"   \
160
                                        "ld             r28, x+                                 \n\t"   \
161
                                        "out    __SP_L__, r28                   \n\t"   \
162
                                        "ld             r29, x+                                 \n\t"   \
163
                                        "out    __SP_H__, r29                   \n\t"   \
164
                                        "pop    r31                                             \n\t"   \
165
                                        "pop    r30                                             \n\t"   \
166
                                        "pop    r29                                             \n\t"   \
167
                                        "pop    r28                                             \n\t"   \
168
                                        "pop    r27                                             \n\t"   \
169
                                        "pop    r26                                             \n\t"   \
170
                                        "pop    r25                                             \n\t"   \
171
                                        "pop    r24                                             \n\t"   \
172
                                        "pop    r23                                             \n\t"   \
173
                                        "pop    r22                                             \n\t"   \
174
                                        "pop    r21                                             \n\t"   \
175
                                        "pop    r20                                             \n\t"   \
176
                                        "pop    r19                                             \n\t"   \
177
                                        "pop    r18                                             \n\t"   \
178
                                        "pop    r17                                             \n\t"   \
179
                                        "pop    r16                                             \n\t"   \
180
                                        "pop    r15                                             \n\t"   \
181
                                        "pop    r14                                             \n\t"   \
182
                                        "pop    r13                                             \n\t"   \
183
                                        "pop    r12                                             \n\t"   \
184
                                        "pop    r11                                             \n\t"   \
185
                                        "pop    r10                                             \n\t"   \
186
                                        "pop    r9                                              \n\t"   \
187
                                        "pop    r8                                              \n\t"   \
188
                                        "pop    r7                                              \n\t"   \
189
                                        "pop    r6                                              \n\t"   \
190
                                        "pop    r5                                              \n\t"   \
191
                                        "pop    r4                                              \n\t"   \
192
                                        "pop    r3                                              \n\t"   \
193
                                        "pop    r2                                              \n\t"   \
194
                                        "pop    r1                                              \n\t"   \
195
                                        "pop    r0                                              \n\t"   \
196
                                        "out    __SREG__, r0                    \n\t"   \
197
                                        "pop    r0                                              \n\t"   \
198
                                );
199
 
200
/*-----------------------------------------------------------*/
201
 
202
/*
203
 * Perform hardware setup to enable ticks from timer 1, compare match A.
204
 */
205
static void prvSetupTimerInterrupt( void );
206
/*-----------------------------------------------------------*/
207
 
208
/*
209
 * See header file for description.
210
 */
211
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
212
{
213
unsigned short usAddress;
214
 
215
        /* Place a few bytes of known values on the bottom of the stack.
216
        This is just useful for debugging. */
217
 
218
        *pxTopOfStack = 0x11;
219
        pxTopOfStack--;
220
        *pxTopOfStack = 0x22;
221
        pxTopOfStack--;
222
        *pxTopOfStack = 0x33;
223
        pxTopOfStack--;
224
 
225
        /* Simulate how the stack would look after a call to vPortYield() generated by
226
        the compiler. */
227
 
228
        /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
229
 
230
        /* The start of the task code will be popped off the stack last, so place
231
        it on first. */
232
        usAddress = ( unsigned short ) pxCode;
233
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
234
        pxTopOfStack--;
235
 
236
        usAddress >>= 8;
237
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
238
        pxTopOfStack--;
239
 
240
        /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
241
        portSAVE_CONTEXT places the flags on the stack immediately after r0
242
        to ensure the interrupts get disabled as soon as possible, and so ensuring
243
        the stack use is minimal should a context switch interrupt occur. */
244
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00;        /* R0 */
245
        pxTopOfStack--;
246
        *pxTopOfStack = portFLAGS_INT_ENABLED;
247
        pxTopOfStack--;
248
 
249
 
250
        /* Now the remaining registers.   The compiler expects R1 to be 0. */
251
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00;        /* R1 */
252
        pxTopOfStack--;
253
        *pxTopOfStack = ( portSTACK_TYPE ) 0x02;        /* R2 */
254
        pxTopOfStack--;
255
        *pxTopOfStack = ( portSTACK_TYPE ) 0x03;        /* R3 */
256
        pxTopOfStack--;
257
        *pxTopOfStack = ( portSTACK_TYPE ) 0x04;        /* R4 */
258
        pxTopOfStack--;
259
        *pxTopOfStack = ( portSTACK_TYPE ) 0x05;        /* R5 */
260
        pxTopOfStack--;
261
        *pxTopOfStack = ( portSTACK_TYPE ) 0x06;        /* R6 */
262
        pxTopOfStack--;
263
        *pxTopOfStack = ( portSTACK_TYPE ) 0x07;        /* R7 */
264
        pxTopOfStack--;
265
        *pxTopOfStack = ( portSTACK_TYPE ) 0x08;        /* R8 */
266
        pxTopOfStack--;
267
        *pxTopOfStack = ( portSTACK_TYPE ) 0x09;        /* R9 */
268
        pxTopOfStack--;
269
        *pxTopOfStack = ( portSTACK_TYPE ) 0x10;        /* R10 */
270
        pxTopOfStack--;
271
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11;        /* R11 */
272
        pxTopOfStack--;
273
        *pxTopOfStack = ( portSTACK_TYPE ) 0x12;        /* R12 */
274
        pxTopOfStack--;
275
        *pxTopOfStack = ( portSTACK_TYPE ) 0x13;        /* R13 */
276
        pxTopOfStack--;
277
        *pxTopOfStack = ( portSTACK_TYPE ) 0x14;        /* R14 */
278
        pxTopOfStack--;
279
        *pxTopOfStack = ( portSTACK_TYPE ) 0x15;        /* R15 */
280
        pxTopOfStack--;
281
        *pxTopOfStack = ( portSTACK_TYPE ) 0x16;        /* R16 */
282
        pxTopOfStack--;
283
        *pxTopOfStack = ( portSTACK_TYPE ) 0x17;        /* R17 */
284
        pxTopOfStack--;
285
        *pxTopOfStack = ( portSTACK_TYPE ) 0x18;        /* R18 */
286
        pxTopOfStack--;
287
        *pxTopOfStack = ( portSTACK_TYPE ) 0x19;        /* R19 */
288
        pxTopOfStack--;
289
        *pxTopOfStack = ( portSTACK_TYPE ) 0x20;        /* R20 */
290
        pxTopOfStack--;
291
        *pxTopOfStack = ( portSTACK_TYPE ) 0x21;        /* R21 */
292
        pxTopOfStack--;
293
        *pxTopOfStack = ( portSTACK_TYPE ) 0x22;        /* R22 */
294
        pxTopOfStack--;
295
        *pxTopOfStack = ( portSTACK_TYPE ) 0x23;        /* R23 */
296
        pxTopOfStack--;
297
 
298
        /* Place the parameter on the stack in the expected location. */
299
        usAddress = ( unsigned short ) pvParameters;
300
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
301
        pxTopOfStack--;
302
 
303
        usAddress >>= 8;
304
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
305
        pxTopOfStack--;
306
 
307
        *pxTopOfStack = ( portSTACK_TYPE ) 0x26;        /* R26 X */
308
        pxTopOfStack--;
309
        *pxTopOfStack = ( portSTACK_TYPE ) 0x27;        /* R27 */
310
        pxTopOfStack--;
311
        *pxTopOfStack = ( portSTACK_TYPE ) 0x28;        /* R28 Y */
312
        pxTopOfStack--;
313
        *pxTopOfStack = ( portSTACK_TYPE ) 0x29;        /* R29 */
314
        pxTopOfStack--;
315
        *pxTopOfStack = ( portSTACK_TYPE ) 0x30;        /* R30 Z */
316
        pxTopOfStack--;
317
        *pxTopOfStack = ( portSTACK_TYPE ) 0x031;       /* R31 */
318
        pxTopOfStack--;
319
 
320
        /*lint +e950 +e611 +e923 */
321
 
322
        return pxTopOfStack;
323
}
324
/*-----------------------------------------------------------*/
325
 
326
portBASE_TYPE xPortStartScheduler( void )
327
{
328
        /* Setup the hardware to generate the tick. */
329
        prvSetupTimerInterrupt();
330
 
331
        /* Restore the context of the first task that is going to run. */
332
        portRESTORE_CONTEXT();
333
 
334
        /* Simulate a function call end as generated by the compiler.  We will now
335
        jump to the start of the task the context of which we have just restored. */
336
        asm volatile ( "ret" );
337
 
338
        /* Should not get here. */
339
        return pdTRUE;
340
}
341
/*-----------------------------------------------------------*/
342
 
343
void vPortEndScheduler( void )
344
{
345
        /* It is unlikely that the AVR port will get stopped.  If required simply
346
        disable the tick interrupt here. */
347
}
348
/*-----------------------------------------------------------*/
349
 
350
/*
351
 * Manual context switch.  The first thing we do is save the registers so we
352
 * can use a naked attribute.
353
 */
354
void vPortYield( void ) __attribute__ ( ( naked ) );
355
void vPortYield( void )
356
{
357
        portSAVE_CONTEXT();
358
        vTaskSwitchContext();
359
        portRESTORE_CONTEXT();
360
 
361
        asm volatile ( "ret" );
362
}
363
/*-----------------------------------------------------------*/
364
 
365
/*
366
 * Context switch function used by the tick.  This must be identical to
367
 * vPortYield() from the call to vTaskSwitchContext() onwards.  The only
368
 * difference from vPortYield() is the tick count is incremented as the
369
 * call comes from the tick ISR.
370
 */
371
void vPortYieldFromTick( void ) __attribute__ ( ( naked ) );
372
void vPortYieldFromTick( void )
373
{
374
        portSAVE_CONTEXT();
375
        vTaskIncrementTick();
376
        vTaskSwitchContext();
377
        portRESTORE_CONTEXT();
378
 
379
        asm volatile ( "ret" );
380
}
381
/*-----------------------------------------------------------*/
382
 
383
/*
384
 * Setup timer 1 compare match A to generate a tick interrupt.
385
 */
386
static void prvSetupTimerInterrupt( void )
387
{
388
unsigned long ulCompareMatch;
389
unsigned char ucHighByte, ucLowByte;
390
 
391
        /* Using 16bit timer 1 to generate the tick.  Correct fuses must be
392
        selected for the configCPU_CLOCK_HZ clock. */
393
 
394
        ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
395
 
396
        /* We only have 16 bits so have to scale to get our required tick rate. */
397
        ulCompareMatch /= portCLOCK_PRESCALER;
398
 
399
        /* Adjust for correct value. */
400
        ulCompareMatch -= ( unsigned long ) 1;
401
 
402
        /* Setup compare match value for compare match A.  Interrupts are disabled
403
        before this is called so we need not worry here. */
404
        ucLowByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff );
405
        ulCompareMatch >>= 8;
406
        ucHighByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff );
407
        OCR1AH = ucHighByte;
408
        OCR1AL = ucLowByte;
409
 
410
        /* Setup clock source and compare match behaviour. */
411
        ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
412
        TCCR1B = ucLowByte;
413
 
414
        /* Enable the interrupt - this is okay as interrupt are currently globally
415
        disabled. */
416
        ucLowByte = TIMSK;
417
        ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
418
        TIMSK = ucLowByte;
419
}
420
/*-----------------------------------------------------------*/
421
 
422
#if configUSE_PREEMPTION == 1
423
 
424
        /*
425
         * Tick ISR for preemptive scheduler.  We can use a naked attribute as
426
         * the context is saved at the start of vPortYieldFromTick().  The tick
427
         * count is incremented after the context is saved.
428
         */
429
        void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );
430
        void SIG_OUTPUT_COMPARE1A( void )
431
        {
432
                vPortYieldFromTick();
433
                asm volatile ( "reti" );
434
        }
435
#else
436
 
437
        /*
438
         * Tick ISR for the cooperative scheduler.  All this does is increment the
439
         * tick count.  We don't need to switch context, this can only be done by
440
         * manual calls to taskYIELD();
441
         */
442
        void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal ) );
443
        void SIG_OUTPUT_COMPARE1A( void )
444
        {
445
                vTaskIncrementTick();
446
        }
447
#endif
448
 
449
 
450
 

powered by: WebSVN 2.1.0

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