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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Source/] [portable/] [MPLAB/] [PIC18F/] [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
/*
55
Changes between V1.2.4 and V1.2.5
56
 
57
        + Introduced portGLOBAL_INTERRUPT_FLAG definition to test the global
58
          interrupt flag setting.  Using the two bits defined within
59
          portINITAL_INTERRUPT_STATE was causing the w register to get clobbered
60
          before the test was performed.
61
 
62
Changes from V1.2.5
63
 
64
        + Set the interrupt vector address to 0x08.  Previously it was at the
65
          incorrect address for compatibility mode of 0x18.
66
 
67
Changes from V2.1.1
68
 
69
        + PCLATU and PCLATH are now saved as part of the context.  This allows
70
          function pointers to be used within tasks.  Thanks to Javier Espeche
71
          for the enhancement.
72
 
73
Changes from V2.3.1
74
 
75
        + TABLAT is now saved as part of the task context.
76
 
77
Changes from V3.2.0
78
 
79
        + TBLPTRU is now initialised to zero as the MPLAB compiler expects this
80
          value and does not write to the register.
81
*/
82
 
83
/* Scheduler include files. */
84
#include "FreeRTOS.h"
85
#include "task.h"
86
 
87
/* MPLAB library include file. */
88
#include "timers.h"
89
 
90
/*-----------------------------------------------------------
91
 * Implementation of functions defined in portable.h for the PIC port.
92
 *----------------------------------------------------------*/
93
 
94
/* Hardware setup for tick. */
95
#define portTIMER_FOSC_SCALE                    ( ( unsigned long ) 4 )
96
 
97
/* Initial interrupt enable state for newly created tasks.  This value is
98
copied into INTCON when a task switches in for the first time. */
99
#define portINITAL_INTERRUPT_STATE                      0xc0
100
 
101
/* Just the bit within INTCON for the global interrupt flag. */
102
#define portGLOBAL_INTERRUPT_FLAG                       0x80
103
 
104
/* Constant used for context switch macro when we require the interrupt
105
enable state to be unchanged when the interrupted task is switched back in. */
106
#define portINTERRUPTS_UNCHANGED                        0x00
107
 
108
/* Some memory areas get saved as part of the task context.  These memory
109
area's get used by the compiler for temporary storage, especially when
110
performing mathematical operations, or when using 32bit data types.  This
111
constant defines the size of memory area which must be saved. */
112
#define portCOMPILER_MANAGED_MEMORY_SIZE        ( ( unsigned char ) 0x13 )
113
 
114
/* We require the address of the pxCurrentTCB variable, but don't want to know
115
any details of its type. */
116
typedef void tskTCB;
117
extern volatile tskTCB * volatile pxCurrentTCB;
118
 
119
/* IO port constants. */
120
#define portBIT_SET             ( ( unsigned char ) 1 )
121
#define portBIT_CLEAR   ( ( unsigned char ) 0 )
122
 
123
/*
124
 * The serial port ISR's are defined in serial.c, but are called from portable
125
 * as they use the same vector as the tick ISR.
126
 */
127
void vSerialTxISR( void );
128
void vSerialRxISR( void );
129
 
130
/*
131
 * Perform hardware setup to enable ticks.
132
 */
133
static void prvSetupTimerInterrupt( void );
134
 
135
/*
136
 * ISR to maintain the tick, and perform tick context switches if the
137
 * preemptive scheduler is being used.
138
 */
139
static void prvTickISR( void );
140
 
141
/*
142
 * ISR placed on the low priority vector.  This calls the appropriate ISR for
143
 * the actual interrupt.
144
 */
145
static void prvLowInterrupt( void );
146
 
147
/*
148
 * Macro that pushes all the registers that make up the context of a task onto
149
 * the stack, then saves the new top of stack into the TCB.
150
 *
151
 * If this is called from an ISR then the interrupt enable bits must have been
152
 * set for the ISR to ever get called.  Therefore we want to save the INTCON
153
 * register with the enable bits forced to be set - and ucForcedInterruptFlags
154
 * must contain these bit settings.  This means the interrupts will again be
155
 * enabled when the interrupted task is switched back in.
156
 *
157
 * If this is called from a manual context switch (i.e. from a call to yield),
158
 * then we want to save the INTCON so it is restored with its current state,
159
 * and ucForcedInterruptFlags must be 0.  This allows a yield from within
160
 * a critical section.
161
 *
162
 * The compiler uses some locations at the bottom of the memory for temporary
163
 * storage during math and other computations.  This is especially true if
164
 * 32bit data types are utilised (as they are by the scheduler).  The .tmpdata
165
 * and MATH_DATA sections have to be stored in there entirety as part of a task
166
 * context.  This macro stores from data address 0x00 to
167
 * portCOMPILER_MANAGED_MEMORY_SIZE.  This is sufficient for the demo
168
 * applications but you should check the map file for your project to ensure
169
 * this is sufficient for your needs.  It is not clear whether this size is
170
 * fixed for all compilations or has the potential to be program specific.
171
 */
172
#define portSAVE_CONTEXT( ucForcedInterruptFlags )                                                              \
173
{                                                                                                                                                               \
174
        _asm                                                                                                                                            \
175
                /* Save the status and WREG registers first, as these will get modified \
176
                by the operations below. */                                                                                             \
177
                MOVFF   WREG, PREINC1                                                                                                   \
178
                MOVFF   STATUS, PREINC1                                                                                                 \
179
                /* Save the INTCON register with the appropriate bits forced if                 \
180
                necessary - as described above. */                                                                              \
181
                MOVFF   INTCON, WREG                                                                                                    \
182
                IORLW   ucForcedInterruptFlags                                                                                  \
183
                MOVFF   WREG, PREINC1                                                                                                   \
184
        _endasm                                                                                                                                         \
185
                                                                                                                                                                \
186
        portDISABLE_INTERRUPTS();                                                                                                       \
187
                                                                                                                                                                \
188
        _asm                                                                                                                                            \
189
                /* Store the necessary registers to the stack. */                                               \
190
                MOVFF   BSR, PREINC1                                                                                                    \
191
                MOVFF   FSR2L, PREINC1                                                                                                  \
192
                MOVFF   FSR2H, PREINC1                                                                                                  \
193
                MOVFF   FSR0L, PREINC1                                                                                                  \
194
                MOVFF   FSR0H, PREINC1                                                                                                  \
195
                MOVFF   TABLAT, PREINC1                                                                                                 \
196
                MOVFF   TBLPTRU, PREINC1                                                                                                \
197
                MOVFF   TBLPTRH, PREINC1                                                                                                \
198
                MOVFF   TBLPTRL, PREINC1                                                                                                \
199
                MOVFF   PRODH, PREINC1                                                                                                  \
200
                MOVFF   PRODL, PREINC1                                                                                                  \
201
                MOVFF   PCLATU, PREINC1                                                                                                 \
202
                MOVFF   PCLATH, PREINC1                                                                                                 \
203
                /* Store the .tempdata and MATH_DATA areas as described above. */               \
204
                CLRF    FSR0L, 0                                                                                                         \
205
                CLRF    FSR0H, 0                                                                                                         \
206
                MOVFF   POSTINC0, PREINC1                                                                                               \
207
                MOVFF   POSTINC0, PREINC1                                                                                               \
208
                MOVFF   POSTINC0, PREINC1                                                                                               \
209
                MOVFF   POSTINC0, PREINC1                                                                                               \
210
                MOVFF   POSTINC0, PREINC1                                                                                               \
211
                MOVFF   POSTINC0, PREINC1                                                                                               \
212
                MOVFF   POSTINC0, PREINC1                                                                                               \
213
                MOVFF   POSTINC0, PREINC1                                                                                               \
214
                MOVFF   POSTINC0, PREINC1                                                                                               \
215
                MOVFF   POSTINC0, PREINC1                                                                                               \
216
                MOVFF   POSTINC0, PREINC1                                                                                               \
217
                MOVFF   POSTINC0, PREINC1                                                                                               \
218
                MOVFF   POSTINC0, PREINC1                                                                                               \
219
                MOVFF   POSTINC0, PREINC1                                                                                               \
220
                MOVFF   POSTINC0, PREINC1                                                                                               \
221
                MOVFF   POSTINC0, PREINC1                                                                                               \
222
                MOVFF   POSTINC0, PREINC1                                                                                               \
223
                MOVFF   POSTINC0, PREINC1                                                                                               \
224
                MOVFF   POSTINC0, PREINC1                                                                                               \
225
                MOVFF   INDF0, PREINC1                                                                                                  \
226
                MOVFF   FSR0L, PREINC1                                                                                                  \
227
                MOVFF   FSR0H, PREINC1                                                                                                  \
228
                /* Store the hardware stack pointer in a temp register before we                \
229
                modify it. */                                                                                                                   \
230
                MOVFF   STKPTR, FSR0L                                                                                                   \
231
        _endasm                                                                                                                                         \
232
                                                                                                                                                                \
233
                /* Store each address from the hardware stack. */                                               \
234
                while( STKPTR > ( unsigned char ) 0 )                                                            \
235
                {                                                                                                                                               \
236
                        _asm                                                                                                                            \
237
                                MOVFF   TOSL, PREINC1                                                                                   \
238
                                MOVFF   TOSH, PREINC1                                                                                   \
239
                                MOVFF   TOSU, PREINC1                                                                                   \
240
                                POP                                                                                                                             \
241
                        _endasm                                                                                                                         \
242
                }                                                                                                                                               \
243
                                                                                                                                                                \
244
        _asm                                                                                                                                            \
245
                /* Store the number of addresses on the hardware stack (from the                \
246
                temporary register). */                                                                                                 \
247
                MOVFF   FSR0L, PREINC1                                                                                                  \
248
                MOVF    PREINC1, 1, 0                                                                                                    \
249
        _endasm                                                                                                                                         \
250
                                                                                                                                                                \
251
        /* Save the new top of the software stack in the TCB. */                                        \
252
        _asm                                                                                                                                            \
253
                MOVFF   pxCurrentTCB, FSR0L                                                                                             \
254
                MOVFF   pxCurrentTCB + 1, FSR0H                                                                                 \
255
                MOVFF   FSR1L, POSTINC0                                                                                                 \
256
                MOVFF   FSR1H, POSTINC0                                                                                                 \
257
        _endasm                                                                                                                                         \
258
}
259
/*-----------------------------------------------------------*/
260
 
261
/*
262
 * This is the reverse of portSAVE_CONTEXT.  See portSAVE_CONTEXT for more
263
 * details.
264
 */
265
#define portRESTORE_CONTEXT()                                                                                                   \
266
{                                                                                                                                                               \
267
        _asm                                                                                                                                            \
268
                /* Set FSR0 to point to pxCurrentTCB->pxTopOfStack. */                                  \
269
                MOVFF   pxCurrentTCB, FSR0L                                                                                             \
270
                MOVFF   pxCurrentTCB + 1, FSR0H                                                                                 \
271
                                                                                                                                                                \
272
                /* De-reference FSR0 to set the address it holds into FSR1.                             \
273
                (i.e. *( pxCurrentTCB->pxTopOfStack ) ). */                                                             \
274
                MOVFF   POSTINC0, FSR1L                                                                                                 \
275
                MOVFF   POSTINC0, FSR1H                                                                                                 \
276
                                                                                                                                                                \
277
                /* How many return addresses are there on the hardware stack?  Discard  \
278
                the first byte as we are pointing to the next free space. */                    \
279
                MOVFF   POSTDEC1, FSR0L                                                                                                 \
280
                MOVFF   POSTDEC1, FSR0L                                                                                                 \
281
        _endasm                                                                                                                                         \
282
                                                                                                                                                                \
283
        /* Fill the hardware stack from our software stack. */                                          \
284
        STKPTR = 0;                                                                                                                                      \
285
                                                                                                                                                                \
286
        while( STKPTR < FSR0L )                                                                                                         \
287
        {                                                                                                                                                       \
288
                _asm                                                                                                                                    \
289
                        PUSH                                                                                                                            \
290
                        MOVF    POSTDEC1, 0, 0                                                                                            \
291
                        MOVWF   TOSU, 0                                                                                                          \
292
                        MOVF    POSTDEC1, 0, 0                                                                                            \
293
                        MOVWF   TOSH, 0                                                                                                          \
294
                        MOVF    POSTDEC1, 0, 0                                                                                            \
295
                        MOVWF   TOSL, 0                                                                                                          \
296
                _endasm                                                                                                                                 \
297
        }                                                                                                                                                       \
298
                                                                                                                                                                \
299
        _asm                                                                                                                                            \
300
                /* Restore the .tmpdata and MATH_DATA memory. */                                                \
301
                MOVFF   POSTDEC1, FSR0H                                                                                                 \
302
                MOVFF   POSTDEC1, FSR0L                                                                                                 \
303
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
304
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
305
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
306
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
307
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
308
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
309
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
310
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
311
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
312
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
313
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
314
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
315
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
316
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
317
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
318
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
319
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
320
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
321
                MOVFF   POSTDEC1, POSTDEC0                                                                                              \
322
                MOVFF   POSTDEC1, INDF0                                                                                                 \
323
                /* Restore the other registers forming the tasks context. */                    \
324
                MOVFF   POSTDEC1, PCLATH                                                                                                \
325
                MOVFF   POSTDEC1, PCLATU                                                                                                \
326
                MOVFF   POSTDEC1, PRODL                                                                                                 \
327
                MOVFF   POSTDEC1, PRODH                                                                                                 \
328
                MOVFF   POSTDEC1, TBLPTRL                                                                                               \
329
                MOVFF   POSTDEC1, TBLPTRH                                                                                               \
330
                MOVFF   POSTDEC1, TBLPTRU                                                                                               \
331
                MOVFF   POSTDEC1, TABLAT                                                                                                \
332
                MOVFF   POSTDEC1, FSR0H                                                                                                 \
333
                MOVFF   POSTDEC1, FSR0L                                                                                                 \
334
                MOVFF   POSTDEC1, FSR2H                                                                                                 \
335
                MOVFF   POSTDEC1, FSR2L                                                                                                 \
336
                MOVFF   POSTDEC1, BSR                                                                                                   \
337
                /* The next byte is the INTCON register.  Read this into WREG as some   \
338
                manipulation is required. */                                                                                    \
339
                MOVFF   POSTDEC1, WREG                                                                                                  \
340
        _endasm                                                                                                                                         \
341
                                                                                                                                                                \
342
        /* From the INTCON register, only the interrupt enable bits form part           \
343
        of the tasks context.  It is perfectly legitimate for another task to           \
344
        have modified any other bits.  We therefore only restore the top two bits.      \
345
        */                                                                                                                                                      \
346
        if( WREG & portGLOBAL_INTERRUPT_FLAG )                                                                          \
347
        {                                                                                                                                                       \
348
                _asm                                                                                                                                    \
349
                        MOVFF   POSTDEC1, STATUS                                                                                        \
350
                        MOVFF   POSTDEC1, WREG                                                                                          \
351
                        /* Return enabling interrupts. */                                                                       \
352
                        RETFIE  0                                                                                                                        \
353
                _endasm                                                                                                                                 \
354
        }                                                                                                                                                       \
355
        else                                                                                                                                            \
356
        {                                                                                                                                                       \
357
                _asm                                                                                                                                    \
358
                        MOVFF   POSTDEC1, STATUS                                                                                        \
359
                        MOVFF   POSTDEC1, WREG                                                                                          \
360
                        /* Return without effecting interrupts.  The context may have           \
361
                        been saved from a critical region. */                                                           \
362
                        RETURN  0                                                                                                                        \
363
                _endasm                                                                                                                                 \
364
        }                                                                                                                                                       \
365
}
366
/*-----------------------------------------------------------*/
367
 
368
/*
369
 * See header file for description.
370
 */
371
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
372
{
373
unsigned long ulAddress;
374
unsigned char ucBlock;
375
 
376
        /* Place a few bytes of known values on the bottom of the stack.
377
        This is just useful for debugging. */
378
 
379
        *pxTopOfStack = 0x11;
380
        pxTopOfStack++;
381
        *pxTopOfStack = 0x22;
382
        pxTopOfStack++;
383
        *pxTopOfStack = 0x33;
384
        pxTopOfStack++;
385
 
386
 
387
        /* Simulate how the stack would look after a call to vPortYield() generated
388
        by the compiler.
389
 
390
        First store the function parameters.  This is where the task will expect to
391
        find them when it starts running. */
392
        ulAddress = ( unsigned long ) pvParameters;
393
        *pxTopOfStack = ( portSTACK_TYPE ) ( ulAddress & ( unsigned long ) 0x00ff );
394
        pxTopOfStack++;
395
 
396
        ulAddress >>= 8;
397
        *pxTopOfStack = ( portSTACK_TYPE ) ( ulAddress & ( unsigned long ) 0x00ff );
398
        pxTopOfStack++;
399
 
400
        /* Next we just leave a space.  When a context is saved the stack pointer
401
        is incremented before it is used so as not to corrupt whatever the stack
402
        pointer is actually pointing to.  This is especially necessary during
403
        function epilogue code generated by the compiler. */
404
        *pxTopOfStack = 0x44;
405
        pxTopOfStack++;
406
 
407
        /* Next are all the registers that form part of the task context. */
408
 
409
        *pxTopOfStack = ( portSTACK_TYPE ) 0x66; /* WREG. */
410
        pxTopOfStack++;
411
 
412
        *pxTopOfStack = ( portSTACK_TYPE ) 0xcc; /* Status. */
413
        pxTopOfStack++;
414
 
415
        /* INTCON is saved with interrupts enabled. */
416
        *pxTopOfStack = ( portSTACK_TYPE ) portINITAL_INTERRUPT_STATE; /* INTCON */
417
        pxTopOfStack++;
418
 
419
        *pxTopOfStack = ( portSTACK_TYPE ) 0x11; /* BSR. */
420
        pxTopOfStack++;
421
 
422
        *pxTopOfStack = ( portSTACK_TYPE ) 0x22; /* FSR2L. */
423
        pxTopOfStack++;
424
 
425
        *pxTopOfStack = ( portSTACK_TYPE ) 0x33; /* FSR2H. */
426
        pxTopOfStack++;
427
 
428
        *pxTopOfStack = ( portSTACK_TYPE ) 0x44; /* FSR0L. */
429
        pxTopOfStack++;
430
 
431
        *pxTopOfStack = ( portSTACK_TYPE ) 0x55; /* FSR0H. */
432
        pxTopOfStack++;
433
 
434
        *pxTopOfStack = ( portSTACK_TYPE ) 0x66; /* TABLAT. */
435
        pxTopOfStack++;
436
 
437
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* TBLPTRU. */
438
        pxTopOfStack++;
439
 
440
        *pxTopOfStack = ( portSTACK_TYPE ) 0x88; /* TBLPTRUH. */
441
        pxTopOfStack++;
442
 
443
        *pxTopOfStack = ( portSTACK_TYPE ) 0x99; /* TBLPTRUL. */
444
        pxTopOfStack++;
445
 
446
        *pxTopOfStack = ( portSTACK_TYPE ) 0xaa; /* PRODH. */
447
        pxTopOfStack++;
448
 
449
        *pxTopOfStack = ( portSTACK_TYPE ) 0xbb; /* PRODL. */
450
        pxTopOfStack++;
451
 
452
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* PCLATU. */
453
        pxTopOfStack++;
454
 
455
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* PCLATH. */
456
        pxTopOfStack++;
457
 
458
        /* Next the .tmpdata and MATH_DATA sections. */
459
        for( ucBlock = 0; ucBlock <= portCOMPILER_MANAGED_MEMORY_SIZE; ucBlock++ )
460
        {
461
                *pxTopOfStack = ( portSTACK_TYPE ) ucBlock;
462
                *pxTopOfStack++;
463
        }
464
 
465
        /* Store the top of the global data section. */
466
        *pxTopOfStack = ( portSTACK_TYPE ) portCOMPILER_MANAGED_MEMORY_SIZE; /* Low. */
467
        pxTopOfStack++;
468
 
469
        *pxTopOfStack = ( portSTACK_TYPE ) 0x00; /* High. */
470
        pxTopOfStack++;
471
 
472
        /* The only function return address so far is the address of the
473
        task. */
474
        ulAddress = ( unsigned long ) pxCode;
475
 
476
        /* TOS low. */
477
        *pxTopOfStack = ( portSTACK_TYPE ) ( ulAddress & ( unsigned long ) 0x00ff );
478
        pxTopOfStack++;
479
        ulAddress >>= 8;
480
 
481
        /* TOS high. */
482
        *pxTopOfStack = ( portSTACK_TYPE ) ( ulAddress & ( unsigned long ) 0x00ff );
483
        pxTopOfStack++;
484
        ulAddress >>= 8;
485
 
486
        /* TOS even higher. */
487
        *pxTopOfStack = ( portSTACK_TYPE ) ( ulAddress & ( unsigned long ) 0x00ff );
488
        pxTopOfStack++;
489
 
490
        /* Store the number of return addresses on the hardware stack - so far only
491
        the address of the task entry point. */
492
        *pxTopOfStack = ( portSTACK_TYPE ) 1;
493
        pxTopOfStack++;
494
 
495
        return pxTopOfStack;
496
}
497
/*-----------------------------------------------------------*/
498
 
499
portBASE_TYPE xPortStartScheduler( void )
500
{
501
        /* Setup a timer for the tick ISR is using the preemptive scheduler. */
502
        prvSetupTimerInterrupt();
503
 
504
        /* Restore the context of the first task to run. */
505
        portRESTORE_CONTEXT();
506
 
507
        /* Should not get here.  Use the function name to stop compiler warnings. */
508
        ( void ) prvLowInterrupt;
509
        ( void ) prvTickISR;
510
 
511
        return pdTRUE;
512
}
513
/*-----------------------------------------------------------*/
514
 
515
void vPortEndScheduler( void )
516
{
517
        /* It is unlikely that the scheduler for the PIC port will get stopped
518
        once running.  If required disable the tick interrupt here, then return
519
        to xPortStartScheduler(). */
520
}
521
/*-----------------------------------------------------------*/
522
 
523
/*
524
 * Manual context switch.  This is similar to the tick context switch,
525
 * but does not increment the tick count.  It must be identical to the
526
 * tick context switch in how it stores the stack of a task.
527
 */
528
void vPortYield( void )
529
{
530
        /* This can get called with interrupts either enabled or disabled.  We
531
        will save the INTCON register with the interrupt enable bits unmodified. */
532
        portSAVE_CONTEXT( portINTERRUPTS_UNCHANGED );
533
 
534
        /* Switch to the highest priority task that is ready to run. */
535
        vTaskSwitchContext();
536
 
537
        /* Start executing the task we have just switched to. */
538
        portRESTORE_CONTEXT();
539
}
540
/*-----------------------------------------------------------*/
541
 
542
/*
543
 * Vector for ISR.  Nothing here must alter any registers!
544
 */
545
#pragma code high_vector=0x08
546
static void prvLowInterrupt( void )
547
{
548
        /* Was the interrupt the tick? */
549
        if( PIR1bits.CCP1IF )
550
        {
551
                _asm
552
                        goto prvTickISR
553
                _endasm
554
        }
555
 
556
        /* Was the interrupt a byte being received? */
557
        if( PIR1bits.RCIF )
558
        {
559
                _asm
560
                        goto vSerialRxISR
561
                _endasm
562
        }
563
 
564
        /* Was the interrupt the Tx register becoming empty? */
565
        if( PIR1bits.TXIF )
566
        {
567
                if( PIE1bits.TXIE )
568
                {
569
                        _asm
570
                                goto vSerialTxISR
571
                        _endasm
572
                }
573
        }
574
}
575
#pragma code
576
 
577
/*-----------------------------------------------------------*/
578
 
579
/*
580
 * ISR for the tick.
581
 * This increments the tick count and, if using the preemptive scheduler,
582
 * performs a context switch.  This must be identical to the manual
583
 * context switch in how it stores the context of a task.
584
 */
585
static void prvTickISR( void )
586
{
587
        /* Interrupts must have been enabled for the ISR to fire, so we have to
588
        save the context with interrupts enabled. */
589
        portSAVE_CONTEXT( portGLOBAL_INTERRUPT_FLAG );
590
        PIR1bits.CCP1IF = 0;
591
 
592
        /* Maintain the tick count. */
593
        vTaskIncrementTick();
594
 
595
        #if configUSE_PREEMPTION == 1
596
        {
597
                /* Switch to the highest priority task that is ready to run. */
598
                vTaskSwitchContext();
599
        }
600
        #endif
601
 
602
        portRESTORE_CONTEXT();
603
}
604
/*-----------------------------------------------------------*/
605
 
606
/*
607
 * Setup a timer for a regular tick.
608
 */
609
static void prvSetupTimerInterrupt( void )
610
{
611
const unsigned long ulConstCompareValue = ( ( configCPU_CLOCK_HZ / portTIMER_FOSC_SCALE ) / configTICK_RATE_HZ );
612
unsigned long ulCompareValue;
613
unsigned char ucByte;
614
 
615
        /* Interrupts are disabled when this function is called.
616
 
617
        Setup CCP1 to provide the tick interrupt using a compare match on timer
618
        1.
619
 
620
        Clear the time count then setup timer. */
621
        TMR1H = ( unsigned char ) 0x00;
622
        TMR1L = ( unsigned char ) 0x00;
623
 
624
        /* Set the compare match value. */
625
        ulCompareValue = ulConstCompareValue;
626
        CCPR1L = ( unsigned char ) ( ulCompareValue & ( unsigned long ) 0xff );
627
        ulCompareValue >>= ( unsigned long ) 8;
628
        CCPR1H = ( unsigned char ) ( ulCompareValue & ( unsigned long ) 0xff );
629
 
630
        CCP1CONbits.CCP1M0 = portBIT_SET;       /*< Compare match mode. */
631
        CCP1CONbits.CCP1M1 = portBIT_SET;       /*< Compare match mode. */
632
        CCP1CONbits.CCP1M2 = portBIT_CLEAR;     /*< Compare match mode. */
633
        CCP1CONbits.CCP1M3 = portBIT_SET;       /*< Compare match mode. */
634
        PIE1bits.CCP1IE = portBIT_SET;          /*< Interrupt enable. */
635
 
636
        /* We are only going to use the global interrupt bit, so set the peripheral
637
        bit to true. */
638
        INTCONbits.GIEL = portBIT_SET;
639
 
640
        /* Provided library function for setting up the timer that will produce the
641
        tick. */
642
        OpenTimer1( T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_1 & T1_CCP1_T3_CCP2 );
643
}
644
 

powered by: WebSVN 2.1.0

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