mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
cpu/atmega_common: checking features instead of CPU models
This commit is contained in:
parent
84a3078a93
commit
6336672c08
@ -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
|
||||
@ -22,6 +23,7 @@
|
||||
* @author Matthew Blue <matthew.blue.neuro@gmail.com>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -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");
|
||||
}
|
||||
@ -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,
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Copyright (C) 2016 Freie Universität Berlin
|
||||
* 2016 INRIA
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 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
|
||||
@ -18,6 +19,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
*/
|
||||
|
||||
@ -42,6 +44,7 @@ extern "C" {
|
||||
/**
|
||||
* @brief Timer register map
|
||||
*/
|
||||
#ifdef TCCR1C
|
||||
typedef struct {
|
||||
REG8 CRA; /**< control A */
|
||||
REG8 CRB; /**< control B */
|
||||
@ -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;
|
||||
|
||||
/**
|
||||
@ -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)
|
||||
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -18,6 +19,7 @@
|
||||
* @author René Herthel <rene-herthel@outlook.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CPU_COMMON_H
|
||||
@ -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
|
||||
*
|
||||
@ -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). */
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Laurent Navet <laurent.navet@gmail.com>
|
||||
* 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
|
||||
@ -17,6 +18,7 @@
|
||||
* @author Laurent Navet <laurent.navet@gmail.com>
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Sebastian Meiling <s@mlng.net>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -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));
|
||||
DDRK &= ~(1 << (line - 8));
|
||||
PORTK &= ~(1 << (line - 8));
|
||||
}
|
||||
#endif /* CPU_ATMEGA2560 */
|
||||
#endif /* CPU_ATMEGA328P */
|
||||
#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 {
|
||||
DDRB &= ~(1 << (line - 7));
|
||||
PORTB &= ~(1 << (line - 7));
|
||||
}
|
||||
#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) {
|
||||
@ -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;
|
||||
@ -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
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 HAW Hamburg
|
||||
* 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
|
||||
@ -22,6 +22,7 @@
|
||||
* @author Robert Hartung <hartung@ibr.cs.tu-bs.de>
|
||||
* @author Torben Petersen <petersen@ibr.cs.tu-bs.de>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -313,20 +314,30 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
cli();
|
||||
|
||||
/* enable interrupt number int_num */
|
||||
#if defined(EIFR) && defined(EIMSK)
|
||||
EIFR |= (1 << int_num);
|
||||
EIMSK |= (1 << int_num);
|
||||
#elif defined(GIFR) && defined(GICR)
|
||||
GIFR |= (1 << (INTF0 + int_num));
|
||||
GICR |= (1 << (INT0 + int_num));
|
||||
#endif
|
||||
|
||||
/* apply flank to interrupt number int_num */
|
||||
#if defined(EICRB)
|
||||
#if defined(EICRB)
|
||||
if (int_num >= 4) {
|
||||
EICRB &= ~(0x3 << ((int_num % 4) * 2));
|
||||
EICRB |= (flank << ((int_num % 4) * 2));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
#if defined(EICRA)
|
||||
EICRA &= ~(0x3 << (int_num * 2));
|
||||
EICRA |= (flank << (int_num * 2));
|
||||
#elif defined(MCUCR)
|
||||
MCUCR &= ~(0x3 << (int_num * 2));
|
||||
MCUCR |= (flank << (int_num * 2));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* set callback */
|
||||
@ -341,13 +352,22 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
|
||||
void gpio_irq_enable(gpio_t pin)
|
||||
{
|
||||
#if defined(EIFR) && defined(EIMSK)
|
||||
EIFR |= (1 << _int_num(pin));
|
||||
EIMSK |= (1 << _int_num(pin));
|
||||
#elif defined(GIFR) && defined(GICR)
|
||||
GIFR |= (1 << (INTF0 + _int_num(pin)));
|
||||
GICR |= (1 << (INT0 + _int_num(pin)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin)
|
||||
{
|
||||
#if defined(EIMSK)
|
||||
EIMSK &= ~(1 << _int_num(pin));
|
||||
#elif defined(GICR)
|
||||
GICR &= ~(1 << (INT0 + _int_num(pin)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void irq_handler(uint8_t int_num)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Hamburg University of Applied Sciences, 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
|
||||
@ -18,6 +19,7 @@
|
||||
*
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Laurent Navet <laurent.navet@gmail.com>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -238,7 +240,9 @@ static void i2c_poweron(i2c_t dev)
|
||||
{
|
||||
assert(dev < I2C_NUMOF);
|
||||
(void) dev;
|
||||
#ifdef PRTWI
|
||||
power_twi_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _start(uint8_t address, uint8_t rw_flag)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Víctor Ariño
|
||||
* 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
|
||||
@ -15,6 +16,7 @@
|
||||
* @brief Low-level PWM driver implementation
|
||||
*
|
||||
* @author Víctor Ariño <victor@lebrush.org>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -35,8 +37,12 @@
|
||||
#define COMA1 7
|
||||
|
||||
static struct {
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
uint8_t CRA;
|
||||
uint8_t CRB;
|
||||
#elif defined(TCCR2)
|
||||
uint8_t CR;
|
||||
#endif
|
||||
uint8_t res;
|
||||
} state[PWM_NUMOF];
|
||||
|
||||
@ -60,6 +66,7 @@ static inline uint8_t get_prescaler(pwm_t dev, uint32_t *scale)
|
||||
return pre;
|
||||
}
|
||||
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
static inline void compute_cra_and_crb(pwm_t dev, uint8_t pre)
|
||||
{
|
||||
uint8_t cra = (1 << WGM1) | (1 << WGM0);
|
||||
@ -79,16 +86,25 @@ static inline void compute_cra_and_crb(pwm_t dev, uint8_t pre)
|
||||
state[dev].CRA = cra;
|
||||
state[dev].CRB = crb;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void apply_config(pwm_t dev)
|
||||
{
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = state[dev].CRA;
|
||||
pwm_conf[dev].dev->CRB = state[dev].CRB;
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = state[dev].CR;
|
||||
#endif
|
||||
|
||||
if (pwm_conf[dev].pin_ch[0] == GPIO_UNDEF) {
|
||||
/* If channel 0 is not used, variable resolutions can be used for
|
||||
* channel 1 */
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[0] = state[dev].res;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = state[dev].res;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,11 +117,17 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
assert(!(res != 256 && pwm_conf[dev].pin_ch[0] != GPIO_UNDEF));
|
||||
|
||||
/* disable PWM */
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = 0x00;
|
||||
pwm_conf[dev].dev->CRB = 0x00;
|
||||
pwm_conf[dev].dev->OCR[0] = 0;
|
||||
pwm_conf[dev].dev->OCR[1] = 0;
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = 0x00;
|
||||
pwm_conf[dev].dev->OCR = 0;
|
||||
#endif
|
||||
|
||||
#if defined(PRT2) || defined(PRTIM2) || defined(PRT0) || defined(PRTIM0)
|
||||
/* disable power reduction */
|
||||
if (dev) {
|
||||
power_timer2_enable();
|
||||
@ -113,6 +135,7 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
else {
|
||||
power_timer0_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* find out prescaler */
|
||||
uint32_t scale = (CLOCK_CORECLOCK / (freq * (uint32_t)res));
|
||||
@ -121,7 +144,12 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||
|
||||
/* Compute configuration and store it in the state. (The state is needed
|
||||
* for later calls to pwm_poweron().)*/
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
compute_cra_and_crb(dev, pre);
|
||||
#elif defined(TCCR2)
|
||||
uint8_t cr = (1 << WGM21) | (1 << WGM20) | (1 << COM21) | pre;
|
||||
state[dev].CR = cr;
|
||||
#endif
|
||||
state[dev].res = res - 1;
|
||||
|
||||
/* Apply configuration stored in state */
|
||||
@ -155,18 +183,30 @@ uint8_t pwm_channels(pwm_t dev)
|
||||
|
||||
void pwm_set(pwm_t dev, uint8_t ch, uint16_t value)
|
||||
{
|
||||
#ifdef OCR2
|
||||
(void)ch;
|
||||
#endif
|
||||
assert(dev < PWM_NUMOF && ch <= 1 && pwm_conf[dev].pin_ch[ch] != GPIO_UNDEF);
|
||||
if (value > state[dev].res) {
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[ch] = state[dev].res;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = state[dev].res;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#if (defined(OCR0A) && defined(OCR0B)) || (defined(OCR2A) && defined(OCR2B))
|
||||
pwm_conf[dev].dev->OCR[ch] = value;
|
||||
#elif defined(OCR2)
|
||||
pwm_conf[dev].dev->OCR = value;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void pwm_poweron(pwm_t dev)
|
||||
{
|
||||
assert(dev < PWM_NUMOF);
|
||||
#if defined(PRT2) || defined(PRTIM2) || defined(PRT0) || defined(PRTIM0)
|
||||
/* disable power reduction */
|
||||
if (dev) {
|
||||
power_timer2_enable();
|
||||
@ -174,6 +214,7 @@ void pwm_poweron(pwm_t dev)
|
||||
else {
|
||||
power_timer0_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
apply_config(dev);
|
||||
}
|
||||
@ -181,6 +222,7 @@ void pwm_poweron(pwm_t dev)
|
||||
void pwm_poweroff(pwm_t dev)
|
||||
{
|
||||
assert(dev < PWM_NUMOF);
|
||||
#if (defined(TCCR0A) && defined(TCCR0B)) || (defined(TCCR2A) && defined(TCCR2B))
|
||||
pwm_conf[dev].dev->CRA = 0x00;
|
||||
pwm_conf[dev].dev->CRB = 0x00;
|
||||
/* disable timers to lower power consumption */
|
||||
@ -190,6 +232,9 @@ void pwm_poweroff(pwm_t dev)
|
||||
else {
|
||||
power_timer0_disable();
|
||||
}
|
||||
#elif defined(TCCR2)
|
||||
pwm_conf[dev].dev->CR = 0x00;
|
||||
#endif
|
||||
|
||||
if (pwm_conf[dev].pin_ch[0] != GPIO_UNDEF) {
|
||||
gpio_clear(pwm_conf[dev].pin_ch[0]);
|
||||
|
@ -3,6 +3,7 @@
|
||||
* 2016 Freie Universität Berlin
|
||||
* 2017 Hamburg University of Applied Sciences
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 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
|
||||
@ -21,6 +22,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Dimitri Nahm <dimitri.nahm@haw-hamburg.de>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -43,8 +45,10 @@ static mutex_t lock = MUTEX_INIT;
|
||||
void spi_init(spi_t bus)
|
||||
{
|
||||
assert(bus == 0);
|
||||
#ifdef PRSPI
|
||||
/* power off the SPI peripheral */
|
||||
power_spi_disable();
|
||||
#endif
|
||||
/* trigger the pin configuration */
|
||||
spi_init_pins(bus);
|
||||
}
|
||||
@ -53,13 +57,13 @@ void spi_init_pins(spi_t bus)
|
||||
{
|
||||
(void)bus;
|
||||
/* set SPI pins as output */
|
||||
#if defined (CPU_ATMEGA2560) || defined (CPU_ATMEGA1281)
|
||||
#if defined(CPU_ATMEGA2560) || defined(CPU_ATMEGA1281)
|
||||
DDRB |= ((1 << DDB2) | (1 << DDB1) | (1 << DDB0));
|
||||
#endif
|
||||
#if defined (CPU_ATMEGA328P)
|
||||
#if defined(CPU_ATMEGA328P) || defined(CPU_ATMEGA8)
|
||||
DDRB |= ((1 << DDB2) | (1 << DDB3) | (1 << DDB5));
|
||||
#endif
|
||||
#if defined (CPU_ATMEGA1284P)
|
||||
#if defined(CPU_ATMEGA1284P)
|
||||
DDRB |= ((1 << DDB4) | (1 << DDB5) | (1 << DDB7));
|
||||
#endif
|
||||
#if defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2)
|
||||
@ -86,7 +90,9 @@ void spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
|
||||
|
||||
/* lock the bus and power on the SPI peripheral */
|
||||
mutex_lock(&lock);
|
||||
#ifdef PRSPI
|
||||
power_spi_enable();
|
||||
#endif
|
||||
|
||||
/* configure as master, with given mode and clock */
|
||||
SPSR = (clk >> S2X_SHIFT);
|
||||
@ -102,7 +108,9 @@ void spi_release(spi_t bus)
|
||||
(void)bus;
|
||||
/* power off and release the bus */
|
||||
SPCR &= ~(1 << SPE);
|
||||
#ifdef PRSPI
|
||||
power_spi_disable();
|
||||
#endif
|
||||
mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
|
||||
* 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
|
||||
@ -16,6 +17,7 @@
|
||||
*
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -134,7 +136,9 @@ int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
/* stop and reset timer */
|
||||
ctx[tim].dev->CRA = 0;
|
||||
ctx[tim].dev->CRB = 0;
|
||||
#ifdef TCCR1C
|
||||
ctx[tim].dev->CRC = 0;
|
||||
#endif
|
||||
ctx[tim].dev->CNT = 0;
|
||||
|
||||
/* save interrupt context and timer mode */
|
||||
@ -158,10 +162,17 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value)
|
||||
unsigned state = irq_disable();
|
||||
|
||||
ctx[tim].dev->OCR[channel] = (uint16_t)value;
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
irq_restore(state);
|
||||
@ -179,17 +190,28 @@ int timer_set(tim_t tim, int channel, unsigned int timeout)
|
||||
unsigned absolute = ctx[tim].dev->CNT + timeout;
|
||||
|
||||
ctx[tim].dev->OCR[channel] = absolute;
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
if ((absolute - ctx[tim].dev->CNT) > timeout) {
|
||||
/* Timer already expired. Trigger the interrupt now and loop until it
|
||||
* is triggered.
|
||||
*/
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
while (!(*ctx[tim].flag & (1 << (OCF1A + channel)))) {
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
while (!(*ctx[tim].flag & (1 << (OCF1A - channel)))) {
|
||||
#endif
|
||||
ctx[tim].dev->OCR[channel] = ctx[tim].dev->CNT;
|
||||
}
|
||||
}
|
||||
@ -215,10 +237,17 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
|
||||
ctx[tim].dev->OCR[channel] = (uint16_t)value;
|
||||
|
||||
#if defined(OCF1A) && defined(OCF1B) && (OCF1A < OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (channel + OCF1A));
|
||||
*ctx[tim].flag = (1 << (OCF1A + channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (channel + OCIE1A));
|
||||
*ctx[tim].mask |= (1 << (OCIE1A + channel));
|
||||
#elif defined(OCF1A) && defined(OCF1B) && (OCF1A > OCF1B)
|
||||
/* clear spurious IRQs, if any */
|
||||
*ctx[tim].flag = (1 << (OCF1A - channel));
|
||||
/* unmask IRQ */
|
||||
*ctx[tim].mask |= (1 << (OCIE1A - channel));
|
||||
#endif
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
||||
@ -253,7 +282,11 @@ int timer_clear(tim_t tim, int channel)
|
||||
return -1;
|
||||
}
|
||||
|
||||
*ctx[tim].mask &= ~(1 << (channel + OCIE1A));
|
||||
#if defined(OCIE1A) && defined(OCIE1B) && (OCIE1A < OCIE1B)
|
||||
*ctx[tim].mask &= ~(1 << (OCIE1A + channel));
|
||||
#elif defined(OCIE1A) && defined(OCIE1B) && (OCIE1A > OCIE1B)
|
||||
*ctx[tim].mask &= ~(1 << (OCIE1A - channel));
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -293,7 +326,7 @@ static inline void _isr(tim_t tim, int chan)
|
||||
avr8_enter_isr();
|
||||
|
||||
if (is_oneshot(tim, chan)) {
|
||||
*ctx[tim].mask &= ~(1 << (chan + OCIE1A));
|
||||
timer_clear(tim, chan);
|
||||
}
|
||||
ctx[tim].cb(ctx[tim].arg, chan);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 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
|
||||
@ -18,6 +19,7 @@
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* @author Hugues Larrive <hugues.larrive@pm.me>
|
||||
*
|
||||
*
|
||||
* Support static BAUD rate calculation using STDIO_UART_BAUDRATE.
|
||||
@ -83,12 +85,20 @@ static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
||||
|
||||
static void _update_brr(uart_t uart, uint16_t brr, bool double_speed)
|
||||
{
|
||||
#if defined(UCSR0A) || defined(UCSR1A)
|
||||
dev[uart]->BRR = brr;
|
||||
#elif defined(UCSRA) /* atmega8 */
|
||||
/* on atmega8 BRRH is shared with CSRC */
|
||||
dev[uart]->CSRC = (brr >> 8);
|
||||
dev[uart]->BRRL = (uint8_t)(brr & 0x00ff);
|
||||
#endif
|
||||
if (double_speed) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRA |= (1 << U2X1);
|
||||
#else
|
||||
#if defined(U2X) /* atmega8 */
|
||||
dev[uart]->CSRA |= (1 << U2X);
|
||||
#elif defined(U2X0)
|
||||
dev[uart]->CSRA |= (1 << U2X0);
|
||||
#elif defined(U2X1) /* atmega32u4 */
|
||||
dev[uart]->CSRA |= (1 << U2X1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -129,34 +139,40 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
/* disable and reset UART */
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
#ifdef UCSR1D /* 32u4 */
|
||||
dev[uart]->CSRD = 0;
|
||||
#endif
|
||||
dev[uart]->CSRB = 0;
|
||||
dev[uart]->CSRA = 0;
|
||||
|
||||
/* configure UART to 8N1 mode */
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRC = (1 << UCSZ10) | (1 << UCSZ11);
|
||||
#else
|
||||
#if defined(UCSZ0) && defined(UCSZ1) /* atmega8 */
|
||||
dev[uart]->CSRC = (1 << UCSZ0) | (1 << UCSZ1);
|
||||
#elif defined(UCSZ00) && defined(UCSZ01)
|
||||
dev[uart]->CSRC = (1 << UCSZ00) | (1 << UCSZ01);
|
||||
#elif defined(UCSZ10) && defined(UCSZ11) /* 32u4 */
|
||||
dev[uart]->CSRC = (1 << UCSZ10) | (1 << UCSZ11);
|
||||
#endif
|
||||
/* set clock divider */
|
||||
_set_brr(uart, baudrate);
|
||||
|
||||
/* enable RX and TX and their respective interrupt */
|
||||
if (rx_cb) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRB = ((1 << RXCIE1) | (1 << TXCIE1) | (1 << RXEN1) | (1 << TXEN1));
|
||||
#else
|
||||
#if defined(RXCIE) /* atmega8 */
|
||||
dev[uart]->CSRB = ((1 << RXCIE) | (1 << TXCIE) | (1 << RXEN) | (1 << TXEN));
|
||||
#elif defined(RXCIE0)
|
||||
dev[uart]->CSRB = ((1 << RXCIE0) | (1 << TXCIE0) | (1 << RXEN0) | (1 << TXEN0));
|
||||
#elif defined(RXCIE1) /* 32u4 */
|
||||
dev[uart]->CSRB = ((1 << RXCIE1) | (1 << TXCIE1) | (1 << RXEN1) | (1 << TXEN1));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
dev[uart]->CSRB = ((1 << TXEN1) | (1 << TXCIE1));
|
||||
#else
|
||||
#if defined(TXEN) /* atmega8 */
|
||||
dev[uart]->CSRB = ((1 << TXEN) | (1 << TXCIE));
|
||||
#elif defined(TXEN0)
|
||||
dev[uart]->CSRB = ((1 << TXEN0) | (1 << TXCIE0));
|
||||
#elif defined(TXEN1) /* 32u4 */
|
||||
dev[uart]->CSRB = ((1 << TXEN1) | (1 << TXCIE1));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -166,10 +182,12 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
#ifdef CPU_ATMEGA32U4
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE1))) {};
|
||||
#else
|
||||
#if defined(UDRE) /* atmega8 */
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE))) {};
|
||||
#elif defined(UDRE0)
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE0))) {}
|
||||
#elif defined(UDRE1) /* 32u4 */
|
||||
while (!(dev[uart]->CSRA & (1 << UDRE1))) {};
|
||||
#endif
|
||||
/* start of TX won't finish until no data in UDRn and transmit shift
|
||||
register is empty */
|
||||
|
Loading…
Reference in New Issue
Block a user