libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
nvic.c
Go to the documentation of this file.
1/*
2 * This file is part of the libopencm3 project.
3 *
4 * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
5 * Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
6 * Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
7 *
8 * This library is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library. If not, see <http://www.gnu.org/licenses/>.
20 */
21/** @defgroup CM3_nvic_file NVIC
22 *
23 * @ingroup CM3_files
24 *
25 * @brief <b>libopencm3 Cortex Nested Vectored Interrupt Controller</b>
26 *
27 * @version 1.0.0
28 *
29 * @author @htmlonly &copy; @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
30 * @author @htmlonly &copy; @endhtmlonly 2012 Fergus Noble
31 * <fergusnoble@gmail.com>
32 *
33 * @date 18 August 2012
34 *
35 * Cortex processors provide 14 cortex-defined interrupts (NMI, usage faults,
36 * systicks etc.) and varying numbers of implementation defined interrupts
37 * (typically peripherial interrupts and DMA).
38 *
39 * @see Cortex-M3 Devices Generic User Guide
40 * @see STM32F10xxx Cortex-M3 programming manual
41 *
42 * LGPL License Terms @ref lgpl_license
43*/
44/**@{*/
45
46#include <libopencm3/cm3/nvic.h>
47#include <libopencm3/cm3/scb.h>
48
49/*---------------------------------------------------------------------------*/
50/** @brief NVIC Enable Interrupt
51 *
52 * Enables a user interrupt.
53 *
54 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
55 */
56
57void nvic_enable_irq(uint8_t irqn)
58{
59 NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
60}
61
62/*---------------------------------------------------------------------------*/
63/** @brief NVIC Disable Interrupt
64 *
65 * Disables a user interrupt.
66 *
67 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
68 */
69
70void nvic_disable_irq(uint8_t irqn)
71{
72 NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
73}
74
75/*---------------------------------------------------------------------------*/
76/** @brief NVIC Return Pending Interrupt
77 *
78 * True if the interrupt has occurred and is waiting for service.
79 *
80 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
81 * @return Boolean. Interrupt pending.
82 */
83
84uint8_t nvic_get_pending_irq(uint8_t irqn)
85{
86 return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
87}
88
89/*---------------------------------------------------------------------------*/
90/** @brief NVIC Set Pending Interrupt
91 *
92 * Force a user interrupt to a pending state. This has no effect if the
93 * interrupt is already pending.
94 *
95 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
96 */
97
98void nvic_set_pending_irq(uint8_t irqn)
99{
100 NVIC_ISPR(irqn / 32) = (1 << (irqn % 32));
101}
102
103/*---------------------------------------------------------------------------*/
104/** @brief NVIC Clear Pending Interrupt
105 *
106 * Force remove a user interrupt from a pending state. This has no effect if
107 * the interrupt is actively being serviced.
108 *
109 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
110 */
111
112void nvic_clear_pending_irq(uint8_t irqn)
113{
114 NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
115}
116
117
118
119/*---------------------------------------------------------------------------*/
120/** @brief NVIC Return Enabled Interrupt
121 *
122 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
123 * @return Boolean. Interrupt enabled.
124 */
125
126uint8_t nvic_get_irq_enabled(uint8_t irqn)
127{
128 return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
129}
130
131#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
132/** @brief NVIC Set Interrupt Priority
133 *
134 * There are 16 priority levels only, given by the upper four bits of the
135 * priority byte, as required by ARM standards. The priority levels are
136 * interpreted according to the pre-emptive priority grouping set in the
137 * SCB Application Interrupt and Reset Control Register (SCB_AIRCR), as done
138 * in @ref scb_set_priority_grouping,
139 * @param[in] irqn Interrupt number @ref CM3_nvic_defines_irqs
140 * @param[in] priority Interrupt priority (0 ... 255 in steps of 16)
141 */
142#else
143/** NVIC Set Interrupt Priority.
144 *
145 * There are 4 priority levels only, given by the upper two bits of the
146 * priority byte, as required by ARM standards. No grouping available.
147 *
148 * @param[in] irqn Interrupt number @ref CM3_nvic_defines_irqs
149 * @param[in] priority Interrupt priority (0 ... 255 in steps of 16)
150 */
151#endif
152void nvic_set_priority(uint8_t irqn, uint8_t priority)
153{
154 /* code from lpc43xx/nvic.c -- this is quite a hack and alludes to the
155 * negative interrupt numbers assigned to the system interrupts. better
156 * handling would mean signed integers. */
157 if (irqn >= NVIC_IRQ_COUNT) {
158 /* Cortex-M system interrupts */
159#if defined(__ARM_ARCH_6M__)
160 /* ARM6M supports only 32bit word access to SHPR registers */
161 irqn = (irqn & 0xF) - 4;
162 uint8_t shift = (irqn & 0x3) << 3;
163 uint8_t reg = irqn >> 2;
164 SCB_SHPR32(reg) = ((SCB_SHPR32(reg) & ~(0xFFUL << shift)) |
165 ((uint32_t) priority) << shift);
166#else
167 SCB_SHPR((irqn & 0xF) - 4) = priority;
168#endif
169 } else {
170 /* Device specific interrupts */
171#if defined(__ARM_ARCH_6M__)
172 /* ARM6M supports only 32bit word access to IPR registers */
173 uint8_t shift = (irqn & 0x3) << 3;
174 uint8_t reg = irqn >> 2;
175 NVIC_IPR32(reg) = ((NVIC_IPR32(reg) & ~(0xFFUL << shift)) |
176 ((uint32_t) priority) << shift);
177#else
178 NVIC_IPR(irqn) = priority;
179#endif
180 }
181}
182
183/* Those are defined only on CM3 or CM4 */
184#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
185/*---------------------------------------------------------------------------*/
186/** @brief NVIC Return Active Interrupt
187 *
188 * Interrupt has occurred and is currently being serviced.
189 *
190 * @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
191 * @return Boolean. Interrupt active.
192 */
193
194uint8_t nvic_get_active_irq(uint8_t irqn)
195{
196 return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
197}
198
199/*---------------------------------------------------------------------------*/
200/** @brief NVIC Software Trigger Interrupt
201 *
202 * Generate an interrupt from software. This has no effect for unprivileged
203 * access unless the privilege level has been elevated through the System
204 * Control Registers.
205 *
206 * @param[in] irqn Unsigned int16. Interrupt number (0 ... 239)
207 */
208
210{
211 if (irqn <= 239) {
212 NVIC_STIR |= irqn;
213 }
214}
215#endif
216/**@}*/
#define NVIC_IRQ_COUNT
uint8_t nvic_get_pending_irq(uint8_t irqn)
NVIC Return Pending Interrupt.
Definition: nvic.c:84
void nvic_generate_software_interrupt(uint16_t irqn)
NVIC Software Trigger Interrupt.
Definition: nvic.c:209
void nvic_set_pending_irq(uint8_t irqn)
NVIC Set Pending Interrupt.
Definition: nvic.c:98
void nvic_set_priority(uint8_t irqn, uint8_t priority)
NVIC Set Interrupt Priority.
Definition: nvic.c:152
void nvic_clear_pending_irq(uint8_t irqn)
NVIC Clear Pending Interrupt.
Definition: nvic.c:112
uint8_t nvic_get_irq_enabled(uint8_t irqn)
NVIC Return Enabled Interrupt.
Definition: nvic.c:126
uint8_t nvic_get_active_irq(uint8_t irqn)
NVIC Return Active Interrupt.
Definition: nvic.c:194
void nvic_enable_irq(uint8_t irqn)
NVIC Enable Interrupt.
Definition: nvic.c:57
void nvic_disable_irq(uint8_t irqn)
NVIC Disable Interrupt.
Definition: nvic.c:70
#define SCB_SHPR(ipr_id)
System Handler Priority 8 bits Registers, SHPR1/2/3.
Definition: scb.h:68
#define NVIC_ICER(icer_id)
ICER: Interrupt Clear Enable Registers.
Definition: cm3/nvic.h:60
#define NVIC_ISER(iser_id)
ISER: Interrupt Set Enable Registers.
Definition: cm3/nvic.h:51
#define NVIC_ISPR(ispr_id)
ISPR: Interrupt Set Pending Registers.
Definition: cm3/nvic.h:69
#define NVIC_STIR
STIR: Software Trigger Interrupt Register.
Definition: cm3/nvic.h:107
#define NVIC_IABR(iabr_id)
IABR: Interrupt Active Bit Register.
Definition: cm3/nvic.h:87
#define NVIC_ICPR(icpr_id)
ICPR: Interrupt Clear Pending Registers.
Definition: cm3/nvic.h:78
#define NVIC_IPR(ipr_id)
IPR: Interrupt Priority Registers.
Definition: cm3/nvic.h:101