mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
150:02e0a0aed4ec
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 149:156823d33999 1 /**
<> 149:156823d33999 2 ******************************************************************************
<> 149:156823d33999 3 * @file gpio_irq_api.c
<> 149:156823d33999 4 * @brief Implementation of a GPIO irq handlers
<> 149:156823d33999 5 * @internal
<> 149:156823d33999 6 * @author ON Semiconductor
<> 149:156823d33999 7 * $Rev:
<> 149:156823d33999 8 * $Date: 2015-11-04 $
<> 149:156823d33999 9 ******************************************************************************
<> 149:156823d33999 10 * Copyright 2016 Semiconductor Components Industries LLC (d/b/a “ON Semiconductor”).
<> 149:156823d33999 11 * All rights reserved. This software and/or documentation is licensed by ON Semiconductor
<> 149:156823d33999 12 * under limited terms and conditions. The terms and conditions pertaining to the software
<> 149:156823d33999 13 * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf
<> 149:156823d33999 14 * (“ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software”) and
<> 149:156823d33999 15 * if applicable the software license agreement. Do not use this software and/or
<> 149:156823d33999 16 * documentation unless you have carefully read and you agree to the limited terms and
<> 149:156823d33999 17 * conditions. By using this software and/or documentation, you agree to the limited
<> 149:156823d33999 18 * terms and conditions.
<> 149:156823d33999 19 *
<> 149:156823d33999 20 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
<> 149:156823d33999 21 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
<> 149:156823d33999 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
<> 149:156823d33999 23 * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,
<> 149:156823d33999 24 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
<> 149:156823d33999 25 * @endinternal
<> 149:156823d33999 26 *
<> 149:156823d33999 27 * @ingroup gpio
<> 149:156823d33999 28 *
<> 149:156823d33999 29 * @details
<> 149:156823d33999 30 *
<> 149:156823d33999 31 * @internal
<> 149:156823d33999 32 * <h1> Reference document(s) </h1>
<> 149:156823d33999 33 * <p>
<> 149:156823d33999 34 * Reference document: IPC7203 APB GPIO Design Specification v1.2</a>
<> 149:156823d33999 35 * </p>
<> 149:156823d33999 36 * @endinternal
<> 149:156823d33999 37 *
<> 149:156823d33999 38 * <h1> Functional description (internal) </h1>
<> 149:156823d33999 39 * <p>
<> 149:156823d33999 40 * Each GPIO line can be independently programmed as an input or an output. Separate Set
<> 149:156823d33999 41 * and Clear registers are provided since it is likely that different software tasks may be
<> 149:156823d33999 42 * servicing different I/O signals. Inputs are synchronized to the system clock
<> 149:156823d33999 43 * through a pair of flip-flops. Each input can be programmed
<> 149:156823d33999 44 * to cause an interrupt to be generated. The interrupt can be programmed to be level-sensitive
<> 149:156823d33999 45 * or edge-sensitive and the level (high or low) or edge (rising, falling or either) that causes
<> 149:156823d33999 46 * the interrupt can be selected. Interrupts can be individually enabled or disabled.
<> 149:156823d33999 47 * Level-sensitive interrupts stay asserted until the interrupting condition is cleared.
<> 149:156823d33999 48 * Edge-triggered interrupts are cleared by writing to the GPIO interrupt clear register.
<> 149:156823d33999 49 * </p>
<> 149:156823d33999 50 *
<> 149:156823d33999 51 * <h1> Use of GPIO driver in SW </h1>
<> 149:156823d33999 52 * <p>
<> 149:156823d33999 53 * The user of the GPIO driver should set the pin as GPIO, using crossbar.
<> 149:156823d33999 54 * Init the GPIO and configure the mode and direction.This will return a device pointer. One device controls all GPIO's. It is not
<> 149:156823d33999 55 * needed nor supported to create a device per GPIO.
<> 149:156823d33999 56 * Next, the user should call the fGpioOpen function with the device and options as paramter.
<> 149:156823d33999 57 * </p>
<> 149:156823d33999 58 * <p>
<> 149:156823d33999 59 * Use the device driver fGpioIoctl function to change the behavior of the GPIO's and to register an
<> 149:156823d33999 60 * interrupt handler for each IO that has an interrupt enabled. There is one interrupt for all GPIO's.
<> 149:156823d33999 61 * The GPIO driver will look up what IO caused the interrupt and call the respective interrupt handler.
<> 149:156823d33999 62 * </p>
<> 149:156823d33999 63 */
<> 149:156823d33999 64
<> 149:156823d33999 65
<> 149:156823d33999 66
<> 149:156823d33999 67 #include "gpio.h"
<> 149:156823d33999 68
<> 149:156823d33999 69 /* Include files from the mbed-hal layer */
<> 149:156823d33999 70 #include "gpio_irq_api.h"
<> 149:156823d33999 71
<> 149:156823d33999 72 #include "device.h"
<> 149:156823d33999 73
<> 149:156823d33999 74 #if DEVICE_INTERRUPTIN
<> 149:156823d33999 75
<> 149:156823d33999 76 /* Handler for the GPIO pin */
<> 149:156823d33999 77 static gpio_irq_handler irq_handler;
<> 149:156823d33999 78 static uint32_t gpioIds[NUMBER_OF_GPIO] = {0};
<> 149:156823d33999 79
<> 149:156823d33999 80 /** Main GPIO IRQ handler called from vector table handler
<> 149:156823d33999 81 *
<> 150:02e0a0aed4ec 82 * @param gpioBase The GPIO register base address
<> 150:02e0a0aed4ec 83 * @return void
<> 149:156823d33999 84 */
<> 149:156823d33999 85 void fGpioHandler(void)
<> 149:156823d33999 86 {
<> 149:156823d33999 87 uint8_t index;
<> 149:156823d33999 88 uint32_t active_interrupts = 0;
<> 150:02e0a0aed4ec 89 gpio_irq_event event = IRQ_NONE;
<> 149:156823d33999 90 GpioReg_pt gpioBase;
<> 149:156823d33999 91
<> 150:02e0a0aed4ec 92 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 93 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 94
<> 149:156823d33999 95 gpioBase = GPIOREG;
<> 149:156823d33999 96
<> 149:156823d33999 97 /** - Store all active interrupts */
<> 149:156823d33999 98 active_interrupts = gpioBase->R_IRQ_W_CLEAR;
<> 149:156823d33999 99
<> 149:156823d33999 100 for (index=0; index < NUMBER_OF_GPIO; index++) {
<> 149:156823d33999 101
<> 149:156823d33999 102 /* Check the pin for which IRQ is raised */
<> 149:156823d33999 103 if ((active_interrupts >> index) & 0x01) {
<> 149:156823d33999 104 /* Check if it is edge triggered and clear the interrupt */
<> 149:156823d33999 105 if ((gpioBase->IRQ_EDGE >> index) & 0x01) {
<> 149:156823d33999 106 if ((gpioBase->IRQ_POLARITY_SET >> index) &0x01) {
<> 149:156823d33999 107 /* Edge triggered high */
<> 149:156823d33999 108 event = IRQ_RISE;
<> 150:02e0a0aed4ec 109 } else {
<> 149:156823d33999 110 /* Edge triggered low */
<> 149:156823d33999 111 event = IRQ_FALL;
<> 149:156823d33999 112 }
<> 149:156823d33999 113 }
<> 150:02e0a0aed4ec 114 gpioBase->IRQ_CLEAR = (0x1 << index);
<> 149:156823d33999 115
<> 149:156823d33999 116 /* Call the handler registered to the pin */
<> 149:156823d33999 117 irq_handler(gpioIds[index], event);
<> 149:156823d33999 118 }
<> 149:156823d33999 119
<> 149:156823d33999 120 }
<> 149:156823d33999 121 }
<> 149:156823d33999 122
<> 149:156823d33999 123 /** Initialize the GPIO IRQ pin
<> 149:156823d33999 124 *
<> 149:156823d33999 125 * @param obj The GPIO object to initialize
<> 149:156823d33999 126 * @param pin The GPIO pin name
<> 149:156823d33999 127 * @param handler The handler to be attached to GPIO IRQ
<> 149:156823d33999 128 * @param id The object ID
<> 149:156823d33999 129 * @return -1 if pin is NC, 0 otherwise
<> 149:156823d33999 130 */
<> 149:156823d33999 131 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
<> 149:156823d33999 132 {
<> 149:156823d33999 133 /* If Pin is not connected; then return -1 */
<> 149:156823d33999 134 if (pin == NC) {
<> 149:156823d33999 135 return(-1);
<> 149:156823d33999 136 }
<> 149:156823d33999 137
<> 149:156823d33999 138 /* Store the pin for which handler is registered */
<> 149:156823d33999 139 obj->pin = pin;
<> 149:156823d33999 140 obj->pinMask = (0x1 << pin);
<> 149:156823d33999 141
<> 149:156823d33999 142 /* Store the ID, this is required by registered handler function */
<> 149:156823d33999 143 gpioIds[pin] = id;
<> 149:156823d33999 144
<> 150:02e0a0aed4ec 145 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 146 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 147
<> 149:156823d33999 148 /* Initialize the GPIO membase */
<> 149:156823d33999 149 obj->GPIOMEMBASE = GPIOREG;
<> 149:156823d33999 150
<> 149:156823d33999 151 /* Set default values for the pin interrupt */
<> 149:156823d33999 152 obj->GPIOMEMBASE->W_IN = obj->pinMask;
<> 149:156823d33999 153 obj->GPIOMEMBASE->IRQ_EDGE = obj->pinMask;
<> 150:02e0a0aed4ec 154 obj->GPIOMEMBASE->IRQ_POLARITY_SET = obj->pinMask;
<> 149:156823d33999 155
<> 149:156823d33999 156 /* Register the handler for this pin */
<> 149:156823d33999 157 irq_handler = handler;
<> 149:156823d33999 158
<> 149:156823d33999 159 /* Enable interruption associated with the gpio */
<> 149:156823d33999 160 NVIC_ClearPendingIRQ(Gpio_IRQn);
<> 149:156823d33999 161 NVIC_EnableIRQ(Gpio_IRQn);
<> 149:156823d33999 162
<> 149:156823d33999 163 return(0);
<> 149:156823d33999 164 }
<> 149:156823d33999 165
<> 149:156823d33999 166 /** Release the GPIO IRQ PIN
<> 149:156823d33999 167 *
<> 149:156823d33999 168 * @param obj The gpio object
<> 149:156823d33999 169 */
<> 149:156823d33999 170 void gpio_irq_free(gpio_irq_t *obj)
<> 149:156823d33999 171 {
<> 150:02e0a0aed4ec 172 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 173 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 174
<> 150:02e0a0aed4ec 175 /* Disable IRQs to indicate that it is now free */
<> 150:02e0a0aed4ec 176 obj->GPIOMEMBASE->IRQ_ENABLE_CLEAR = obj->pinMask;
<> 149:156823d33999 177 gpioIds[obj->pin] = 0;
<> 149:156823d33999 178 }
<> 149:156823d33999 179
<> 149:156823d33999 180 /** Enable/disable pin IRQ event
<> 149:156823d33999 181 *
<> 149:156823d33999 182 * @param obj The GPIO object
<> 149:156823d33999 183 * @param event The GPIO IRQ event
<> 149:156823d33999 184 * @param enable The enable flag
<> 149:156823d33999 185 */
<> 149:156823d33999 186 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
<> 149:156823d33999 187 {
<> 150:02e0a0aed4ec 188 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 189 CLOCK_ENABLE(CLOCK_GPIO);
<> 150:02e0a0aed4ec 190 obj->GPIOMEMBASE->IRQ_EDGE = obj->pinMask;
<> 150:02e0a0aed4ec 191
<> 149:156823d33999 192 switch(event) {
<> 150:02e0a0aed4ec 193 case IRQ_RISE:
<> 150:02e0a0aed4ec 194
<> 150:02e0a0aed4ec 195 /* Enable rising edge */
<> 150:02e0a0aed4ec 196 obj->GPIOMEMBASE->IRQ_POLARITY_SET = obj->pinMask;
<> 150:02e0a0aed4ec 197 break;
<> 149:156823d33999 198
<> 149:156823d33999 199 case IRQ_FALL:
<> 150:02e0a0aed4ec 200
<> 150:02e0a0aed4ec 201 /* Enable falling edge */
<> 150:02e0a0aed4ec 202 obj->GPIOMEMBASE->IRQ_POLARITY_CLEAR = obj->pinMask;
<> 149:156823d33999 203 break;
<> 149:156823d33999 204
<> 149:156823d33999 205 default:
<> 149:156823d33999 206 /* No event is set */
<> 149:156823d33999 207 break;
<> 149:156823d33999 208 }
<> 150:02e0a0aed4ec 209 /* Enable the IRQ based on enable parameter */
<> 150:02e0a0aed4ec 210 if (enable) {
<> 149:156823d33999 211
<> 150:02e0a0aed4ec 212 obj->GPIOMEMBASE->IRQ_ENABLE_SET = obj->pinMask;
<> 150:02e0a0aed4ec 213 } else {
<> 150:02e0a0aed4ec 214
<> 150:02e0a0aed4ec 215 obj->GPIOMEMBASE->IRQ_ENABLE_CLEAR = obj->pinMask;
<> 150:02e0a0aed4ec 216 }
<> 149:156823d33999 217 }
<> 149:156823d33999 218
<> 149:156823d33999 219 /** Enable GPIO IRQ
<> 149:156823d33999 220 *
<> 149:156823d33999 221 * This is target dependent, as it might enable the entire port or just a pin
<> 149:156823d33999 222 * @param obj The GPIO object
<> 149:156823d33999 223 */
<> 149:156823d33999 224 void gpio_irq_enable(gpio_irq_t *obj)
<> 149:156823d33999 225 {
<> 150:02e0a0aed4ec 226 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 227 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 228
<> 150:02e0a0aed4ec 229 obj->GPIOMEMBASE->IRQ_ENABLE_SET = obj->pinMask;
<> 149:156823d33999 230 }
<> 149:156823d33999 231
<> 149:156823d33999 232 /** Disable GPIO IRQ
<> 149:156823d33999 233 *
<> 149:156823d33999 234 * This is target dependent, as it might disable the entire port or just a pin
<> 149:156823d33999 235 * @param obj The GPIO object
<> 149:156823d33999 236 */
<> 149:156823d33999 237 void gpio_irq_disable(gpio_irq_t *obj)
<> 149:156823d33999 238 {
<> 150:02e0a0aed4ec 239
<> 150:02e0a0aed4ec 240 /* Enable the GPIO clock which may have been switched off by other drivers */
<> 149:156823d33999 241 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 242
<> 150:02e0a0aed4ec 243 obj->GPIOMEMBASE->IRQ_ENABLE_CLEAR = obj->pinMask;
<> 149:156823d33999 244 }
<> 149:156823d33999 245
<> 149:156823d33999 246 #endif //DEVICE_INTERRUPTIN