diff --git a/boards/samr21-xpro/Makefile.dep b/boards/samr21-xpro/Makefile.dep new file mode 100644 index 0000000000..ab5c150ef0 --- /dev/null +++ b/boards/samr21-xpro/Makefile.dep @@ -0,0 +1,6 @@ +ifneq (,$(filter defaulttransceiver,$(USEMODULE))) + USEMODULE += at86rf231 + ifeq (,$(filter netdev_base,$(USEMODULE))) + USEMODULE += transceiver + endif +endif diff --git a/boards/samr21-xpro/Makefile.features b/boards/samr21-xpro/Makefile.features index ff165d6fd9..32f908d777 100644 --- a/boards/samr21-xpro/Makefile.features +++ b/boards/samr21-xpro/Makefile.features @@ -1 +1 @@ -FEATURES_PROVIDED += periph_gpio cpp periph_uart periph_timer periph_i2c +FEATURES_PROVIDED += transceiver periph_gpio periph_spi cpp periph_timer periph_uart periph_i2c cpp diff --git a/boards/samr21-xpro/Makefile.include b/boards/samr21-xpro/Makefile.include index 166aa7ee8f..074dd7fb3a 100644 --- a/boards/samr21-xpro/Makefile.include +++ b/boards/samr21-xpro/Makefile.include @@ -41,4 +41,5 @@ export LINKFLAGS += -specs=nano.specs -lc -lnosys endif # export board specific includes to the global includes-listing -export INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include +export INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include/ +include $(RIOTBOARD)/$(BOARD)/Makefile.dep diff --git a/boards/samr21-xpro/include/board.h b/boards/samr21-xpro/include/board.h index df2e56704a..b124a8b120 100644 --- a/boards/samr21-xpro/include/board.h +++ b/boards/samr21-xpro/include/board.h @@ -37,6 +37,18 @@ extern "C" { */ #define HW_TIMER TIMER_0 +/** +* @name AT86RF231 config +* @{ +*/ +#define AT86RF231_SPI SPI_0 +#define AT86RF231_CS GPIO_4 +#define AT86RF231_INT GPIO_5 +#define AT86RF231_RESET GPIO_6 +#define AT86RF231_SLEEP GPIO_7 + +#define AT86RF231_SPI_SPEED SPI_SPEED_1MHZ +/** @}*/ /** * @name Define UART device and baudrate for stdio * @{ @@ -51,7 +63,7 @@ extern "C" { * @{ */ #define LED_PORT PORT->Group[0] -#define LED_PIN PORT_PA19 +#define LED_PIN (19) /** @} */ /** @@ -74,6 +86,11 @@ extern "C" { #define LED_RED_TOGGLE LED_TOGGLE /** @} */ +/** + * @brief Define the type for the radio packet length for the transceiver + */ +typedef uint8_t radio_packet_length_t; + /** * @brief Initialize board specific hardware, including clock, LEDs and std-IO */ diff --git a/boards/samr21-xpro/include/periph_conf.h b/boards/samr21-xpro/include/periph_conf.h index 0017997803..98524e1740 100644 --- a/boards/samr21-xpro/include/periph_conf.h +++ b/boards/samr21-xpro/include/periph_conf.h @@ -69,8 +69,8 @@ extern "C" { #define UART_0_ISR isr_sercom0 /* UART 0 pin configuration */ #define UART_0_PORT (PORT->Group[0]) -#define UART_0_TX_PIN PIN_PA04 -#define UART_0_RX_PIN PIN_PA05 +#define UART_0_TX_PIN (4) +#define UART_0_RX_PIN (5) #define UART_0_PINS (PORT_PA04 | PORT_PA05) #define UART_0_REF_F (8000000UL) @@ -84,6 +84,48 @@ extern "C" { #define UART_1_PINS /** @} */ + +/** + * @name SPI configuration + * @{ + */ +#define SPI_NUMOF (2) +#define SPI_0_EN 1 +#define SPI_1_EN 1 + +/* SPI0 */ +#define SPI_0_DEV SERCOM4->SPI +#define SPI_IRQ_0 SERCOM4_IRQn +#define SPI_0_DOPO (1) +#define SPI_0_DIPO (0) +#define SPI_0_F_REF (8000000UL) + +#define SPI_0_SCLK_DEV PORT->Group[2] +#define SPI_0_SCLK_PIN (18) + +#define SPI_0_MISO_DEV PORT->Group[2] +#define SPI_0_MISO_PIN (19) + +#define SPI_0_MOSI_DEV PORT->Group[1] +#define SPI_0_MOSI_PIN (30) + +/* SPI1 */ +#define SPI_1_DEV SERCOM5->SPI +#define SPI_IRQ_1 SERCOM5_IRQn +#define SPI_1_DOPO (1) +#define SPI_1_DIPO (2) +#define SPI_1_F_REF (8000000UL) + +#define SPI_1_SCLK_DEV PORT->Group[1] +#define SPI_1_SCLK_PIN (23) + +#define SPI_1_MISO_DEV PORT->Group[1] +#define SPI_1_MISO_PIN (02) + +#define SPI_1_MOSI_DEV PORT->Group[1] +#define SPI_1_MOSI_PIN (22) +/** @} */ + /** * @name I2C configuration * @{ @@ -110,36 +152,96 @@ extern "C" { * @name Random Number Generator configuration * @{ */ -#define RANDOM_NUMOF (0U) +#define RANDOM_NUMOF (0U) /** @} */ /** * @name GPIO configuration * @{ */ -#define GPIO_NUMOF (4U) -#define GPIO_0_EN 1 -#define GPIO_1_EN 1 -#define GPIO_2_EN 1 -#define GPIO_3_EN 1 +#define GPIO_NUMOF (9U) +#define GPIO_0_EN 1 +#define GPIO_1_EN 1 +#define GPIO_2_EN 1 +#define GPIO_3_EN 1 +/*4-7 -> internal */ +#define GPIO_4_EN 1 +#define GPIO_5_EN 1 +#define GPIO_6_EN 1 +#define GPIO_7_EN 1 +#define GPIO_8_EN 1 +#define GPIO_9_EN 0 +#define GPIO_10_EN 0 +#define GPIO_11_EN 0 + +#define GPIO_12_EN 0 +#define GPIO_13_EN 0 +#define GPIO_14_EN 0 +#define GPIO_15_EN 0 + +#define GPIO_NO_EXTINT (18) /* GPIO channel 0 config */ -#define GPIO_0_DEV PORT->Group[0] -#define GPIO_0_PIN PIN_PA13 -#define GPIO_0_EXTINT 13 +#define GPIO_0_DEV PORT->Group[0] +#define GPIO_0_PIN (13) +#define GPIO_0_EXTINT (13) /* GPIO channel 1 config */ -/* SW0 Button, configure w/ GPIO_PULLUP and GPIO_FALLING */ -#define GPIO_1_DEV PORT->Group[0] -#define GPIO_1_PIN PIN_PA28 -#define GPIO_1_EXTINT 8 +#define GPIO_1_DEV PORT->Group[0] +#define GPIO_1_PIN (28) +#define GPIO_1_EXTINT (8) /* GPIO channel 2 config */ -#define GPIO_2_DEV PORT->Group[0] -#define GPIO_2_PIN PIN_PA15 -#define GPIO_2_EXTINT 15 +#define GPIO_2_DEV PORT->Group[0] +#define GPIO_2_PIN (15) +#define GPIO_2_EXTINT (15) /* GPIO channel 3 config */ -#define GPIO_3_DEV PORT->Group[0] -#define GPIO_3_PIN PIN_PA19 -#define GPIO_3_EXTINT 3 +#define GPIO_3_DEV PORT->Group[0] +#define GPIO_3_PIN (19) +#define GPIO_3_EXTINT (3) +/* GPIO 4-7 Internal radio pins*/ +/* GPIO channel 4 config radio CS*/ +#define GPIO_4_DEV PORT->Group[1] +#define GPIO_4_PIN (31) +#define GPIO_4_EXTINT GPIO_NO_EXTINT +/* GPIO channel 5 config radio IRQ0*/ +#define GPIO_5_DEV PORT->Group[1] +#define GPIO_5_PIN (0) +#define GPIO_5_EXTINT (0) +/* GPIO channel 6 config radio reset*/ +#define GPIO_6_DEV PORT->Group[1] +#define GPIO_6_PIN (15) +#define GPIO_6_EXTINT GPIO_NO_EXTINT +/* GPIO channel 7 config radio sleep*/ +#define GPIO_7_DEV PORT->Group[0] +#define GPIO_7_PIN (20) +#define GPIO_7_EXTINT GPIO_NO_EXTINT +/* GPIO channel 8 config */ +#define GPIO_8_DEV PORT->Group[0] +#define GPIO_8_PIN (27) +#define GPIO_8_EXTINT GPIO_NO_EXTINT +/* GPIO channel 9 config */ +#define GPIO_9_DEV +#define GPIO_9_PIN +#define GPIO_9_EXTINT +/* GPIO channel 10 config */ +#define GPIO_10_DEV +#define GPIO_10_PIN +#define GPIO_10_EXTINT +/* GPIO channel 11 config */ +#define GPIO_11_DEV +#define GPIO_11_PIN +#define GPIO_11_EXTINT +/* GPIO channel 12 config */ +#define GPIO_12_PIN +#define GPIO_12_EXTINT +/* GPIO channel 13 config */ +#define GPIO_13_PIN +#define GPIO_13_EXTINT +/* GPIO channel 14 config */ +#define GPIO_14_PIN +#define GPIO_14_EXTINT +/* GPIO channel 15 config */ +#define GPIO_15_PIN +#define GPIO_15_EXTINT /** @} */ #ifdef __cplusplus diff --git a/cpu/samd21/include/cpu-conf.h b/cpu/samd21/include/cpu-conf.h index c0416ac8ab..bbd7eefbd0 100644 --- a/cpu/samd21/include/cpu-conf.h +++ b/cpu/samd21/include/cpu-conf.h @@ -50,6 +50,7 @@ extern "C" { #endif /** @} */ +#define TRANSCEIVER_BUFFER_SIZE (3) #ifdef __cplusplus } #endif diff --git a/cpu/samd21/periph/gpio.c b/cpu/samd21/periph/gpio.c index e772268190..1f8bc6d340 100644 --- a/cpu/samd21/periph/gpio.c +++ b/cpu/samd21/periph/gpio.c @@ -25,6 +25,8 @@ #include "sched.h" #include "thread.h" +#define ENABLE_DEBUG (0) +#include "debug.h" /* guard file in case no GPIO devices are defined */ #if GPIO_NUMOF @@ -34,7 +36,7 @@ typedef struct { void *arg; /**< argument passed to the callback */ } gpio_state_t; -static gpio_state_t gpio_config[16]; +static gpio_state_t gpio_config[GPIO_NUMOF]; int gpio_init_out(gpio_t dev, gpio_pp_t pushpull) { @@ -146,17 +148,17 @@ int gpio_init_out(gpio_t dev, gpio_pp_t pushpull) } /* configure as output */ - port->DIRSET.reg = (1<<(pin%32)); + port->DIRSET.reg = 1 << pin; /* configure the pin's pull resistor state */ switch (pushpull) { case GPIO_PULLDOWN: return -1; case GPIO_PULLUP: - port->PINCFG[pin % 32].bit.PULLEN = true; + port->PINCFG[pin].bit.PULLEN = true; break; case GPIO_NOPULL: - port->PINCFG[pin % 32].bit.PULLEN = false; + port->PINCFG[pin].bit.PULLEN = false; break; } @@ -273,22 +275,22 @@ int gpio_init_in(gpio_t dev, gpio_pp_t pushpull) } /* configure as input */ - port->DIRCLR.reg = (1<<(pin%32)); + port->DIRCLR.reg = 1 << pin; /* buffer input value */ - port->PINCFG[pin%32].bit.INEN = true; + port->PINCFG[pin].bit.INEN = true; /* configure the pin's pull resistor state */ switch (pushpull) { case GPIO_PULLDOWN: - port->OUTCLR.reg = (1 << (pin % 32)); - port->PINCFG[pin % 32].bit.PULLEN = true; + port->OUTCLR.reg = 1 << pin; + port->PINCFG[pin].bit.PULLEN = true; break; case GPIO_PULLUP: - port->OUTSET.reg = (1 << (pin % 32)); - port->PINCFG[pin % 32].bit.PULLEN = true; + port->OUTSET.reg = 1 << pin; + port->PINCFG[pin].bit.PULLEN = true; break; case GPIO_NOPULL: - port->PINCFG[pin % 32].bit.PULLEN = false; + port->PINCFG[pin].bit.PULLEN = false; break; } @@ -423,18 +425,14 @@ int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb return -1; } - /* configure pin as input */ - res = gpio_init_in(dev, pullup); - if (res < 0) { - return res; - } - if (pin<16) { + + if (pin < 16) { port->WRCONFIG.reg = PORT_WRCONFIG_WRPINCFG \ | PORT_WRCONFIG_WRPMUX \ | PORT_WRCONFIG_PMUX(0x0) \ | PORT_WRCONFIG_PMUXEN \ - | (1<WRCONFIG.reg = PORT_WRCONFIG_HWSEL \ @@ -442,20 +440,27 @@ int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb | PORT_WRCONFIG_WRPMUX \ | PORT_WRCONFIG_PMUX(0x0) \ | PORT_WRCONFIG_PMUXEN \ - | (1<<(pin-16)); + | ((1 << pin) >> 16); } + + /* configure pin as input */ + res = gpio_init_in(dev, pullup); + if (res < 0) { + return res; + } + /* Turn on APB clock */ PM->APBAMASK.reg |= PM_APBAMASK_EIC; GCLK->CLKCTRL = (GCLK_CLKCTRL_Type){ .bit.ID = EIC_GCLK_ID, - .bit.GEN = 0, //Generator 0 + .bit.GEN = 0, .bit.CLKEN = 1, .bit.WRTLOCK = 0 }; /* Setup interrupt */ - NVIC_SetPriority(EIC_IRQn, 10); //TODO: Come up with a sensible prio, now highest + NVIC_SetPriority(EIC_IRQn, 10); NVIC_EnableIRQ(EIC_IRQn); /* save callback */ @@ -463,8 +468,9 @@ int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb gpio_config[extint].arg = arg; /*Enable pin interrupt */ - EIC->INTENSET.reg = (1 << (extint)); - EIC->WAKEUP.reg |= (1 << (extint)); + EIC->INTFLAG.reg |= (1 << extint); + EIC->INTENSET.reg = 1 << extint; + EIC->WAKEUP.reg |= 1 << extint; /*Set config */ uint8_t config_pos = (4 * (extint % 8)); @@ -473,15 +479,15 @@ int gpio_init_int(gpio_t dev, gpio_pp_t pullup, gpio_flank_t flank, gpio_cb_t cb switch (flank) { case GPIO_FALLING: EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_FALL_Val << (config_pos)); + |= (EIC_CONFIG_SENSE0_FALL_Val << config_pos); break; case GPIO_RISING: EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_RISE_Val << (config_pos)); + |= (EIC_CONFIG_SENSE0_RISE_Val << config_pos); break; case GPIO_BOTH: EIC->CONFIG[config_reg].reg - |= (EIC_CONFIG_SENSE0_BOTH_Val << (config_pos)); + |= (EIC_CONFIG_SENSE0_BOTH_Val << config_pos); break; } @@ -495,82 +501,82 @@ void gpio_irq_enable(gpio_t dev) switch (dev) { #if GPIO_0_EN case GPIO_0: - EIC->INTENSET.reg = (1 << GPIO_0_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_0_EXTINT; break; #endif #if GPIO_1_EN case GPIO_1: - EIC->INTENSET.reg = (1 << GPIO_1_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_1_EXTINT; break; #endif #if GPIO_2_EN case GPIO_2: - EIC->INTENSET.reg = (1 << GPIO_2_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_2_EXTINT; break; #endif #if GPIO_3_EN case GPIO_3: - EIC->INTENSET.reg = (1 << GPIO_3_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_3_EXTINT; break; #endif #if GPIO_4_EN case GPIO_4: - EIC->INTENSET.reg = (1 << GPIO_4_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_4_EXTINT; break; #endif #if GPIO_5_EN case GPIO_5: - EIC->INTENSET.reg = (1 << GPIO_5_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_5_EXTINT; break; #endif #if GPIO_6_EN case GPIO_6: - EIC->INTENSET.reg = (1 << GPIO_6_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_6_EXTINT; break; #endif #if GPIO_7_EN case GPIO_7: - EIC->INTENSET.reg = (1 << GPIO_7_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_7_EXTINT; break; #endif #if GPIO_8_EN case GPIO_8: - EIC->INTENSET.reg = (1 << GPIO_8_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_8_EXTINT; break; #endif #if GPIO_9_EN case GPIO_9: - EIC->INTENSET.reg = (1 << GPIO_9_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_9_EXTINT; break; #endif #if GPIO_10_EN case GPIO_10: - EIC->INTENSET.reg = (1 << GPIO_10_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_10_EXTINT; break; #endif #if GPIO_11_EN case GPIO_11: - EIC->INTENSET.reg = (1 << GPIO_11_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_11_EXTINT; break; #endif #if GPIO_12_EN case GPIO_12: - EIC->INTENSET.reg = (1 << GPIO_12_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_12_EXTINT; break; #endif #if GPIO_13_EN case GPIO_13: - EIC->INTENSET.reg = (1 << GPIO_13_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_13_EXTINT; break; #endif #if GPIO_14_EN case GPIO_14: - EIC->INTENSET.reg = (1 << GPIO_14_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_14_EXTINT; break; #endif #if GPIO_15_EN case GPIO_15: - EIC->INTENSET.reg = (1 << GPIO_15_EXTINT); + EIC->INTENSET.reg = 1 << GPIO_15_EXTINT; break; #endif } @@ -581,82 +587,82 @@ void gpio_irq_disable(gpio_t dev) switch (dev) { #if GPIO_0_EN case GPIO_0: - EIC->INTENCLR.reg = (1 << GPIO_0_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_0_EXTINT; break; #endif #if GPIO_1_EN case GPIO_1: - EIC->INTENCLR.reg = (1 << GPIO_1_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_1_EXTINT; break; #endif #if GPIO_2_EN case GPIO_2: - EIC->INTENCLR.reg = (1 << GPIO_2_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_2_EXTINT; break; #endif #if GPIO_3_EN case GPIO_3: - EIC->INTENCLR.reg = (1 << GPIO_3_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_3_EXTINT; break; #endif #if GPIO_4_EN case GPIO_4: - EIC->INTENCLR.reg = (1 << GPIO_4_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_4_EXTINT; break; #endif #if GPIO_5_EN case GPIO_5: - EIC->INTENCLR.reg = (1 << GPIO_5_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_5_EXTINT; break; #endif #if GPIO_6_EN case GPIO_6: - EIC->INTENCLR.reg = (1 << GPIO_6_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_6_EXTINT; break; #endif #if GPIO_7_EN case GPIO_7: - EIC->INTENCLR.reg = (1 << GPIO_7_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_7_EXTINT; break; #endif #if GPIO_8_EN case GPIO_8: - EIC->INTENCLR.reg = (1 << GPIO_8_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_8_EXTINT; break; #endif #if GPIO_9_EN case GPIO_9: - EIC->INTENCLR.reg = (1 << GPIO_9_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_9_EXTINT; break; #endif #if GPIO_10_EN case GPIO_10: - EIC->INTENCLR.reg = (1 << GPIO_10_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_10_EXTINT; break; #endif #if GPIO_11_EN case GPIO_11: - EIC->INTENCLR.reg = (1 << GPIO_11_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_11_EXTINT; break; #endif #if GPIO_12_EN case GPIO_12: - EIC->INTENCLR.reg = (1 << GPIO_12_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_12_EXTINT; break; #endif #if GPIO_13_EN case GPIO_13: - EIC->INTENCLR.reg = (1 << GPIO_13_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_13_EXTINT; break; #endif #if GPIO_14_EN case GPIO_14: - EIC->INTENCLR.reg = (1 << GPIO_14_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_14_EXTINT; break; #endif #if GPIO_15_EN case GPIO_15: - EIC->INTENCLR.reg = (1 << GPIO_15_EXTINT); + EIC->INTENCLR.reg = 1 << GPIO_15_EXTINT; break; #endif } @@ -670,66 +676,82 @@ int gpio_read(gpio_t dev) #if GPIO_0_EN case GPIO_0: res = (&GPIO_0_DEV)->IN.reg & (1 << GPIO_0_PIN); + break; #endif #if GPIO_1_EN case GPIO_1: res = (&GPIO_1_DEV)->IN.reg & (1 << GPIO_1_PIN); + break; #endif #if GPIO_2_EN case GPIO_2: res = (&GPIO_2_DEV)->IN.reg & (1 << GPIO_2_PIN); + break; #endif #if GPIO_3_EN case GPIO_3: res = (&GPIO_3_DEV)->IN.reg & (1 << GPIO_3_PIN); + break; #endif #if GPIO_4_EN case GPIO_4: res = (&GPIO_4_DEV)->IN.reg & (1 << GPIO_4_PIN); + break; #endif #if GPIO_5_EN case GPIO_5: res = (&GPIO_5_DEV)->IN.reg & (1 << GPIO_5_PIN); + break; #endif #if GPIO_6_EN case GPIO_6: res = (&GPIO_6_DEV)->IN.reg & (1 << GPIO_6_PIN); + break; #endif #if GPIO_7_EN case GPIO_7: res = (&GPIO_7_DEV)->IN.reg & (1 << GPIO_7_PIN); + break; #endif #if GPIO_8_EN case GPIO_8: res = (&GPIO_8_DEV)->IN.reg & (1 << GPIO_8_PIN); + break; #endif #if GPIO_9_EN case GPIO_9: res = (&GPIO_9_DEV)->IN.reg & (1 << GPIO_9_PIN); + break; #endif #if GPIO_10_EN case GPIO_10: res = (&GPIO_10_DEV)->IN.reg & (1 << GPIO_10_PIN); + break; #endif #if GPIO_11_EN case GPIO_11: res = (&GPIO_11_DEV)->IN.reg & (1 << GPIO_11_PIN); + break; #endif #if GPIO_12_EN case GPIO_12: res = (&GPIO_12_DEV)->IN.reg & (1 << GPIO_12_PIN); + break; #endif #if GPIO_13_EN case GPIO_13: res = (&GPIO_13_DEV)->IN.reg & (1 << GPIO_13_PIN); + break; #endif #if GPIO_14_EN case GPIO_14: res = (&GPIO_14_DEV)->IN.reg & (1 << GPIO_14_PIN); + break; #endif #if GPIO_15_EN case GPIO_15: res = (&GPIO_15_DEV)->IN.reg & (1 << GPIO_15_PIN); + break; #endif } @@ -746,67 +768,83 @@ void gpio_set(gpio_t dev) switch (dev) { #if GPIO_0_EN case GPIO_0: - (&GPIO_0_DEV)->OUTSET.reg = (1 << GPIO_3_PIN); + (&GPIO_0_DEV)->OUTSET.reg = 1 << GPIO_0_PIN; + break; #endif #if GPIO_1_EN case GPIO_1: - (&GPIO_1_DEV)->OUTSET.reg = (1 << GPIO_3_PIN); + (&GPIO_1_DEV)->OUTSET.reg = 1 << GPIO_1_PIN; + break; #endif #if GPIO_2_EN case GPIO_2: - (&GPIO_2_DEV)->OUTSET.reg = (1 << GPIO_3_PIN); + (&GPIO_2_DEV)->OUTSET.reg = 1 << GPIO_2_PIN; + break; #endif #if GPIO_3_EN case GPIO_3: - (&GPIO_3_DEV)->OUTSET.reg = (1 << GPIO_3_PIN); + (&GPIO_3_DEV)->OUTSET.reg = 1 << GPIO_3_PIN; + break; #endif #if GPIO_4_EN case GPIO_4: - (&GPIO_4_DEV)->OUTSET.reg = (1 << GPIO_4_PIN); + (&GPIO_4_DEV)->OUTSET.reg = 1 << GPIO_4_PIN; + break; #endif #if GPIO_5_EN case GPIO_5: - (&GPIO_5_DEV)->OUTSET.reg = (1 << GPIO_5_PIN); + (&GPIO_5_DEV)->OUTSET.reg = 1 << GPIO_5_PIN; + break; #endif #if GPIO_6_EN case GPIO_6: - (&GPIO_6_DEV)->OUTSET.reg = (1 << GPIO_6_PIN); + (&GPIO_6_DEV)->OUTSET.reg = 1 << GPIO_6_PIN; + break; #endif #if GPIO_7_EN case GPIO_7: - (&GPIO_7_DEV)->OUTSET.reg = (1 << GPIO_7_PIN); + (&GPIO_7_DEV)->OUTSET.reg = 1 << GPIO_7_PIN; + break; #endif #if GPIO_8_EN case GPIO_8: - (&GPIO_8_DEV)->OUTSET.reg = (1 << GPIO_8_PIN); + (&GPIO_8_DEV)->OUTSET.reg = 1 << GPIO_8_PIN; + break; #endif #if GPIO_9_EN case GPIO_9: - (&GPIO_9_DEV)->OUTSET.reg = (1 << GPIO_9_PIN); + (&GPIO_9_DEV)->OUTSET.reg = 1 << GPIO_9_PIN; + break; #endif #if GPIO_10_EN case GPIO_10: - (&GPIO_10_DEV)->OUTSET.reg = (1 << GPIO_10_PIN); + (&GPIO_10_DEV)->OUTSET.reg = 1 << GPIO_10_PIN; + break; #endif #if GPIO_11_EN case GPIO_11: - (&GPIO_11_DEV)->OUTSET.reg = (1 << GPIO_11_PIN); + (&GPIO_11_DEV)->OUTSET.reg = 1 << GPIO_11_PIN; + break; #endif #if GPIO_12_EN case GPIO_12: - (&GPIO_12_DEV)->OUTSET.reg = (1 << GPIO_12_PIN); + (&GPIO_12_DEV)->OUTSET.reg = 1 << GPIO_12_PIN; + break; #endif #if GPIO_13_EN case GPIO_13: - (&GPIO_13_DEV)->OUTSET.reg = (1 << GPIO_13_PIN); + (&GPIO_13_DEV)->OUTSET.reg = 1 << GPIO_13_PIN; + break; #endif #if GPIO_14_EN case GPIO_14: - (&GPIO_14_DEV)->OUTSET.reg = (1 << GPIO_14_PIN); + (&GPIO_14_DEV)->OUTSET.reg = 1 << GPIO_14_PIN; + break; #endif #if GPIO_15_EN case GPIO_15: - (&GPIO_15_DEV)->OUTSET.reg = (1 << GPIO_15_PIN); + (&GPIO_15_DEV)->OUTSET.reg = 1 << GPIO_15_PIN; + break; #endif } } @@ -816,67 +854,84 @@ void gpio_clear(gpio_t dev) switch (dev) { #if GPIO_0_EN case GPIO_0: - (&GPIO_0_DEV)->OUTCLR.reg = (1 << GPIO_3_PIN); + (&GPIO_0_DEV)->OUTCLR.reg = 1 << GPIO_0_PIN; + break; #endif #if GPIO_1_EN case GPIO_1: - (&GPIO_1_DEV)->OUTCLR.reg = (1 << GPIO_3_PIN); + (&GPIO_1_DEV)->OUTCLR.reg = 1 << GPIO_1_PIN; + break; #endif #if GPIO_2_EN case GPIO_2: - (&GPIO_2_DEV)->OUTCLR.reg = (1 << GPIO_3_PIN); + (&GPIO_2_DEV)->OUTCLR.reg = 1 << GPIO_2_PIN; + break; #endif #if GPIO_3_EN case GPIO_3: - (&GPIO_3_DEV)->OUTCLR.reg = (1 << GPIO_3_PIN); + (&GPIO_3_DEV)->OUTCLR.reg = 1 << GPIO_3_PIN; + break; #endif #if GPIO_4_EN case GPIO_4: - (&GPIO_4_DEV)->OUTCLR.reg = (1 << GPIO_4_PIN); + (&GPIO_4_DEV)->OUTCLR.reg = 1 << GPIO_4_PIN; + break; + #endif #if GPIO_5_EN case GPIO_5: - (&GPIO_5_DEV)->OUTCLR.reg = (1 << GPIO_5_PIN); + (&GPIO_5_DEV)->OUTCLR.reg = 1 << GPIO_5_PIN; + break; #endif #if GPIO_6_EN case GPIO_6: - (&GPIO_6_DEV)->OUTCLR.reg = (1 << GPIO_6_PIN); + (&GPIO_6_DEV)->OUTCLR.reg = 1 << GPIO_6_PIN; + break; #endif #if GPIO_7_EN case GPIO_7: - (&GPIO_7_DEV)->OUTCLR.reg = (1 << GPIO_7_PIN); + (&GPIO_7_DEV)->OUTCLR.reg = 1 << GPIO_7_PIN; + break; #endif #if GPIO_8_EN case GPIO_8: - (&GPIO_8_DEV)->OUTCLR.reg = (1 << GPIO_8_PIN); + (&GPIO_8_DEV)->OUTCLR.reg = 1 << GPIO_8_PIN; + break; #endif #if GPIO_9_EN case GPIO_9: - (&GPIO_9_DEV)->OUTCLR.reg = (1 << GPIO_9_PIN); + (&GPIO_9_DEV)->OUTCLR.reg = 1 << GPIO_9_PIN; + break; #endif #if GPIO_10_EN case GPIO_10: - (&GPIO_10_DEV)->OUTCLR.reg = (1 << GPIO_10_PIN); + (&GPIO_10_DEV)->OUTCLR.reg = 1 << GPIO_10_PIN; + break; #endif #if GPIO_11_EN case GPIO_11: - (&GPIO_11_DEV)->OUTCLR.reg = (1 << GPIO_11_PIN); + (&GPIO_11_DEV)->OUTCLR.reg = 1 << GPIO_11_PIN; + break; #endif #if GPIO_12_EN case GPIO_12: - (&GPIO_12_DEV)->OUTCLR.reg = (1 << GPIO_12_PIN); + (&GPIO_12_DEV)->OUTCLR.reg = 1 << GPIO_12_PIN; + break; #endif #if GPIO_13_EN case GPIO_13: - (&GPIO_13_DEV)->OUTCLR.reg = (1 << GPIO_13_PIN); + (&GPIO_13_DEV)->OUTCLR.reg = 1 << GPIO_13_PIN; + break; #endif #if GPIO_14_EN case GPIO_14: - (&GPIO_14_DEV)->OUTCLR.reg = (1 << GPIO_14_PIN); + (&GPIO_14_DEV)->OUTCLR.reg = 1 << GPIO_14_PIN; + break; #endif #if GPIO_15_EN case GPIO_15: - (&GPIO_15_DEV)->OUTCLR.reg = (1 << GPIO_15_PIN); + (&GPIO_15_DEV)->OUTCLR.reg = 1 << GPIO_15_PIN; + break; #endif } } diff --git a/cpu/samd21/periph/spi.c b/cpu/samd21/periph/spi.c new file mode 100644 index 0000000000..d921e42204 --- /dev/null +++ b/cpu/samd21/periph/spi.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2014 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_samd21 + * @{ + * + * @file spi.c + * @brief Low-level SPI driver implementation + * + * @author Thomas Eichinger + * Troels Hoffmeyer + * + * @} + */ + +#include "cpu.h" +#include "periph/gpio.h" +#include "periph/spi.h" +#include "periph_conf.h" +#include "board.h" +#define ENABLE_DEBUG (0) +#include "debug.h" +#if SPI_0_EN || SPI_1_EN + +int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) +{ + SercomSpi* spi_dev = 0; + uint8_t dopo = 0; + uint8_t dipo = 0; + uint8_t cpha = 0; + uint8_t cpol = 0; + uint32_t f_baud = 0; + switch(speed) + { + case SPI_SPEED_100KHZ: + f_baud = 100000; + break; + case SPI_SPEED_400KHZ: + f_baud = 400000; + break; + case SPI_SPEED_1MHZ: + f_baud = 1000000; + break; + case SPI_SPEED_5MHZ: + return -1; + case SPI_SPEED_10MHZ: + return -1; + } + switch(conf) + { + case SPI_CONF_FIRST_RISING: /**< first data bit is transacted on the first rising SCK edge */ + cpha = 0; + cpol = 0; + break; + case SPI_CONF_SECOND_RISING:/**< first data bit is transacted on the second rising SCK edge */ + cpha = 1; + cpol = 0; + break; + case SPI_CONF_FIRST_FALLING:/**< first data bit is transacted on the first falling SCK edge */ + cpha = 0; + cpol = 1; + break; + case SPI_CONF_SECOND_FALLING:/**< first data bit is transacted on the second falling SCK edge */ + cpha = 1; + cpol = 1; + break; + } + switch(dev) + { +#ifdef SPI_0_EN + case SPI_0: + spi_dev = &SPI_0_DEV; + + /* Enable sercom4 in power manager */ + PM->APBCMASK.reg |= PM_APBCMASK_SERCOM4; + GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN_GCLK0 + | (SERCOM4_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos))); + + /* Setup clock */ + while (GCLK->STATUS.bit.SYNCBUSY); + /* Mux enable*/ + SPI_0_SCLK_DEV.PINCFG[ SPI_0_SCLK_PIN ].bit.PMUXEN = 1; + SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.PMUXEN = 1; + SPI_0_MOSI_DEV.PINCFG[ SPI_0_MOSI_PIN ].bit.PMUXEN = 1; + + /*Set mux function to spi. seperate registers, for even or odd pins */ + SPI_0_SCLK_DEV.PMUX[ SPI_0_SCLK_PIN / 2].bit.PMUXE = 5; + SPI_0_MISO_DEV.PMUX[ SPI_0_MISO_PIN / 2].bit.PMUXO = 5; + SPI_0_MOSI_DEV.PMUX[ SPI_0_MOSI_PIN / 2].bit.PMUXE = 5; + + /* SCLK+MOSI */ + SPI_0_SCLK_DEV.DIRSET.reg = 1 << SPI_0_SCLK_PIN; + SPI_0_MOSI_DEV.DIRSET.reg = 1 << SPI_0_MOSI_PIN; + + /* MISO = input */ + /* configure as input */ + SPI_0_MISO_DEV.DIRCLR.reg = 1 << SPI_0_MISO_PIN; + SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.INEN = true; + + SPI_0_MISO_DEV.OUTCLR.reg = 1 << SPI_0_MISO_PIN; + SPI_0_MISO_DEV.PINCFG[ SPI_0_MISO_PIN ].bit.PULLEN = true; + + dopo = SPI_0_DOPO; + dipo = SPI_0_DIPO; + break; +#endif +#ifdef SPI_1_EN + case SPI_1: + spi_dev = &SPI_1_DEV; + + /* Enable sercom5 in power manager */ + PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5; + /* Setup clock */ /* configure GCLK0 to feed sercom5 */; + GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN_GCLK0 + | (SERCOM5_GCLK_ID_CORE << GCLK_CLKCTRL_ID_Pos))); + + /* Mux enable*/ + SPI_1_SCLK_DEV.PINCFG[ SPI_1_SCLK_PIN ].bit.PMUXEN = 1; + SPI_1_MISO_DEV.PINCFG[ SPI_1_MISO_PIN ].bit.PMUXEN = 1; + SPI_1_MOSI_DEV.PINCFG[ SPI_1_MOSI_PIN ].bit.PMUXEN = 1; + /*Set mux function to spi. seperate registers, for even or odd pins */ + SPI_1_SCLK_DEV.PMUX[ SPI_1_SCLK_PIN / 2].bit.PMUXO = 3; + SPI_1_MISO_DEV.PMUX[ SPI_1_MISO_PIN / 2].bit.PMUXE = 3; + SPI_1_MOSI_DEV.PMUX[ SPI_1_MOSI_PIN / 2].bit.PMUXE = 3; + /* SCLK+MOSI */ + SPI_1_SCLK_DEV.DIRSET.reg = 1 << SPI_1_SCLK_PIN; + SPI_1_MOSI_DEV.DIRSET.reg = 1 << SPI_1_MOSI_PIN; + + /* MISO = input */ + /* configure as input */ + SPI_1_MISO_DEV.DIRCLR.reg = 1 << SPI_1_MISO_PIN; + SPI_1_MISO_DEV.PINCFG[ SPI_1_MISO_PIN ].bit.INEN = true; + + SPI_1_MISO_DEV.OUTCLR.reg = 1 << SPI_1_MISO_PIN; + SPI_1_MISO_DEV.PINCFG[SPI_1_MISO_PIN].bit.PULLEN = true; + + dopo = SPI_1_DOPO; + dipo = SPI_1_DIPO; + break; +#endif + default: + return -1; + } + spi_dev->CTRLA.bit.ENABLE = 0; /* Disable spi to write confs */ + while (spi_dev->SYNCBUSY.reg); + spi_dev->CTRLA.reg |= SERCOM_SPI_CTRLA_MODE_SPI_MASTER; + while (spi_dev->SYNCBUSY.reg); + + spi_dev->BAUD.bit.BAUD = (uint8_t) (((uint32_t) SPI_0_F_REF) / (2 * f_baud) - 1); /* Syncronous mode*/ + spi_dev->CTRLA.reg |= (SERCOM_SPI_CTRLA_DOPO(dopo)) + | (SERCOM_SPI_CTRLA_DIPO(dipo)) + | (cpha << SERCOM_SPI_CTRLA_CPHA_Pos) + | (cpol << SERCOM_SPI_CTRLA_CPOL_Pos); + + while (spi_dev->SYNCBUSY.reg); + spi_dev->CTRLB.reg = (SERCOM_SPI_CTRLB_CHSIZE(0) | SERCOM_SPI_CTRLB_RXEN); + while(spi_dev->SYNCBUSY.reg); + spi_poweron(dev); + return 0; +} + +int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char)) +{ + /* TODO */ + return 0; +} +void spi_transmission_begin(spi_t dev, char reset_val) +{ + /* TODO*/ +} + +int spi_transfer_byte(spi_t dev, char out, char *in) +{ + SercomSpi* spi_dev = 0; + int transfered = 0; + + switch(dev) + { +#ifdef SPI_0_EN + case SPI_0: + spi_dev = &(SPI_0_DEV); + break; +#endif +#ifdef SPI_1_EN + case SPI_1: + spi_dev = &(SPI_1_DEV); + break; +#endif + } + + while (!spi_dev->INTFLAG.bit.DRE); /* while data register is not empty*/ + spi_dev->DATA.bit.DATA = out; + transfered++; + if (in != NULL) + { + while (!spi_dev->INTFLAG.bit.RXC); /* while receive is not complete*/ + *in = spi_dev->DATA.bit.DATA; + transfered++; + } + else + { + spi_dev->DATA.reg; + } + return transfered; +} + +int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length) +{ + int transfered = 0; + + if (out != NULL) { + DEBUG("out*: %p out: %x length: %x\n", out, *out, length); + while (length--) { + int ret = spi_transfer_byte(dev, *(out)++, 0); + if (ret < 0) { + return ret; + } + transfered += ret; + } + } + if (in != NULL) { + while (length--) { + int ret = spi_transfer_byte(dev, 0, in++); + if (ret < 0) { + return ret; + } + transfered += ret; + } + DEBUG("in*: %p in: %x transfered: %x\n", in, *(in-transfered), transfered); + } + + DEBUG("sent %x byte(s)\n", transfered); + return transfered; +} + +int spi_transfer_reg(spi_t dev, uint8_t reg, char out, char *in) +{ + spi_transfer_byte(dev, reg, NULL); + return spi_transfer_byte(dev, out, in); +} + +int spi_transfer_regs(spi_t dev, uint8_t reg, char *out, char *in, unsigned int length) +{ + spi_transfer_byte(dev, reg, NULL); + return spi_transfer_bytes(dev, out, in, length); +} + +void spi_poweron(spi_t dev) +{ + switch(dev) { +#ifdef SPI_0_EN + case SPI_0: + SPI_0_DEV.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; + while(SPI_0_DEV.SYNCBUSY.bit.ENABLE); + break; +#endif +#ifdef SPI_1_EN + case SPI_1: + SPI_1_DEV.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE; + while(SPI_1_DEV.SYNCBUSY.bit.ENABLE); + break; +#endif + } +} + +void spi_poweroff(spi_t dev) +{ + switch(dev) { +#ifdef SPI_0_EN + case SPI_0: + SPI_0_DEV.CTRLA.bit.ENABLE = 0; /*Disable spi*/ + while(SPI_0_DEV.SYNCBUSY.bit.ENABLE); + break; +#endif +#ifdef SPI_1_EN + case SPI_1: + SPI_1_DEV.CTRLA.bit.ENABLE = 0; /*Disable spi*/ + while(SPI_1_DEV.SYNCBUSY.bit.ENABLE); + break; +#endif + } +} +#endif /* SPI_0_EN || SPI_1_EN */ diff --git a/drivers/at86rf231/at86rf231.c b/drivers/at86rf231/at86rf231.c index bc5b5a1fa3..8bd58903fb 100644 --- a/drivers/at86rf231/at86rf231.c +++ b/drivers/at86rf231/at86rf231.c @@ -31,6 +31,12 @@ #define ENABLE_DEBUG (0) #include "debug.h" +#ifndef AT86RF231_SPI_SPEED +#define SPI_SPEED SPI_SPEED_5MHZ +#else +#define SPI_SPEED AT86RF231_SPI_SPEED +#endif + #define _MAX_RETRIES (100) static uint16_t radio_pan; @@ -396,7 +402,7 @@ int at86rf231_get_monitor(void) void at86rf231_gpio_spi_interrupts_init(void) { /* SPI init */ - spi_init_master(AT86RF231_SPI, SPI_CONF_FIRST_RISING, SPI_SPEED_5MHZ); + spi_init_master(AT86RF231_SPI, SPI_CONF_FIRST_RISING, SPI_SPEED); /* IRQ0 */ gpio_init_int(AT86RF231_INT, GPIO_NOPULL, GPIO_RISING, (gpio_cb_t)at86rf231_rx_irq, NULL); /* CS */ @@ -417,9 +423,8 @@ void at86rf231_reset(void) gpio_clear(AT86RF231_SLEEP); /* additional waiting to comply to min rst pulse width */ - uint8_t delay = 50; - while (delay--){} - + uint8_t volatile delay = 50; /* volatile to ensure it isn't optimized away */ + while (--delay); gpio_set(AT86RF231_RESET); }