1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 14:03:55 +01:00

Merge pull request #5529 from kYc0o/atmega_common_unify

cpu/atmega*: unify common code for atmega CPUs
This commit is contained in:
Alexandre Abadie 2016-06-22 15:43:57 +02:00 committed by GitHub
commit 42d34e69c3
14 changed files with 162 additions and 76 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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" {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */
/** @} */

View File

@ -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

View File

@ -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;

View File

@ -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)