test
Fork of mbed-dev by
Diff: targets/TARGET_ONSEMI/TARGET_NCS36510/gpio_api.c
- Revision:
- 149:156823d33999
- Parent:
- 147:30b64687e01f
- Child:
- 150:02e0a0aed4ec
--- /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; +}