summaryrefslogtreecommitdiff
path: root/peripherals/irq/nvic.c
blob: b7d40b297d163b52dad62929f9c076d540bc12e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support 
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

//------------------------------------------------------------------------------
//         Headers
//------------------------------------------------------------------------------

#include "board.h"
#include "irq.h"
#include "exceptions.h"
#include <utility/trace.h>

/// The index of IRQ handler in the exception table
#define NVIC_IRQ_HANDLER_INDEX     16

//------------------------------------------------------------------------------
//         Global functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Configures an interrupt in the NVIC. The interrupt is identified by its
/// source (AT91C_ID_xxx) and is configured to a specified priority and
/// interrupt handler function. priority is the value that will be put in NVIC_IPRx
/// and the function address will be set in "ExceptionTable". The parameter priority
/// will include the preemptionPriority and the subPriority, where the subPriority
/// defined in the B[7:0] of the parameter "priority", and the preemptionPriority defined
/// in the B[15:8] of the parameter "priority". 
/// The interrupt is disabled before configuration, so it is useless
/// to do it before calling this function. When NVIC_ConfigureIT returns, the
/// interrupt will always be disabled and cleared; it must be enabled by a
/// call to NVIC_EnableIT().
/// \param source               Interrupt source to configure.
/// \param priority              Pre-emption priority (B[15:8] )+ subPriority (B[7:0])
/// \param handler              Interrupt handler function.
//------------------------------------------------------------------------------
void IRQ_ConfigureIT(
    unsigned int source,
    //unsigned int preemptionPriority,
    //unsigned int subPriority,
    unsigned int priority,
    IntFunc handler)
{
    unsigned int priGroup = __NVIC_PRIO_BITS;
    unsigned int nPre = 8 - priGroup;
    unsigned int nSub = priGroup;
    unsigned int preemptionPriority;
    unsigned int subPriority;
    unsigned int IRQpriority;

    preemptionPriority = (priority & 0xff00) >> 8;
    subPriority = (priority & 0xff);

    // Disable the interrupt first
    NVIC_DisableIRQ((IRQn_Type)source);

    // Clear any pending status
    NVIC_ClearPendingIRQ((IRQn_Type)source);

    // Configure interrupt handler
    //if (handler == 0) handler = IrqHandlerNotUsed;
      //  GetExceptionTable()[NVIC_IRQ_HANDLER_INDEX + source] = handler;

    if (subPriority >= (0x01 << nSub))
      subPriority = (0x01 << nSub) - 1;
    if (preemptionPriority >= (0x01 << nPre))
      preemptionPriority = (0x01 << nPre) - 1;

    IRQpriority = (subPriority | (preemptionPriority << nSub));
    NVIC_SetPriority((IRQn_Type)source, IRQpriority);
}

//------------------------------------------------------------------------------
/// Enables interrupt coming from the given (unique) source (AT91C_ID_xxx).
/// \param source  Interrupt source to enable.
//------------------------------------------------------------------------------
void IRQ_EnableIT(unsigned int source)
{
    NVIC_EnableIRQ((IRQn_Type)source);
}

//------------------------------------------------------------------------------
/// Disables interrupt coming from the given (unique) source (AT91C_ID_xxx).
/// \param source  Interrupt source to disable.
//------------------------------------------------------------------------------
void IRQ_DisableIT(unsigned int source)
{
    NVIC_DisableIRQ((IRQn_Type)source);
}

//------------------------------------------------------------------------------
/// Set interrupt pending bit from the given (unique) source (AT91C_ID_xxx).
/// \param source  Interrupt source to set.
//------------------------------------------------------------------------------
void NVIC_SetPending(unsigned int source)
{
    NVIC_SetPendingIRQ((IRQn_Type)source);
}

//------------------------------------------------------------------------------
/// Clear interrupt pending bit from the given (unique) source (AT91C_ID_xxx).
/// \param source  Interrupt source to clear.
//------------------------------------------------------------------------------
void NVIC_ClrPending(unsigned int source)
{
    NVIC_ClearPendingIRQ((IRQn_Type)source);
}

#if !defined(USE_CMSIS_on)
//------------------------------------------------------------------------------
/// Use the Software Trigger Interrupt Register to pend an interrupt.
/// \param source Interrupt source to trigger.
//------------------------------------------------------------------------------
void NVIC_Swi(unsigned int source)
{
    AT91C_BASE_NVIC->NVIC_STIR = source;
}
#endif

personal git repositories of Harald Welte. Your mileage may vary