1 /* mbed Microcontroller Library
2 *******************************************************************************
3 * Copyright (c) 2014, STMicroelectronics
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *******************************************************************************
33 #include "gpio_irq_api.h"
35 #include "mbed_error.h"
42 #define CHANNEL_NUM (7)
44 static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0};
45 static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0};
46 static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0};
48 static gpio_irq_handler irq_handler;
50 static void handle_interrupt_in(uint32_t irq_index) {
51 // Retrieve the gpio and pin that generate the irq
52 GPIO_TypeDef *gpio = (GPIO_TypeDef *)(channel_gpio[irq_index]);
53 uint32_t pin = (uint32_t)(1 << channel_pin[irq_index]);
55 // Clear interrupt flag
56 if (EXTI_GetITStatus(channel_pin[irq_index]) != RESET) {
57 EXTI_ClearITPendingBit(channel_pin[irq_index]);
60 if (channel_ids[irq_index] == 0) return;
62 // Check which edge has generated the irq
63 if ((gpio->IDR & pin) == 0) {
64 irq_handler(channel_ids[irq_index], IRQ_FALL);
66 irq_handler(channel_ids[irq_index], IRQ_RISE);
70 static void gpio_irq0(void) {
71 handle_interrupt_in(0); // EXTI line 0
74 static void gpio_irq1(void) {
75 handle_interrupt_in(1); // EXTI line 1
78 static void gpio_irq2(void) {
79 handle_interrupt_in(2); // EXTI line 2
82 static void gpio_irq3(void) {
83 handle_interrupt_in(3); // EXTI line 3
86 static void gpio_irq4(void) {
87 handle_interrupt_in(4); // EXTI line 4
90 static void gpio_irq5(void) {
91 handle_interrupt_in(5); // EXTI lines 5 to 9
94 static void gpio_irq6(void) {
95 handle_interrupt_in(6); // EXTI lines 10 to 15
98 extern uint32_t Set_GPIO_Clock(uint32_t port_idx);
100 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
101 IRQn_Type irq_n = (IRQn_Type)0;
105 if (pin == NC) return -1;
107 uint32_t port_index = STM_PORT(pin);
108 uint32_t pin_index = STM_PIN(pin);
110 // Select irq number and interrupt routine
114 vector = (uint32_t)&gpio_irq0;
119 vector = (uint32_t)&gpio_irq1;
123 irq_n = EXTI2_TS_IRQn;
124 vector = (uint32_t)&gpio_irq2;
129 vector = (uint32_t)&gpio_irq3;
134 vector = (uint32_t)&gpio_irq4;
142 irq_n = EXTI9_5_IRQn;
143 vector = (uint32_t)&gpio_irq5;
152 irq_n = EXTI15_10_IRQn;
153 vector = (uint32_t)&gpio_irq6;
157 error("This pin is not supported with InterruptIn.");
162 uint32_t gpio_add = Set_GPIO_Clock(port_index);
164 // Enable SYSCFG clock
165 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
167 // Connect EXTI line to pin
168 SYSCFG_EXTILineConfig(port_index, pin_index);
170 // Configure EXTI line
171 EXTI_InitTypeDef EXTI_InitStructure;
172 EXTI_InitStructure.EXTI_Line = pin_index;
173 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
174 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
175 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
176 EXTI_Init(&EXTI_InitStructure);
178 // Enable and set EXTI interrupt to the lowest priority
179 NVIC_InitTypeDef NVIC_InitStructure;
180 NVIC_InitStructure.NVIC_IRQChannel = irq_n;
181 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
182 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
183 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
184 NVIC_Init(&NVIC_InitStructure);
186 NVIC_SetVector(irq_n, vector);
187 NVIC_EnableIRQ(irq_n);
189 // Save informations for future use
191 obj->irq_index = irq_index;
192 obj->event = EDGE_NONE;
193 channel_ids[irq_index] = id;
194 channel_gpio[irq_index] = gpio_add;
195 channel_pin[irq_index] = pin_index;
197 irq_handler = handler;
202 void gpio_irq_free(gpio_irq_t *obj) {
203 channel_ids[obj->irq_index] = 0;
204 channel_gpio[obj->irq_index] = 0;
205 channel_pin[obj->irq_index] = 0;
207 EXTI_InitTypeDef EXTI_InitStructure;
208 EXTI_StructInit(&EXTI_InitStructure);
209 EXTI_Init(&EXTI_InitStructure);
210 obj->event = EDGE_NONE;
213 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
214 EXTI_InitTypeDef EXTI_InitStructure;
216 EXTI_InitStructure.EXTI_Line = channel_pin[obj->irq_index];
217 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
219 if (event == IRQ_RISE) {
220 if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) {
221 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
222 obj->event = EDGE_BOTH;
223 } else { // NONE or RISE
224 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
225 obj->event = EDGE_RISE;
229 if (event == IRQ_FALL) {
230 if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) {
231 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
232 obj->event = EDGE_BOTH;
233 } else { // NONE or FALL
234 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
235 obj->event = EDGE_FALL;
240 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
242 EXTI_InitStructure.EXTI_LineCmd = DISABLE;
245 EXTI_Init(&EXTI_InitStructure);
248 void gpio_irq_enable(gpio_irq_t *obj) {
249 NVIC_EnableIRQ(obj->irq_n);
252 void gpio_irq_disable(gpio_irq_t *obj) {
253 NVIC_DisableIRQ(obj->irq_n);
254 obj->event = EDGE_NONE;