mbed

Fork of mbed-dev by mbed official

Revision:
149:156823d33999
Parent:
147:30b64687e01f
Child:
150:02e0a0aed4ec
diff -r 21d94c44109e -r 156823d33999 targets/TARGET_ONSEMI/TARGET_NCS36510/gpio_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/TARGET_ONSEMI/TARGET_NCS36510/gpio_api.c	Fri Oct 28 11:17:30 2016 +0100
@@ -0,0 +1,197 @@
+/**
+ ******************************************************************************
+ * @file gpio_api.c
+ * @brief Implementation of a GPIO driver
+ * @internal
+ * @author ON Semiconductor
+ * $Rev:
+ * $Date: 2015-11-04 $
+ ******************************************************************************
+ * Copyright 2016 Semiconductor Components Industries LLC (d/b/a “ON Semiconductor”).
+ * All rights reserved.  This software and/or documentation is licensed by ON Semiconductor
+ * under limited terms and conditions.  The terms and conditions pertaining to the software
+ * and/or documentation are available at http://www.onsemi.com/site/pdf/ONSEMI_T&C.pdf
+ * (“ON Semiconductor Standard Terms and Conditions of Sale, Section 8 Software”) and
+ * if applicable the software license agreement.  Do not use this software and/or
+ * documentation unless you have carefully read and you agree to the limited terms and
+ * conditions.  By using this software and/or documentation, you agree to the limited
+ * terms and conditions.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
+ * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
+ * ON SEMICONDUCTOR SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
+ * @endinternal
+ *
+ * @ingroup gpio
+ *
+ * @details
+ *
+ * @internal
+ * <h1> Reference document(s) </h1>
+ * <p>
+ * Reference document: IPC7203 APB GPIO Design Specification v1.2</a>
+ * </p>
+ * @endinternal
+ *
+ * <h1> Functional description (internal) </h1>
+ * <p>
+ * Each GPIO line can be independently programmed as an input or an output. Separate Set
+ * and Clear registers are provided since it is likely that different software tasks may be
+ * servicing different I/O signals. Inputs are synchronized to the system clock
+ * through a pair of flip-flops.  Each input can be programmed
+ * to cause an interrupt to be generated.  The interrupt can be programmed to be level-sensitive
+ * or edge-sensitive and the level (high or low) or edge (rising, falling or either) that causes
+ * the interrupt can be selected.  Interrupts can be individually enabled or disabled.
+ * Level-sensitive interrupts stay asserted until the interrupting condition is cleared.
+ * Edge-triggered interrupts are cleared by writing to the GPIO interrupt clear register.
+ * </p>
+ *
+ * <h1> Use of GPIO driver in SW </h1>
+ * <p>
+ * The user of the GPIO driver should set the pin as GPIO, using crossbar.
+ * Init the GPIO and configure the mode and direction.This will return a device pointer.  One device controls all GPIO's.  It is not
+ * needed nor supported to create a device per GPIO.
+ * Next, the user should call the fGpioOpen function with the device and options as paramter.
+ * </p>
+ * <p>
+ * Use the device driver fGpioIoctl function to change the behavior of the GPIO's and to register an
+ * interrupt handler for each IO that has an interrupt enabled.  There is one interrupt for all GPIO's.
+ * The GPIO driver will look up what IO caused the interrupt and call the respective interrupt handler.
+ * </p>
+ */
+
+#include "gpio.h"
+
+/* Include from the mbed-hal layer */
+#include "gpio_api.h"
+#include "pinmap.h"
+
+
+/** Set the given pin as GPIO
+ *
+ * @param pin The pin to be set as GPIO
+ * @return The GPIO port mask for this pin
+ **/
+uint32_t gpio_set(PinName pin)
+{
+    if (pin != NC) {
+        /* Configure to GPIO using pin function API*/
+        pin_function(pin, CONFIGURE_AS_GPIO);
+
+        return ((uint32_t) 0x1 << pin);
+
+    }
+
+    return(0x00000000);
+
+}
+
+/** Initialize the GPIO pin
+ *
+ * @param obj The GPIO object to initialize
+ * @param pin The GPIO pin to initialize
+ */
+void gpio_init(gpio_t *obj, PinName pin)
+{
+    /* Initialize the GPIO membase */
+    obj->GPIOMEMBASE = GPIOREG;
+
+    /* Initialize the pin to be GPIO */
+    obj->gpioPin = pin;
+    obj->gpioMask = gpio_set(pin);
+
+    /* Enable the GPIO clock */
+    CLOCK_ENABLE(CLOCK_GPIO);
+
+    /* Set the drive strength of the pin to 1 by default */
+    /** - Get PAD IO register address for the PAD number */
+    PadReg_t *PadRegOffset = (PadReg_t*)(PADREG_BASE + (pin * PAD_REG_ADRS_BYTE_SIZE));
+
+    /* - Disable the GPIO clock */
+    CLOCK_DISABLE(CLOCK_GPIO);
+
+    /** - Enable the clock for PAD peripheral device */
+    CLOCK_ENABLE(CLOCK_PAD);
+
+    /** - Set drive type, pulltype & drive strength */
+    PadRegOffset->PADIO0.BITS.POWER = 1;
+
+    /** - Disable the clock for PAD peripheral device */
+    CLOCK_DISABLE(CLOCK_PAD);
+}
+
+/** Set the input pin mode
+ *
+ * @param obj  The GPIO object
+ * @param mode The pin mode to be set
+ */
+void gpio_mode(gpio_t *obj, PinMode mode)
+{
+    uint32_t pin = obj->gpioPin;
+
+    /* Set the mode for the pin */
+    pin_mode((PinName)pin, mode);
+}
+
+/** Set the pin direction
+ *
+ * @param obj       The GPIO object
+ * @param direction The pin direction to be set
+ */
+void gpio_dir(gpio_t *obj, PinDirection direction)
+{
+    /* Enable the GPIO clock */
+    CLOCK_ENABLE(CLOCK_GPIO);
+
+    if (direction == PIN_INPUT) {
+        obj->GPIOMEMBASE->W_IN = obj->gpioMask;
+    } else if (direction == PIN_OUTPUT) {
+        obj->GPIOMEMBASE->W_OUT = obj->gpioMask;
+    }
+
+    /* - Disable the GPIO clock */
+    CLOCK_DISABLE(CLOCK_GPIO);
+}
+
+/** Set the output value
+ *
+ * @param obj   The GPIO object
+ * @param value The value to be set
+ */
+void gpio_write(gpio_t *obj, int value)
+{
+    /* Enable the GPIO clock */
+    CLOCK_ENABLE(CLOCK_GPIO);
+
+    /* Set the GPIO based on value */
+    if (value) {
+        obj->GPIOMEMBASE->R_STATE_W_SET = obj->gpioMask;
+    } else {
+        obj->GPIOMEMBASE->R_IRQ_W_CLEAR = obj->gpioMask;
+    }
+
+    /* - Disable the GPIO clock */
+    CLOCK_DISABLE(CLOCK_GPIO);
+}
+
+/** Read the input value
+ *
+ * @param obj The GPIO object
+ * @return An integer value 1 or 0
+ */
+int gpio_read(gpio_t *obj)
+{
+    int ret;
+
+    /* Enable the GPIO clock */
+    CLOCK_ENABLE(CLOCK_GPIO);
+
+    ret = (obj->GPIOMEMBASE->R_STATE_W_SET & obj->gpioMask) ? 1: 0;
+
+    /* - Disable the GPIO clock */
+    CLOCK_DISABLE(CLOCK_GPIO);
+
+    return ret;
+}