mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
<>
Date:
Fri Oct 28 11:17:30 2016 +0100
Revision:
149:156823d33999
Child:
150:02e0a0aed4ec
This updates the lib to the mbed lib v128

NOTE: This release includes a restructuring of the file and directory locations and thus some
include paths in your code may need updating accordingly.

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 *
<> 149:156823d33999 82 * @param gpioBase The GPIO register base address
<> 149:156823d33999 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;
<> 149:156823d33999 89 gpio_irq_event event;
<> 149:156823d33999 90 GpioReg_pt gpioBase;
<> 149:156823d33999 91
<> 149:156823d33999 92 /* Enable the GPIO clock */
<> 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;
<> 149:156823d33999 109 } else if ((gpioBase->IRQ_POLARITY_CLEAR >> index) &0x01) {
<> 149:156823d33999 110 /* Edge triggered low */
<> 149:156823d33999 111 event = IRQ_FALL;
<> 149:156823d33999 112 } else {
<> 149:156823d33999 113 /* Edge none */
<> 149:156823d33999 114 event = IRQ_NONE;
<> 149:156823d33999 115 }
<> 149:156823d33999 116 }
<> 149:156823d33999 117 gpioBase->IRQ_CLEAR |= (0x1 << index);
<> 149:156823d33999 118
<> 149:156823d33999 119 /* Call the handler registered to the pin */
<> 149:156823d33999 120 irq_handler(gpioIds[index], event);
<> 149:156823d33999 121 }
<> 149:156823d33999 122
<> 149:156823d33999 123 }
<> 149:156823d33999 124 }
<> 149:156823d33999 125
<> 149:156823d33999 126 /** Initialize the GPIO IRQ pin
<> 149:156823d33999 127 *
<> 149:156823d33999 128 * @param obj The GPIO object to initialize
<> 149:156823d33999 129 * @param pin The GPIO pin name
<> 149:156823d33999 130 * @param handler The handler to be attached to GPIO IRQ
<> 149:156823d33999 131 * @param id The object ID
<> 149:156823d33999 132 * @return -1 if pin is NC, 0 otherwise
<> 149:156823d33999 133 */
<> 149:156823d33999 134 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
<> 149:156823d33999 135 {
<> 149:156823d33999 136 /* If Pin is not connected; then return -1 */
<> 149:156823d33999 137 if (pin == NC) {
<> 149:156823d33999 138 return(-1);
<> 149:156823d33999 139 }
<> 149:156823d33999 140
<> 149:156823d33999 141 /* Store the pin for which handler is registered */
<> 149:156823d33999 142 obj->pin = pin;
<> 149:156823d33999 143 obj->pinMask = (0x1 << pin);
<> 149:156823d33999 144
<> 149:156823d33999 145 /* Store the ID, this is required by registered handler function */
<> 149:156823d33999 146 gpioIds[pin] = id;
<> 149:156823d33999 147
<> 149:156823d33999 148 /* Enable the GPIO clock */
<> 149:156823d33999 149 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 150
<> 149:156823d33999 151 /* Initialize the GPIO membase */
<> 149:156823d33999 152 obj->GPIOMEMBASE = GPIOREG;
<> 149:156823d33999 153
<> 149:156823d33999 154 /* Set default values for the pin interrupt */
<> 149:156823d33999 155 /* TODO: Only one DIO line is configured using this function; overrides other DIO line setting
<> 149:156823d33999 156 * If mbed layer wants to call this function repeatedly for setting multiple DIO lines as input
<> 149:156823d33999 157 * then change this setting to obj->GPIOMEMBASE->W_IN |= obj->pinMask. All parameter setting needs to change from = to |=
<> 149:156823d33999 158 */
<> 149:156823d33999 159 obj->GPIOMEMBASE->W_IN = obj->pinMask;
<> 149:156823d33999 160 obj->GPIOMEMBASE->IRQ_ENABLE_SET = obj->pinMask;
<> 149:156823d33999 161 obj->GPIOMEMBASE->IRQ_EDGE = obj->pinMask;
<> 149:156823d33999 162 obj->GPIOMEMBASE->IRQ_POLARITY_SET = (obj->pinMask);
<> 149:156823d33999 163 obj->GPIOMEMBASE->ANYEDGE_SET = IO_NONE;
<> 149:156823d33999 164
<> 149:156823d33999 165 /* Register the handler for this pin */
<> 149:156823d33999 166 irq_handler = handler;
<> 149:156823d33999 167
<> 149:156823d33999 168 /* Enable interruption associated with the gpio */
<> 149:156823d33999 169 NVIC_ClearPendingIRQ(Gpio_IRQn);
<> 149:156823d33999 170 NVIC_EnableIRQ(Gpio_IRQn);
<> 149:156823d33999 171
<> 149:156823d33999 172 return(0);
<> 149:156823d33999 173 }
<> 149:156823d33999 174
<> 149:156823d33999 175 /** Release the GPIO IRQ PIN
<> 149:156823d33999 176 *
<> 149:156823d33999 177 * @param obj The gpio object
<> 149:156823d33999 178 */
<> 149:156823d33999 179 void gpio_irq_free(gpio_irq_t *obj)
<> 149:156823d33999 180 {
<> 149:156823d33999 181 /* Enable the GPIO clock */
<> 149:156823d33999 182 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 183
<> 149:156823d33999 184 obj->GPIOMEMBASE->W_IN = (IO_ALL ^ (obj->pinMask));
<> 149:156823d33999 185 gpioIds[obj->pin] = 0;
<> 149:156823d33999 186 }
<> 149:156823d33999 187
<> 149:156823d33999 188 /** Enable/disable pin IRQ event
<> 149:156823d33999 189 *
<> 149:156823d33999 190 * @param obj The GPIO object
<> 149:156823d33999 191 * @param event The GPIO IRQ event
<> 149:156823d33999 192 * @param enable The enable flag
<> 149:156823d33999 193 */
<> 149:156823d33999 194 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
<> 149:156823d33999 195 {
<> 149:156823d33999 196
<> 149:156823d33999 197 /* Enable the GPIO clock */
<> 149:156823d33999 198 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 199
<> 149:156823d33999 200 switch(event) {
<> 149:156823d33999 201 case IRQ_RISE:
<> 149:156823d33999 202 obj->GPIOMEMBASE->IRQ_EDGE = (obj->pinMask);
<> 149:156823d33999 203 obj->GPIOMEMBASE->IRQ_LEVEL = (IO_ALL ^ (obj->pinMask));
<> 149:156823d33999 204 /* Enable is an integer; hence checking for 1 or 0*/
<> 149:156823d33999 205 if (enable == 1) {
<> 149:156823d33999 206 /* Enable rising edge */
<> 149:156823d33999 207 obj->GPIOMEMBASE->IRQ_POLARITY_SET = (obj->pinMask);
<> 149:156823d33999 208 } else if (enable == 0) {
<> 149:156823d33999 209 /* Disable rising edge */
<> 149:156823d33999 210 obj->GPIOMEMBASE->IRQ_POLARITY_SET = (IO_ALL ^ (obj->pinMask));
<> 149:156823d33999 211 }
<> 149:156823d33999 212 break;
<> 149:156823d33999 213
<> 149:156823d33999 214 case IRQ_FALL:
<> 149:156823d33999 215 obj->GPIOMEMBASE->IRQ_EDGE = (obj->pinMask);
<> 149:156823d33999 216 obj->GPIOMEMBASE->IRQ_LEVEL = (IO_ALL ^ (obj->pinMask));
<> 149:156823d33999 217 /* Enable is an integer; hence checking for 1 or 0*/
<> 149:156823d33999 218 if (enable == 1) {
<> 149:156823d33999 219 /* Enable falling edge */
<> 149:156823d33999 220 obj->GPIOMEMBASE->IRQ_POLARITY_CLEAR = (obj->pinMask);
<> 149:156823d33999 221 } else if (enable == 0) {
<> 149:156823d33999 222 /* Disable falling edge */
<> 149:156823d33999 223 obj->GPIOMEMBASE->IRQ_POLARITY_CLEAR = (IO_ALL ^ (obj->pinMask));
<> 149:156823d33999 224 }
<> 149:156823d33999 225 break;
<> 149:156823d33999 226
<> 149:156823d33999 227 default:
<> 149:156823d33999 228 /* No event is set */
<> 149:156823d33999 229 break;
<> 149:156823d33999 230 }
<> 149:156823d33999 231
<> 149:156823d33999 232 }
<> 149:156823d33999 233
<> 149:156823d33999 234 /** Enable GPIO IRQ
<> 149:156823d33999 235 *
<> 149:156823d33999 236 * This is target dependent, as it might enable the entire port or just a pin
<> 149:156823d33999 237 * @param obj The GPIO object
<> 149:156823d33999 238 */
<> 149:156823d33999 239 void gpio_irq_enable(gpio_irq_t *obj)
<> 149:156823d33999 240 {
<> 149:156823d33999 241 /* Enable the GPIO clock */
<> 149:156823d33999 242 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 243
<> 149:156823d33999 244 obj->GPIOMEMBASE->IRQ_ENABLE_SET = (obj->pinMask);
<> 149:156823d33999 245 }
<> 149:156823d33999 246
<> 149:156823d33999 247 /** Disable GPIO IRQ
<> 149:156823d33999 248 *
<> 149:156823d33999 249 * This is target dependent, as it might disable the entire port or just a pin
<> 149:156823d33999 250 * @param obj The GPIO object
<> 149:156823d33999 251 */
<> 149:156823d33999 252 void gpio_irq_disable(gpio_irq_t *obj)
<> 149:156823d33999 253 {
<> 149:156823d33999 254 /* Enable the GPIO clock */
<> 149:156823d33999 255 CLOCK_ENABLE(CLOCK_GPIO);
<> 149:156823d33999 256
<> 149:156823d33999 257 obj->GPIOMEMBASE->IRQ_ENABLE_CLEAR = (obj->pinMask);
<> 149:156823d33999 258 }
<> 149:156823d33999 259
<> 149:156823d33999 260 #endif //DEVICE_INTERRUPTIN