mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /**
elessair 0:f269e3021894 2 ******************************************************************************
elessair 0:f269e3021894 3 * @file gpio_api.c
elessair 0:f269e3021894 4 * @brief Implementation of a GPIO driver
elessair 0:f269e3021894 5 * @internal
elessair 0:f269e3021894 6 * @author ON Semiconductor
elessair 0:f269e3021894 7 * $Rev:
elessair 0:f269e3021894 8 * $Date: 2015-11-04 $
elessair 0:f269e3021894 9 ******************************************************************************
elessair 0:f269e3021894 10 * Copyright 2016 Semiconductor Components Industries LLC (d/b/a “ON Semiconductor”).
elessair 0:f269e3021894 11 * All rights reserved. This software and/or documentation is licensed by ON Semiconductor
elessair 0:f269e3021894 12 * under limited terms and conditions. The terms and conditions pertaining to the software
elessair 0:f269e3021894 13 * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf
elessair 0:f269e3021894 14 * (“ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software”) and
elessair 0:f269e3021894 15 * if applicable the software license agreement. Do not use this software and/or
elessair 0:f269e3021894 16 * documentation unless you have carefully read and you agree to the limited terms and
elessair 0:f269e3021894 17 * conditions. By using this software and/or documentation, you agree to the limited
elessair 0:f269e3021894 18 * terms and conditions.
elessair 0:f269e3021894 19 *
elessair 0:f269e3021894 20 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
elessair 0:f269e3021894 21 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
elessair 0:f269e3021894 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
elessair 0:f269e3021894 23 * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,
elessair 0:f269e3021894 24 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
elessair 0:f269e3021894 25 * @endinternal
elessair 0:f269e3021894 26 *
elessair 0:f269e3021894 27 * @ingroup gpio
elessair 0:f269e3021894 28 *
elessair 0:f269e3021894 29 * @details
elessair 0:f269e3021894 30 *
elessair 0:f269e3021894 31 * @internal
elessair 0:f269e3021894 32 * <h1> Reference document(s) </h1>
elessair 0:f269e3021894 33 * <p>
elessair 0:f269e3021894 34 * Reference document: IPC7203 APB GPIO Design Specification v1.2</a>
elessair 0:f269e3021894 35 * </p>
elessair 0:f269e3021894 36 * @endinternal
elessair 0:f269e3021894 37 *
elessair 0:f269e3021894 38 * <h1> Functional description (internal) </h1>
elessair 0:f269e3021894 39 * <p>
elessair 0:f269e3021894 40 * Each GPIO line can be independently programmed as an input or an output. Separate Set
elessair 0:f269e3021894 41 * and Clear registers are provided since it is likely that different software tasks may be
elessair 0:f269e3021894 42 * servicing different I/O signals. Inputs are synchronized to the system clock
elessair 0:f269e3021894 43 * through a pair of flip-flops. Each input can be programmed
elessair 0:f269e3021894 44 * to cause an interrupt to be generated. The interrupt can be programmed to be level-sensitive
elessair 0:f269e3021894 45 * or edge-sensitive and the level (high or low) or edge (rising, falling or either) that causes
elessair 0:f269e3021894 46 * the interrupt can be selected. Interrupts can be individually enabled or disabled.
elessair 0:f269e3021894 47 * Level-sensitive interrupts stay asserted until the interrupting condition is cleared.
elessair 0:f269e3021894 48 * Edge-triggered interrupts are cleared by writing to the GPIO interrupt clear register.
elessair 0:f269e3021894 49 * </p>
elessair 0:f269e3021894 50 *
elessair 0:f269e3021894 51 * <h1> Use of GPIO driver in SW </h1>
elessair 0:f269e3021894 52 * <p>
elessair 0:f269e3021894 53 * The user of the GPIO driver should set the pin as GPIO, using crossbar.
elessair 0:f269e3021894 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
elessair 0:f269e3021894 55 * needed nor supported to create a device per GPIO.
elessair 0:f269e3021894 56 * Next, the user should call the fGpioOpen function with the device and options as paramter.
elessair 0:f269e3021894 57 * </p>
elessair 0:f269e3021894 58 * <p>
elessair 0:f269e3021894 59 * Use the device driver fGpioIoctl function to change the behavior of the GPIO's and to register an
elessair 0:f269e3021894 60 * interrupt handler for each IO that has an interrupt enabled. There is one interrupt for all GPIO's.
elessair 0:f269e3021894 61 * The GPIO driver will look up what IO caused the interrupt and call the respective interrupt handler.
elessair 0:f269e3021894 62 * </p>
elessair 0:f269e3021894 63 */
elessair 0:f269e3021894 64
elessair 0:f269e3021894 65 #include "gpio.h"
elessair 0:f269e3021894 66
elessair 0:f269e3021894 67 /* Include from the mbed-hal layer */
elessair 0:f269e3021894 68 #include "gpio_api.h"
elessair 0:f269e3021894 69 #include "pinmap.h"
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71
elessair 0:f269e3021894 72 /** Set the given pin as GPIO
elessair 0:f269e3021894 73 *
elessair 0:f269e3021894 74 * @param pin The pin to be set as GPIO
elessair 0:f269e3021894 75 * @return The GPIO port mask for this pin
elessair 0:f269e3021894 76 **/
elessair 0:f269e3021894 77 uint32_t gpio_set(PinName pin)
elessair 0:f269e3021894 78 {
elessair 0:f269e3021894 79 if (pin != NC) {
elessair 0:f269e3021894 80 /* Configure to GPIO using pin function API*/
elessair 0:f269e3021894 81 pin_function(pin, CONFIGURE_AS_GPIO);
elessair 0:f269e3021894 82
elessair 0:f269e3021894 83 return ((uint32_t) 0x1 << pin);
elessair 0:f269e3021894 84
elessair 0:f269e3021894 85 }
elessair 0:f269e3021894 86
elessair 0:f269e3021894 87 return(0x00000000);
elessair 0:f269e3021894 88
elessair 0:f269e3021894 89 }
elessair 0:f269e3021894 90
elessair 0:f269e3021894 91 /** Initialize the GPIO pin
elessair 0:f269e3021894 92 *
elessair 0:f269e3021894 93 * @param obj The GPIO object to initialize
elessair 0:f269e3021894 94 * @param pin The GPIO pin to initialize
elessair 0:f269e3021894 95 */
elessair 0:f269e3021894 96 void gpio_init(gpio_t *obj, PinName pin)
elessair 0:f269e3021894 97 {
elessair 0:f269e3021894 98 /* Initialize the GPIO membase */
elessair 0:f269e3021894 99 obj->GPIOMEMBASE = GPIOREG;
elessair 0:f269e3021894 100
elessair 0:f269e3021894 101 /* Initialize the pin to be GPIO */
elessair 0:f269e3021894 102 obj->gpioPin = pin;
elessair 0:f269e3021894 103 obj->gpioMask = gpio_set(pin);
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 /* Enable the GPIO clock */
elessair 0:f269e3021894 106 CLOCK_ENABLE(CLOCK_GPIO);
elessair 0:f269e3021894 107
elessair 0:f269e3021894 108 /* Set the drive strength of the pin to 1 by default */
elessair 0:f269e3021894 109 /** - Get PAD IO register address for the PAD number */
elessair 0:f269e3021894 110 PadReg_t *PadRegOffset = (PadReg_t*)(PADREG_BASE + (pin * PAD_REG_ADRS_BYTE_SIZE));
elessair 0:f269e3021894 111
elessair 0:f269e3021894 112 /* - Disable the GPIO clock */
elessair 0:f269e3021894 113 CLOCK_DISABLE(CLOCK_GPIO);
elessair 0:f269e3021894 114
elessair 0:f269e3021894 115 /** - Enable the clock for PAD peripheral device */
elessair 0:f269e3021894 116 CLOCK_ENABLE(CLOCK_PAD);
elessair 0:f269e3021894 117
elessair 0:f269e3021894 118 /** - Set drive type, pulltype & drive strength */
elessair 0:f269e3021894 119 PadRegOffset->PADIO0.BITS.POWER = 1;
elessair 0:f269e3021894 120
elessair 0:f269e3021894 121 /** - Disable the clock for PAD peripheral device */
elessair 0:f269e3021894 122 CLOCK_DISABLE(CLOCK_PAD);
elessair 0:f269e3021894 123 }
elessair 0:f269e3021894 124
elessair 0:f269e3021894 125 /** Set the input pin mode
elessair 0:f269e3021894 126 *
elessair 0:f269e3021894 127 * @param obj The GPIO object
elessair 0:f269e3021894 128 * @param mode The pin mode to be set
elessair 0:f269e3021894 129 */
elessair 0:f269e3021894 130 void gpio_mode(gpio_t *obj, PinMode mode)
elessair 0:f269e3021894 131 {
elessair 0:f269e3021894 132 uint32_t pin = obj->gpioPin;
elessair 0:f269e3021894 133
elessair 0:f269e3021894 134 /* Set the mode for the pin */
elessair 0:f269e3021894 135 pin_mode((PinName)pin, mode);
elessair 0:f269e3021894 136 }
elessair 0:f269e3021894 137
elessair 0:f269e3021894 138 /** Set the pin direction
elessair 0:f269e3021894 139 *
elessair 0:f269e3021894 140 * @param obj The GPIO object
elessair 0:f269e3021894 141 * @param direction The pin direction to be set
elessair 0:f269e3021894 142 */
elessair 0:f269e3021894 143 void gpio_dir(gpio_t *obj, PinDirection direction)
elessair 0:f269e3021894 144 {
elessair 0:f269e3021894 145 /* Enable the GPIO clock */
elessair 0:f269e3021894 146 CLOCK_ENABLE(CLOCK_GPIO);
elessair 0:f269e3021894 147
elessair 0:f269e3021894 148 if (direction == PIN_INPUT) {
elessair 0:f269e3021894 149 obj->GPIOMEMBASE->W_IN = obj->gpioMask;
elessair 0:f269e3021894 150 } else if (direction == PIN_OUTPUT) {
elessair 0:f269e3021894 151 obj->GPIOMEMBASE->W_OUT = obj->gpioMask;
elessair 0:f269e3021894 152 }
elessair 0:f269e3021894 153
elessair 0:f269e3021894 154 /* - Disable the GPIO clock */
elessair 0:f269e3021894 155 CLOCK_DISABLE(CLOCK_GPIO);
elessair 0:f269e3021894 156 }
elessair 0:f269e3021894 157
elessair 0:f269e3021894 158 /** Set the output value
elessair 0:f269e3021894 159 *
elessair 0:f269e3021894 160 * @param obj The GPIO object
elessair 0:f269e3021894 161 * @param value The value to be set
elessair 0:f269e3021894 162 */
elessair 0:f269e3021894 163 void gpio_write(gpio_t *obj, int value)
elessair 0:f269e3021894 164 {
elessair 0:f269e3021894 165 /* Enable the GPIO clock */
elessair 0:f269e3021894 166 CLOCK_ENABLE(CLOCK_GPIO);
elessair 0:f269e3021894 167
elessair 0:f269e3021894 168 /* Set the GPIO based on value */
elessair 0:f269e3021894 169 if (value) {
elessair 0:f269e3021894 170 obj->GPIOMEMBASE->R_STATE_W_SET = obj->gpioMask;
elessair 0:f269e3021894 171 } else {
elessair 0:f269e3021894 172 obj->GPIOMEMBASE->R_IRQ_W_CLEAR = obj->gpioMask;
elessair 0:f269e3021894 173 }
elessair 0:f269e3021894 174
elessair 0:f269e3021894 175 /* - Disable the GPIO clock */
elessair 0:f269e3021894 176 CLOCK_DISABLE(CLOCK_GPIO);
elessair 0:f269e3021894 177 }
elessair 0:f269e3021894 178
elessair 0:f269e3021894 179 /** Read the input value
elessair 0:f269e3021894 180 *
elessair 0:f269e3021894 181 * @param obj The GPIO object
elessair 0:f269e3021894 182 * @return An integer value 1 or 0
elessair 0:f269e3021894 183 */
elessair 0:f269e3021894 184 int gpio_read(gpio_t *obj)
elessair 0:f269e3021894 185 {
elessair 0:f269e3021894 186 int ret;
elessair 0:f269e3021894 187
elessair 0:f269e3021894 188 /* Enable the GPIO clock */
elessair 0:f269e3021894 189 CLOCK_ENABLE(CLOCK_GPIO);
elessair 0:f269e3021894 190
elessair 0:f269e3021894 191 ret = (obj->GPIOMEMBASE->R_STATE_W_SET & obj->gpioMask) ? 1: 0;
elessair 0:f269e3021894 192
elessair 0:f269e3021894 193 /* - Disable the GPIO clock */
elessair 0:f269e3021894 194 CLOCK_DISABLE(CLOCK_GPIO);
elessair 0:f269e3021894 195
elessair 0:f269e3021894 196 return ret;
elessair 0:f269e3021894 197 }