diff --git a/cpu/saml21/include/periph_cpu.h b/cpu/saml21/include/periph_cpu.h new file mode 100644 index 0000000000..309a699359 --- /dev/null +++ b/cpu/saml21/include/periph_cpu.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * 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_saml21 + * @{ + * + * @file + * @brief CPU specific definitions for internal peripheral handling + * + * @author Hauke Petersen + */ + +#ifndef PERIPH_CPU_H_ +#define PERIPH_CPU_H_ + +#include "cpu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Define mandatory GPIO types for NRF51822 CPUs + * @{ + */ +#define HAVE_GPIO_T +typedef uint32_t gpio_t; +/** @} */ + +/** + * @brief Mandatory function for defining a GPIO pins + * @{ + */ +#define GPIO(x, y) (((gpio_t)(&PORT->Group[x])) | y) + +/** + * @brief Available ports on the SAML21 for convenient access + */ +enum { + PA = 0, /**< port A */ + PB = 1, /**< port B */ +}; + +/** + * @brief Override active flank configuration values + * @{ + */ +#define HAVE_GPIO_FLANK_T +typedef enum { + GPIO_FALLING = 2, /**< emit interrupt on falling flank */ + GPIO_RISING = 1, /**< emit interrupt on rising flank */ + GPIO_BOTH = 3 /**< emit interrupt on both flanks */ +} gpio_flank_t; +/** @} */ + +/** + * @brief Available MUX values for configuring a pin's alternate function + */ +typedef enum { + GPIO_MUX_A = 0x0, /**< select peripheral function A */ + GPIO_MUX_B = 0x1, /**< select peripheral function B */ + GPIO_MUX_C = 0x2, /**< select peripheral function C */ + GPIO_MUX_D = 0x3, /**< select peripheral function D */ + GPIO_MUX_E = 0x4, /**< select peripheral function E */ + GPIO_MUX_F = 0x5, /**< select peripheral function F */ + GPIO_MUX_G = 0x6, /**< select peripheral function G */ + GPIO_MUX_H = 0x7, /**< select peripheral function H */ +} gpio_mux_t; + +/** + * @brief Set up alternate function (PMUX setting) for a PORT pin + * + * @param[in] dev Pin to set the multiplexing for + * @param[in] mux Mux value + */ +void gpio_init_mux(gpio_t dev, gpio_mux_t mux); + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CPU_H_ */ +/** @} */ diff --git a/cpu/saml21/include/saml21_periph.h b/cpu/saml21/include/saml21_periph.h index 6a4593a2d7..fae207f99b 100644 --- a/cpu/saml21/include/saml21_periph.h +++ b/cpu/saml21/include/saml21_periph.h @@ -27,52 +27,6 @@ extern "C" { #include "cpu_conf.h" #include "panic.h" -/** - * @brief gpio dev to gpio id mapping table (used internally by implementation) - */ -extern const uint8_t gpio_table[]; - -/** - * @brief return PORT ptr for GPIO pin - * - * @param[in] dev GPIO dev to get PORT for - * - * @returns pointer to PORT instance - */ -static inline PortGroup* _port(gpio_t dev) -{ - /* Config validity check. See saml21 periph_conf.h. - * This gets optimized out if the configuration is correct. - * I put it here so it crashes the board on first GPIO use. */ - if (GPIO_NUMOF != GPIO_UNUSED) { - core_panic(0, "unmatched GPIO_NUMOF and GPIO_UNUSED. Fix periph_conf.\n"); - } - return &PORT->Group[gpio_table[dev]/32]; -} - -/** - * @brief return pin nr for gpio dev - * - * E.g., PA02 -> 2, PC19 -> 19 - * - * @param[in] dev GPIO dev to get pin nr from - * @returns pin nr of GPIO dev - */ -static inline uint32_t _pin(gpio_t dev) -{ - return gpio_table[dev] % 32; -} - -/** - * @brief Set up alternate function (PMUX setting) for a PORT pin - * - * @param[in] dev The Port ID to work on (port*32 + pin) - * @param[in] mux required PMUX setting (Mapping A = 0, B=1, ...) - * - * @returns 0 on success, <0 on error - */ -int gpio_init_mux(gpio_t dev, uint32_t mux); - #ifdef __cplusplus } #endif diff --git a/cpu/saml21/periph/gpio.c b/cpu/saml21/periph/gpio.c index 3fad5262f6..1d5130c74b 100644 --- a/cpu/saml21/periph/gpio.c +++ b/cpu/saml21/periph/gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Freie Universität Berlin + * Copyright (C) 2014-2015 Freie Universität Berlin * 2015 Kaspar Schleiser * 2015 FreshTemp, LLC. * @@ -18,6 +18,7 @@ * @author Troels Hoffmeyer * @author Thomas Eichinger * @author Kaspar Schleiser + * @author Hauke Petersen * * @} */ @@ -32,366 +33,196 @@ #include "thread.h" #include "panic.h" -#define ENABLE_DEBUG (1) +#define ENABLE_DEBUG (0) #include "debug.h" -/* guard file in case no GPIO devices are defined */ -#if GPIO_NUMOF +/** + * @brief Number of external interrupt lines + */ +#define NUMOF_IRQS (16U) + +/** + * @brief Mapping of pins to EXTI lines, -1 means not EXTI possible + */ +static const int8_t exti_config[2][32] = { + { 0, 1, 2, 3, 4, 5, 6, 7, -1, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, -1, 15, -1, -1, 10, 11}, + {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, -1, -1, -1, -1, 6, 7, -1, -1, -1, -1, -1, -1, 14, 15}, +}; typedef struct { gpio_cb_t cb; /**< callback called from GPIO interrupt */ void *arg; /**< argument passed to the callback */ } gpio_state_t; -/** - * Shitloads of macros just to make sure we don't have to allocate - * more than the actually enabled amount of exti states. - * The result is an array with the amount of enabled EXIT lines times gpio_state_t, - * and an array mapping any EXTI nr to either a unique slot or -1. - * - * Example: only GPIO_EXTI3_EN and GPIO_EXTI7_EN are set. - * GPIO_EXTI_TOTAL will be "2" - * gpio_config will be 2*sizeof(gpio_state_t) - * gpio_exti_map will have the following content: - * - * { -1, -1, -1, 0, -1, -1, -1, 1, -1 , ...} - * - * This maps EXTI3 to gpio_config[0], EXTI7 to gpio_config[1]. - * - * */ -#define GPIO_EXTI0_POS 0 -#define GPIO_EXTI1_POS GPIO_EXTI0_EN -#define GPIO_EXTI2_POS (GPIO_EXTI1_POS + GPIO_EXTI1_EN) -#define GPIO_EXTI3_POS (GPIO_EXTI2_POS + GPIO_EXTI2_EN) -#define GPIO_EXTI4_POS (GPIO_EXTI3_POS + GPIO_EXTI3_EN) -#define GPIO_EXTI5_POS (GPIO_EXTI4_POS + GPIO_EXTI4_EN) -#define GPIO_EXTI6_POS (GPIO_EXTI5_POS + GPIO_EXTI5_EN) -#define GPIO_EXTI7_POS (GPIO_EXTI6_POS + GPIO_EXTI6_EN) -#define GPIO_EXTI8_POS (GPIO_EXTI7_POS + GPIO_EXTI7_EN) -#define GPIO_EXTI9_POS (GPIO_EXTI8_POS + GPIO_EXTI8_EN) -#define GPIO_EXTI10_POS (GPIO_EXTI9_POS + GPIO_EXTI9_EN) -#define GPIO_EXTI11_POS (GPIO_EXTI10_POS + GPIO_EXTI10_EN) -#define GPIO_EXTI12_POS (GPIO_EXTI11_POS + GPIO_EXTI11_EN) -#define GPIO_EXTI13_POS (GPIO_EXTI12_POS + GPIO_EXTI12_EN) -#define GPIO_EXTI14_POS (GPIO_EXTI13_POS + GPIO_EXTI13_EN) -#define GPIO_EXTI15_POS (GPIO_EXTI14_POS + GPIO_EXTI14_EN) +static gpio_state_t gpio_config[NUMOF_IRQS]; -const static int8_t gpio_exti_map[] = { - GPIO_EXTI0_EN ? GPIO_EXTI0_POS : -1, - GPIO_EXTI1_EN ? GPIO_EXTI1_POS : -1, - GPIO_EXTI2_EN ? GPIO_EXTI2_POS : -1, - GPIO_EXTI3_EN ? GPIO_EXTI3_POS : -1, - GPIO_EXTI4_EN ? GPIO_EXTI4_POS : -1, - GPIO_EXTI5_EN ? GPIO_EXTI5_POS : -1, - GPIO_EXTI6_EN ? GPIO_EXTI6_POS : -1, - GPIO_EXTI7_EN ? GPIO_EXTI7_POS : -1, - GPIO_EXTI8_EN ? GPIO_EXTI8_POS : -1, - GPIO_EXTI9_EN ? GPIO_EXTI9_POS : -1, - GPIO_EXTI10_EN ? GPIO_EXTI10_POS : -1, - GPIO_EXTI11_EN ? GPIO_EXTI11_POS : -1, - GPIO_EXTI12_EN ? GPIO_EXTI12_POS : -1, - GPIO_EXTI13_EN ? GPIO_EXTI13_POS : -1, - GPIO_EXTI14_EN ? GPIO_EXTI14_POS : -1, - GPIO_EXTI15_EN ? GPIO_EXTI15_POS : -1, -}; -#define GPIO_EXTI_TOTAL (\ - GPIO_EXTI0_EN + \ - GPIO_EXTI1_EN + \ - GPIO_EXTI2_EN + \ - GPIO_EXTI3_EN + \ - GPIO_EXTI4_EN + \ - GPIO_EXTI5_EN + \ - GPIO_EXTI6_EN + \ - GPIO_EXTI7_EN + \ - GPIO_EXTI8_EN + \ - GPIO_EXTI9_EN + \ - GPIO_EXTI10_EN + \ - GPIO_EXTI11_EN + \ - GPIO_EXTI12_EN + \ - GPIO_EXTI13_EN + \ - GPIO_EXTI14_EN + \ - GPIO_EXTI15_EN) - -static gpio_state_t gpio_config[GPIO_EXTI_TOTAL]; - -/** - * @brief Convenience enum - */ -enum { - PA, - PB, - PC, - PD, - PE, - PF -}; - -/** - * @brief Map from 0..GPIO_NUMOF-1 to actual GPIO pins - * - * This map/macro combo is used to map natural integers - * starting by 0 upto GPIO_NUMOF-1 to the actual GPIO pin. - * - * GPIO pins are mapped into an implicit flat number space, e.g., - * Port C Pin 14 is mapped to (2*32 + 14) - * - * Pxn is supposed to be part of an enum set in "periph_conf.h". - * - * Example: - * - * enum { - * PA2, - * PB10, - * GPIO_UNUSED, - * PB5, - * PA3, - * }; - * - * All pins > GPIO_UNUSED are mapped to the same spot so - * they don't waste memory. - */ -#define DEFINE_GPIO_PIN(port, pin) [(port ## pin) > GPIO_UNUSED ? GPIO_UNUSED : (port ## pin)] = (port*32 + pin) -const uint8_t gpio_table[] = { - DEFINE_GPIO_PIN(PA, 2), - DEFINE_GPIO_PIN(PA, 4), - DEFINE_GPIO_PIN(PA, 5), - DEFINE_GPIO_PIN(PA, 6), - DEFINE_GPIO_PIN(PA, 7), - DEFINE_GPIO_PIN(PA, 3), - DEFINE_GPIO_PIN(PA, 12), - DEFINE_GPIO_PIN(PA, 13), - DEFINE_GPIO_PIN(PB, 4), - DEFINE_GPIO_PIN(PB, 5), - DEFINE_GPIO_PIN(PB, 6), - DEFINE_GPIO_PIN(PB, 7), - DEFINE_GPIO_PIN(PB, 9), - DEFINE_GPIO_PIN(PB, 10), -}; - -int gpio_init_mux(gpio_t dev, uint32_t mux) +static inline PortGroup *_port(gpio_t pin) { - if (dev >= GPIO_NUMOF) { - return -1; - } - - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - - /* WRCONFIG supports only half of the pin-space, selected by HWSEL - * (half-word selection). - * So here we either just use the lower half, or shift it by a - * half-word and set the half-word select (HWSEL) flag. - * */ - uint32_t hwmode = (pin < 16) ? (1 << pin) : (((1 << pin) >> 16) | PORT_WRCONFIG_HWSEL); - - port->WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG - | PORT_WRCONFIG_WRPMUX - | PORT_WRCONFIG_PMUX(mux) - | PORT_WRCONFIG_PMUXEN - /*| (mux ? PORT_WRCONFIG_PMUXEN : 0)*/ - | hwmode; - - return 0; + return (PortGroup *)(pin & ~(0x1f)); } -int gpio_init_out(gpio_t dev, gpio_pp_t pushpull) + +static inline int _pin_pos(gpio_t pin) { - if (dev >= GPIO_NUMOF) { + return (pin & 0x1f); +} + +static inline int _pin_mask(gpio_t pin) +{ + return (1 << _pin_pos(pin)); +} + +static int _exti(gpio_t pin) +{ + int port_num = ((pin >> 7) & 0x03); + + if (port_num > 1) { return -1; } + return exti_config[port_num][_pin_pos(pin)]; +} - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); +void gpio_init_mux(gpio_t pin, gpio_mux_t mux) +{ + PortGroup* port = _port(pin); + int pin_pos = _pin_pos(pin); - /* configure as output */ - port->DIRSET.reg = 1 << pin; + port->PINCFG[pin_pos].reg |= PORT_PINCFG_PMUXEN; + port->PMUX[pin_pos >> 1].reg &= ~(0xf << (4 * (pin_pos & 0x1))); + port->PMUX[pin_pos >> 1].reg |= (mux << (4 * (pin_pos & 0x1))); +} - /* configure the pin's pull resistor state */ +int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pushpull) +{ + 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; + } + /* set pin_pos direction */ + if (dir == GPIO_DIR_OUT) { + if (pushpull == GPIO_PULLDOWN) { return -1; - case GPIO_PULLUP: - port->PINCFG[pin].bit.PULLEN = true; - break; - case GPIO_NOPULL: - port->PINCFG[pin].bit.PULLEN = false; - break; + } + port->DIRSET.reg = pin_mask; /* configure as output */ + port->OUTCLR.reg = pin_mask; /* set pin LOW on init */ + } + else { + port->DIRCLR.reg = pin_mask; /* configure as input */ + port->PINCFG[pin_pos].reg |= PORT_PINCFG_INEN; } - return 0; } -int gpio_init_in(gpio_t dev, gpio_pp_t pushpull) +int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank, + gpio_cb_t cb, void *arg) { - if (dev >= GPIO_NUMOF) { + int exti = _exti(pin); + + /* make sure EIC channel is valid */ + if (exti == -1) { return -1; } - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - - /* configure as input */ - port->DIRCLR.reg = 1 << pin; - /* buffer input value */ - port->PINCFG[pin].bit.INEN = true; - - /* configure the pin's pull resistor state */ - switch (pushpull) { - case GPIO_PULLDOWN: - port->OUTCLR.reg = 1 << pin; - port->PINCFG[pin].bit.PULLEN = true; - break; - case GPIO_PULLUP: - port->OUTSET.reg = 1 << pin; - port->PINCFG[pin].bit.PULLEN = true; - break; - case GPIO_NOPULL: - port->PINCFG[pin].bit.PULLEN = false; - break; - } - - return 0; -} - -int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb, void *arg) -{ - if (dev >= GPIO_NUMOF) { - return -1; - } - - uint32_t pin = _pin(dev); - uint32_t extint = pin % 16; - - int exti_pos = gpio_exti_map[extint]; - if (exti_pos == -1) { - /* EXTI line not enabled. */ - return -1; - } - - int res = 0; - - /* set pin mux */ - gpio_init_mux(dev, 0); - - /* configure pin as input */ - res = gpio_init_in(dev, pullup); - if (res < 0) { - return res; - } - - /* Turn on APB clock */ - MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; - - /* setup GCLK for EIC */ - GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; - - /* Setup interrupt */ - NVIC_SetPriority(EIC_IRQn, 10); - NVIC_EnableIRQ(EIC_IRQn); - /* save callback */ - gpio_config[exti_pos].cb = cb; - gpio_config[exti_pos].arg = arg; - - /* must disable EIC before configuring. */ - EIC->CTRLA.bit.ENABLE = false; - + gpio_config[exti].cb = cb; + gpio_config[exti].arg = arg; + /* configure ping as input and set MUX to peripheral function A */ + gpio_init(pin, GPIO_DIR_IN, pullup); + gpio_init_mux(pin, GPIO_MUX_A); + /* enable clocks for the EIC module */ + MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC; + GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0; + /* configure the active flank */ + EIC->CONFIG[exti >> 3].reg &= ~(0xf << ((exti & 0x7) * 4)); + EIC->CONFIG[exti >> 3].reg |= (flank << ((exti & 0x7) * 4)); + /* enable the global EIC interrupt */ + NVIC_EnableIRQ(EIC_IRQn); /*Enable pin interrupt */ - EIC->INTFLAG.reg |= (1 << extint); - EIC->INTENSET.reg = 1 << extint; - - /*Set config */ - uint8_t config_pos = (4 * (extint % 8)); - uint8_t config_reg = extint / 8; - /*Set flank detection */ - switch (flank) { - case GPIO_FALLING: - EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_FALL_Val << config_pos); - break; - case GPIO_RISING: - EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_RISE_Val << config_pos); - break; - case GPIO_BOTH: - EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_BOTH_Val << config_pos); - break; - } - - /*Enable external interrupts*/ - EIC->CTRLA.bit.ENABLE = true; + EIC->INTFLAG.reg = (1 << exti); + EIC->INTENSET.reg = (1 << exti); + /* enable the EIC module*/ + EIC->CTRLA.reg = EIC_CTRLA_ENABLE; + while (EIC->SYNCBUSY.reg & EIC_SYNCBUSY_ENABLE); return 0; } -void gpio_irq_enable(gpio_t dev) +void gpio_irq_enable(gpio_t pin) { - uint32_t extint = _pin(dev) % 16; - EIC->INTENSET.reg = 1 << extint; -} - -void gpio_irq_disable(gpio_t dev) -{ - uint32_t extint = _pin(dev) % 16; - EIC->INTENCLR.reg = 1 << extint; -} - -int gpio_read(gpio_t dev) -{ - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - int res = -1; - - res = port->IN.reg & (1 << pin); - - /* make sure we are not returning a negative value if bit 31 is set */ - if (res < -1) { - res = 1; + int exti = _exti(pin); + if (exti == -1) { + return; } - - return res; + EIC->INTENSET.reg = (1 << exti); } -void gpio_set(gpio_t dev) +void gpio_irq_disable(gpio_t pin) { - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - - port->OUTSET.reg = 1 << pin; + int exti = _exti(pin); + if (exti == -1) { + return; + } + EIC->INTENCLR.reg = (1 << exti); } -void gpio_clear(gpio_t dev) +int gpio_read(gpio_t pin) { - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - port->OUTCLR.reg = 1 << pin; + PortGroup *port = _port(pin); + int mask = _pin_mask(pin); + + if (port->DIR.reg & mask) { + return (port->OUT.reg & mask) ? 1 : 0; + } + else { + return (port->IN.reg & mask) ? 1 : 0; + } } -void gpio_toggle(gpio_t dev) +void gpio_set(gpio_t pin) { - PortGroup* port = _port(dev); - uint32_t pin = _pin(dev); - port->OUTTGL.reg = 1 << pin; + _port(pin)->OUTSET.reg = _pin_mask(pin); } -void gpio_write(gpio_t dev, int value) +void gpio_clear(gpio_t pin) +{ + _port(pin)->OUTCLR.reg = _pin_mask(pin); +} + +void gpio_toggle(gpio_t pin) +{ + _port(pin)->OUTTGL.reg = _pin_mask(pin); +} + +void gpio_write(gpio_t pin, int value) { if (value) { - gpio_set(dev); + _port(pin)->OUTSET.reg = _pin_mask(pin); } else { - gpio_clear(dev); + _port(pin)->OUTCLR.reg = _pin_mask(pin); } } void isr_eic(void) { - uint16_t status = EIC->INTFLAG.reg; - for (int i = 0; i < 16; i++) { - if (status & (0x1<INTFLAG.reg = 0x1 << i; - break; + for (int i = 0; i < NUMOF_IRQS; i++) { + if (EIC->INTFLAG.reg & (1 << i)) { + EIC->INTFLAG.reg = (1 << i); + gpio_config[i].cb(gpio_config[i].arg); } } @@ -399,5 +230,3 @@ void isr_eic(void) thread_yield(); } } - -#endif /* GPIO_NUMOF */ diff --git a/cpu/saml21/periph/spi.c b/cpu/saml21/periph/spi.c index 8cb5f4d590..846a818ac0 100644 --- a/cpu/saml21/periph/spi.c +++ b/cpu/saml21/periph/spi.c @@ -72,7 +72,7 @@ typedef struct spi_saml21 { static const spi_saml21_t spi[] = { #if SPI_0_EN /* SPI device */ /* MCLK flag */ /* GLCK id */ /* SCLK */ /* MISO */ /* MOSI */ /* dipo+dopo */ - { &(SERCOM0->SPI), MCLK_APBCMASK_SERCOM0, SERCOM0_GCLK_ID_CORE, { PA7, 3 }, { PA4, 3 }, { PA6, 3 }, 0, 1 } + { &(SERCOM0->SPI), MCLK_APBCMASK_SERCOM0, SERCOM0_GCLK_ID_CORE, { GPIO(PA,7), 3 }, { GPIO(PA,4), 3 }, { GPIO(PA,6), 3 }, 0, 1 } #endif }; @@ -133,21 +133,19 @@ 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); + /* MISO = input */ + gpio_init(spi[dev].miso.pin, GPIO_DIR_IN, GPIO_PULLUP); + /* * Set alternate funcion (PMUX) for our ports. - * This has to be done before gpio_init_[in|out]. */ gpio_init_mux(spi[dev].sclk.pin, spi[dev].sclk.pmux); gpio_init_mux(spi[dev].miso.pin, spi[dev].miso.pmux); gpio_init_mux(spi[dev].mosi.pin, spi[dev].mosi.pmux); - /* SCLK+MOSI = output */ - gpio_init_out(spi[dev].sclk.pin, GPIO_NOPULL); - gpio_init_out(spi[dev].mosi.pin, GPIO_NOPULL); - - /* MISO = input */ - gpio_init_in(spi[dev].miso.pin, GPIO_PULLUP); - /* pin pad mapping */ dipo = spi[dev].dipo; dopo = spi[dev].dopo;