/** * @ingroup PAC55xx_gpio * @brief PAC55xxxx General-Purpose Input/Output (GPIO) * @author @htmlonly © @endhtmlonly 2019 Brian Viele * @date December 1, 2019 * * This library supports the GPIO module in the PAC55xx SoC from Qorvo. * * LGPL License Terms @ref lgpl_license */ /* * This file is part of the libopencm3 project. * * This library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see . */ #include static uint32_t get_ccs_port_base(uint32_t gpioport) { switch (gpioport) { case GPIOA: return CCS_PORTA; case GPIOB: return CCS_PORTB; case GPIOC: return CCS_PORTC; case GPIOD: return CCS_PORTD; case GPIOE: return CCS_PORTE; case GPIOF: return CCS_PORTF; case GPIOG: return CCS_PORTG; default: return 0U; } } void gpio_mode_setup(uint32_t gpioport, gpio_mode_t mode, ccs_pull_updown_t pull_up_down, uint16_t gpios) { /* Read the current value of the register. */ uint32_t reg = GPIO_MODER(gpioport); uint32_t port = get_ccs_port_base(gpioport); /* Loop through only set bits, utilize built-ins for optimized assembly. */ int ffs = __builtin_ffs(gpios); while (ffs) { const int pin = ffs - 1; const int bit = (1 << pin); /* Update the cached mode value by clearing then setting values. */ reg &= ~GPIO_MODER_MASK_PIN(pin); reg |= GPIO_MODER_MODE(pin, mode); /* Set the pinmux configurations for the pull-up / pull-down. */ if (pull_up_down == CCS_IO_PULL_UP) { CCS_PDENR(port) &= ~bit; CCS_PUENR(port) |= bit; } else if (pull_up_down == CCS_IO_PULL_DOWN) { CCS_PUENR(port) &= ~bit; CCS_PDENR(port) |= bit; } else { CCS_PDENR(port) &= ~bit; CCS_PUENR(port) &= ~bit; } gpios ^= bit; /* Clear the bit we just serviced. */ ffs = __builtin_ffs(gpios); } GPIO_MODER(gpioport) = reg; } void gpio_set_outmask(uint32_t gpioport, bool enable, uint16_t gpios) { uint32_t reg = GPIO_OUTMASKR(gpioport); if (enable) { reg |= gpios; } else { reg &= ~gpios; } GPIO_OUTMASKR(gpioport) = reg; } void gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_DOSETR(gpioport) = gpios; } void gpio_clear(uint32_t gpioport, uint16_t gpios) { GPIO_DOCLEARR(gpioport) = gpios; } uint16_t gpio_get(uint32_t gpioport, uint16_t gpios) { return GPIO_INR(gpioport) & gpios; } void gpio_set_af(uint32_t gpioport, ccs_muxsel_func_t muxsel, uint16_t gpios) { uint32_t port = get_ccs_port_base(gpioport); /* Update each of the pin configs. */ uint32_t reg = CCS_MUXSELR(port); int ffs = __builtin_ffs(gpios); while (ffs) { const int pin = ffs - 1; reg &= ~CCS_MUXSELR_MASK_PIN(pin); reg |= CCS_MUXSELR_VAL(pin, muxsel); /* Set the pinmux configurations for the pull-up / pull-down. */ gpios ^= (1 << pin); /* Clear the bit we just serviced. */ ffs = __builtin_ffs(gpios); } CCS_MUXSELR(port) = reg; } void gpio_set_output_options(uint32_t gpioport, ccs_drive_strength_t strength, uint16_t gpios) { uint32_t port = get_ccs_port_base(gpioport); /* Update each of the pin configs. */ uint32_t reg = CCS_DSR(port); int ffs = __builtin_ffs(gpios); while (ffs) { const int pin = ffs - 1; reg &= ~CCS_DSR_MASK_PIN(pin); reg |= CCS_DSR_DS_VAL(pin, strength); /* Set the pinmux configurations for the pull-up / pull-down. */ gpios ^= (1 << pin); /* Clear the bit we just serviced. */ ffs = __builtin_ffs(gpios); } CCS_DSR(port) = reg; } void gpio_set_schmidt_trigger(uint32_t gpioport, bool enable, uint16_t gpios) { uint32_t port = get_ccs_port_base(gpioport); /* Update each of the pin configs. */ uint32_t reg = CCS_DSR(port); int ffs = __builtin_ffs(gpios); while (ffs) { const int pin = ffs - 1; if (enable) { reg |= CCS_DSR_SCHMIDT_PIN(pin); } else { reg &= ~CCS_DSR_SCHMIDT_PIN(pin); } /* Set the pinmux configurations for the pull-up / pull-down. */ gpios ^= (1 << pin); /* Clear the bit we just serviced. */ ffs = __builtin_ffs(gpios); } CCS_DSR(port) = reg; }