/* * Copyright (C) 2015 Marc Poulhiès * * This file is subject to the terms and conditions of the GNU Lesser General * Public License v2.1. See the file LICENSE in the top level directory for more * details. */ /** * @ingroup cpu_lm4f120 * @{ * * @file * @brief Low-level GPIO driver implementation * * @author Marc Poulhiès * * @} */ #include #include "cpu.h" #include "cpu_conf.h" #include "periph/gpio.h" #include "periph_conf.h" #define ENABLE_DEBUG (0) #include "debug.h" /** * @brief Mask out the pin type from the gpio_mode_t value */ #define TYPE(mode) (mode >> 4) /** * @brief Mask out the pin mode from the gpio_mode_t value */ #define MODE(mode) (mode & 0x0f) /** * @brief Extract the pin number of the given pin */ static inline uint8_t _pin_num(gpio_t pin) { return (pin & 0x0f); } /** * @brief Extract the port number of the given pin */ static inline uint8_t _port_num(gpio_t pin) { return (pin >> 4); } static const uint32_t _sysctl_port_base[] = { SYSCTL_PERIPH_GPIOA, SYSCTL_PERIPH_GPIOB, SYSCTL_PERIPH_GPIOC, SYSCTL_PERIPH_GPIOD, SYSCTL_PERIPH_GPIOE, SYSCTL_PERIPH_GPIOF, }; static const uint32_t _port_base[] = { GPIO_PORTA_BASE, GPIO_PORTB_BASE, GPIO_PORTC_BASE, GPIO_PORTD_BASE, GPIO_PORTE_BASE, GPIO_PORTF_BASE, }; static const uint32_t _int_assign[] = { INT_GPIOA, INT_GPIOB, INT_GPIOC, INT_GPIOD, INT_GPIOE, INT_GPIOF, }; #define NUM_OF_PORT 6 #define NUM_OF_PINS 8 typedef struct { gpio_cb_t cb; /**< callback called from GPIO interrupt */ void *arg; /**< argument passed to the callback */ } gpio_state_t; static gpio_state_t gpio_config[NUM_OF_PORT][NUM_OF_PINS]; int gpio_init(gpio_t pin, gpio_mode_t mode) { const uint8_t port_num = _port_num(pin); const uint32_t port_addr = _port_base[port_num]; const uint8_t pin_num = _pin_num(pin); const uint32_t sysctl_port_base = _sysctl_port_base[port_num]; const unsigned long pin_bit = 1 << pin_num; DEBUG("Init GPIO: port %c, %d\n", 'A' + port_num, pin_num); DEBUG("Sysctl %" PRIx32 "\n", sysctl_port_base); ROM_SysCtlPeripheralEnable(sysctl_port_base); HWREG(port_addr+GPIO_LOCK_R_OFF) = GPIO_LOCK_KEY; HWREG(port_addr+GPIO_CR_R_OFF) |= pin_bit; HWREG(port_addr+GPIO_DEN_R_OFF) |= pin_bit; HWREG(port_addr+GPIO_LOCK_R_OFF) = 0; ROM_GPIOPadConfigSet(port_addr, pin_bit, GPIO_STRENGTH_2MA, TYPE(mode)); ROM_GPIODirModeSet(port_addr, pin_bit, MODE(mode)); return 0; } static void _isr_gpio(uint32_t port_num){ const uint32_t port_addr = _port_base[port_num]; uint32_t isr = ROM_GPIOPinIntStatus(port_addr, true); uint8_t i; ROM_GPIOPinIntClear(port_addr, isr); for (i=0; i<8; i++, isr>>=1) { if ((isr & 0x1) == 0){ continue; } if (gpio_config[port_num][i].cb){ gpio_config[port_num][i].cb(gpio_config[port_num][i].arg); } } } void isr_gpio_porta(void){ _isr_gpio(0); } void isr_gpio_portb(void){ _isr_gpio(1); } void isr_gpio_portc(void){ _isr_gpio(2); } void isr_gpio_portd(void){ _isr_gpio(3); } void isr_gpio_porte(void){ _isr_gpio(4); } void isr_gpio_portf(void){ _isr_gpio(5); } int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { const uint8_t port_num = _port_num(pin); const uint32_t port_addr = _port_base[port_num]; const uint32_t icr_reg_addr = port_addr + GPIO_ICR_R_OFF; const uint8_t pin_num = _pin_num(pin); const uint8_t pin_bit = 1<