diff --git a/boards/arduino-mega2560/include/board.h b/boards/arduino-mega2560/include/board.h index 8bd917f531fb81230b4e1f26b6b37b7557cc2116..543266941745d543af0805e03cc2df8f758f3f60 100644 --- a/boards/arduino-mega2560/include/board.h +++ b/boards/arduino-mega2560/include/board.h @@ -28,6 +28,11 @@ extern "C" { #endif +/** + * @brief Use the UART 0 for STDIO on this board + */ +#define UART_STDIO_DEV UART_DEV(0) + /** * @brief As the CPU is too slow to handle 115200 baud, we set the default * baudrate to 9600 for this board diff --git a/cpu/atmega2560/Makefile b/cpu/atmega2560/Makefile index 5148810cfa673b6e7b397f91f539d7f7c1627c69..e17e41db7225d898b224d42b91d3f00fa6f6bc0f 100644 --- a/cpu/atmega2560/Makefile +++ b/cpu/atmega2560/Makefile @@ -1,5 +1,5 @@ # define the module that is build MODULE = cpu # add a list of subdirectories, that should also be build -DIRS = periph $(ATMEGA_COMMON) +DIRS = $(ATMEGA_COMMON) include $(RIOTBASE)/Makefile.base diff --git a/cpu/atmega2560/Makefile.include b/cpu/atmega2560/Makefile.include index a3ddf00809f6380176b79a5773afa4cd10198d78..dfbc4bc326ca6e6f72f4eb5f553da819391a013f 100644 --- a/cpu/atmega2560/Makefile.include +++ b/cpu/atmega2560/Makefile.include @@ -4,18 +4,9 @@ export CFLAGS += -DCOREIF_NG=1 # tell the build system that the CPU depends on the atmega common files USEMODULE += atmega_common -# export the peripheral drivers to be linked into the final binary -export USEMODULE += periph - -# the atmel port uses uart_stdio -export USEMODULE += uart_stdio - # define path to atmega common module, which is needed for this CPU export ATMEGA_COMMON = $(RIOTCPU)/atmega_common/ -# define the linker script to use for this CPU -#export LINKERSCRIPT = $(RIOTCPU)/$(CPU)/ldscripts/atmega2560.ld - # explicitly tell the linker to link the syscalls and startup code. # Without this the interrupt vectors will not be linked correctly! export UNDEF += $(BINDIR)cpu/startup.o diff --git a/cpu/atmega2560/include/cpu_conf.h b/cpu/atmega2560/include/cpu_conf.h index 2219a0af402826471fa70de34f8e044600e0fab1..7216b2800649d56238449266d156b8d0f1befd40 100644 --- a/cpu/atmega2560/include/cpu_conf.h +++ b/cpu/atmega2560/include/cpu_conf.h @@ -20,7 +20,7 @@ #ifndef CPU_CONF_H #define CPU_CONF_H -#include "atmega2560_regs.h" +#include "atmega_regs_common.h" #ifdef __cplusplus extern "C" { diff --git a/cpu/atmega2560/include/periph_cpu.h b/cpu/atmega2560/include/periph_cpu.h index 9d94934bb86224cf2738a62b86f35a45b69e43b4..9f08ffdaeefebb9d81444529f62e612b6c3b20ea 100644 --- a/cpu/atmega2560/include/periph_cpu.h +++ b/cpu/atmega2560/include/periph_cpu.h @@ -21,15 +21,12 @@ #ifndef PERIPH_CPU_H_ #define PERIPH_CPU_H_ +#include "periph_cpu_common.h" + #ifdef __cplusplus extern "C" { #endif -/** - * @brief Define a CPU specific GPIO pin generator macro - */ -#define GPIO_PIN(x, y) ((x << 4) | y) - /** * @brief Available ports on the ATmega2560 family */ @@ -47,54 +44,6 @@ enum { PORT_L = 10 /**< port L */ }; -/** - * @brief SPI mode select macro - * - * The polarity is determined by bit 3 in the configuration register, the phase - * by bit 2. - */ -#define SPI_MODE_SEL(pol, pha) ((pol << 3) | (pha << 2)) - -/** - * @brief Override the SPI mode values - * - * As the mode is set in bit 3 and 2 of the configuration register, we put the - * correct configuration there - * @{ - */ -#define HAVE_SPI_CONF_T -typedef enum { - SPI_CONF_FIRST_RISING = SPI_MODE_SEL(0, 0), /**< mode 0 */ - SPI_CONF_SECOND_RISING = SPI_MODE_SEL(0, 1), /**< mode 1 */ - SPI_CONF_FIRST_FALLING = SPI_MODE_SEL(1, 0), /**< mode 2 */ - SPI_CONF_SECOND_FALLING = SPI_MODE_SEL(1, 1) /**< mode 3 */ -} spi_conf_t; -/** @} */ - -/** - * @brief SPI speed selection macro - * - * We encode the speed in bits 2, 1, and 0, where bit0 and bit1 hold the SPCR - * prescaler bits, while bit2 holds the SPI2X bit. - */ -#define SPI_SPEED_SEL(s2x, pr1, pr0) ((s2x << 2) | (pr1 << 1) | pr0) - -/** - * @brief Override SPI speed values - * - * We assume a master clock speed of 16MHz here. - * @{ - */ -#define HAVE_SPI_SPEED_T -typedef enum { - SPI_SPEED_100KHZ = SPI_SPEED_SEL(0, 1, 1), /**< 16/128 -> 125KHz */ - SPI_SPEED_400KHZ = SPI_SPEED_SEL(1, 1, 0), /**< 16/32 -> 500KHz */ - SPI_SPEED_1MHZ = SPI_SPEED_SEL(0, 0, 1), /**< 16/16 -> 1MHz */ - SPI_SPEED_5MHZ = SPI_SPEED_SEL(0, 0, 0), /**< 16/4 -> 4MHz */ - SPI_SPEED_10MHZ = SPI_SPEED_SEL(1, 0, 0) /**< 16/2 -> 8MHz */ -} spi_speed_t; -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/atmega_common/Makefile b/cpu/atmega_common/Makefile index affd083e6f421d0c12c9d2bcc1b92e59b057f832..387e91627c4526c4990e6aef48bc8e5bc75b41eb 100644 --- a/cpu/atmega_common/Makefile +++ b/cpu/atmega_common/Makefile @@ -1,5 +1,5 @@ - # define the module that is build MODULE = atmega_common - +# add a list of subdirectories, that should also be build +DIRS = periph include $(RIOTBASE)/Makefile.base diff --git a/cpu/atmega_common/Makefile.include b/cpu/atmega_common/Makefile.include index efd66a0dbf8fb84e74d56bcbc654bb631d3b1021..6e59bcd9117fe087a911fcd1489c608c9f5fe5b6 100644 --- a/cpu/atmega_common/Makefile.include +++ b/cpu/atmega_common/Makefile.include @@ -1,5 +1,11 @@ # Target architecture for the build. Use avr if you are unsure. export TARGET_ARCH ?= avr +# export the peripheral drivers to be linked into the final binary +export USEMODULE += periph + +# the atmel port uses uart_stdio +export USEMODULE += uart_stdio + # include module specific includes export INCLUDES += -I$(RIOTCPU)/atmega_common/include -isystem$(RIOTCPU)/atmega_common/avr-libc-extra diff --git a/cpu/atmega2560/include/atmega2560_regs.h b/cpu/atmega_common/include/atmega_regs_common.h similarity index 82% rename from cpu/atmega2560/include/atmega2560_regs.h rename to cpu/atmega_common/include/atmega_regs_common.h index 9a47ee5759125e7d4a15ac089fe97f013daf0690..a9721224d3893c3c6b60b514c086bc138e34d72d 100644 --- a/cpu/atmega2560/include/atmega2560_regs.h +++ b/cpu/atmega_common/include/atmega_regs_common.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Freie Universität Berlin + * 2016 INRIA * * 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 @@ -7,17 +8,18 @@ */ /** - * @ingroup cpu_atmega2560 + * @ingroup cpu_atmega_common * @{ * * @file - * @brief CMSIS style register definitions for the atmega2560 + * @brief CMSIS style register definitions for the atmega family * * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> */ -#ifndef ATMEGA2560_REGS_H -#define ATMEGA2560_REGS_H +#ifndef ATMEGA_REGS_COMMON_H +#define ATMEGA_REGS_COMMON_H #include <avr/io.h> @@ -63,14 +65,23 @@ typedef struct { * @{ */ #define MEGA_TIMER1_BASE (uint16_t *)(&TCCR1A) +#if defined(__AVR_ATmega2560__) #define MEGA_TIMER3_BASE (uint16_t *)(&TCCR3A) #define MEGA_TIMER4_BASE (uint16_t *)(&TCCR4A) #define MEGA_TIMER5_BASE (uint16_t *)(&TCCR5A) +#endif +/** @} */ +/** + * @brief Base register address definitions + * @{ + */ #define MEGA_UART0_BASE ((uint16_t *)(&UCSR0A)) +#if defined(__AVR_ATmega2560__) #define MEGA_UART1_BASE ((uint16_t *)(&UCSR1A)) #define MEGA_UART2_BASE ((uint16_t *)(&UCSR2A)) #define MEGA_UART3_BASE ((uint16_t *)(&UCSR3A)) +#endif /** @} */ /** @@ -78,14 +89,23 @@ typedef struct { * @{ */ #define MEGA_TIMER1 ((mega_timer_t *)MEGA_TIMER1_BASE) +#if defined(__AVR_ATmega2560__) #define MEGA_TIMER3 ((mega_timer_t *)MEGA_TIMER3_BASE) #define MEGA_TIMER4 ((mega_timer_t *)MEGA_TIMER4_BASE) #define MEGA_TIMER5 ((mega_timer_t *)MEGA_TIMER5_BASE) +#endif +/** @} */ +/** + * @brief Peripheral instances + * @{ + */ #define MEGA_UART0 ((mega_uart_t *)MEGA_UART0_BASE) +#if defined(__AVR_ATmega2560__) #define MEGA_UART1 ((mega_uart_t *)MEGA_UART1_BASE) #define MEGA_UART2 ((mega_uart_t *)MEGA_UART2_BASE) #define MEGA_UART3 ((mega_uart_t *)MEGA_UART3_BASE) +#endif /** @} */ #ifdef __cplusplus diff --git a/cpu/atmega_common/include/periph_cpu_common.h b/cpu/atmega_common/include/periph_cpu_common.h new file mode 100644 index 0000000000000000000000000000000000000000..7f005ddca72fd05a1e9bc331ae80cdcb791df604 --- /dev/null +++ b/cpu/atmega_common/include/periph_cpu_common.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 HAW Hamburg + * 2016 Freie Universität Berlin + * 2016 INRIA + * + * 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_atmega_common + * @{ + * + * @file + * @brief CPU specific definitions for internal peripheral handling + * + * @author René Herthel <rene-herthel@outlook.de> + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> + */ + +#ifndef PERIPH_CPU_COMMON_H_ +#define PERIPH_CPU_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Define a CPU specific GPIO pin generator macro + */ +#define GPIO_PIN(x, y) ((x << 4) | y) + +/** + * @brief SPI mode select macro + * + * The polarity is determined by bit 3 in the configuration register, the phase + * by bit 2. + */ +#define SPI_MODE_SEL(pol, pha) ((pol << 3) | (pha << 2)) + +/** + * @brief Override the SPI mode values + * + * As the mode is set in bit 3 and 2 of the configuration register, we put the + * correct configuration there + * @{ + */ +#define HAVE_SPI_CONF_T +typedef enum { + SPI_CONF_FIRST_RISING = SPI_MODE_SEL(0, 0), /**< mode 0 */ + SPI_CONF_SECOND_RISING = SPI_MODE_SEL(0, 1), /**< mode 1 */ + SPI_CONF_FIRST_FALLING = SPI_MODE_SEL(1, 0), /**< mode 2 */ + SPI_CONF_SECOND_FALLING = SPI_MODE_SEL(1, 1) /**< mode 3 */ +} spi_conf_t; +/** @} */ + +/** + * @brief SPI speed selection macro + * + * We encode the speed in bits 2, 1, and 0, where bit0 and bit1 hold the SPCR + * prescaler bits, while bit2 holds the SPI2X bit. + */ +#define SPI_SPEED_SEL(s2x, pr1, pr0) ((s2x << 2) | (pr1 << 1) | pr0) + +/** + * @brief Override SPI speed values + * + * We assume a master clock speed of 16MHz here. + * @{ + */ +#define HAVE_SPI_SPEED_T +typedef enum { + SPI_SPEED_100KHZ = SPI_SPEED_SEL(0, 1, 1), /**< 16/128 -> 125KHz */ + SPI_SPEED_400KHZ = SPI_SPEED_SEL(1, 1, 0), /**< 16/32 -> 500KHz */ + SPI_SPEED_1MHZ = SPI_SPEED_SEL(0, 0, 1), /**< 16/16 -> 1MHz */ + SPI_SPEED_5MHZ = SPI_SPEED_SEL(0, 0, 0), /**< 16/4 -> 4MHz */ + SPI_SPEED_10MHZ = SPI_SPEED_SEL(1, 0, 0) /**< 16/2 -> 8MHz */ +} spi_speed_t; +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CPU_COMMON_H_ */ +/** @} */ diff --git a/cpu/atmega2560/periph/Makefile b/cpu/atmega_common/periph/Makefile similarity index 100% rename from cpu/atmega2560/periph/Makefile rename to cpu/atmega_common/periph/Makefile diff --git a/cpu/atmega2560/periph/gpio.c b/cpu/atmega_common/periph/gpio.c similarity index 92% rename from cpu/atmega2560/periph/gpio.c rename to cpu/atmega_common/periph/gpio.c index 7ce2ec76616b4c8b3393853c14712191ced76030..c4d3752c93d1d1ae4aeac144983f989cd1eca5dd 100644 --- a/cpu/atmega2560/periph/gpio.c +++ b/cpu/atmega_common/periph/gpio.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 HAW Hamburg + * 2016 INRIA * * This file is subject to the terms and conditions of the GNU Lesser @@ -12,9 +13,10 @@ * @{ * * @file - * @brief Low-level GPIO driver implementation for ATmega2560 + * @brief Low-level GPIO driver implementation for ATmega family * * @author René Herthel <rene-herthel@outlook.de> + * @author Francisco Acosta <francisco.acosta@inria.fr> * * @} */ @@ -32,7 +34,16 @@ #define GPIO_OFFSET_PORT_H (0xCB) #define GPIO_OFFSET_PIN_PORT (0x02) #define GPIO_OFFSET_PIN_PIN (0x03) + +/* + * @brief Define GPIO interruptions for an specific atmega CPU, by default + * 2 (for small atmega CPUs) + */ +#if defined(__AVR_ATmega2560__) #define GPIO_EXT_INT_NUMOF (8U) +#else +#define GPIO_EXT_INT_NUMOF (2U) +#endif static gpio_isr_ctx_t config[GPIO_EXT_INT_NUMOF]; @@ -226,6 +237,7 @@ ISR(INT1_vect, ISR_BLOCK) irq_handler(1); /**< predefined interrupt pin */ } +#if defined(__AVR_ATmega2560__) ISR(INT2_vect, ISR_BLOCK) { irq_handler(2); /**< predefined interrupt pin */ @@ -255,3 +267,4 @@ ISR(INT7_vect, ISR_BLOCK) { irq_handler(7); /**< predefined interrupt pin */ } +#endif diff --git a/cpu/atmega2560/periph/spi.c b/cpu/atmega_common/periph/spi.c similarity index 94% rename from cpu/atmega2560/periph/spi.c rename to cpu/atmega_common/periph/spi.c index 17f1e85b7dadd2be1a62a4a9968e9d1f5d83e6be..7a48aba5a7b2abdba6283af132503f003522cc4b 100644 --- a/cpu/atmega2560/periph/spi.c +++ b/cpu/atmega_common/periph/spi.c @@ -24,6 +24,9 @@ #include "mutex.h" #include "periph/spi.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + /* guard this file in case no SPI device is defined */ #if SPI_NUMOF @@ -39,6 +42,7 @@ static mutex_t lock = MUTEX_INIT; int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) { + DEBUG("spi.c: conf = %d, speed = %d\n", conf, speed); /* make sure device is valid (there is only one...) */ if (dev != 0) { return -1; @@ -63,8 +67,10 @@ int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) SPSR = (speed >> S2X_SHIFT); SPCR = ((1 << SPE) | (1 << MSTR) | conf | (speed & SPEED_MASK)); - /* clear interrupt flag */ + /* clear interrupt flag by reading SPSR */ (void)SPSR; + + /* clear data register */ (void)SPDR; return 0; diff --git a/cpu/atmega2560/periph/timer.c b/cpu/atmega_common/periph/timer.c similarity index 92% rename from cpu/atmega2560/periph/timer.c rename to cpu/atmega_common/periph/timer.c index e923f6666aeedd4841fe3d9e352fc759755f63f6..ac0df5995fa3cd3888f2f3c16d15c2791220d897 100644 --- a/cpu/atmega2560/periph/timer.c +++ b/cpu/atmega_common/periph/timer.c @@ -28,6 +28,9 @@ #include "periph/timer.h" #include "periph_conf.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + /** * @brief All timers have three channels */ @@ -60,7 +63,7 @@ typedef struct { * @brief Allocate memory for saving the device states * @{ */ -#if TIMER_NUMOF +#ifdef TIMER_NUMOF static ctx_t ctx[] = { #ifdef TIMER_0 { TIMER_0, TIMER_0_MASK, TIMER_0_FLAG, NULL, NULL, 0, 0 }, @@ -86,6 +89,7 @@ static ctx_t *ctx[] = {{ NULL }}; */ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) { + DEBUG("timer.c: freq = %ld\n", freq); uint8_t pre = 0; /* make sure given device is valid */ @@ -100,6 +104,7 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) } } if (pre == PRESCALE_NUMOF) { + DEBUG("timer.c: prescaling failed!\n"); return -1; } @@ -116,6 +121,7 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) /* enable timer with calculated prescaler */ ctx[tim].dev->CRB = (pre + 1); + DEBUG("timer.c: prescaler set at %d\n", pre + 1); return 0; } @@ -175,12 +181,13 @@ void timer_irq_disable(tim_t tim) *ctx[tim].mask = 0; } -static inline void _isr(int num, int chan) +#ifdef TIMER_NUMOF +static inline void _isr(tim_t tim, int chan) { __enter_isr(); - *ctx[num].mask &= ~(1 << (chan + OCIE1A)); - ctx[num].cb(ctx[num].arg, chan); + *ctx[tim].mask &= ~(1 << (chan + OCIE1A)); + ctx[tim].cb(ctx[tim].arg, chan); if (sched_context_switch_request) { thread_yield(); @@ -188,6 +195,7 @@ static inline void _isr(int num, int chan) __exit_isr(); } +#endif #ifdef TIMER_0 ISR(TIMER_0_ISRA, ISR_BLOCK) diff --git a/cpu/atmega2560/periph/uart.c b/cpu/atmega_common/periph/uart.c similarity index 100% rename from cpu/atmega2560/periph/uart.c rename to cpu/atmega_common/periph/uart.c