Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_ONSEMI/TARGET_NCS36510/gpio_irq_api.c@178:d650f5d4c87a, 2017-11-08 (annotated)
- Committer:
- AnnaBridge
- Date:
- Wed Nov 08 13:50:44 2017 +0000
- Revision:
- 178:d650f5d4c87a
- Parent:
- 150:02e0a0aed4ec
This updates the lib to the mbed lib v 155
Who changed what in which revision?
User | Revision | Line number | New 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 |