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

Subversion Repositories openrisc

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

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
#include <stdlib.h>
55
 
56
#include "FreeRTOS.h"
57
#include "task.h"
58
 
59
/*-----------------------------------------------------------
60
 * Implementation of functions defined in portable.h for the AVR/IAR port.
61
 *----------------------------------------------------------*/
62
 
63
/* Start tasks with interrupts enables. */
64
#define portFLAGS_INT_ENABLED                                   ( ( portSTACK_TYPE ) 0x80 )
65
 
66
/* Hardware constants for timer 1. */
67
#define portCLEAR_COUNTER_ON_MATCH                              ( ( unsigned char ) 0x08 )
68
#define portPRESCALE_64                                                 ( ( unsigned char ) 0x03 )
69
#define portCLOCK_PRESCALER                                             ( ( unsigned long ) 64 )
70
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE    ( ( unsigned char ) 0x10 )
71
 
72
/* The number of bytes used on the hardware stack by the task start address. */
73
#define portBYTES_USED_BY_RETURN_ADDRESS                ( 2 )
74
/*-----------------------------------------------------------*/
75
 
76
/* Stores the critical section nesting.  This must not be initialised to 0.
77
It will be initialised when a task starts. */
78
#define portNO_CRITICAL_NESTING                                 ( ( unsigned portBASE_TYPE ) 0 )
79
unsigned portBASE_TYPE uxCriticalNesting = 0x50;
80
 
81
 
82
/*
83
 * Perform hardware setup to enable ticks from timer 1, compare match A.
84
 */
85
static void prvSetupTimerInterrupt( void );
86
 
87
/*
88
 * The IAR compiler does not have full support for inline assembler, so
89
 * these are defined in the portmacro assembler file.
90
 */
91
extern void vPortYieldFromTick( void );
92
extern void vPortStart( void );
93
 
94
/*-----------------------------------------------------------*/
95
 
96
/*
97
 * See header file for description.
98
 */
99
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
100
{
101
unsigned short usAddress;
102
portSTACK_TYPE *pxTopOfHardwareStack;
103
 
104
        /* Place a few bytes of known values on the bottom of the stack.
105
        This is just useful for debugging. */
106
 
107
        *pxTopOfStack = 0x11;
108
        pxTopOfStack--;
109
        *pxTopOfStack = 0x22;
110
        pxTopOfStack--;
111
        *pxTopOfStack = 0x33;
112
        pxTopOfStack--;
113
 
114
        /* Remember where the top of the hardware stack is - this is required
115
        below. */
116
        pxTopOfHardwareStack = pxTopOfStack;
117
 
118
 
119
        /* Simulate how the stack would look after a call to vPortYield(). */
120
 
121
        /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
122
 
123
 
124
 
125
        /* The IAR compiler requires two stacks per task.  First there is the
126
        hardware call stack which uses the AVR stack pointer.  Second there is the
127
        software stack (local variables, parameter passing, etc.) which uses the
128
        AVR Y register.
129
 
130
        This function places both stacks within the memory block passed in as the
131
        first parameter.  The hardware stack is placed at the bottom of the memory
132
        block.  A gap is then left for the hardware stack to grow.  Next the software
133
        stack is placed.  The amount of space between the software and hardware
134
        stacks is defined by configCALL_STACK_SIZE.
135
 
136
 
137
 
138
        The first part of the stack is the hardware stack.  Place the start
139
        address of the task on the hardware stack. */
140
        usAddress = ( unsigned short ) pxCode;
141
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
142
        pxTopOfStack--;
143
 
144
        usAddress >>= 8;
145
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
146
        pxTopOfStack--;
147
 
148
 
149
        /* Leave enough space for the hardware stack before starting the software
150
        stack.  The '- 2' is because we have already used two spaces for the
151
        address of the start of the task. */
152
        pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
153
 
154
 
155
 
156
        /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
157
        portSAVE_CONTEXT places the flags on the stack immediately after r0
158
        to ensure the interrupts get disabled as soon as possible, and so ensuring
159
        the stack use is minimal should a context switch interrupt occur. */
160
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00;        /* R0 */
161
        pxTopOfStack--;
162
        *pxTopOfStack = portFLAGS_INT_ENABLED;
163
        pxTopOfStack--;
164
 
165
        /* Next place the address of the hardware stack.  This is required so
166
        the AVR stack pointer can be restored to point to the hardware stack. */
167
        pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
168
        usAddress = ( unsigned short ) pxTopOfHardwareStack;
169
 
170
        /* SPL */
171
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
172
        pxTopOfStack--;
173
 
174
        /* SPH */
175
        usAddress >>= 8;
176
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
177
        pxTopOfStack--;
178
 
179
 
180
 
181
 
182
        /* Now the remaining registers. */
183
        *pxTopOfStack = ( portSTACK_TYPE ) 0x01;        /* R1 */
184
        pxTopOfStack--;
185
        *pxTopOfStack = ( portSTACK_TYPE ) 0x02;        /* R2 */
186
        pxTopOfStack--;
187
        *pxTopOfStack = ( portSTACK_TYPE ) 0x03;        /* R3 */
188
        pxTopOfStack--;
189
        *pxTopOfStack = ( portSTACK_TYPE ) 0x04;        /* R4 */
190
        pxTopOfStack--;
191
        *pxTopOfStack = ( portSTACK_TYPE ) 0x05;        /* R5 */
192
        pxTopOfStack--;
193
        *pxTopOfStack = ( portSTACK_TYPE ) 0x06;        /* R6 */
194
        pxTopOfStack--;
195
        *pxTopOfStack = ( portSTACK_TYPE ) 0x07;        /* R7 */
196
        pxTopOfStack--;
197
        *pxTopOfStack = ( portSTACK_TYPE ) 0x08;        /* R8 */
198
        pxTopOfStack--;
199
        *pxTopOfStack = ( portSTACK_TYPE ) 0x09;        /* R9 */
200
        pxTopOfStack--;
201
        *pxTopOfStack = ( portSTACK_TYPE ) 0x10;        /* R10 */
202
        pxTopOfStack--;
203
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11;        /* R11 */
204
        pxTopOfStack--;
205
        *pxTopOfStack = ( portSTACK_TYPE ) 0x12;        /* R12 */
206
        pxTopOfStack--;
207
        *pxTopOfStack = ( portSTACK_TYPE ) 0x13;        /* R13 */
208
        pxTopOfStack--;
209
        *pxTopOfStack = ( portSTACK_TYPE ) 0x14;        /* R14 */
210
        pxTopOfStack--;
211
        *pxTopOfStack = ( portSTACK_TYPE ) 0x15;        /* R15 */
212
        pxTopOfStack--;
213
 
214
        /* Place the parameter on the stack in the expected location. */
215
        usAddress = ( unsigned short ) pvParameters;
216
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
217
        pxTopOfStack--;
218
 
219
        usAddress >>= 8;
220
        *pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned short ) 0x00ff );
221
        pxTopOfStack--;
222
 
223
        *pxTopOfStack = ( portSTACK_TYPE ) 0x18;        /* R18 */
224
        pxTopOfStack--;
225
        *pxTopOfStack = ( portSTACK_TYPE ) 0x19;        /* R19 */
226
        pxTopOfStack--;
227
        *pxTopOfStack = ( portSTACK_TYPE ) 0x20;        /* R20 */
228
        pxTopOfStack--;
229
        *pxTopOfStack = ( portSTACK_TYPE ) 0x21;        /* R21 */
230
        pxTopOfStack--;
231
        *pxTopOfStack = ( portSTACK_TYPE ) 0x22;        /* R22 */
232
        pxTopOfStack--;
233
        *pxTopOfStack = ( portSTACK_TYPE ) 0x23;        /* R23 */
234
        pxTopOfStack--;
235
        *pxTopOfStack = ( portSTACK_TYPE ) 0x24;        /* R24 */
236
        pxTopOfStack--;
237
        *pxTopOfStack = ( portSTACK_TYPE ) 0x25;        /* R25 */
238
        pxTopOfStack--;
239
        *pxTopOfStack = ( portSTACK_TYPE ) 0x26;        /* R26 X */
240
        pxTopOfStack--;
241
        *pxTopOfStack = ( portSTACK_TYPE ) 0x27;        /* R27 */
242
        pxTopOfStack--;
243
 
244
        /* The Y register is not stored as it is used as the software stack and
245
        gets saved into the task control block. */
246
 
247
        *pxTopOfStack = ( portSTACK_TYPE ) 0x30;        /* R30 Z */
248
        pxTopOfStack--;
249
        *pxTopOfStack = ( portSTACK_TYPE ) 0x031;       /* R31 */
250
 
251
        pxTopOfStack--;
252
        *pxTopOfStack = portNO_CRITICAL_NESTING;        /* Critical nesting is zero when the task starts. */
253
 
254
        /*lint +e950 +e611 +e923 */
255
 
256
        return pxTopOfStack;
257
}
258
/*-----------------------------------------------------------*/
259
 
260
portBASE_TYPE xPortStartScheduler( void )
261
{
262
        /* Setup the hardware to generate the tick. */
263
        prvSetupTimerInterrupt();
264
 
265
        /* Restore the context of the first task that is going to run.
266
        Normally we would just call portRESTORE_CONTEXT() here, but as the IAR
267
        compiler does not fully support inline assembler we have to make a call.*/
268
        vPortStart();
269
 
270
 
271
        /* Should not get here! */
272
        return pdTRUE;
273
}
274
/*-----------------------------------------------------------*/
275
 
276
void vPortEndScheduler( void )
277
{
278
        /* It is unlikely that the AVR port will get stopped.  If required simply
279
        disable the tick interrupt here. */
280
}
281
/*-----------------------------------------------------------*/
282
 
283
/*
284
 * Setup timer 1 compare match A to generate a tick interrupt.
285
 */
286
static void prvSetupTimerInterrupt( void )
287
{
288
unsigned long ulCompareMatch;
289
unsigned char ucHighByte, ucLowByte;
290
 
291
        /* Using 16bit timer 1 to generate the tick.  Correct fuses must be
292
        selected for the configCPU_CLOCK_HZ clock. */
293
 
294
        ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
295
 
296
        /* We only have 16 bits so have to scale to get our required tick rate. */
297
        ulCompareMatch /= portCLOCK_PRESCALER;
298
 
299
        /* Adjust for correct value. */
300
        ulCompareMatch -= ( unsigned long ) 1;
301
 
302
        /* Setup compare match value for compare match A.  Interrupts are disabled
303
        before this is called so we need not worry here. */
304
        ucLowByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff );
305
        ulCompareMatch >>= 8;
306
        ucHighByte = ( unsigned char ) ( ulCompareMatch & ( unsigned long ) 0xff );
307
        OCR1AH = ucHighByte;
308
        OCR1AL = ucLowByte;
309
 
310
        /* Setup clock source and compare match behaviour. */
311
        ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
312
        TCCR1B = ucLowByte;
313
 
314
        /* Enable the interrupt - this is okay as interrupt are currently globally
315
        disabled. */
316
        TIMSK |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
317
}
318
/*-----------------------------------------------------------*/
319
 
320
#if configUSE_PREEMPTION == 1
321
 
322
        /*
323
         * Tick ISR for preemptive scheduler.  We can use a __task attribute as
324
         * the context is saved at the start of vPortYieldFromTick().  The tick
325
         * count is incremented after the context is saved.
326
         */
327
        __task void SIG_OUTPUT_COMPARE1A( void )
328
        {
329
                vPortYieldFromTick();
330
                asm( "reti" );
331
        }
332
 
333
#else
334
 
335
        /*
336
         * Tick ISR for the cooperative scheduler.  All this does is increment the
337
         * tick count.  We don't need to switch context, this can only be done by
338
         * manual calls to taskYIELD();
339
         *
340
         * THE INTERRUPT VECTOR IS POPULATED IN portmacro.s90.  DO NOT INSTALL
341
         * IT HERE USING THE USUAL PRAGMA.
342
         */
343
        __interrupt void SIG_OUTPUT_COMPARE1A( void )
344
        {
345
                vTaskIncrementTick();
346
        }
347
#endif
348
/*-----------------------------------------------------------*/
349
 
350
void vPortEnterCritical( void )
351
{
352
        portDISABLE_INTERRUPTS();
353
        uxCriticalNesting++;
354
}
355
/*-----------------------------------------------------------*/
356
 
357
void vPortExitCritical( void )
358
{
359
        uxCriticalNesting--;
360
        if( uxCriticalNesting == portNO_CRITICAL_NESTING )
361
        {
362
                portENABLE_INTERRUPTS();
363
        }
364
}
365
 
366
 

powered by: WebSVN 2.1.0

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