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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [CORTEX_LM3S811_IAR/] [LuminaryCode/] [interrupt.c] - Blame information for rev 581

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 581 jeremybenn
//*****************************************************************************
2
//
3
// interrupt.c - Driver for the NVIC Interrupt Controller.
4
//
5
// Copyright (c) 2005,2006 Luminary Micro, Inc.  All rights reserved.
6
//
7
// Software License Agreement
8
//
9
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
10
// exclusively on LMI's Stellaris Family of microcontroller products.
11
//
12
// The software is owned by LMI and/or its suppliers, and is protected under
13
// applicable copyright laws.  All rights are reserved.  Any use in violation
14
// of the foregoing restrictions may subject the user to criminal sanctions
15
// under applicable laws, as well as to civil liability for the breach of the
16
// terms and conditions of this license.
17
//
18
// THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
19
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
20
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
21
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
22
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
23
//
24
// This is part of revision 991 of the Stellaris Driver Library.
25
//
26
//*****************************************************************************
27
 
28
//*****************************************************************************
29
//
30
//! \addtogroup interrupt_api
31
//! @{
32
//
33
//*****************************************************************************
34
 
35
#include "../hw_ints.h"
36
#include "../hw_nvic.h"
37
#include "../hw_types.h"
38
#include "cpu.h"
39
#include "debug.h"
40
#include "interrupt.h"
41
 
42
//*****************************************************************************
43
//
44
// This is a mapping between priority grouping encodings and the number of
45
// preemption priority bits.
46
//
47
//*****************************************************************************
48
#if defined(GROUP_pulpriority) || defined(BUILD_ALL)
49
const unsigned long g_pulPriority[] =
50
{
51
    NVIC_APINT_PRIGROUP_0_8, NVIC_APINT_PRIGROUP_1_7, NVIC_APINT_PRIGROUP_2_6,
52
    NVIC_APINT_PRIGROUP_3_5, NVIC_APINT_PRIGROUP_4_4, NVIC_APINT_PRIGROUP_5_3,
53
    NVIC_APINT_PRIGROUP_6_2, NVIC_APINT_PRIGROUP_7_1
54
};
55
#else
56
extern const unsigned long g_pulPriority[];
57
#endif
58
 
59
//*****************************************************************************
60
//
61
// This is a mapping between interrupt number and the register that contains
62
// the priority encoding for that interrupt.
63
//
64
//*****************************************************************************
65
#if defined(GROUP_pulregs) || defined(BUILD_ALL)
66
const unsigned long g_pulRegs[12] =
67
{
68
    0, NVIC_SYS_PRI1, NVIC_SYS_PRI2, NVIC_SYS_PRI3, NVIC_PRI0, NVIC_PRI1,
69
    NVIC_PRI2, NVIC_PRI3, NVIC_PRI4, NVIC_PRI5, NVIC_PRI6, NVIC_PRI7
70
};
71
#else
72
extern const unsigned long g_pulRegs[12];
73
#endif
74
 
75
//*****************************************************************************
76
//
77
//! \internal
78
//! The default interrupt handler.
79
//!
80
//! This is the default interrupt handler for all interrupts.  It simply loops
81
//! forever so that the system state is preserved for observation by a
82
//! debugger.  Since interrupts should be disabled before unregistering the
83
//! corresponding handler, this should never be called.
84
//!
85
//! \return None.
86
//
87
//*****************************************************************************
88
#if defined(GROUP_defaulthandler) || defined(BUILD_ALL)
89
void
90
IntDefaultHandler(void)
91
{
92
    //
93
    // Go into an infinite loop.
94
    //
95
    while(1)
96
    {
97
    }
98
}
99
#else
100
extern void IntDefaultHandler(void);
101
#endif
102
 
103
//*****************************************************************************
104
//
105
// The processor vector table.
106
//
107
// This contains a list of the handlers for the various interrupt sources in
108
// the system.  The layout of this list is defined by the hardware; assertion
109
// of an interrupt causes the processor to start executing directly at the
110
// address given in the corresponding location in this list.
111
//
112
//*****************************************************************************
113
#if defined(GROUP_vtable) || defined(BUILD_ALL)
114
#ifdef ewarm
115
__no_init void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void) @ "VTABLE";
116
#else
117
__attribute__((section("vtable")))
118
void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
119
#endif
120
#else
121
extern void (*g_pfnRAMVectors[NUM_INTERRUPTS])(void);
122
#endif
123
 
124
//*****************************************************************************
125
//
126
//! Enables the processor interrupt.
127
//!
128
//! Allows the processor to respond to interrupts.  This does not affect the
129
//! set of interrupts enabled in the interrupt controller; it just gates the
130
//! single interrupt from the controller to the processor.
131
//!
132
//! \return None.
133
//
134
//*****************************************************************************
135
#if defined(GROUP_masterenable) || defined(BUILD_ALL) || defined(DOXYGEN)
136
void
137
IntMasterEnable(void)
138
{
139
    //
140
    // Enable processor interrupts.
141
    //
142
    CPUcpsie();
143
}
144
#endif
145
 
146
//*****************************************************************************
147
//
148
//! Disables the processor interrupt.
149
//!
150
//! Prevents the processor from receiving interrupts.  This does not affect the
151
//! set of interrupts enabled in the interrupt controller; it just gates the
152
//! single interrupt from the controller to the processor.
153
//!
154
//! \return None.
155
//
156
//*****************************************************************************
157
#if defined(GROUP_masterdisable) || defined(BUILD_ALL) || defined(DOXYGEN)
158
void
159
IntMasterDisable(void)
160
{
161
    //
162
    // Disable processor interrupts.
163
    //
164
    CPUcpsid();
165
}
166
#endif
167
 
168
//*****************************************************************************
169
//
170
//! Registers a function to be called when an interrupt occurs.
171
//!
172
//! \param ulInterrupt specifies the interrupt in question.
173
//! \param pfnHandler is a pointer to the function to be called.
174
//!
175
//! This function is used to specify the handler function to be called when the
176
//! given interrupt is asserted to the processor.  When the interrupt occurs,
177
//! if it is enabled (via IntEnable()), the handler function will be called in
178
//! interrupt context.  Since the handler function can preempt other code, care
179
//! must be taken to protect memory or peripherals that are accessed by the
180
//! handler and other non-handler code.
181
//!
182
//! \note The use of this function (directly or indirectly via a peripheral
183
//! driver interrupt register function) moves the interrupt vector table from
184
//! flash to SRAM.  Therefore, care must be taken when linking the application
185
//! to ensure that the SRAM vector table is located at the beginning of SRAM;
186
//! otherwise NVIC will not look in the correct portion of memory for the
187
//! vector table (it requires the vector table be on a 1 kB memory alignment).
188
//! Normally, the SRAM vector table is so placed via the use of linker scripts;
189
//! some tool chains, such as the evaluation version of RV-MDK, do not support
190
//! linker scripts and therefore will not produce a valid executable.  See the
191
//! discussion of compile-time versus run-time interrupt handler registration
192
//! in the introduction to this chapter.
193
//!
194
//! \return None.
195
//
196
//*****************************************************************************
197
#if defined(GROUP_register) || defined(BUILD_ALL) || defined(DOXYGEN)
198
void
199
IntRegister(unsigned long ulInterrupt, void (*pfnHandler)(void))
200
{
201
    unsigned long ulIdx;
202
 
203
    //
204
    // Check the arguments.
205
    //
206
    ASSERT(ulInterrupt < NUM_INTERRUPTS);
207
 
208
    //
209
    // Make sure that the RAM vector table is correctly aligned.
210
    //
211
    ASSERT(((unsigned long)g_pfnRAMVectors & 0x000003ff) == 0);
212
 
213
    //
214
    // See if the RAM vector table has been initialized.
215
    //
216
    if(HWREG(NVIC_VTABLE) != (unsigned long)g_pfnRAMVectors)
217
    {
218
        //
219
        // Copy the vector table from the beginning of FLASH to the RAM vector
220
        // table.
221
        //
222
        for(ulIdx = 0; ulIdx < NUM_INTERRUPTS; ulIdx++)
223
        {
224
            g_pfnRAMVectors[ulIdx] = (void (*)(void))HWREG(ulIdx * 4);
225
        }
226
 
227
        //
228
        // Point NVIC at the RAM vector table.
229
        //
230
        HWREG(NVIC_VTABLE) = (unsigned long)g_pfnRAMVectors;
231
    }
232
 
233
    //
234
    // Save the interrupt handler.
235
    //
236
    g_pfnRAMVectors[ulInterrupt] = pfnHandler;
237
}
238
#endif
239
 
240
//*****************************************************************************
241
//
242
//! Unregisters the function to be called when an interrupt occurs.
243
//!
244
//! \param ulInterrupt specifies the interrupt in question.
245
//!
246
//! This function is used to indicate that no handler should be called when the
247
//! given interrupt is asserted to the processor.  The interrupt source will be
248
//! automatically disabled (via IntDisable()) if necessary.
249
//!
250
//! \sa IntRegister() for important information about registering interrupt
251
//! handlers.
252
//!
253
//! \return None.
254
//
255
//*****************************************************************************
256
#if defined(GROUP_unregister) || defined(BUILD_ALL) || defined(DOXYGEN)
257
void
258
IntUnregister(unsigned long ulInterrupt)
259
{
260
    //
261
    // Check the arguments.
262
    //
263
    ASSERT(ulInterrupt < NUM_INTERRUPTS);
264
 
265
    //
266
    // Reset the interrupt handler.
267
    //
268
    g_pfnRAMVectors[ulInterrupt] = IntDefaultHandler;
269
}
270
#endif
271
 
272
//*****************************************************************************
273
//
274
//! Sets the priority grouping of the interrupt controller.
275
//!
276
//! \param ulBits specifies the number of bits of preemptable priority.
277
//!
278
//! This function specifies the split between preemptable priority levels and
279
//! subpriority levels in the interrupt priority specification.  The range of
280
//! the grouping values are dependent upon the hardware implementation; on
281
//! the Stellaris family it can range from 0 to 3.
282
//!
283
//! \return None.
284
//
285
//*****************************************************************************
286
#if defined(GROUP_prioritygroupingset) || defined(BUILD_ALL) || \
287
    defined(DOXYGEN)
288
void
289
IntPriorityGroupingSet(unsigned long ulBits)
290
{
291
    //
292
    // Check the arguments.
293
    //
294
    ASSERT(ulBits < NUM_PRIORITY_BITS);
295
 
296
    //
297
    // Set the priority grouping.
298
    //
299
    HWREG(NVIC_APINT) = NVIC_APINT_VECTKEY | g_pulPriority[ulBits];
300
}
301
#endif
302
 
303
//*****************************************************************************
304
//
305
//! Gets the priority grouping of the interrupt controller.
306
//!
307
//! This function returns the split between preemptable priority levels and
308
//! subpriority levels in the interrupt priority specification.
309
//!
310
//! \return The number of bits of preemptable priority.
311
//
312
//*****************************************************************************
313
#if defined(GROUP_prioritygroupingget) || defined(BUILD_ALL) || \
314
    defined(DOXYGEN)
315
unsigned long
316
IntPriorityGroupingGet(void)
317
{
318
    unsigned long ulLoop, ulValue;
319
 
320
    //
321
    // Read the priority grouping.
322
    //
323
    ulValue = HWREG(NVIC_APINT) & NVIC_APINT_PRIGROUP_M;
324
 
325
    //
326
    // Loop through the priority grouping values.
327
    //
328
    for(ulLoop = 0; ulLoop < 8; ulLoop++)
329
    {
330
        //
331
        // Stop looping if this value matches.
332
        //
333
        if(ulValue == g_pulPriority[ulLoop])
334
        {
335
            break;
336
        }
337
    }
338
 
339
    //
340
    // Return the number of priority bits.
341
    //
342
    return(ulLoop);
343
}
344
#endif
345
 
346
//*****************************************************************************
347
//
348
//! Sets the priority of an interrupt.
349
//!
350
//! \param ulInterrupt specifies the interrupt in question.
351
//! \param ucPriority specifies the priority of the interrupt.
352
//!
353
//! This function is used to set the priority of an interrupt.  When multiple
354
//! interrupts are asserted simultaneously, the ones with the highest priority
355
//! are processed before the lower priority interrupts.  Smaller numbers
356
//! correspond to higher interrupt priorities; priority 0 is the highest
357
//! interrupt priority.
358
//!
359
//! The hardware priority mechanism will only look at the upper N bits of the
360
//! priority level (where N is 3 for the Stellaris family), so any
361
//! prioritization must be performed in those bits.  The remaining bits can be
362
//! used to sub-prioritize the interrupt sources, and may be used by the
363
//! hardware priority mechanism on a future part.  This arrangement allows
364
//! priorities to migrate to different NVIC implementations without changing
365
//! the gross prioritization of the interrupts.
366
//!
367
//! \return None.
368
//
369
//*****************************************************************************
370
#if defined(GROUP_priorityset) || defined(BUILD_ALL) || defined(DOXYGEN)
371
void
372
IntPrioritySet(unsigned long ulInterrupt, unsigned char ucPriority)
373
{
374
    unsigned long ulTemp;
375
 
376
    //
377
    // Check the arguments.
378
    //
379
    ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
380
 
381
    //
382
    // Set the interrupt priority.
383
    //
384
    ulTemp = HWREG(g_pulRegs[ulInterrupt >> 2]);
385
    ulTemp &= ~(0xFF << (8 * (ulInterrupt & 3)));
386
    ulTemp |= ucPriority << (8 * (ulInterrupt & 3));
387
    HWREG(g_pulRegs[ulInterrupt >> 2]) = ulTemp;
388
}
389
#endif
390
 
391
//*****************************************************************************
392
//
393
//! Gets the priority of an interrupt.
394
//!
395
//! \param ulInterrupt specifies the interrupt in question.
396
//!
397
//! This function gets the priority of an interrupt.  See IntPrioritySet() for
398
//! a definition of the priority value.
399
//!
400
//! \return Returns the interrupt priority, or -1 if an invalid interrupt was
401
//! specified.
402
//
403
//*****************************************************************************
404
#if defined(GROUP_priorityget) || defined(BUILD_ALL) || defined(DOXYGEN)
405
long
406
IntPriorityGet(unsigned long ulInterrupt)
407
{
408
    //
409
    // Check the arguments.
410
    //
411
    ASSERT((ulInterrupt >= 4) && (ulInterrupt < NUM_INTERRUPTS));
412
 
413
    //
414
    // Return the interrupt priority.
415
    //
416
    return((HWREG(g_pulRegs[ulInterrupt >> 2]) >> (8 * (ulInterrupt & 3))) &
417
           0xFF);
418
}
419
#endif
420
 
421
//*****************************************************************************
422
//
423
//! Enables an interrupt.
424
//!
425
//! \param ulInterrupt specifies the interrupt to be enabled.
426
//!
427
//! The specified interrupt is enabled in the interrupt controller.  Other
428
//! enables for the interrupt (such as at the peripheral level) are unaffected
429
//! by this function.
430
//!
431
//! \return None.
432
//
433
//*****************************************************************************
434
#if defined(GROUP_enable) || defined(BUILD_ALL) || defined(DOXYGEN)
435
void
436
IntEnable(unsigned long ulInterrupt)
437
{
438
    //
439
    // Check the arguments.
440
    //
441
    ASSERT(ulInterrupt < NUM_INTERRUPTS);
442
 
443
    //
444
    // Determine the interrupt to enable.
445
    //
446
    if(ulInterrupt == FAULT_MPU)
447
    {
448
        //
449
        // Enable the MemManage interrupt.
450
        //
451
        HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_MEM;
452
    }
453
    else if(ulInterrupt == FAULT_BUS)
454
    {
455
        //
456
        // Enable the bus fault interrupt.
457
        //
458
        HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_BUS;
459
    }
460
    else if(ulInterrupt == FAULT_USAGE)
461
    {
462
        //
463
        // Enable the usage fault interrupt.
464
        //
465
        HWREG(NVIC_SYS_HND_CTRL) |= NVIC_SYS_HND_CTRL_USAGE;
466
    }
467
    else if(ulInterrupt == FAULT_SYSTICK)
468
    {
469
        //
470
        // Enable the System Tick interrupt.
471
        //
472
        HWREG(NVIC_ST_CTRL) |= NVIC_ST_CTRL_INTEN;
473
    }
474
    else if(ulInterrupt >= INT_GPIOA)
475
    {
476
        //
477
        // Enable the general interrupt.
478
        //
479
        HWREG(NVIC_EN0) = 1 << (ulInterrupt - INT_GPIOA);
480
    }
481
}
482
#endif
483
 
484
//*****************************************************************************
485
//
486
//! Disables an interrupt.
487
//!
488
//! \param ulInterrupt specifies the interrupt to be disabled.
489
//!
490
//! The specified interrupt is disabled in the interrupt controller.  Other
491
//! enables for the interrupt (such as at the peripheral level) are unaffected
492
//! by this function.
493
//!
494
//! \return None.
495
//
496
//*****************************************************************************
497
#if defined(GROUP_disable) || defined(BUILD_ALL) || defined(DOXYGEN)
498
void
499
IntDisable(unsigned long ulInterrupt)
500
{
501
    //
502
    // Check the arguments.
503
    //
504
    ASSERT(ulInterrupt < NUM_INTERRUPTS);
505
 
506
    //
507
    // Determine the interrupt to disable.
508
    //
509
    if(ulInterrupt == FAULT_MPU)
510
    {
511
        //
512
        // Disable the MemManage interrupt.
513
        //
514
        HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_MEM);
515
    }
516
    else if(ulInterrupt == FAULT_BUS)
517
    {
518
        //
519
        // Disable the bus fault interrupt.
520
        //
521
        HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_BUS);
522
    }
523
    else if(ulInterrupt == FAULT_USAGE)
524
    {
525
        //
526
        // Disable the usage fault interrupt.
527
        //
528
        HWREG(NVIC_SYS_HND_CTRL) &= ~(NVIC_SYS_HND_CTRL_USAGE);
529
    }
530
    else if(ulInterrupt == FAULT_SYSTICK)
531
    {
532
        //
533
        // Disable the System Tick interrupt.
534
        //
535
        HWREG(NVIC_ST_CTRL) &= ~(NVIC_ST_CTRL_INTEN);
536
    }
537
    else if(ulInterrupt >= INT_GPIOA)
538
    {
539
        //
540
        // Disable the general interrupt.
541
        //
542
        HWREG(NVIC_DIS0) = 1 << (ulInterrupt - INT_GPIOA);
543
    }
544
}
545
#endif
546
 
547
//*****************************************************************************
548
//
549
// Close the Doxygen group.
550
//! @}
551
//
552
//*****************************************************************************

powered by: WebSVN 2.1.0

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