ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Committer:
group-onsemi
Date:
Wed Jan 25 20:34:15 2017 +0000
Revision:
0:098463de4c5d
Initial commit

Who changed what in which revision?

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