diff --git a/cpu/saml21/include/periph_cpu.h b/cpu/saml21/include/periph_cpu.h index 1067842fe68976556f0fa28daa9049b777d6a7b4..3da96d183eaea6af94c85d18a7e9b5bf494aaa74 100644 --- a/cpu/saml21/include/periph_cpu.h +++ b/cpu/saml21/include/periph_cpu.h @@ -33,6 +33,31 @@ enum { PB = 1, /**< port B */ }; +/** + * @brief Generate GPIO mode bitfields + * + * We use 3 bit to determine the pin functions: + * - bit 0: PU or PU + * - bit 1: input enable + * - bit 2: pull enable + */ +#define GPIO_MODE(pr, ie, pe) (pr | (ie << 1) | (pe << 2)) + +/** + * @brief Override GPIO modes + * @{ + */ +#define HAVE_GPIO_MODE_T +typedef enum { + GPIO_IN = GPIO_MODE(0, 1, 0), /**< IN */ + GPIO_IN_PD = GPIO_MODE(0, 1, 1), /**< IN with pull-down */ + GPIO_IN_PU = GPIO_MODE(1, 1, 1), /**< IN with pull-up */ + GPIO_OUT = GPIO_MODE(0, 0, 0), /**< OUT (push-pull) */ + GPIO_OD = 0xfe, /**< not supported by HW */ + GPIO_OD_PU = 0xff /**< not supported by HW */ +} gpio_mode_t; +/** @} */ + #ifdef __cplusplus } #endif diff --git a/cpu/saml21/periph/gpio.c b/cpu/saml21/periph/gpio.c index 74f6bce3e698149635f4eb8de71961f460d4c571..29d10bf826993d1dc4dad94236f8c0dc0b555594 100644 --- a/cpu/saml21/periph/gpio.c +++ b/cpu/saml21/periph/gpio.c @@ -41,6 +41,11 @@ */ #define NUMOF_IRQS (16U) +/** + * @brief Mask to get PINCFG reg value from mode value + */ +#define MODE_PINCFG_MASK (0x06) + /** * @brief Mapping of pins to EXTI lines, -1 means not EXTI possible */ @@ -89,42 +94,38 @@ void gpio_init_mux(gpio_t pin, gpio_mux_t mux) port->PMUX[pin_pos >> 1].reg |= (mux << (4 * (pin_pos & 0x1))); } -int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pushpull) +int gpio_init(gpio_t pin, gpio_mode_t mode) { PortGroup* port = _port(pin); int pin_pos = _pin_pos(pin); int pin_mask = _pin_mask(pin); - /* configure the pin's pull resistor and reset all other configuration */ - switch (pushpull) { - case GPIO_PULLDOWN: - port->OUTCLR.reg = pin_mask; - port->PINCFG[pin_pos].reg = PORT_PINCFG_PULLEN; - break; - case GPIO_PULLUP: - port->OUTSET.reg = pin_mask; - port->PINCFG[pin_pos].reg = PORT_PINCFG_PULLEN; - break; - case GPIO_NOPULL: - port->PINCFG[pin_pos].reg = 0; - break; + /* make sure pin mode is applicable */ + if (mode > 0x7) { + return -1; } - /* set pin_pos direction */ - if (dir == GPIO_DIR_OUT) { - if (pushpull == GPIO_PULLDOWN) { - return -1; - } - port->DIRSET.reg = pin_mask; /* configure as output */ - port->OUTCLR.reg = pin_mask; /* set pin LOW on init */ + + /* set pin direction */ + if (mode & 0x2) { + port->DIRCLR.reg = pin_mask; } else { - port->DIRCLR.reg = pin_mask; /* configure as input */ - port->PINCFG[pin_pos].reg |= PORT_PINCFG_INEN; + port->DIRSET.reg = pin_mask; } + + /* configure the pin cfg and clear output register */ + port->PINCFG[pin_pos].reg = (mode & MODE_PINCFG_MASK); + port->OUTCLR.reg = pin_mask; + + /* and set pull-up/pull-down if applicable */ + if (mode == 0x7) { + port->OUTSET.reg = pin_mask; + } + return 0; } -int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank, +int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { int exti = _exti(pin); @@ -138,7 +139,7 @@ int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank, gpio_config[exti].cb = cb; gpio_config[exti].arg = arg; /* configure pin as input and set MUX to peripheral function A */ - gpio_init(pin, GPIO_DIR_IN, pullup); + gpio_init(pin, mode); gpio_init_mux(pin, GPIO_MUX_A); /* enable clocks for the EIC module */ MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; diff --git a/cpu/saml21/periph/spi.c b/cpu/saml21/periph/spi.c index 38c12cebcb1df4911f049241ff4898c326237d3f..617024308a0ad9b0eca4396734782904e65cde4f 100644 --- a/cpu/saml21/periph/spi.c +++ b/cpu/saml21/periph/spi.c @@ -134,10 +134,10 @@ int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) while (!(GCLK->PCHCTRL[spi[dev].gclk_id].reg & GCLK_PCHCTRL_CHEN)) {} /* SCLK+MOSI = output */ - gpio_init(spi[dev].sclk.pin, GPIO_DIR_OUT, GPIO_NOPULL); - gpio_init(spi[dev].mosi.pin, GPIO_DIR_OUT, GPIO_NOPULL); + gpio_init(spi[dev].sclk.pin, GPIO_OUT); + gpio_init(spi[dev].mosi.pin, GPIO_OUT); /* MISO = input */ - gpio_init(spi[dev].miso.pin, GPIO_DIR_IN, GPIO_PULLUP); + gpio_init(spi[dev].miso.pin, GPIO_IN); /* * Set alternate funcion (PMUX) for our ports.