OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

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

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
        Changes from V2.5.2
56
 
57
        + usCriticalNesting now has a volatile qualifier.
58
*/
59
 
60
/* Standard includes. */
61
#include <stdlib.h>
62
#include <signal.h>
63
 
64
/* Scheduler includes. */
65
#include "FreeRTOS.h"
66
#include "task.h"
67
 
68
/*-----------------------------------------------------------
69
 * Implementation of functions defined in portable.h for the MSP430 port.
70
 *----------------------------------------------------------*/
71
 
72
/* Constants required for hardware setup.  The tick ISR runs off the ACLK,
73
not the MCLK. */
74
#define portACLK_FREQUENCY_HZ                   ( ( portTickType ) 32768 )
75
#define portINITIAL_CRITICAL_NESTING    ( ( unsigned short ) 10 )
76
#define portFLAGS_INT_ENABLED   ( ( portSTACK_TYPE ) 0x08 )
77
 
78
/* We require the address of the pxCurrentTCB variable, but don't want to know
79
any details of its type. */
80
typedef void tskTCB;
81
extern volatile tskTCB * volatile pxCurrentTCB;
82
 
83
/* Most ports implement critical sections by placing the interrupt flags on
84
the stack before disabling interrupts.  Exiting the critical section is then
85
simply a case of popping the flags from the stack.  As mspgcc does not use
86
a frame pointer this cannot be done as modifying the stack will clobber all
87
the stack variables.  Instead each task maintains a count of the critical
88
section nesting depth.  Each time a critical section is entered the count is
89
incremented.  Each time a critical section is left the count is decremented -
90
with interrupts only being re-enabled if the count is zero.
91
 
92
usCriticalNesting will get set to zero when the scheduler starts, but must
93
not be initialised to zero as this will cause problems during the startup
94
sequence. */
95
volatile unsigned short usCriticalNesting = portINITIAL_CRITICAL_NESTING;
96
/*-----------------------------------------------------------*/
97
 
98
/*
99
 * Macro to save a task context to the task stack.  This simply pushes all the
100
 * general purpose msp430 registers onto the stack, followed by the
101
 * usCriticalNesting value used by the task.  Finally the resultant stack
102
 * pointer value is saved into the task control block so it can be retrieved
103
 * the next time the task executes.
104
 */
105
#define portSAVE_CONTEXT()                                                                      \
106
        asm volatile (  "push   r4                                              \n\t"   \
107
                                        "push   r5                                              \n\t"   \
108
                                        "push   r6                                              \n\t"   \
109
                                        "push   r7                                              \n\t"   \
110
                                        "push   r8                                              \n\t"   \
111
                                        "push   r9                                              \n\t"   \
112
                                        "push   r10                                             \n\t"   \
113
                                        "push   r11                                             \n\t"   \
114
                                        "push   r12                                             \n\t"   \
115
                                        "push   r13                                             \n\t"   \
116
                                        "push   r14                                             \n\t"   \
117
                                        "push   r15                                             \n\t"   \
118
                                        "mov.w  usCriticalNesting, r14  \n\t"   \
119
                                        "push   r14                                             \n\t"   \
120
                                        "mov.w  pxCurrentTCB, r12               \n\t"   \
121
                                        "mov.w  r1, @r12                                \n\t"   \
122
                                );
123
 
124
/*
125
 * Macro to restore a task context from the task stack.  This is effectively
126
 * the reverse of portSAVE_CONTEXT().  First the stack pointer value is
127
 * loaded from the task control block.  Next the value for usCriticalNesting
128
 * used by the task is retrieved from the stack - followed by the value of all
129
 * the general purpose msp430 registers.
130
 *
131
 * The bic instruction ensures there are no low power bits set in the status
132
 * register that is about to be popped from the stack.
133
 */
134
#define portRESTORE_CONTEXT()                                                           \
135
        asm volatile (  "mov.w  pxCurrentTCB, r12               \n\t"   \
136
                                        "mov.w  @r12, r1                                \n\t"   \
137
                                        "pop    r15                                             \n\t"   \
138
                                        "mov.w  r15, usCriticalNesting  \n\t"   \
139
                                        "pop    r15                                             \n\t"   \
140
                                        "pop    r14                                             \n\t"   \
141
                                        "pop    r13                                             \n\t"   \
142
                                        "pop    r12                                             \n\t"   \
143
                                        "pop    r11                                             \n\t"   \
144
                                        "pop    r10                                             \n\t"   \
145
                                        "pop    r9                                              \n\t"   \
146
                                        "pop    r8                                              \n\t"   \
147
                                        "pop    r7                                              \n\t"   \
148
                                        "pop    r6                                              \n\t"   \
149
                                        "pop    r5                                              \n\t"   \
150
                                        "pop    r4                                              \n\t"   \
151
                                        "bic    #(0xf0),0(r1)                   \n\t"   \
152
                                        "reti                                                   \n\t"   \
153
                                );
154
/*-----------------------------------------------------------*/
155
 
156
/*
157
 * Sets up the periodic ISR used for the RTOS tick.  This uses timer 0, but
158
 * could have alternatively used the watchdog timer or timer 1.
159
 */
160
static void prvSetupTimerInterrupt( void );
161
/*-----------------------------------------------------------*/
162
 
163
/*
164
 * Initialise the stack of a task to look exactly as if a call to
165
 * portSAVE_CONTEXT had been called.
166
 *
167
 * See the header file portable.h.
168
 */
169
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
170
{
171
        /*
172
                Place a few bytes of known values on the bottom of the stack.
173
                This is just useful for debugging and can be included if required.
174
 
175
                *pxTopOfStack = ( portSTACK_TYPE ) 0x1111;
176
                pxTopOfStack--;
177
                *pxTopOfStack = ( portSTACK_TYPE ) 0x2222;
178
                pxTopOfStack--;
179
                *pxTopOfStack = ( portSTACK_TYPE ) 0x3333;
180
                pxTopOfStack--;
181
        */
182
 
183
        /* The msp430 automatically pushes the PC then SR onto the stack before
184
        executing an ISR.  We want the stack to look just as if this has happened
185
        so place a pointer to the start of the task on the stack first - followed
186
        by the flags we want the task to use when it starts up. */
187
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode;
188
        pxTopOfStack--;
189
        *pxTopOfStack = portFLAGS_INT_ENABLED;
190
        pxTopOfStack--;
191
 
192
        /* Next the general purpose registers. */
193
        *pxTopOfStack = ( portSTACK_TYPE ) 0x4444;
194
        pxTopOfStack--;
195
        *pxTopOfStack = ( portSTACK_TYPE ) 0x5555;
196
        pxTopOfStack--;
197
        *pxTopOfStack = ( portSTACK_TYPE ) 0x6666;
198
        pxTopOfStack--;
199
        *pxTopOfStack = ( portSTACK_TYPE ) 0x7777;
200
        pxTopOfStack--;
201
        *pxTopOfStack = ( portSTACK_TYPE ) 0x8888;
202
        pxTopOfStack--;
203
        *pxTopOfStack = ( portSTACK_TYPE ) 0x9999;
204
        pxTopOfStack--;
205
        *pxTopOfStack = ( portSTACK_TYPE ) 0xaaaa;
206
        pxTopOfStack--;
207
        *pxTopOfStack = ( portSTACK_TYPE ) 0xbbbb;
208
        pxTopOfStack--;
209
        *pxTopOfStack = ( portSTACK_TYPE ) 0xcccc;
210
        pxTopOfStack--;
211
        *pxTopOfStack = ( portSTACK_TYPE ) 0xdddd;
212
        pxTopOfStack--;
213
        *pxTopOfStack = ( portSTACK_TYPE ) 0xeeee;
214
        pxTopOfStack--;
215
 
216
        /* When the task starts is will expect to find the function parameter in
217
        R15. */
218
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
219
        pxTopOfStack--;
220
 
221
        /* The code generated by the mspgcc compiler does not maintain separate
222
        stack and frame pointers. The portENTER_CRITICAL macro cannot therefore
223
        use the stack as per other ports.  Instead a variable is used to keep
224
        track of the critical section nesting.  This variable has to be stored
225
        as part of the task context and is initially set to zero. */
226
        *pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_SECTION_NESTING;
227
 
228
        /* Return a pointer to the top of the stack we have generated so this can
229
        be stored in the task control block for the task. */
230
        return pxTopOfStack;
231
}
232
/*-----------------------------------------------------------*/
233
 
234
portBASE_TYPE xPortStartScheduler( void )
235
{
236
        /* Setup the hardware to generate the tick.  Interrupts are disabled when
237
        this function is called. */
238
        prvSetupTimerInterrupt();
239
 
240
        /* Restore the context of the first task that is going to run. */
241
        portRESTORE_CONTEXT();
242
 
243
        /* Should not get here as the tasks are now running! */
244
        return pdTRUE;
245
}
246
/*-----------------------------------------------------------*/
247
 
248
void vPortEndScheduler( void )
249
{
250
        /* It is unlikely that the MSP430 port will get stopped.  If required simply
251
        disable the tick interrupt here. */
252
}
253
/*-----------------------------------------------------------*/
254
 
255
/*
256
 * Manual context switch called by portYIELD or taskYIELD.
257
 *
258
 * The first thing we do is save the registers so we can use a naked attribute.
259
 */
260
void vPortYield( void ) __attribute__ ( ( naked ) );
261
void vPortYield( void )
262
{
263
        /* We want the stack of the task being saved to look exactly as if the task
264
        was saved during a pre-emptive RTOS tick ISR.  Before calling an ISR the
265
        msp430 places the status register onto the stack.  As this is a function
266
        call and not an ISR we have to do this manually. */
267
        asm volatile ( "push    r2" );
268
        _DINT();
269
 
270
        /* Save the context of the current task. */
271
        portSAVE_CONTEXT();
272
 
273
        /* Switch to the highest priority task that is ready to run. */
274
        vTaskSwitchContext();
275
 
276
        /* Restore the context of the new task. */
277
        portRESTORE_CONTEXT();
278
}
279
/*-----------------------------------------------------------*/
280
 
281
/*
282
 * Hardware initialisation to generate the RTOS tick.  This uses timer 0
283
 * but could alternatively use the watchdog timer or timer 1.
284
 */
285
static void prvSetupTimerInterrupt( void )
286
{
287
        /* Ensure the timer is stopped. */
288
        TACTL = 0;
289
 
290
        /* Run the timer of the ACLK. */
291
        TACTL = TASSEL_1;
292
 
293
        /* Clear everything to start with. */
294
        TACTL |= TACLR;
295
 
296
        /* Set the compare match value according to the tick rate we want. */
297
        TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ;
298
 
299
        /* Enable the interrupts. */
300
        TACCTL0 = CCIE;
301
 
302
        /* Start up clean. */
303
        TACTL |= TACLR;
304
 
305
        /* Up mode. */
306
        TACTL |= MC_1;
307
}
308
/*-----------------------------------------------------------*/
309
 
310
/*
311
 * The interrupt service routine used depends on whether the pre-emptive
312
 * scheduler is being used or not.
313
 */
314
 
315
#if configUSE_PREEMPTION == 1
316
 
317
        /*
318
         * Tick ISR for preemptive scheduler.  We can use a naked attribute as
319
         * the context is saved at the start of vPortYieldFromTick().  The tick
320
         * count is incremented after the context is saved.
321
         */
322
        interrupt (TIMERA0_VECTOR) prvTickISR( void ) __attribute__ ( ( naked ) );
323
        interrupt (TIMERA0_VECTOR) prvTickISR( void )
324
        {
325
                /* Save the context of the interrupted task. */
326
                portSAVE_CONTEXT();
327
 
328
                /* Increment the tick count then switch to the highest priority task
329
                that is ready to run. */
330
                vTaskIncrementTick();
331
                vTaskSwitchContext();
332
 
333
                /* Restore the context of the new task. */
334
                portRESTORE_CONTEXT();
335
        }
336
 
337
#else
338
 
339
        /*
340
         * Tick ISR for the cooperative scheduler.  All this does is increment the
341
         * tick count.  We don't need to switch context, this can only be done by
342
         * manual calls to taskYIELD();
343
         */
344
        interrupt (TIMERA0_VECTOR) prvTickISR( void );
345
        interrupt (TIMERA0_VECTOR) prvTickISR( void )
346
        {
347
                vTaskIncrementTick();
348
        }
349
#endif
350
 
351
 
352
 

powered by: WebSVN 2.1.0

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