Skip to content

Commit

Permalink
cpu/atmega_common: checking features instead of CPU models
Browse files Browse the repository at this point in the history
  • Loading branch information
hugueslarrive committed Jul 4, 2023
1 parent 84a3078 commit 6336672
Show file tree
Hide file tree
Showing 11 changed files with 277 additions and 49 deletions.
17 changes: 12 additions & 5 deletions cpu/atmega_common/atmega_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* 2017 RWTH Aachen, Josua Arndt
* 2018 Matthew Blue
* 2021 Gerson Fernando Budke
* 2023 Hugues Larrive
*
* 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
Expand All @@ -22,6 +23,7 @@
* @author Matthew Blue <[email protected]>
* @author Francisco Acosta <[email protected]>
* @author Gerson Fernando Budke <[email protected]>
* @author Hugues Larrive <[email protected]>
*
* @}
*/
Expand Down Expand Up @@ -58,7 +60,7 @@ void avr8_reset_cause(void)
DEBUG("Watchdog reset!\n");
}
}
#if !defined (CPU_ATMEGA328P)
#if defined(JTRF)
if (mcusr_mirror & (1 << JTRF)) {
DEBUG("JTAG reset!\n");
}
Expand All @@ -67,7 +69,9 @@ void avr8_reset_cause(void)

void __attribute__((weak)) avr8_clk_init(void)
{
#if defined(CLKPR)
atmega_set_prescaler(CPU_ATMEGA_CLK_SCALE_INIT);
#endif
}

/* This is a vector which is aliased to __vector_default,
Expand All @@ -85,9 +89,12 @@ ISR(BADISR_vect)
{
avr8_reset_cause();

#if defined (CPU_ATMEGA256RFR2)
printf("IRQ_STATUS %#02x\nIRQ_STATUS1 %#02x\n",
(unsigned int)IRQ_STATUS, (unsigned int)IRQ_STATUS1);
#if defined(TRX_CTRL_0) /* megaRF */
printf("IRQ_STATUS %#02x\n", (unsigned int)IRQ_STATUS);

#if defined(IRQ_STATUS1)
printf("IRQ_STATUS1 %#02x\n", (unsigned int)IRQ_STATUS1);
#endif

printf("SCIRQS %#02x\nBATMON %#02x\n", (unsigned int)SCIRQS, (unsigned int)BATMON);

Expand All @@ -101,7 +108,7 @@ ISR(BADISR_vect)
core_panic(PANIC_GENERAL_ERROR, "BADISR");
}

#if defined(CPU_ATMEGA128RFA1) || defined (CPU_ATMEGA256RFR2)
#if defined(BAT_LOW_vect)
ISR(BAT_LOW_vect, ISR_BLOCK)
{
avr8_enter_isr();
Expand Down
44 changes: 42 additions & 2 deletions cpu/atmega_common/include/atmega_regs_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright (C) 2016 Freie Universität Berlin
* 2016 INRIA
* 2017 Thomas Perrot <[email protected]>
* 2023 Hugues Larrive
*
* 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
Expand All @@ -18,6 +19,7 @@
* @author Hauke Petersen <[email protected]>
* @author Francisco Acosta <[email protected]>
* @author Thomas Perrot <[email protected]>
* @author Hugues Larrive <[email protected]>
*
*/

Expand All @@ -42,6 +44,7 @@ extern "C" {
/**
* @brief Timer register map
*/
#ifdef TCCR1C
typedef struct {
REG8 CRA; /**< control A */
REG8 CRB; /**< control B */
Expand All @@ -51,31 +54,57 @@ typedef struct {
REG16 ICR; /**< input capture */
REG16 OCR[3]; /**< output compare */
} mega_timer_t;
#else /* atmega8 */
typedef struct {
REG16 ICR; /**< input capture */
REG16 OCR[2]; /**< output compare */
REG16 CNT; /**< counter */
REG8 CRB; /**< control B */
REG8 CRA; /**< control A */
} mega_timer_t;
#endif

/**
* @brief 8-bit timer register map
*/
typedef struct {
#if ((defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B)))
REG8 CRA; /**< control A */
REG8 CRB; /**< control B */
REG8 CNT; /**< counter */
REG8 OCR[2]; /**< output compare */
#elif defined(TCCR2)
REG8 OCR; /**< output compare */
REG8 CNT; /**< counter */
REG8 CR; /**< control */
#endif
} mini_timer_t;

/**
* @brief UART register map
*/
typedef struct {
#if defined(UCSR0A) || defined(UCSR1A)
REG8 CSRA; /**< control and status register A */
REG8 CSRB; /**< control and status register B */
REG8 CSRC; /**< control and status register C */
#ifdef CPU_ATMEGA32U4
#ifdef UCSR1D /* 32u4 */
REG8 CSRD; /**< control and status register D */
#else
REG8 reserved; /**< reserved */
#endif
REG16 BRR; /**< baud rate register */
REG8 DR; /**< data register */
#elif defined(UCSRA) /* atmega8 */
REG8 BRRL; /**< baud rate register low byte */
REG8 CSRB; /**< control and status register B */
REG8 CSRA; /**< control and status register A */
REG8 DR; /**< data register */
REG8 padding[19]; /**< 3 SPI + 3 PORTD + 3 PORTC + 3 PORTB
* + 3 reserved + 4 EEPROM = 19 */
REG8 CSRC; /**< control and status register C shared
* with baud rate register high byte */
#endif
} mega_uart_t;

/**
Expand All @@ -87,14 +116,20 @@ typedef struct {
#define MINI_TIMER0_DIV TIMER_DIV1_8_64_128_1024
#endif

#if defined(TCCR1A)
#if defined(TCCR1C)
#define MEGA_TIMER1_BASE (uint16_t *)(&TCCR1A)
#define MEGA_TIMER1 ((mega_timer_t *)MEGA_TIMER1_BASE)
#elif defined(TCCR1A) /* atmega8 */
#define MEGA_TIMER1_BASE (uint16_t *)(&ICR1L)
#define MEGA_TIMER1 ((mega_timer_t *)MEGA_TIMER1_BASE)
#endif

#if defined(TCCR2A)
#define MINI_TIMER2 ((mini_timer_t *)(uint16_t *)(&TCCR2A))
#define MINI_TIMER2_DIV TIMER_DIV1_8_32_64_128_256_1024
#elif defined(TCCR2) /* atmega8 */
#define MINI_TIMER2 ((mini_timer_t *)(uint16_t *)(&OCR2))
#define MINI_TIMER2_DIV TIMER_DIV1_8_32_64_128_256_1024
#endif

#if defined(TCCR3A)
Expand All @@ -117,6 +152,11 @@ typedef struct {
* @brief Peripheral register definitions and instances
* @{
*/
#if defined(UCSRA)
#define MEGA_UART_BASE ((uint16_t *)(&UBRRL))
#define MEGA_UART ((mega_uart_t *)MEGA_UART_BASE)
#endif

#if defined(UCSR0A)
#define MEGA_UART0_BASE ((uint16_t *)(&UCSR0A))
#define MEGA_UART0 ((mega_uart_t *)MEGA_UART0_BASE)
Expand Down
4 changes: 4 additions & 0 deletions cpu/atmega_common/include/cpu_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,15 @@ enum {
static inline void atmega_set_prescaler(uint8_t clk_scale)
{
/* Enable clock change */
#ifdef CLKPR
/* Must be assignment to set all other bits to zero, see datasheet */
CLKPR = (1 << CLKPCE);

/* Write clock within 4 cycles */
CLKPR = clk_scale;
#else
(void) clk_scale;
#endif
}

#ifdef __cplusplus
Expand Down
28 changes: 27 additions & 1 deletion cpu/atmega_common/include/periph_cpu_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* Copyright (C) 2015 HAW Hamburg
* 2016 Freie Universität Berlin
* 2016 INRIA
* 2023 Hugues Larrive
*
* 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
Expand All @@ -18,6 +19,7 @@
* @author René Herthel <[email protected]>
* @author Hauke Petersen <[email protected]>
* @author Francisco Acosta <[email protected]>
* @author Hugues Larrive <[email protected]>
*/

#ifndef PERIPH_CPU_COMMON_H
Expand Down Expand Up @@ -61,7 +63,27 @@ typedef uint8_t gpio_t;
*
* Must be identical to the address of `PINA` provided by avr/io.h
*/
#define ATMEGA_GPIO_BASE_A (0x20)
#if (defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)) \
|| (defined(PUD) && (PUD != 4)) || (defined(INT0) && (INT0 == 6))
/* match with 65 devices against 61 for (PORTB == _SFR_IO8(0x18)) which
* did not work here anyway */
#define GPIO_PORT_DESCENDENT
#endif

#ifdef GPIO_PORT_DESCENDENT
#ifdef _AVR_ATTINY1634_H_INCLUDED
/* the only one that requires particular treatment! */
#define ATMEGA_GPIO_BASE_A (0x2F)
#else
/* all other port descendent, including :
- _AVR_IO8534_ (only have port A but with 0x1B address) ;
- _AVR_IOAT94K_H_ (only have ports D and E) ;
- _AVR_IOTN28_H_ (only have ports A and D). */
#define ATMEGA_GPIO_BASE_A (0x39)
#endif /* _AVR_ATTINY1634_H_INCLUDED */
#else /* !GPIO_PORT_DESCENDENT */
#define ATMEGA_GPIO_BASE_A (0x20)
#endif /* GPIO_PORT_DESCENDENT */
/**
* @brief Base of the GPIO port G register as memory address
*
Expand Down Expand Up @@ -137,7 +159,11 @@ typedef struct {
static inline atmega_gpio_port_t *atmega_gpio_port(uint8_t port_num)
{
static const uintptr_t base_addr = (uintptr_t)ATMEGA_GPIO_BASE_A;
#ifdef GPIO_PORT_DESCENDENT
uintptr_t res = base_addr - port_num * sizeof(atmega_gpio_port_t);
#else
uintptr_t res = base_addr + port_num * sizeof(atmega_gpio_port_t);
#endif
/* GPIO ports up to (including) G are mapped in the I/O address space,
* port H and higher (if present) are mapped in a different contiguous
* region afterwards (e.g. 0x100 for ATmega2560). */
Expand Down
45 changes: 34 additions & 11 deletions cpu/atmega_common/periph/adc.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2016 Laurent Navet <[email protected]>
* 2017 HAW Hamburg, Dimitri Nahm
* 2023 Hugues Larrive
*
* 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
Expand All @@ -17,6 +18,7 @@
* @author Laurent Navet <[email protected]>
* @author Dimitri Nahm <[email protected]>
* @author Sebastian Meiling <[email protected]>
* @author Hugues Larrive <[email protected]>
* @}
*/

Expand Down Expand Up @@ -52,35 +54,53 @@ int adc_init(adc_t line)

_prep();

#if defined(DIDR0)
/* Disable corresponding Digital input */
if (line < 8) {
DIDR0 |= (1 << line);
}
#if defined(CPU_ATMEGA2560)
#if defined(DIDR2)
else {
DIDR2 |= (1 << (line - 8));
}
#endif
#endif

/* Set ADC-pin as input */
#if defined(CPU_ATMEGA328P)
#if !defined(PORTA) && defined(PC0)
/* 328p and 8 do not have PORTA, on 32u4 pins are named differently
* and it only have PORTC6 and PORTC7 */
DDRC &= ~(1 << line);
PORTC &= ~(1 << line);
#elif defined(CPU_ATMEGA1284P)
#elif defined(PORTA) && !defined(DIDR2) /* 1284p do not have DIDR2 */
DDRA &= ~(1 << line);
PORTA &= ~(1 << line);
#elif defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA1281)
#elif defined(PORTF) /* 2560 and 1281 */
if (line < 8) {
DDRF &= ~(1 << line);
PORTF &= ~(1 << line);
}
#if defined(CPU_ATMEGA2560)
#if defined(PORTK) /* 2560 */
else {
DDRK &= ~(1 << (line - 8));
PORTK &= ~(1 << (line - 8));
}
#elif defined(PORTF0) && !defined(PORTF2) && !defined(PORTF3)
/* 32u4 do not have PORTF2 and PORTF3 */
else if (line == 8) {
DDRD &= ~(1 << PORTD4);
PORTD &= ~(1 << PORTD4);
}
else if (line < 11) {
DDRD &= ~(1 << (line - 3));
PORTD &= ~(1 << (line - 3));
}
else {
DDRK &= ~(1 << (line-8));
PORTK &= ~(1 << (line-8));
DDRB &= ~(1 << (line - 7));
PORTB &= ~(1 << (line - 7));
}
#endif /* CPU_ATMEGA2560 */
#endif /* CPU_ATMEGA328P */
#endif /* PORTK */
#endif /* PORTF */

/* set clock prescaler to get the maximal possible ADC clock value */
for (uint32_t clk_div = 1; clk_div < 8; ++clk_div) {
Expand Down Expand Up @@ -110,10 +130,12 @@ int32_t adc_sample(adc_t line, adc_res_t res)
_prep();

/* set conversion channel */
#if defined(CPU_ATMEGA328P) || defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA32U4)
#if defined(ADMUX)
#if !defined(MUX5)
/* atmega8 ; 328p ; 1281 ; 1284p ; 32u4 */
ADMUX &= 0xf0;
ADMUX |= line;
#elif defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2)
#else /* 2560 ; 128rfa1 ; 256rfr2 */
if (line < 8) {
ADCSRB &= ~(1 << MUX5);
ADMUX &= 0xf0;
Expand All @@ -124,6 +146,7 @@ int32_t adc_sample(adc_t line, adc_res_t res)
ADMUX &= 0xf0;
ADMUX |= (line-8);
}
#endif
#endif

/* Start a new conversion. By default, this conversion will
Expand Down
Loading

0 comments on commit 6336672

Please sign in to comment.