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