mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #15758 from nandojve/avr8_xmega
Introduce ATxmega CPU and Boards
This commit is contained in:
commit
ee5b70730b
@ -9,6 +9,7 @@
|
||||
|
||||
/.murdock @kaspar030
|
||||
|
||||
/boards/common/atxmega/ @nandojve
|
||||
/boards/common/esp*/ @gschorcht
|
||||
/boards/common/nrf*/ @aabadie @haukepetersen
|
||||
/boards/common/nucleo*/ @aabadie
|
||||
@ -34,11 +35,14 @@
|
||||
/boards/stk3*00/ @basilfx
|
||||
/boards/openmote*/ @MrKevinWeiss
|
||||
/boards/cc1352p-launchpad @luisan00
|
||||
/boards/atxmega*/ @nandojve
|
||||
|
||||
/core/ @kaspar030
|
||||
|
||||
/cpu/arm7_common/ @kaspar030 @maribu
|
||||
/cpu/avr8_common/ @kYc0o @roberthartung @maribu @nandojve
|
||||
/cpu/atmega*/ @kYc0o @roberthartung @maribu
|
||||
/cpu/atxmega/ @nandojve
|
||||
/cpu/cc2538/ @hexluthor @smlng @fjmolinas
|
||||
/cpu/cc26x0/ @hexluthor @smlng
|
||||
/cpu/cc26x2_cc13x2/ @hexluthor @smlng
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#ifndef CPU_ATMEGA_CLK_SCALE_INIT
|
||||
@ -38,5 +37,4 @@ void board_init(void)
|
||||
avr8_stdio_init();
|
||||
cpu_init();
|
||||
led_init();
|
||||
irq_enable();
|
||||
}
|
||||
|
24
boards/atxmega-a1u-xpro/Kconfig
Normal file
24
boards/atxmega-a1u-xpro/Kconfig
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2020 HAW Hamburg
|
||||
# Copyright (c) 2021 Gerson Fernando Budle
|
||||
#
|
||||
# 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.
|
||||
|
||||
config BOARD
|
||||
default "atxmega-a1u-xpro" if BOARD_ATXMEGA_A1U_XPRO
|
||||
|
||||
config BOARD_ATXMEGA_A1U_XPRO
|
||||
bool
|
||||
default y
|
||||
select CPU_MODEL_XMEGA128A1U
|
||||
select HAS_PERIPH_CPUID
|
||||
select HAS_PERIPH_GPIO
|
||||
select HAS_PERIPH_GPIO_IRQ
|
||||
select HAS_PERIPH_NVM
|
||||
select HAS_PERIPH_PM
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_TIMER_PERIODIC
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
select HAVE_SAUL_GPIO
|
5
boards/atxmega-a1u-xpro/Makefile
Normal file
5
boards/atxmega-a1u-xpro/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
MODULE = board
|
||||
|
||||
DIRS = $(RIOTBOARD)/common/atxmega
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
5
boards/atxmega-a1u-xpro/Makefile.dep
Normal file
5
boards/atxmega-a1u-xpro/Makefile.dep
Normal file
@ -0,0 +1,5 @@
|
||||
USEMODULE += boards_common_atxmega
|
||||
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += saul_gpio
|
||||
endif
|
3
boards/atxmega-a1u-xpro/Makefile.features
Normal file
3
boards/atxmega-a1u-xpro/Makefile.features
Normal file
@ -0,0 +1,3 @@
|
||||
CPU_MODEL = atxmega128a1u
|
||||
|
||||
include $(RIOTBOARD)/common/atxmega/Makefile.features
|
4
boards/atxmega-a1u-xpro/Makefile.include
Normal file
4
boards/atxmega-a1u-xpro/Makefile.include
Normal file
@ -0,0 +1,4 @@
|
||||
AVRDUDE_PROGRAMMER = xplainedpro_pdi
|
||||
DEBUGPROTO = -X
|
||||
|
||||
include $(RIOTBOARD)/common/atxmega/Makefile.include
|
66
boards/atxmega-a1u-xpro/doc.txt
Normal file
66
boards/atxmega-a1u-xpro/doc.txt
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
@defgroup boards_atxmega-a1u-xpro ATxmega-A1U Xplained Pro board
|
||||
@ingroup boards
|
||||
@brief Support for the ATxmega-A1U Xplained Pro board
|
||||
|
||||
## Overview
|
||||
|
||||
The ATxmega-A1U Xplained Pro is the reference to develop with XMEGA's.
|
||||
|
||||
### MCU
|
||||
| MCU | ATxmega128A1U |
|
||||
|:------------- |:--------------------------------------------- |
|
||||
| Family | AVR/ATxmega |
|
||||
| Vendor | Microchip (previously Atmel) |
|
||||
| Flash | 128KiB |
|
||||
| RAM | 8KiB |
|
||||
| EBI | 16MiB SRAM, 128MiB SDRAM |
|
||||
| EEPROM | 2KiB |
|
||||
| Frequency | up to 32MHz |
|
||||
| Timers | 8 16bit (32 bit combining 2 x 16 bit) |
|
||||
| ACs | 4 Analog Comparators |
|
||||
| ADCs | 2 - 16 channels - 12 bit - 2msps |
|
||||
| ADCs | 2 - 2 channels - 12 bit - 1msps |
|
||||
| UARTs | 8 (can be used in SPI mode) with 1 IrDA |
|
||||
| SPIs | 4 |
|
||||
| I2Cs | 4 (called TWI) |
|
||||
| USB | 1 port |
|
||||
| DMA | 4 Channels |
|
||||
| Event System | 8 Channels |
|
||||
| Ext. INT | All GPIOs |
|
||||
| Crypto | AES/DES, CRC-16, CRC-32 |
|
||||
| Vcc | 1.6V - 3.6V |
|
||||
| Datasheet | [Datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/ATxmega128A1U-64A1U-Data-Sheet-DS40002058A.pdf) |
|
||||
| Xmega Manual | [Manual](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf) |
|
||||
| Guide | [User Guide](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42211-XMEGA-A1U-Xplained-Pro_User-Guide.pdf) |
|
||||
| Design Files | [Files](https://ww1.microchip.com/downloads/en/DeviceDoc/XMEGA-A1U-Xplained-Pro_Design-Documentation.zip) |
|
||||
|
||||
## Flashing the Device
|
||||
|
||||
The ATxmega-A1U Xplained Pro came with a full EDBG + CDC-ACM. The EDBG works
|
||||
with default avrdude tool. However, the below programmer must have at
|
||||
/etc/avrdude.conf file:
|
||||
|
||||
programmer
|
||||
id = "xplainedpro_pdi";
|
||||
desc = "Atmel AVR XplainedPro in PDI mode";
|
||||
type = "jtagice3_pdi";
|
||||
connection_type = usb;
|
||||
usbpid = 0x2111;
|
||||
;
|
||||
|
||||
In order to flash the ATxmega128A1U, simple run:
|
||||
|
||||
make BOARD=atxmega-a1u-xpro flash
|
||||
|
||||
## Serial Terminal
|
||||
|
||||
The CDC-ACM will enumerate a /dev/ttyACM device.
|
||||
|
||||
make BOARD=atxmega-a1u-xpro term
|
||||
|
||||
## On-Chip Debugging (OCD)
|
||||
|
||||
make debug
|
||||
|
||||
*/
|
104
boards/atxmega-a1u-xpro/include/board.h
Normal file
104
boards/atxmega-a1u-xpro/include/board.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* 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 boards_atxmega-a1u-xpro
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Board specific definitions for the ATxmegaA1U Xplained Pro board.
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef BOARD_H
|
||||
#define BOARD_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "macros/units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Clock configuration
|
||||
*/
|
||||
#define CLOCK_CORECLOCK MHZ(32)
|
||||
|
||||
/**
|
||||
* @name Baudrate for STDIO terminal
|
||||
*
|
||||
* The standard configuration for STDIO in cpu/atxmega/periph/uart.c
|
||||
* is to use double speed.
|
||||
*
|
||||
* For 32MHz F_CPU following Baudrate have good error rates
|
||||
* 115200
|
||||
*
|
||||
* Matches this with BAUD in Board/Makefile.include
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef STDIO_UART_BAUDRATE
|
||||
#define STDIO_UART_BAUDRATE (115200U)
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name LED pin definitions and handlers
|
||||
* @{
|
||||
*/
|
||||
#define LED_PORT PORTQ
|
||||
|
||||
#define LED0_PIN GPIO_PIN(PORT_Q, 3)
|
||||
#define LED0_MODE GPIO_OUT
|
||||
#define LED0_MASK (PIN3_bm)
|
||||
#define LED0_ON (LED_PORT.OUTCLR = LED0_MASK)
|
||||
#define LED0_OFF (LED_PORT.OUTSET = LED0_MASK)
|
||||
#define LED0_TOGGLE (LED_PORT.OUTTGL = LED0_MASK)
|
||||
|
||||
#define LED_PORT_MASK (LED0_MASK)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Button pin configuration
|
||||
* @{
|
||||
*/
|
||||
#define BTN0_PIN GPIO_PIN(PORT_Q, 2)
|
||||
#define BTN0_MODE (GPIO_IN | GPIO_OPC_PU | GPIO_SLEW_RATE)
|
||||
#define BTN0_INT_FLANK (GPIO_ISC_FALLING | GPIO_LVL_LOW)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name xtimer configuration values
|
||||
* if XTIMER_HZ > 1MHz then (XTIMER_HZ != (1000000ul << XTIMER_SHIFT))
|
||||
* if XTIMER_HZ < 1MHz then ((XTIMER_HZ << XTIMER_SHIFT) != 1000000ul)
|
||||
*
|
||||
* 32MHz Core Clock
|
||||
* XTIMER_HZ 4000000 (clkdiv 8 ) XTIMER_SHIFT 2
|
||||
* XTIMER_HZ 1000000 () XTIMER_SHIFT 0
|
||||
* XTIMER_HZ 500000 (clkdiv 64) XTIMER_SHIFT 1
|
||||
* XTIMER_HZ 250000 (clkdiv 128) XTIMER_SHIFT 2
|
||||
* XTIMER_HZ 31250 (clkdiv 1024) XTIMER_SHIFT 5
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define XTIMER_DEV TIMER_DEV(0)
|
||||
#define XTIMER_CHAN (0)
|
||||
#define XTIMER_WIDTH (16)
|
||||
#define XTIMER_HZ KHZ(500)
|
||||
#define XTIMER_BACKOFF (150)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BOARD_H */
|
||||
/** @} */
|
53
boards/atxmega-a1u-xpro/include/gpio_params.h
Normal file
53
boards/atxmega-a1u-xpro/include/gpio_params.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* 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 boards_atxmega-a1u-xpro
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Configuration of SAUL mapped GPIO pins
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef GPIO_PARAMS_H
|
||||
#define GPIO_PARAMS_H
|
||||
|
||||
#include "board.h"
|
||||
#include "saul/periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief GPIO configuration
|
||||
*/
|
||||
static const saul_gpio_params_t saul_gpio_params[] =
|
||||
{
|
||||
{
|
||||
.name = "SW0",
|
||||
.pin = BTN0_PIN,
|
||||
.mode = BTN0_MODE,
|
||||
.flags = SAUL_GPIO_INVERTED,
|
||||
},
|
||||
{
|
||||
.name = "LED0 (Yellow)",
|
||||
.pin = LED0_PIN,
|
||||
.mode = LED0_MODE,
|
||||
.flags = SAUL_GPIO_INVERTED,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GPIO_PARAMS_H */
|
||||
/** @} */
|
99
boards/atxmega-a1u-xpro/include/periph_conf.h
Normal file
99
boards/atxmega-a1u-xpro/include/periph_conf.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* 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 boards_atxmega-a1u-xpro
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Peripheral MCU configuration for the ATxmegaA1U Xplained Pro board.
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
#include "mutex.h"
|
||||
|
||||
#ifndef PERIPH_CONF_H
|
||||
#define PERIPH_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "periph_cpu.h"
|
||||
|
||||
/**
|
||||
* @name Timer peripheral configuration
|
||||
* @{
|
||||
*/
|
||||
static const timer_conf_t timer_config[] = {
|
||||
{
|
||||
.dev = (void *)&TCC1,
|
||||
.type = TC_TYPE_1,
|
||||
.int_lvl = { CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_OFF,
|
||||
CPU_INT_LVL_OFF,
|
||||
CPU_INT_LVL_OFF },
|
||||
},
|
||||
{
|
||||
.dev = (void *)&TCC0,
|
||||
.type = TC_TYPE_0,
|
||||
.int_lvl = { CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_LOW,
|
||||
CPU_INT_LVL_LOW },
|
||||
}
|
||||
};
|
||||
|
||||
#define TIMER_0_ISRA TCC1_CCA_vect
|
||||
|
||||
#define TIMER_1_ISRA TCC0_CCA_vect
|
||||
#define TIMER_1_ISRB TCC0_CCB_vect
|
||||
#define TIMER_1_ISRC TCC0_CCC_vect
|
||||
#define TIMER_1_ISRD TCC0_CCD_vect
|
||||
|
||||
#define TIMER_NUMOF ARRAY_SIZE(timer_config)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
* @{
|
||||
*/
|
||||
static const uart_conf_t uart_config[] = {
|
||||
{ /* CDC-ACM */
|
||||
.dev = &USARTE0,
|
||||
.rx_pin = GPIO_PIN(PORT_E, 2),
|
||||
.tx_pin = GPIO_PIN(PORT_E, 3),
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
.rts_pin = GPIO_UNDEF,
|
||||
.cts_pin = GPIO_UNDEF,
|
||||
#endif
|
||||
.rx_int_lvl = CPU_INT_LVL_LOW,
|
||||
.tx_int_lvl = CPU_INT_LVL_LOW,
|
||||
.dre_int_lvl = CPU_INT_LVL_OFF,
|
||||
},
|
||||
};
|
||||
|
||||
/* interrupt function name mapping */
|
||||
#define UART_0_RXC_ISR USARTE0_RXC_vect /* Reception Complete Interrupt */
|
||||
#define UART_0_DRE_ISR USARTE0_DRE_vect /* Data Register Empty Interrupt */
|
||||
#define UART_0_TXC_ISR USARTE0_TXC_vect /* Transmission Complete Interrupt */
|
||||
|
||||
#define UART_NUMOF ARRAY_SIZE(uart_config)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "periph_conf_common.h"
|
||||
|
||||
#endif /* PERIPH_CONF_H */
|
||||
/** @} */
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#ifndef CPU_ATMEGA_CLK_SCALE_INIT
|
||||
@ -42,5 +41,4 @@ void __attribute__((weak)) board_init(void)
|
||||
#ifdef LED0_ON
|
||||
led_init();
|
||||
#endif
|
||||
irq_enable();
|
||||
}
|
||||
|
3
boards/common/atxmega/Makefile
Normal file
3
boards/common/atxmega/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = boards_common_atxmega
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
1
boards/common/atxmega/Makefile.features
Normal file
1
boards/common/atxmega/Makefile.features
Normal file
@ -0,0 +1 @@
|
||||
CPU = atxmega
|
38
boards/common/atxmega/Makefile.include
Normal file
38
boards/common/atxmega/Makefile.include
Normal file
@ -0,0 +1,38 @@
|
||||
INCLUDES += -I$(RIOTBOARD)/common/atxmega/include
|
||||
|
||||
# Use JTAG as default protocol for debugging
|
||||
DEBUGPROTO ?= -x
|
||||
FLASHFILE ?= $(ELFFILE)
|
||||
|
||||
# Use avrdude programmer with Atmel ICE as default flash/debug system
|
||||
PROGRAMMER ?= avrdude
|
||||
AVRDUDE_PROGRAMMER ?= atmelice
|
||||
|
||||
ifneq (,$(filter flash%,$(MAKECMDGOALS)))
|
||||
FFLAGS_EXTRA ?= -e
|
||||
endif
|
||||
|
||||
# If avrdude specific programmer is not set, set it based on the bootloader used
|
||||
ifeq (,$(AVRDUDE_PROGRAMMER))
|
||||
FLASHFILE ?= $(BINFILE)
|
||||
|
||||
ifeq (stk500v2,$(BOOTLOADER))
|
||||
AVRDUDE_PROGRAMMER = stk500v2
|
||||
BOOTLOADER_SIZE ?= 4K
|
||||
# Disable auto erase; erasing the flash is done implicitly by the bootloader
|
||||
# and explicit erase is not supported
|
||||
FFLAGS_EXTRA += -D
|
||||
endif
|
||||
|
||||
ifeq (avr109,$(BOOTLOADER))
|
||||
AVRDUDE_PROGRAMMER = avr109
|
||||
BOOTLOADER_SIZE ?= 4K
|
||||
endif
|
||||
|
||||
ifneq (,$(BOOTLOADER_BAUD))
|
||||
FFLAGS_EXTRA += -b $(BOOTLOADER_BAUD)
|
||||
endif
|
||||
endif
|
||||
|
||||
BOOTLOADER_SIZE ?= 0
|
||||
ROM_RESERVED ?= $(BOOTLOADER_SIZE)
|
38
boards/common/atxmega/board.c
Normal file
38
boards/common/atxmega/board.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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 boards_common
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Common implementations for ATxmega boards
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
|
||||
#ifdef LED_PORT
|
||||
void __attribute__((weak)) led_init(void)
|
||||
{
|
||||
LED_PORT.DIR = LED_PORT_MASK;
|
||||
LED_PORT.OUT = LED_PORT_MASK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __attribute__((weak)) board_init(void)
|
||||
{
|
||||
cpu_init();
|
||||
#ifdef LED_PORT
|
||||
led_init();
|
||||
#endif
|
||||
}
|
5
boards/common/atxmega/doc.txt
Normal file
5
boards/common/atxmega/doc.txt
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
@defgroup boards_common_atxmega ATxmega common
|
||||
@ingroup boards
|
||||
@brief Shared files and configuration for ATxmega-based boards
|
||||
*/
|
100
boards/common/atxmega/include/periph_conf_common.h
Normal file
100
boards/common/atxmega/include/periph_conf_common.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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 boards_common_atxmega
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Common configuration of MCU periphery for ATxmega boards
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CONF_COMMON_H
|
||||
#define PERIPH_CONF_COMMON_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "macros/units.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Clock configuration
|
||||
* @{
|
||||
*/
|
||||
#ifndef CLOCK_CORECLOCK
|
||||
#define CLOCK_CORECLOCK MHZ(32)
|
||||
#endif /* CLOCK_CORECLOCK */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ADC Configuration
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef ADC_NUMOF
|
||||
#define ADC_NUMOF (0U)
|
||||
#endif /* ADC_NUMOF */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name I2C configuration
|
||||
* @{
|
||||
*/
|
||||
#ifndef I2C_NUMOF
|
||||
#define I2C_NUMOF (0U)
|
||||
#endif /* I2C_NUMOF */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name PWM configuration
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef PWM_NUMOF
|
||||
#define PWM_NUMOF (0U)
|
||||
#endif /* PWM_NUMOF */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name SPI configuration
|
||||
*
|
||||
* The SS pin must be configured as output for the SPI device to work as
|
||||
* master correctly, though we do not use it for now (as we handle the chip
|
||||
* select externally for now)
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef SPI_NUMOF
|
||||
#define SPI_NUMOF (0U)
|
||||
#endif /* SPI_NUMOF */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name UART configuration
|
||||
*
|
||||
* The UART devices have fixed pin mappings, so all we need to do, is to specify
|
||||
* which devices we would like to use and their corresponding RX interrupts. See
|
||||
* the reference manual for the fixed pin mapping.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef UART_NUMOF
|
||||
#define UART_NUMOF (0U)
|
||||
#endif /* UART_NUMOF */
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CONF_COMMON_H */
|
||||
/** @} */
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
#include "irq.h"
|
||||
|
||||
/**
|
||||
* @brief Initialize the boards on-board LEDs (green and red)
|
||||
@ -61,5 +60,4 @@ void board_init(void)
|
||||
|
||||
cpu_init();
|
||||
led_init();
|
||||
irq_enable();
|
||||
}
|
||||
|
@ -4,11 +4,16 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
#
|
||||
|
||||
config HAS_CPU_CORE_ATMEGA
|
||||
bool
|
||||
select CPU_ARCH_AVR8
|
||||
select HAS_CPP
|
||||
|
||||
config CPU_COMMON_ATMEGA
|
||||
bool
|
||||
select CPU_CORE_AVR
|
||||
select HAS_CPU_CORE_ATMEGA
|
||||
select HAS_ATMEGA_PCINT0
|
||||
select HAS_CPP
|
||||
select HAS_DBGPIN
|
||||
select HAS_PERIPH_CPUID
|
||||
select HAS_PERIPH_EEPROM
|
||||
|
@ -3,6 +3,7 @@ include $(RIOTCPU)/avr8_common/Makefile.features
|
||||
# common feature are defined in avr8_common/Makefile.features
|
||||
# Only add Additional features
|
||||
|
||||
FEATURES_PROVIDED += cpu_core_atmega
|
||||
FEATURES_PROVIDED += atmega_pcint0
|
||||
FEATURES_PROVIDED += dbgpin
|
||||
FEATURES_PROVIDED += periph_cpuid
|
||||
|
85
cpu/atxmega/Kconfig
Normal file
85
cpu/atxmega/Kconfig
Normal file
@ -0,0 +1,85 @@
|
||||
# Copyright (c) 2020 HAW Hamburg
|
||||
# Copyright (c) 2021 Gerson Fernando Budke
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
config HAS_CPU_CORE_ATXMEGA
|
||||
bool
|
||||
select CPU_ARCH_AVR8
|
||||
select HAS_CPU_ATXMEGA
|
||||
select HAS_CPP
|
||||
|
||||
config CPU_COMMON_ATXMEGA
|
||||
bool
|
||||
select HAS_CPU_CORE_ATXMEGA
|
||||
select HAS_PERIPH_CPUID
|
||||
select HAS_PERIPH_GPIO
|
||||
select HAS_PERIPH_GPIO_IRQ
|
||||
select HAS_PERIPH_NVM
|
||||
select HAS_PERIPH_PM
|
||||
select HAS_PERIPH_TIMER
|
||||
select HAS_PERIPH_TIMER_PERIODIC
|
||||
select HAS_PERIPH_UART
|
||||
|
||||
config CPU_CORE_ATXMEGA_A1
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_A3
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_A4
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_B1
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_B3
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_C3
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_C4
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_D3
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_D4
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU_CORE_ATXMEGA_E5
|
||||
bool
|
||||
select CPU_COMMON_ATXMEGA
|
||||
|
||||
config CPU
|
||||
default "atxmega" if CPU_COMMON_ATXMEGA
|
||||
|
||||
source "$(RIOTCPU)/atxmega/Kconfig.XMEGAA"
|
||||
source "$(RIOTCPU)/atxmega/Kconfig.XMEGAB"
|
||||
source "$(RIOTCPU)/atxmega/Kconfig.XMEGAC"
|
||||
source "$(RIOTCPU)/atxmega/Kconfig.XMEGAD"
|
||||
source "$(RIOTCPU)/atxmega/Kconfig.XMEGAE"
|
||||
|
||||
## Declaration of specific features
|
||||
config HAS_CPU_ATXMEGA
|
||||
bool
|
||||
|
||||
config HAS_PERIPH_NVM
|
||||
bool
|
||||
help
|
||||
Indicates that the Non Volatile Memory controller is present.
|
||||
|
||||
source "$(RIOTCPU)/avr8_common/Kconfig"
|
105
cpu/atxmega/Kconfig.XMEGAA
Normal file
105
cpu/atxmega/Kconfig.XMEGAA
Normal file
@ -0,0 +1,105 @@
|
||||
## CPU Models
|
||||
# XMEGA - A1/A1U
|
||||
config CPU_MODEL_XMEGA64A1
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A1
|
||||
|
||||
config CPU_MODEL_XMEGA128A1
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A1
|
||||
|
||||
config CPU_MODEL_XMEGA64A1U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A1
|
||||
|
||||
config CPU_MODEL_XMEGA128A1U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A1
|
||||
|
||||
# XMEGA - A3/A3U/A3BU
|
||||
config CPU_MODEL_XMEGA64A3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA128A3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA192A3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA256A3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA64A3U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA128A3U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA192A3U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA256A3U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
config CPU_MODEL_XMEGA256A3BU
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A3
|
||||
|
||||
# XMEGA - A4/A4U
|
||||
config CPU_MODEL_XMEGA16A4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL_XMEGA32A4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL_XMEGA16A4U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL_XMEGA32A4U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL_XMEGA64A4U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL_XMEGA128A4U
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_A4
|
||||
|
||||
config CPU_MODEL
|
||||
string
|
||||
default "atxmega64a1" if CPU_MODEL_XMEGA64A1
|
||||
default "atxmega128a1" if CPU_MODEL_XMEGA128A1
|
||||
default "atxmega192a1" if CPU_MODEL_XMEGA192A1
|
||||
default "atxmega256a1" if CPU_MODEL_XMEGA256A1
|
||||
default "atxmega64a1u" if CPU_MODEL_XMEGA64A1U
|
||||
default "atxmega128a1u" if CPU_MODEL_XMEGA128A1U
|
||||
|
||||
default "atxmega64a3" if CPU_MODEL_XMEGA64A3
|
||||
default "atxmega128a3" if CPU_MODEL_XMEGA128A3
|
||||
default "atxmega192a3" if CPU_MODEL_XMEGA192A3
|
||||
default "atxmega256a3" if CPU_MODEL_XMEGA256A3
|
||||
default "atxmega64a3u" if CPU_MODEL_XMEGA64A3U
|
||||
default "atxmega128a3u" if CPU_MODEL_XMEGA128A3U
|
||||
default "atxmega192a3u" if CPU_MODEL_XMEGA192A3U
|
||||
default "atxmega256a3u" if CPU_MODEL_XMEGA256A3U
|
||||
default "atxmega256a3bu" if CPU_MODEL_XMEGA256A3BU
|
||||
|
||||
default "atxmega16a4" if CPU_MODEL_XMEGA16A4
|
||||
default "atxmega32a4" if CPU_MODEL_XMEGA32A4
|
||||
default "atxmega16a4u" if CPU_MODEL_XMEGA16A4U
|
||||
default "atxmega32a4u" if CPU_MODEL_XMEGA32A4U
|
||||
default "atxmega64a4u" if CPU_MODEL_XMEGA64A4U
|
||||
default "atxmega128a4u" if CPU_MODEL_XMEGA128A4U
|
25
cpu/atxmega/Kconfig.XMEGAB
Normal file
25
cpu/atxmega/Kconfig.XMEGAB
Normal file
@ -0,0 +1,25 @@
|
||||
## CPU Models
|
||||
# XMEGA - B1
|
||||
config CPU_MODEL_XMEGA64B1
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_B1
|
||||
|
||||
config CPU_MODEL_XMEGA128B1
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_B1
|
||||
|
||||
# XMEGA - B3
|
||||
config CPU_MODEL_XMEGA64B3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_B3
|
||||
|
||||
config CPU_MODEL_XMEGA128B3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_B3
|
||||
|
||||
config CPU_MODEL
|
||||
default "atxmega64b3" if CPU_MODEL_XMEGA64B3
|
||||
default "atxmega128b3" if CPU_MODEL_XMEGA128B3
|
||||
|
||||
default "atxmega64b1" if CPU_MODEL_XMEGA64B1
|
||||
default "atxmega128b1" if CPU_MODEL_XMEGA128B1
|
45
cpu/atxmega/Kconfig.XMEGAC
Normal file
45
cpu/atxmega/Kconfig.XMEGAC
Normal file
@ -0,0 +1,45 @@
|
||||
## CPU Models
|
||||
# XMEGA - C3
|
||||
config CPU_MODEL_XMEGA32C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
config CPU_MODEL_XMEGA64C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
config CPU_MODEL_XMEGC128C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
config CPU_MODEL_XMEGC192C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
config CPU_MODEL_XMEGA256C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
config CPU_MODEL_XMEGA384C3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C3
|
||||
|
||||
# XMEGA - C4
|
||||
config CPU_MODEL_XMEGA16C4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C4
|
||||
|
||||
config CPU_MODEL_XMEGA32C4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_C4
|
||||
|
||||
config CPU_MODEL
|
||||
default "atxmega32c3" if CPU_MODEL_XMEGA32C3
|
||||
default "atxmega64c3" if CPU_MODEL_XMEGA64C3
|
||||
default "atxmega128c3" if CPU_MODEL_XMEGC128C3
|
||||
default "atxmega192c3" if CPU_MODEL_XMEGC192C3
|
||||
default "atxmega256c3" if CPU_MODEL_XMEGA256C3
|
||||
default "atxmega384c3" if CPU_MODEL_XMEGA384C3
|
||||
|
||||
default "atxmega16c4" if CPU_MODEL_XMEGA16C4
|
||||
default "atxmega32c4" if CPU_MODEL_XMEGA32C4
|
55
cpu/atxmega/Kconfig.XMEGAD
Normal file
55
cpu/atxmega/Kconfig.XMEGAD
Normal file
@ -0,0 +1,55 @@
|
||||
## CPU Models
|
||||
# XMEGA - D3
|
||||
config CPU_MODEL_XMEGA32D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
config CPU_MODEL_XMEGA64D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
config CPU_MODEL_XMEGC128D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
config CPU_MODEL_XMEGC192D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
config CPU_MODEL_XMEGA256D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
config CPU_MODEL_XMEGA384D3
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D3
|
||||
|
||||
# XMEGA - D4
|
||||
config CPU_MODEL_XMEGA16D4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D4
|
||||
|
||||
config CPU_MODEL_XMEGA32D4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D4
|
||||
|
||||
config CPU_MODEL_XMEGA64D4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D4
|
||||
|
||||
config CPU_MODEL_XMEGA128D4
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_D4
|
||||
|
||||
config CPU_MODEL
|
||||
default "atxmega32d3" if CPU_MODEL_XMEGA32D3
|
||||
default "atxmega64d3" if CPU_MODEL_XMEGA64D3
|
||||
default "atxmega128d3" if CPU_MODEL_XMEGC128D3
|
||||
default "atxmega192d3" if CPU_MODEL_XMEGC192D3
|
||||
default "atxmega256d3" if CPU_MODEL_XMEGA256D3
|
||||
default "atxmega384d3" if CPU_MODEL_XMEGA384D3
|
||||
|
||||
default "atxmega16d4" if CPU_MODEL_XMEGA16D4
|
||||
default "atxmega32d4" if CPU_MODEL_XMEGA32D4
|
||||
default "atxmega64d4" if CPU_MODEL_XMEGA64D4
|
||||
default "atxmega128d4" if CPU_MODEL_XMEGA128D4
|
17
cpu/atxmega/Kconfig.XMEGAE
Normal file
17
cpu/atxmega/Kconfig.XMEGAE
Normal file
@ -0,0 +1,17 @@
|
||||
## CPU Models
|
||||
config CPU_MODEL_XMEGA8E5
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_E5
|
||||
|
||||
config CPU_MODEL_XMEGA16E5
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_E5
|
||||
|
||||
config CPU_MODEL_XMEGA32E5
|
||||
bool
|
||||
select CPU_CORE_ATXMEGA_E5
|
||||
|
||||
config CPU_MODEL
|
||||
default "atxmega8e5" if CPU_MODEL_XMEGA8E5
|
||||
default "atxmega16e5" if CPU_MODEL_XMEGA16E5
|
||||
default "atxmega32e5" if CPU_MODEL_XMEGA32E5
|
7
cpu/atxmega/Makefile
Normal file
7
cpu/atxmega/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# define the module that is build
|
||||
MODULE = cpu
|
||||
|
||||
# add a list of subdirectories, that should also be build
|
||||
DIRS = periph $(RIOTCPU)/avr8_common/
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
11
cpu/atxmega/Makefile.dep
Normal file
11
cpu/atxmega/Makefile.dep
Normal file
@ -0,0 +1,11 @@
|
||||
# peripheral drivers are linked into the final binary
|
||||
USEMODULE += atxmega_periph
|
||||
|
||||
# All ATxmega based CPUs provide PM
|
||||
USEMODULE += pm_layered
|
||||
|
||||
ifeq (,$(filter cpuid,$(USEMODULE)))
|
||||
USEMODULE += periph_nvm
|
||||
endif
|
||||
|
||||
include $(RIOTCPU)/avr8_common/Makefile.dep
|
12
cpu/atxmega/Makefile.features
Normal file
12
cpu/atxmega/Makefile.features
Normal file
@ -0,0 +1,12 @@
|
||||
include $(RIOTCPU)/avr8_common/Makefile.features
|
||||
|
||||
# common feature are defined in avr8_common/Makefile.features
|
||||
# Only add Additional features
|
||||
|
||||
FEATURES_PROVIDED += cpu_core_atxmega
|
||||
FEATURES_PROVIDED += periph_cpuid
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_nvm
|
||||
FEATURES_PROVIDED += periph_pm
|
||||
FEATURES_PROVIDED += periph_timer periph_timer_periodic
|
||||
FEATURES_PROVIDED += periph_uart
|
38
cpu/atxmega/Makefile.include
Normal file
38
cpu/atxmega/Makefile.include
Normal file
@ -0,0 +1,38 @@
|
||||
export CPU_ATXMEGA 1
|
||||
|
||||
# CPU ROM/RAM
|
||||
ifneq (,$(findstring atxmega8,$(CPU_MODEL)))
|
||||
RAM_LEN = 1K
|
||||
ROM_LEN = 8K
|
||||
endif
|
||||
ifneq (,$(findstring atxmega16,$(CPU_MODEL)))
|
||||
RAM_LEN = 2K
|
||||
ROM_LEN = 16K
|
||||
endif
|
||||
ifneq (,$(findstring atxmega32,$(CPU_MODEL)))
|
||||
RAM_LEN = 4K
|
||||
ROM_LEN = 32K
|
||||
endif
|
||||
ifneq (,$(findstring atxmega64,$(CPU_MODEL)))
|
||||
RAM_LEN ?= 4K
|
||||
ROM_LEN = 64K
|
||||
endif
|
||||
#ifneq (,$(findstring atxmega128,$(CPU_MODEL)))
|
||||
RAM_LEN ?= 8K
|
||||
ROM_LEN = 128K
|
||||
#endif
|
||||
ifneq (,$(findstring atxmega192,$(CPU_MODEL)))
|
||||
RAM_LEN = 16K
|
||||
ROM_LEN = 192K
|
||||
endif
|
||||
ifneq (,$(findstring atxmega256,$(CPU_MODEL)))
|
||||
RAM_LEN = 16K
|
||||
ROM_LEN = 256K
|
||||
endif
|
||||
ifneq (,$(findstring atxmega384,$(CPU_MODEL)))
|
||||
RAM_LEN = 32K
|
||||
ROM_LEN = 384K
|
||||
endif
|
||||
|
||||
# CPU depends on the avr8 common module, so include it
|
||||
include $(RIOTCPU)/avr8_common/Makefile.include
|
132
cpu/atxmega/atxmega_cpu.c
Normal file
132
cpu/atxmega/atxmega_cpu.c
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* 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_atxmega
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the CPU initialization
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_clock.h"
|
||||
#include "panic.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef CPU_ATXMEGA_CLK_SCALE_INIT
|
||||
#define CPU_ATXMEGA_CLK_SCALE_INIT CPU_ATXMEGA_CLK_SCALE_DIV1
|
||||
#endif
|
||||
#ifndef CPU_ATXMEGA_BUS_SCALE_INIT
|
||||
#define CPU_ATXMEGA_BUS_SCALE_INIT CPU_ATXMEGA_BUS_SCALE_DIV1_1
|
||||
#endif
|
||||
|
||||
extern uint8_t mcusr_mirror;
|
||||
|
||||
void avr8_reset_cause(void)
|
||||
{
|
||||
if (mcusr_mirror & (1 << RST_PORF_bp)) {
|
||||
DEBUG("Power-on reset.\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_EXTRF_bp)) {
|
||||
DEBUG("External reset!\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_BORF_bp)) {
|
||||
DEBUG("Brown-out reset!\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_WDRF_bp)) {
|
||||
DEBUG("Watchdog reset!\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_PDIRF_bp)) {
|
||||
DEBUG("Programming and Debug Interface reset!\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_SRF_bp)) {
|
||||
DEBUG("Software reset!\n");
|
||||
}
|
||||
if (mcusr_mirror & (1 << RST_SDRF_bp)) {
|
||||
DEBUG("Spike Detection reset!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((weak)) avr8_clk_init(void)
|
||||
{
|
||||
volatile uint8_t *reg = (uint8_t *)&PR.PRGEN;
|
||||
uint8_t i;
|
||||
|
||||
/* Turn off all peripheral clocks that can be turned off. */
|
||||
for (i = 0; i <= 7; i++) {
|
||||
reg[i] = 0xff;
|
||||
}
|
||||
|
||||
/* Turn on all peripheral clocks that can be turned on. */
|
||||
for (i = 0; i <= 7; i++) {
|
||||
reg[i] = 0x00;
|
||||
}
|
||||
|
||||
/* XMEGA A3U [DATASHEET] p.23 After reset, the device starts up running
|
||||
* from the 2MHz internal oscillator. The other clock sources, DFLLs
|
||||
* and PLL, are turned off by default.
|
||||
*
|
||||
* Configure clock to 32MHz with calibration
|
||||
* application note AVR1003
|
||||
*
|
||||
* From errata http://www.avrfreaks.net/forum/xmega-dfll-does-it-work
|
||||
* In order to use the automatic runtime calibration for the 2 MHz or
|
||||
* the 32 MHz internal oscillators, the DFLL for both oscillators and
|
||||
* both oscillators has to be enabled for one to work.
|
||||
*/
|
||||
OSC.PLLCTRL = 0;
|
||||
|
||||
/* Enable the internal PLL & 32MHz & 32KHz oscillators */
|
||||
OSC.CTRL |= OSC_PLLEN_bm | OSC_RC32MEN_bm | OSC_RC32KEN_bm;
|
||||
|
||||
/* Wait for 32Khz and 32MHz oscillator to stabilize */
|
||||
while ((OSC.STATUS & (OSC_RC32KRDY_bm | OSC_RC32MRDY_bm))
|
||||
!= (OSC_RC32KRDY_bm | OSC_RC32MRDY_bm)) {}
|
||||
|
||||
/* Enable DFLL - defaults to calibrate against internal 32Khz clock */
|
||||
DFLLRC32M.CTRL = DFLL_ENABLE_bm;
|
||||
|
||||
/* Enable DFLL - defaults to calibrate against internal 32Khz clock */
|
||||
DFLLRC2M.CTRL = DFLL_ENABLE_bm;
|
||||
|
||||
atxmega_set_prescaler(CPU_ATXMEGA_CLK_SCALE_INIT,
|
||||
CPU_ATXMEGA_BUS_SCALE_INIT);
|
||||
|
||||
/* Disable CCP for Protected IO register and set new value*/
|
||||
/* Switch to 32MHz clock */
|
||||
_PROTECTED_WRITE(CLK.CTRL, CLK_SCLKSEL_RC32M_gc);
|
||||
}
|
||||
|
||||
/* This is a vector which is aliased to __vector_default,
|
||||
* the vector executed when an ISR fires with no accompanying
|
||||
* ISR handler. This may be used along with the ISR() macro to
|
||||
* create a catch-all for undefined but used ISRs for debugging
|
||||
* purposes.
|
||||
*/
|
||||
ISR(BADISR_vect)
|
||||
{
|
||||
avr8_reset_cause();
|
||||
|
||||
#ifdef LED_PANIC
|
||||
/* Use LED light to signal ERROR. */
|
||||
LED_PANIC;
|
||||
#endif
|
||||
|
||||
core_panic(PANIC_GENERAL_ERROR,
|
||||
PSTR("FATAL ERROR: BADISR_vect called, unprocessed Interrupt.\n"
|
||||
"STOP Execution.\n"));
|
||||
}
|
10
cpu/atxmega/doc.txt
Normal file
10
cpu/atxmega/doc.txt
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @defgroup cpu_atxmega Atmel ATxmega MCU
|
||||
* @ingroup cpu
|
||||
* @brief Implementation of Atmel's ATxmega MCU
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup cpu_atxmega_periph Atmel ATxmega MCU Peripherals
|
||||
* @ingroup cpu_atxmega
|
||||
*/
|
75
cpu/atxmega/include/cpu_clock.h
Normal file
75
cpu/atxmega/include/cpu_clock.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @brief Common implementations and headers for ATxmega family based micro-controllers
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Basic definitions for the ATxmega common clock module
|
||||
*
|
||||
* When ever you want to do something hardware related, that is accessing MCUs registers directly,
|
||||
* just include this file. It will then make sure that the MCU specific headers are included.
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_CLOCK_H
|
||||
#define CPU_CLOCK_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ATxmega system clock prescaler settings
|
||||
*
|
||||
* Some CPUs may not support the highest prescaler settings
|
||||
*/
|
||||
enum {
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV1 = 0,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV2 = 1,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV4 = 3,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV8 = 5,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV16 = 7,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV32 = 9,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV64 = 11,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV128 = 13,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV256 = 15,
|
||||
CPU_ATXMEGA_CLK_SCALE_DIV512 = 17,
|
||||
};
|
||||
|
||||
enum {
|
||||
CPU_ATXMEGA_BUS_SCALE_DIV1_1 = 0,
|
||||
CPU_ATXMEGA_BUS_SCALE_DIV1_2 = 1,
|
||||
CPU_ATXMEGA_BUS_SCALE_DIV4_1 = 2,
|
||||
CPU_ATXMEGA_BUS_SCALE_DIV2_2 = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initializes system clock prescaler
|
||||
*/
|
||||
static inline void atxmega_set_prescaler(uint8_t clk_scale, uint8_t bus_scale)
|
||||
{
|
||||
/* Disable CCP for Protected IO register and set new value
|
||||
* Set system clock prescalers to zero. PSCTRL contains A Prescaler
|
||||
* Value and one value for and B and C Prescaler
|
||||
*/
|
||||
_PROTECTED_WRITE(CLK.PSCTRL, clk_scale | bus_scale);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CPU_CLOCK_H */
|
||||
/** @} */
|
76
cpu/atxmega/include/cpu_conf.h
Normal file
76
cpu/atxmega/include/cpu_conf.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke
|
||||
*
|
||||
* 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_atxmega
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation specific CPU configuration options
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef CPU_CONF_H
|
||||
#define CPU_CONF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define THREAD_EXTRA_STACKSIZE_PRINTF (128)
|
||||
|
||||
/**
|
||||
* @name Kernel configuration
|
||||
*
|
||||
* Since printf seems to get memory allocated by the
|
||||
* linker/avr-libc the stack size tested successfully
|
||||
* even with pretty small stacks.
|
||||
* @{
|
||||
*/
|
||||
#ifndef THREAD_STACKSIZE_DEFAULT
|
||||
#define THREAD_STACKSIZE_DEFAULT (512)
|
||||
#endif
|
||||
|
||||
/* keep THREAD_STACKSIZE_IDLE > THREAD_EXTRA_STACKSIZE_PRINTF
|
||||
* to avoid not printing of debug in interrupts
|
||||
*/
|
||||
#ifndef THREAD_STACKSIZE_IDLE
|
||||
#ifdef MODULE_XTIMER
|
||||
/* xtimer's 64 bit arithmetic doesn't perform well on 8 bit archs. In order to
|
||||
* prevent a stack overflow when an timer triggers while the idle thread is
|
||||
* running, we have to increase the stack size then
|
||||
*/
|
||||
#define THREAD_STACKSIZE_IDLE (384)
|
||||
#else
|
||||
#define THREAD_STACKSIZE_IDLE (192)
|
||||
#endif
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Declare the heap_stats function as available
|
||||
*/
|
||||
#define HAVE_HEAP_STATS
|
||||
|
||||
/**
|
||||
* @brief This arch uses the inlined IRQ API.
|
||||
*/
|
||||
#define IRQ_API_INLINED (1)
|
||||
|
||||
/**
|
||||
* @brief This arch require special clock initialization.
|
||||
*/
|
||||
#define CPU_AVR8_HAS_CLOCK_INIT 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CPU_CONF_H */
|
||||
/** @} */
|
65
cpu/atxmega/include/cpu_nvm.h
Normal file
65
cpu/atxmega/include/cpu_nvm.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @brief Non Volatile Memory (NVM) internal API
|
||||
* @{
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_NVM_H
|
||||
#define CPU_NVM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get offset of calibration bytes in the production signature row
|
||||
*
|
||||
* @note In some distributions may require most recent vendor headers, even
|
||||
* more recent than the upstream avr-libc. The headers can be download
|
||||
* directly from Microchip web site. In general, Microchip have a
|
||||
* dedicated page at Tools and Software / AVR and SAM Downloads Archive.
|
||||
* The most recent version is AVR 8-bit Toolchain (3.4.4) 6.2.0.334.
|
||||
* http://ww1.microchip.com/downloads/archive/avr8-headers-6.2.0.334.zip
|
||||
*
|
||||
* The official RIOT-OS docker container, Debian and Ubuntu are
|
||||
* distributions that already had updated versions of those files.
|
||||
*
|
||||
* @param regname Name of register within the production signature row
|
||||
* @retval Offset of register into the production signature row
|
||||
*/
|
||||
#define nvm_get_production_signature_row_offset(regname) \
|
||||
offsetof(NVM_PROD_SIGNATURES_t, regname)
|
||||
|
||||
/**
|
||||
* @brief Read one byte from the production signature row
|
||||
*
|
||||
* This function reads one byte from the production signature row of the device
|
||||
* at the given address.
|
||||
*
|
||||
* @note This function is modifying the NVM.CMD register.
|
||||
* If the application are using program space access in interrupts
|
||||
* (__flash pointers in IAR EW or pgm_read_byte in GCC) interrupts
|
||||
* needs to be disabled when running EEPROM access functions. If not
|
||||
* the program space reads will be corrupted.
|
||||
*
|
||||
* @param address Byte offset into the signature row
|
||||
*/
|
||||
uint8_t nvm_read_production_signature_row(uint8_t address);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CPU_NVM_H */
|
||||
/** @} */
|
247
cpu/atxmega/include/periph_cpu.h
Normal file
247
cpu/atxmega/include/periph_cpu.h
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief CPU specific definitions for internal peripheral handling
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CPU_H
|
||||
#define PERIPH_CPU_H
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Length of the CPU_ID in octets
|
||||
* @{
|
||||
*/
|
||||
#define CPUID_LEN (11U)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Interrupt level used to control nested interrupts
|
||||
* @{
|
||||
*/
|
||||
typedef enum {
|
||||
CPU_INT_LVL_OFF, /**< Interrupt Disabled */
|
||||
CPU_INT_LVL_LOW, /**< Interrupt Low Level */
|
||||
CPU_INT_LVL_MID, /**< Interrupt Medium Level */
|
||||
CPU_INT_LVL_HIGH, /**< Interrupt High Level */
|
||||
} cpu_int_lvl_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Available ports on the ATxmega family
|
||||
*/
|
||||
enum {
|
||||
PORT_A, /**< port A - 600 - 0 */
|
||||
PORT_B, /**< port B - 620 - 1 */
|
||||
PORT_C, /**< port C - 640 - 2 */
|
||||
PORT_D, /**< port D - 660 - 3 */
|
||||
PORT_E, /**< port E - 680 - 4 */
|
||||
PORT_F, /**< port F - 6A0 - 5 */
|
||||
PORT_G, /**< port G - 6C0 - 6 */
|
||||
PORT_H, /**< port H - 6E0 - 7 */
|
||||
PORT_J, /**< port J - 700 - 8 */
|
||||
PORT_K, /**< port K - 720 - 9 */
|
||||
PORT_L, /**< port L - 740 - A */
|
||||
PORT_M, /**< port M - 760 - B */
|
||||
PORT_N, /**< port N - 780 - C */
|
||||
PORT_P, /**< port P - 7A0 - D */
|
||||
PORT_Q, /**< port Q - 7C0 - E */
|
||||
PORT_R, /**< port R - 7E0 - F */
|
||||
/* ... */
|
||||
PORT_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Power management configuration
|
||||
* @{
|
||||
*/
|
||||
#define PM_NUM_MODES (4)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Define the number of GPIO interrupts vectors for ATxmega CPU.
|
||||
* @{
|
||||
*/
|
||||
#define GPIO_EXT_INT_NUMOF (2 * PORT_MAX)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Override GPIO type
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_T
|
||||
typedef uint16_t gpio_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Definition of a fitting UNDEF value
|
||||
*/
|
||||
#define GPIO_UNDEF (0xffff)
|
||||
|
||||
/**
|
||||
* @brief Define a CPU specific GPIO pin generator macro
|
||||
*
|
||||
* The ATxmega internally uses pin mask to manipulate all gpio functions.
|
||||
* This allows simultaneous pin actions at any method call. ATxmega specific
|
||||
* applications can use ATXMEGA_GPIO_PIN macro to define pins and generic
|
||||
* RIOT-OS application should continue to use GPIO_PIN API for compatibility.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define ATXMEGA_GPIO_PIN(x, y) (((x & 0x0f) << 8) | (y & 0xff))
|
||||
#define GPIO_PIN(x, y) ATXMEGA_GPIO_PIN(x, (1U << (y & 0x07)))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Available pin modes
|
||||
*
|
||||
* Generally, a pin can be configured to be input or output. In output mode, a
|
||||
* pin can further be put into push-pull or open drain configuration. Though
|
||||
* this is supported by most platforms, this is not always the case, so driver
|
||||
* implementations may return an error code if a mode is not supported.
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_MODE_T
|
||||
typedef enum GPIO_MODE {
|
||||
GPIO_SLEW_RATE = (1 << 7), /**< enable slew rate */
|
||||
GPIO_INVERTED = (1 << 6), /**< enable inverted signal */
|
||||
|
||||
GPIO_OPC_TOTEN = (0 << 3), /**< select no pull resistor (TOTEM) */
|
||||
GPIO_OPC_BSKPR = (1 << 3), /**< push-pull mode (BUSKEEPER) */
|
||||
GPIO_OPC_PD = (2 << 3), /**< pull-down resistor */
|
||||
GPIO_OPC_PU = (3 << 3), /**< pull-up resistor */
|
||||
GPIO_OPC_WRD_OR = (4 << 3), /**< enable wired OR */
|
||||
GPIO_OPC_WRD_AND = (5 << 3), /**< enable wired AND */
|
||||
GPIO_OPC_WRD_OR_PULL = (6 << 3), /**< enable wired OR and pull-down resistor */
|
||||
GPIO_OPC_WRD_AND_PULL = (7 << 3), /**< enable wired AND and pull-up resistor */
|
||||
|
||||
GPIO_ANALOG = (1 << 1), /**< select GPIO for analog function */
|
||||
|
||||
GPIO_IN = (0 << 0), /**< select GPIO MASK as input */
|
||||
GPIO_OUT = (1 << 0), /**< select GPIO MASK as output */
|
||||
|
||||
/* Compatibility Mode */
|
||||
GPIO_IN_PU = GPIO_IN | GPIO_OPC_PU,
|
||||
GPIO_IN_PD = GPIO_IN | GPIO_OPC_PD,
|
||||
GPIO_OD = GPIO_OUT | GPIO_OPC_WRD_OR,
|
||||
GPIO_OD_PU = GPIO_OUT | GPIO_OPC_WRD_OR_PULL,
|
||||
} gpio_mode_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Definition of possible active flanks for external interrupt mode
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_FLANK_T
|
||||
typedef enum {
|
||||
GPIO_ISC_BOTH = (0 << 4), /**< emit interrupt on both flanks (default) */
|
||||
GPIO_ISC_RISING = (1 << 4), /**< emit interrupt on rising flank */
|
||||
GPIO_ISC_FALLING = (2 << 4), /**< emit interrupt on falling flank */
|
||||
GPIO_ISC_LOW_LEVEL = (3 << 4), /**< emit interrupt on low level */
|
||||
|
||||
GPIO_INT_DISABLED_ALL = (1 << 3), /**< disable all interrupts */
|
||||
|
||||
GPIO_INT0_VCT = (0 << 2), /**< enable interrupt on Vector 0 (default) */
|
||||
GPIO_INT1_VCT = (1 << 2), /**< enable interrupt on Vector 1 */
|
||||
|
||||
GPIO_LVL_OFF = (0 << 0), /**< interrupt disabled (default) */
|
||||
GPIO_LVL_LOW = (1 << 0), /**< interrupt low level */
|
||||
GPIO_LVL_MID = (2 << 0), /**< interrupt medium level */
|
||||
GPIO_LVL_HIGH = (3 << 0), /**< interrupt higher */
|
||||
|
||||
/* Compatibility Mode */
|
||||
GPIO_FALLING = GPIO_ISC_FALLING | GPIO_LVL_LOW,
|
||||
GPIO_RISING = GPIO_ISC_RISING | GPIO_LVL_LOW,
|
||||
GPIO_BOTH = GPIO_ISC_BOTH | GPIO_LVL_LOW,
|
||||
} gpio_flank_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Max number of available UARTs
|
||||
*/
|
||||
#define UART_MAX_NUMOF (7)
|
||||
|
||||
/**
|
||||
* @brief Size of the UART TX buffer for non-blocking mode.
|
||||
*/
|
||||
#ifndef UART_TXBUF_SIZE
|
||||
#define UART_TXBUF_SIZE (64)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART device configuration
|
||||
*/
|
||||
typedef struct {
|
||||
USART_t *dev; /**< pointer to the used UART device */
|
||||
gpio_t rx_pin; /**< pin used for RX */
|
||||
gpio_t tx_pin; /**< pin used for TX */
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
gpio_t rts_pin; /**< RTS pin */
|
||||
gpio_t cts_pin; /**< CTS pin */
|
||||
#endif
|
||||
cpu_int_lvl_t rx_int_lvl; /**< RX Complete Interrupt Level */
|
||||
cpu_int_lvl_t tx_int_lvl; /**< TX Complete Interrupt Level */
|
||||
cpu_int_lvl_t dre_int_lvl; /**< Data Registry Empty Interrupt Level */
|
||||
} uart_conf_t;
|
||||
|
||||
/**
|
||||
* @brief Max number of available timer channels
|
||||
*/
|
||||
#define TIMER_CH_MAX_NUMOF (4)
|
||||
|
||||
/**
|
||||
* @brief A low-level timer_set() implementation is provided
|
||||
*/
|
||||
#define PERIPH_TIMER_PROVIDES_SET
|
||||
|
||||
/**
|
||||
* @brief Timer Type
|
||||
*
|
||||
* Timer Type 1 is equal to Type 0 (two channels instead four)
|
||||
* Timer Type 2 is Type 0 configured as two 8 bit timers instead one 16 bit
|
||||
* Timer Type 2 won't be available as a standard timer
|
||||
* Timer Type 5 is equal to Type 4 (two channels instead four)
|
||||
*/
|
||||
typedef enum {
|
||||
TC_TYPE_0 = 0,
|
||||
TC_TYPE_1 = 1,
|
||||
TC_TYPE_2 = 2,
|
||||
TC_TYPE_4 = 4,
|
||||
TC_TYPE_5 = 5,
|
||||
} timer_type_t;
|
||||
|
||||
/**
|
||||
* @brief Timer device configuration
|
||||
*
|
||||
* All timers can be derived from TC0_t struct. Need check at runtime the
|
||||
* type and number of channels to perform all operations.
|
||||
*/
|
||||
typedef struct {
|
||||
TC0_t *dev; /**< Pointer to the used as Timer device */
|
||||
timer_type_t type; /**< Timer Type */
|
||||
cpu_int_lvl_t int_lvl[TIMER_CH_MAX_NUMOF]; /**< Interrupt channels level */
|
||||
} timer_conf_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PERIPH_CPU_H */
|
||||
/** @} */
|
3
cpu/atxmega/periph/Makefile
Normal file
3
cpu/atxmega/periph/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = atxmega_periph
|
||||
|
||||
include $(RIOTMAKE)/periph.mk
|
64
cpu/atxmega/periph/cpuid.c
Normal file
64
cpu/atxmega/periph/cpuid.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level CPUID driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "cpu_nvm.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
void cpuid_get(void *id)
|
||||
{
|
||||
uint8_t *addr = id;
|
||||
|
||||
addr[0x0] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM0));
|
||||
addr[0x1] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM1));
|
||||
addr[0x2] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM2));
|
||||
addr[0x3] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM3));
|
||||
addr[0x4] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM4));
|
||||
addr[0x5] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(LOTNUM5));
|
||||
|
||||
addr[0x6] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(WAFNUM));
|
||||
|
||||
addr[0x7] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(COORDX0));
|
||||
addr[0x8] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(COORDX1));
|
||||
addr[0x9] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(COORDY0));
|
||||
addr[0xa] = nvm_read_production_signature_row(
|
||||
nvm_get_production_signature_row_offset(COORDY1));
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
DEBUG("CPUID: ");
|
||||
for (uint8_t i = 0; i < CPUID_LEN; i++) {
|
||||
DEBUG("%02x ", addr[i]);
|
||||
}
|
||||
DEBUG("\n");
|
||||
}
|
||||
}
|
546
cpu/atxmega/periph/gpio.c
Normal file
546
cpu/atxmega/periph/gpio.c
Normal file
@ -0,0 +1,546 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level GPIO driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "periph_conf.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "bitarithm.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief GPIO port base
|
||||
*
|
||||
* GPIO_PORT_BASE resides in the IO address space and must be 16 bits.
|
||||
*/
|
||||
#define GPIO_PORT_BASE ((uint16_t)&PORTA)
|
||||
|
||||
/**
|
||||
* @brief GPIO port structure offset
|
||||
*
|
||||
* The PORT_t struct it is not complete filled and it is necessary define the
|
||||
* address offset manually.
|
||||
*/
|
||||
#define GPIO_PORT_OFFSET (0x20)
|
||||
|
||||
static gpio_isr_ctx_t config_ctx[GPIO_EXT_INT_NUMOF];
|
||||
static uint8_t config_irq[GPIO_EXT_INT_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief Extract the pin number of the given pin
|
||||
*/
|
||||
static inline uint8_t _pin_mask(gpio_t pin)
|
||||
{
|
||||
return (pin & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract the port number of the given pin
|
||||
*/
|
||||
static inline uint8_t _port_num(gpio_t pin)
|
||||
{
|
||||
return (pin >> 8) & 0x0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate the PORTx address of the give pin in the IO address space
|
||||
*/
|
||||
static inline PORT_t *_port_addr(gpio_t pin)
|
||||
{
|
||||
uint8_t port_num = _port_num(pin);
|
||||
uint16_t port_addr = GPIO_PORT_BASE + (port_num * GPIO_PORT_OFFSET);
|
||||
|
||||
return (PORT_t *) port_addr;
|
||||
}
|
||||
|
||||
static inline void _print_config(gpio_t pin)
|
||||
{
|
||||
PORT_t *port = _port_addr(pin);
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
volatile uint8_t *pin_ctrl = &port->PIN0CTRL;
|
||||
|
||||
DEBUG("PORT: 0x%04x, PIN: 0x%02x\n", (uint16_t)port, pin_mask);
|
||||
DEBUG("DIR: 0x%02x, IN: 0x%02x, OUT: 0x%02x\n", port->DIR, port->IN, port->OUT);
|
||||
DEBUG("INTCTRL: 0x%02x\nINTFLAGS: 0x%02x\n", port->INTCTRL, port->INTFLAGS);
|
||||
DEBUG("INT0MASK: 0x%02x\nINT1MASK: 0x%02x\n", port->INT0MASK, port->INT1MASK);
|
||||
|
||||
for (uint8_t p = 0; p < 8; p++) {
|
||||
DEBUG("PIN%dCTRL: 0x%02x\n", p, pin_ctrl[p]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _gpio_pinctrl_set(gpio_t pin, gpio_mode_t mode,
|
||||
gpio_flank_t flank, gpio_cb_t cb,
|
||||
void *arg)
|
||||
{
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
uint8_t port_num = _port_num(pin);
|
||||
PORT_t *port = _port_addr(pin);
|
||||
volatile uint8_t *pin_ctrl = &port->PIN0CTRL;
|
||||
uint8_t irq_state;
|
||||
uint8_t in_sense_cfg;
|
||||
uint8_t pins;
|
||||
uint8_t pin_idx;
|
||||
|
||||
in_sense_cfg = (mode & ~PORT_ISC_gm);
|
||||
in_sense_cfg |= (mode & GPIO_ANALOG)
|
||||
? PORT_ISC_INPUT_DISABLE_gc
|
||||
: ((flank >> 4) & PORT_ISC_gm);
|
||||
|
||||
pins = pin_mask;
|
||||
pin_idx = 0;
|
||||
|
||||
if (mode & GPIO_OUT) {
|
||||
port->DIRSET = pin_mask;
|
||||
}
|
||||
else {
|
||||
port->DIRCLR = pin_mask;
|
||||
}
|
||||
|
||||
irq_state = irq_disable();
|
||||
|
||||
while (pins) {
|
||||
pins = bitarithm_test_and_clear(pins, &pin_idx);
|
||||
pin_ctrl[pin_idx] = in_sense_cfg;
|
||||
}
|
||||
|
||||
if (flank & GPIO_INT_DISABLED_ALL) {
|
||||
config_ctx[port_num + PORT_MAX].cb = NULL;
|
||||
config_ctx[port_num + PORT_MAX].arg = NULL;
|
||||
config_irq[port_num + PORT_MAX] = 0;
|
||||
config_ctx[port_num].cb = NULL;
|
||||
config_ctx[port_num].arg = NULL;
|
||||
config_irq[port_num] = 0;
|
||||
|
||||
port->INTCTRL = 0;
|
||||
port->INT1MASK = 0;
|
||||
port->INT0MASK = 0;
|
||||
port->INTFLAGS = PORT_INT1IF_bm | PORT_INT0IF_bm;
|
||||
}
|
||||
else if (flank & GPIO_INT1_VCT) {
|
||||
config_ctx[port_num + PORT_MAX].cb = cb;
|
||||
config_ctx[port_num + PORT_MAX].arg = arg;
|
||||
config_irq[port_num + PORT_MAX] = (flank & GPIO_LVL_HIGH)
|
||||
<< PORT_INT1LVL_gp;
|
||||
|
||||
if ((flank & GPIO_LVL_HIGH) == GPIO_LVL_OFF) {
|
||||
port->INT1MASK &= ~pin_mask;
|
||||
}
|
||||
else {
|
||||
port->INT1MASK |= pin_mask;
|
||||
}
|
||||
|
||||
port->INTFLAGS = PORT_INT1IF_bm;
|
||||
|
||||
/* Get mask from INT 0 and apply new INT 1 mask */
|
||||
port->INTCTRL = (port->INTCTRL & PORT_INT0LVL_gm)
|
||||
| config_irq[port_num + PORT_MAX];
|
||||
}
|
||||
else {
|
||||
config_ctx[port_num].cb = cb;
|
||||
config_ctx[port_num].arg = arg;
|
||||
config_irq[port_num] = (flank & GPIO_LVL_HIGH)
|
||||
<< PORT_INT0LVL_gp;
|
||||
|
||||
if ((flank & GPIO_LVL_HIGH) == GPIO_LVL_OFF) {
|
||||
port->INT0MASK &= ~pin_mask;
|
||||
}
|
||||
else {
|
||||
port->INT0MASK |= pin_mask;
|
||||
}
|
||||
|
||||
port->INTFLAGS = PORT_INT0IF_bm;
|
||||
|
||||
/* Get mask from INT 1 and apply new INT 0 mask */
|
||||
port->INTCTRL = (port->INTCTRL & PORT_INT1LVL_gm)
|
||||
| config_irq[port_num];
|
||||
}
|
||||
|
||||
irq_restore(irq_state);
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_mode_t mode)
|
||||
{
|
||||
DEBUG("gpio_init pin = 0x%02x mode = 0x%02x\n", pin, mode);
|
||||
|
||||
_gpio_pinctrl_set(pin, mode, GPIO_INT_DISABLED_ALL, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
gpio_cb_t cb, void *arg)
|
||||
{
|
||||
DEBUG("gpio_init_int pin = 0x%02x mode = 0x%02x flank = 0x%02x\n", pin,
|
||||
mode, flank);
|
||||
|
||||
if (mode & GPIO_ANALOG) {
|
||||
DEBUG("Pin can't be ANALOG (input buffer disabled) and INT at same time.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_gpio_pinctrl_set(pin, mode, flank, cb, arg);
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_t pin)
|
||||
{
|
||||
DEBUG("gpio_irq_enable pin = 0x%04x \n", pin);
|
||||
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
uint8_t port_num = _port_num(pin);
|
||||
PORT_t *port = _port_addr(pin);
|
||||
|
||||
if (port->INT1MASK & pin_mask) {
|
||||
port->INTFLAGS = PORT_INT1IF_bm;
|
||||
port->INTCTRL |= config_irq[port_num + PORT_MAX];
|
||||
}
|
||||
if (port->INT0MASK & pin_mask) {
|
||||
port->INTFLAGS = PORT_INT0IF_bm;
|
||||
port->INTCTRL |= config_irq[port_num];
|
||||
}
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin)
|
||||
{
|
||||
DEBUG("gpio_irq_disable pin = 0x%04x \n", pin);
|
||||
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
PORT_t *port = _port_addr(pin);
|
||||
|
||||
if (port->INT1MASK & pin_mask) {
|
||||
port->INTCTRL &= ~PORT_INT1LVL_gm;
|
||||
}
|
||||
if (port->INT0MASK & pin_mask) {
|
||||
port->INTCTRL &= ~PORT_INT0LVL_gm;
|
||||
}
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_read(gpio_t pin)
|
||||
{
|
||||
PORT_t *port = _port_addr(pin);
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
|
||||
return port->IN & pin_mask;
|
||||
}
|
||||
|
||||
void gpio_set(gpio_t pin)
|
||||
{
|
||||
DEBUG("gpio_set pin = 0x%04x \n", pin);
|
||||
|
||||
PORT_t *port = _port_addr(pin);
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
|
||||
port->OUTSET = pin_mask;
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_clear(gpio_t pin)
|
||||
{
|
||||
DEBUG("gpio_clear pin = 0x%04x \n", pin);
|
||||
|
||||
PORT_t *port = _port_addr(pin);
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
|
||||
port->OUTCLR = pin_mask;
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_toggle(gpio_t pin)
|
||||
{
|
||||
DEBUG("gpio_toggle pin = 0x%04x \n", pin);
|
||||
|
||||
PORT_t *port = _port_addr(pin);
|
||||
uint8_t pin_mask = _pin_mask(pin);
|
||||
|
||||
port->OUTTGL = pin_mask;
|
||||
|
||||
if (IS_ACTIVE(ENABLE_DEBUG)) {
|
||||
_print_config(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t pin, int value)
|
||||
{
|
||||
DEBUG("gpio_write pin = 0x%04x, value = 0x%02x \n", pin, value);
|
||||
|
||||
if (value) {
|
||||
gpio_set(pin);
|
||||
}
|
||||
else {
|
||||
gpio_clear(pin);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void irq_handler(uint8_t port_num, uint8_t isr_vct_num)
|
||||
{
|
||||
avr8_enter_isr();
|
||||
|
||||
DEBUG("irq_handler port = 0x%02x, vct_num = %d \n", port_num, isr_vct_num);
|
||||
|
||||
if (isr_vct_num) {
|
||||
port_num += PORT_MAX;
|
||||
}
|
||||
|
||||
if (config_ctx[port_num].cb) {
|
||||
config_ctx[port_num].cb(config_ctx[port_num].arg);
|
||||
}
|
||||
else {
|
||||
DEBUG("WARNING! irq_handler without callback\n");
|
||||
}
|
||||
|
||||
avr8_exit_isr();
|
||||
}
|
||||
|
||||
#if defined(PORTA_INT0_vect)
|
||||
ISR(PORTA_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_A, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTA_INT1_vect)
|
||||
ISR(PORTA_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_A, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTB_INT0_vect)
|
||||
ISR(PORTB_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_B, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTB_INT1_vect)
|
||||
ISR(PORTB_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_B, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTC_INT0_vect)
|
||||
ISR(PORTC_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_C, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTC_INT1_vect)
|
||||
ISR(PORTC_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_C, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTD_INT0_vect)
|
||||
ISR(PORTD_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_D, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTD_INT1_vect)
|
||||
ISR(PORTD_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_D, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTE_INT0_vect)
|
||||
ISR(PORTE_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_E, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTE_INT1_vect)
|
||||
ISR(PORTE_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_E, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTF_INT0_vect)
|
||||
ISR(PORTF_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_F, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTF_INT1_vect)
|
||||
ISR(PORTF_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_F, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTG_INT0_vect)
|
||||
ISR(PORTG_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_G, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTG_INT1_vect)
|
||||
ISR(PORTG_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_G, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTH_INT0_vect)
|
||||
ISR(PORTH_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_H, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTH_INT1_vect)
|
||||
ISR(PORTH_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_H, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTJ_INT0_vect)
|
||||
ISR(PORTJ_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_J, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTJ_INT1_vect)
|
||||
ISR(PORTJ_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_J, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTK_INT0_vect)
|
||||
ISR(PORTK_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_K, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTK_INT1_vect)
|
||||
ISR(PORTK_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_K, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTL_INT0_vect)
|
||||
ISR(PORTL_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_L, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTL_INT1_vect)
|
||||
ISR(PORTL_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_L, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTM_INT0_vect)
|
||||
ISR(PORTM_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_M, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTM_INT1_vect)
|
||||
ISR(PORTM_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_M, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTN_INT0_vect)
|
||||
ISR(PORTN_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_N, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTN_INT1_vect)
|
||||
ISR(PORTN_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_N, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTP_INT0_vect)
|
||||
ISR(PORTP_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_P, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTP_INT1_vect)
|
||||
ISR(PORTP_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_P, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTQ_INT0_vect)
|
||||
ISR(PORTQ_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_Q, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTQ_INT1_vect)
|
||||
ISR(PORTQ_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_Q, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PORTR_INT0_vect)
|
||||
ISR(PORTR_INT0_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_R, 0);
|
||||
}
|
||||
#endif
|
||||
#if defined(PORTR_INT1_vect)
|
||||
ISR(PORTR_INT1_vect, ISR_BLOCK)
|
||||
{
|
||||
irq_handler(PORT_R, 1);
|
||||
}
|
||||
#endif
|
78
cpu/atxmega/periph/nvm.c
Normal file
78
cpu/atxmega/periph/nvm.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level NVM driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <avr/io.h>
|
||||
|
||||
#include "cpu_nvm.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Read one byte using the Load Program Memory (LPM) instruction
|
||||
* @internal
|
||||
*
|
||||
* This function sets the specified NVM_CMD, reads one byte using at the
|
||||
* specified byte address with the LPM instruction. NVM_CMD is restored after
|
||||
* use.
|
||||
*
|
||||
* @note This will disable interrupts during execution.
|
||||
*
|
||||
* @param nvm_cmd NVM command to load before running LPM
|
||||
* @param address Byte offset into the signature row
|
||||
*/
|
||||
static inline uint8_t _nvm_read_byte(uint8_t nvm_cmd, uint16_t address)
|
||||
{
|
||||
uint8_t result;
|
||||
|
||||
__asm__ volatile (
|
||||
"in __tmp_reg__, __SREG__ \n\t"
|
||||
"cli \n\t"
|
||||
"lds __zero_reg__, %3 \n\t"
|
||||
"sts %3, %1 \n\t"
|
||||
"lpm %0, %a2 \n\t"
|
||||
"sts %3, __zero_reg__ \n\t"
|
||||
"clr __zero_reg__ \n\t"
|
||||
"out __SREG__, __tmp_reg__ \n\t"
|
||||
:
|
||||
"=&r" (result)
|
||||
:
|
||||
"r" (nvm_cmd), "e" (address), "m" (NVM_CMD)
|
||||
: /* no clobbers */
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one byte from the production signature row
|
||||
*
|
||||
* This function reads one byte from the production signature row of the device
|
||||
* at the given address.
|
||||
*
|
||||
* @note The execution can take some time. It is recommended not call this
|
||||
* inside an interrupt service routine.
|
||||
*
|
||||
* @param address Byte offset into the signature row
|
||||
*/
|
||||
uint8_t nvm_read_production_signature_row(uint8_t address)
|
||||
{
|
||||
return _nvm_read_byte(NVM_CMD_READ_CALIB_ROW_gc, address);
|
||||
}
|
80
cpu/atxmega/periph/pm.c
Normal file
80
cpu/atxmega/periph/pm.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level PM driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <avr/sleep.h>
|
||||
|
||||
#include "periph_conf.h"
|
||||
#include "periph/pm.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
void pm_reboot(void)
|
||||
{
|
||||
DEBUG("Reboot Software Reset\n" );
|
||||
|
||||
/* XMEGA AU [MANUAL] p. 116 CTRL->Control register
|
||||
* page 13 3.12.1 Sequence for write operation to protected I/O registers
|
||||
* page 15 3.14.1 CCP – Configuration Change Protection register
|
||||
*/
|
||||
|
||||
/* Disable CCP for Protected IO registerand set new value*/
|
||||
_PROTECTED_WRITE(RST_CTRL, RST_SWRST_bm);
|
||||
while (1) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* DEBUG may affect this routine.
|
||||
*
|
||||
* --- Do NOT add DEBUG macro here ---
|
||||
*
|
||||
*/
|
||||
void pm_set(unsigned mode)
|
||||
{
|
||||
unsigned irq_state = irq_disable();
|
||||
|
||||
if (avr8_is_uart_tx_pending() && mode < 4) {
|
||||
irq_restore(irq_state);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
set_sleep_mode(SLEEP_SMODE_PDOWN_gc);
|
||||
break;
|
||||
case 1:
|
||||
set_sleep_mode(SLEEP_SMODE_PSAVE_gc);
|
||||
break;
|
||||
case 2:
|
||||
set_sleep_mode(SLEEP_SMODE_STDBY_gc);
|
||||
break;
|
||||
case 3:
|
||||
set_sleep_mode(SLEEP_SMODE_ESTDBY_gc);
|
||||
break;
|
||||
default:
|
||||
set_sleep_mode(SLEEP_SMODE_IDLE_gc);
|
||||
}
|
||||
sleep_enable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
sleep_disable();
|
||||
irq_restore(irq_state);
|
||||
}
|
533
cpu/atxmega/periph/timer.c
Normal file
533
cpu/atxmega/periph/timer.c
Normal file
@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level TIMER driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "periph/timer.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief We have 7 possible prescaler values
|
||||
*/
|
||||
#define PRESCALE_NUMOF (7U)
|
||||
|
||||
/**
|
||||
* @brief Possible prescaler values, encoded as 2 ^ val
|
||||
*/
|
||||
static const uint8_t prescalers[] = { 0, 1, 2, 3, 6, 8, 10 };
|
||||
|
||||
/**
|
||||
* @brief Timer state context
|
||||
*/
|
||||
typedef struct {
|
||||
timer_cb_t cb; /**< interrupt callback */
|
||||
void *arg; /**< interrupt callback argument */
|
||||
uint8_t prescaler; /**< remember the prescaler value */
|
||||
uint8_t channels; /**< number of channels */
|
||||
} ctx_t;
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for saving the device states
|
||||
* @{
|
||||
*/
|
||||
#ifdef TIMER_NUMOF
|
||||
static ctx_t ctx[TIMER_NUMOF] = { { NULL } };
|
||||
#else
|
||||
/* fallback if no timer is configured */
|
||||
static ctx_t *ctx[] = { { NULL } };
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
static uint32_t _oneshot;
|
||||
|
||||
static inline void set_oneshot(tim_t tim, int chan)
|
||||
{
|
||||
_oneshot |= (1 << chan) << (TIMER_CH_MAX_NUMOF * tim);
|
||||
}
|
||||
|
||||
static inline void clear_oneshot(tim_t tim, int chan)
|
||||
{
|
||||
_oneshot &= ~((1 << chan) << (TIMER_CH_MAX_NUMOF * tim));
|
||||
}
|
||||
|
||||
static inline bool is_oneshot(tim_t tim, int chan)
|
||||
{
|
||||
return _oneshot & ((1 << chan) << (TIMER_CH_MAX_NUMOF * tim));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the given timer
|
||||
*/
|
||||
int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg)
|
||||
{
|
||||
DEBUG("timer.c: freq = %ld, Core Clock = %ld\n", freq, CLOCK_CORECLOCK);
|
||||
|
||||
TC0_t *dev;
|
||||
uint8_t pre;
|
||||
uint8_t ch;
|
||||
|
||||
assert(TIMER_CH_MAX_NUMOF * TIMER_NUMOF < 32);
|
||||
|
||||
/* make sure given device is valid */
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* figure out if freq is applicable */
|
||||
for (pre = 0; pre < PRESCALE_NUMOF; pre++) {
|
||||
if ((CLOCK_CORECLOCK >> prescalers[pre]) == freq) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pre == PRESCALE_NUMOF) {
|
||||
DEBUG("timer.c: prescaling failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev = timer_config[tim].dev;
|
||||
|
||||
/* stop and reset timer */
|
||||
dev->CTRLA = 0; /* Stop */
|
||||
dev->CTRLFSET = TC_CMD_RESET_gc; /* Force Reset */
|
||||
|
||||
/* save interrupt context and timer Prescaler */
|
||||
ctx[tim].cb = cb;
|
||||
ctx[tim].arg = arg;
|
||||
ctx[tim].prescaler = (0x07 & (pre + 1));
|
||||
|
||||
/* Check enabled channels */
|
||||
ctx[tim].channels = 0;
|
||||
for (ch = 0; ch < TIMER_CH_MAX_NUMOF; ch++) {
|
||||
if (timer_config[tim].int_lvl[ch] != CPU_INT_LVL_OFF) {
|
||||
ctx[tim].channels++;
|
||||
}
|
||||
}
|
||||
|
||||
if (timer_config[tim].type != TC_TYPE_0
|
||||
&& timer_config[tim].type != TC_TYPE_4) {
|
||||
if (ctx[tim].channels > 2) {
|
||||
DEBUG("timer.c: wrong number of channels. max value is 2.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (timer_config[tim].type == TC_TYPE_2) {
|
||||
DEBUG("timer.c: Timer version %d is current not supported.\n",
|
||||
timer_config[tim].type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Normal Counter with rollover */
|
||||
dev->CTRLB = TC_WGMODE_NORMAL_gc;
|
||||
|
||||
/* Compare or Capture disable all channels */
|
||||
dev->INTCTRLB = 0;
|
||||
|
||||
/* Free running counter */
|
||||
dev->PER = 0xFFFF;
|
||||
|
||||
DEBUG("timer.c: prescaler set to %d \n", ctx[tim].prescaler);
|
||||
dev->CTRLA = ctx[tim].prescaler;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set_absolute(tim_t tim, int channel, unsigned int value)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channel >= ctx[tim].channels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("Setting timer %i channel %i to %04x\n", tim, channel, value);
|
||||
|
||||
TC0_t *dev = timer_config[tim].dev;
|
||||
|
||||
dev->INTCTRLB &= ~(TC0_CCAINTLVL_gm << (channel * 2));
|
||||
dev->INTFLAGS |= TC0_CCAIF_bm << channel;
|
||||
|
||||
uint8_t irq_state = irq_disable();
|
||||
|
||||
*(((uint16_t *)(&dev->CCA)) + channel) = (uint16_t)value;
|
||||
|
||||
irq_restore(irq_state);
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
dev->INTCTRLB |= (timer_config[tim].int_lvl[channel] << (channel * 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags)
|
||||
{
|
||||
(void)flags;
|
||||
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channel > 0 || ctx[tim].channels != 1) {
|
||||
DEBUG("Only channel 0 can be set as periodic and channels must be 1\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("Setting timer %i channel 0 to %i and flags %i (repeating)\n",
|
||||
tim, value, flags);
|
||||
|
||||
TC0_t *dev = timer_config[tim].dev;
|
||||
uint8_t irq_state = irq_disable();
|
||||
|
||||
dev->CTRLA = 0;
|
||||
dev->CTRLFSET = TC_CMD_RESET_gc;
|
||||
dev->CTRLB = TC_WGMODE_FRQ_gc;
|
||||
dev->INTCTRLB = 0;
|
||||
dev->INTFLAGS |= TC0_CCAIF_bm;
|
||||
dev->CCA = (uint16_t)value;
|
||||
dev->INTCTRLB = timer_config[tim].int_lvl[0];
|
||||
dev->CTRLA = ctx[tim].prescaler;
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
irq_restore(irq_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_clear(tim_t tim, int channel)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channel >= ctx[tim].channels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("timer_clear channel %d\n", channel );
|
||||
|
||||
TC0_t *dev = timer_config[tim].dev;
|
||||
|
||||
/* Compare or Capture Disable */
|
||||
dev->INTCTRLB &= ~(TC0_CCAINTLVL_gm << (channel * 2));
|
||||
|
||||
/* Clear Interrupt Flag
|
||||
* The CCxIF is automatically cleared when the corresponding
|
||||
* interrupt vector is executed.*/
|
||||
dev->INTFLAGS |= TC0_CCAIF_bm << channel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_set(tim_t tim, int channel, unsigned int timeout)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (channel >= ctx[tim].channels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TC0_t *dev = timer_config[tim].dev;
|
||||
|
||||
/* Compare or Capture Disable */
|
||||
dev->INTCTRLB &= ~(TC0_CCAINTLVL_gm << (channel * 2));
|
||||
|
||||
/* Clear Interrupt Flag */
|
||||
dev->INTFLAGS |= TC0_CCAIF_bm << channel;
|
||||
|
||||
uint8_t irq_state = irq_disable();
|
||||
|
||||
/* set value to compare with rollover */
|
||||
uint16_t absolute = dev->CNT + timeout;
|
||||
*(((uint16_t *)(&dev->CCA)) + channel) = absolute;
|
||||
|
||||
irq_restore(irq_state);
|
||||
set_oneshot(tim, channel);
|
||||
|
||||
/* Compare or Capture Enable */
|
||||
dev->INTCTRLB |= (timer_config[tim].int_lvl[channel] << (channel * 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int timer_read(tim_t tim)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG("timer_read\n");
|
||||
return (unsigned int)timer_config[tim].dev->CNT;
|
||||
}
|
||||
|
||||
void timer_stop(tim_t tim)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("timer_stop\n");
|
||||
timer_config[tim].dev->CTRLA = 0;
|
||||
timer_config[tim].dev->CTRLFSET = TC_CMD_RESTART_gc;
|
||||
}
|
||||
|
||||
void timer_start(tim_t tim)
|
||||
{
|
||||
if (tim >= TIMER_NUMOF) {
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("timer_start\n");
|
||||
timer_config[tim].dev->CTRLA = ctx[tim].prescaler;
|
||||
}
|
||||
|
||||
#ifdef TIMER_NUMOF
|
||||
static inline void _isr(tim_t tim, int channel)
|
||||
{
|
||||
avr8_enter_isr();
|
||||
|
||||
DEBUG("timer %d _isr channel %d\n", tim, channel);
|
||||
|
||||
if (is_oneshot(tim, channel)) {
|
||||
timer_config[tim].dev->INTCTRLB &= ~(TC0_CCAINTLVL_gm << (channel * 2));
|
||||
}
|
||||
|
||||
if (ctx[tim].cb) {
|
||||
ctx[tim].cb(ctx[tim].arg, channel);
|
||||
}
|
||||
|
||||
avr8_exit_isr();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TIMER_0_ISRA
|
||||
ISR(TIMER_0_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(0, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_0_ISRB
|
||||
ISR(TIMER_0_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(0, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_0_ISRC
|
||||
ISR(TIMER_0_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(0, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_0_ISRD
|
||||
ISR(TIMER_0_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(0, 3);
|
||||
}
|
||||
#endif /* TIMER_0 */
|
||||
|
||||
#ifdef TIMER_1_ISRA
|
||||
ISR(TIMER_1_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(1, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_1_ISRB
|
||||
ISR(TIMER_1_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(1, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_1_ISRC
|
||||
ISR(TIMER_1_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(1, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_1_ISRD
|
||||
ISR(TIMER_1_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(1, 3);
|
||||
}
|
||||
#endif /* TIMER_1 */
|
||||
|
||||
#ifdef TIMER_2_ISRA
|
||||
ISR(TIMER_2_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(2, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_2_ISRB
|
||||
ISR(TIMER_2_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(2, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_2_ISRC
|
||||
ISR(TIMER_2_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(2, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_2_ISRD
|
||||
ISR(TIMER_2_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(2, 3);
|
||||
}
|
||||
#endif /* TIMER_2 */
|
||||
|
||||
#ifdef TIMER_3_ISRA
|
||||
ISR(TIMER_3_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(3, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_3_ISRB
|
||||
ISR(TIMER_3_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(3, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_3_ISRC
|
||||
ISR(TIMER_3_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(3, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_3_ISRD
|
||||
ISR(TIMER_3_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(3, 3);
|
||||
}
|
||||
#endif /* TIMER_3 */
|
||||
|
||||
#ifdef TIMER_4_ISRA
|
||||
ISR(TIMER_4_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(4, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_4_ISRB
|
||||
ISR(TIMER_4_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(4, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_4_ISRC
|
||||
ISR(TIMER_4_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(4, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_4_ISRD
|
||||
ISR(TIMER_4_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(4, 3);
|
||||
}
|
||||
#endif /* TIMER_4 */
|
||||
|
||||
#ifdef TIMER_5_ISRA
|
||||
ISR(TIMER_5_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(5, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_5_ISRB
|
||||
ISR(TIMER_5_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(5, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_5_ISRC
|
||||
ISR(TIMER_5_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(5, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_5_ISRD
|
||||
ISR(TIMER_5_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(5, 3);
|
||||
}
|
||||
#endif /* TIMER_5 */
|
||||
|
||||
#ifdef TIMER_6_ISRA
|
||||
ISR(TIMER_6_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(6, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_6_ISRB
|
||||
ISR(TIMER_6_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(6, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_6_ISRC
|
||||
ISR(TIMER_6_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(6, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_6_ISRD
|
||||
ISR(TIMER_6_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(6, 3);
|
||||
}
|
||||
#endif /* TIMER_6 */
|
||||
|
||||
#ifdef TIMER_7_ISRA
|
||||
ISR(TIMER_7_ISRA, ISR_BLOCK)
|
||||
{
|
||||
_isr(7, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_7_ISRB
|
||||
ISR(TIMER_7_ISRB, ISR_BLOCK)
|
||||
{
|
||||
_isr(7, 1);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_7_ISRC
|
||||
ISR(TIMER_7_ISRC, ISR_BLOCK)
|
||||
{
|
||||
_isr(7, 2);
|
||||
}
|
||||
#endif
|
||||
#ifdef TIMER_7_ISRB
|
||||
ISR(TIMER_7_ISRD, ISR_BLOCK)
|
||||
{
|
||||
_isr(7, 3);
|
||||
}
|
||||
#endif /* TIMER_7 */
|
425
cpu/atxmega/periph/uart.c
Normal file
425
cpu/atxmega/periph/uart.c
Normal file
@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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_atxmega
|
||||
* @ingroup cpu_atxmega_periph
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level UART driver implementation
|
||||
*
|
||||
* @author Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
*
|
||||
* Supports runtime calculation of the BSEL and BSCALE register values.
|
||||
* Supports reconfiguring UART after a clock change.
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
#include <avr/io.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu.h"
|
||||
#include "sched.h"
|
||||
#include "thread.h"
|
||||
#include "periph/uart.h"
|
||||
#include "periph/gpio.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief UART Baudrate Tolerance
|
||||
*
|
||||
* The tolerance is expressed as baud rate percentage multiplied by 100.
|
||||
* For bigger tolerances UART double frequency can be avoided, thus saving
|
||||
* power.
|
||||
*
|
||||
* The default baud tolerance is 2%.
|
||||
*/
|
||||
#ifndef BAUD_TOL
|
||||
#define BAUD_TOL 2 * 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Allocate memory to store the callback functions.
|
||||
*/
|
||||
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief Get the pointer to the base register of the given USART device
|
||||
*
|
||||
* @param[in] dev USART device identifier
|
||||
*
|
||||
* @return base register address
|
||||
*/
|
||||
static inline USART_t *dev(uart_t dev)
|
||||
{
|
||||
return uart_config[dev].dev;
|
||||
}
|
||||
|
||||
static inline int8_t _check_bsel(uint32_t baud, uint32_t calcbaud,
|
||||
int16_t *precision)
|
||||
{
|
||||
/* Avoid negative values and with precision of two positions
|
||||
* after the decimal point for the deviation in percent
|
||||
*
|
||||
* result is the absolute deviation eg. 10 001
|
||||
*
|
||||
* MAX BAUD fper/2 = 16MHz a shift of 8 can be used to increase
|
||||
* accuracy
|
||||
*/
|
||||
uint16_t pre;
|
||||
|
||||
if (baud < calcbaud) {
|
||||
pre = (uint16_t)((calcbaud * 10000ULL) / baud);
|
||||
}
|
||||
else {
|
||||
pre = (uint16_t)((baud * 10000ULL) / calcbaud);
|
||||
}
|
||||
|
||||
if (pre < ((uint16_t)*precision)) {
|
||||
*precision = pre;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int16_t _xmega_bsel_bscale(uint32_t *fper, uint32_t *baud,
|
||||
uint8_t clk2x, uint16_t *bsel,
|
||||
int8_t *bscale)
|
||||
{
|
||||
uint32_t calcbaud = 0;
|
||||
uint32_t deno = 0;
|
||||
int16_t precision = UINT_MAX;
|
||||
uint16_t loc_bsel = 0;
|
||||
int8_t loc_bscale;
|
||||
|
||||
/* Some explanation for equation transformation
|
||||
* bsel = ( (fper / (2^bscale*16*baud) ) - 1 )
|
||||
* = ( (fper / (2^bscale*(16-8*clk2x)*baud) ) - 1 )
|
||||
* = ( fper - (2^bscale*(16-8*clk2x)*baud) )
|
||||
* / (2^bscale*(16-8*clk2x)*baud)
|
||||
*
|
||||
* deno = ( baud * (16-8*clk2x) * 2^bscale )
|
||||
* = ( baud * (1<<(4-clk2x)) * (1<<bscale) )
|
||||
* = ( baud<<( 4-clk2x +bscale));
|
||||
*
|
||||
* some rounding math explanation for unsigned integer
|
||||
* ABS(x +0,5) = (x*10+ 5 )/(10)
|
||||
* Equation above is as follows, using denominator as base to round
|
||||
* bsel = ( x - y )/y
|
||||
* = ( x - y +0,5*y )/y
|
||||
* = ( 2*x - y )/(2*y)
|
||||
* = ((x<<1)- y )/(y<<1)
|
||||
*
|
||||
* baud = (fper*1/2^bscale) / ((bsel+1)*16)
|
||||
*/
|
||||
for (loc_bscale = 0; loc_bscale <= 7; loc_bscale++) {
|
||||
int32_t sub = 0;
|
||||
|
||||
deno = (*baud << (4 - clk2x + loc_bscale));
|
||||
sub = (*fper << 1) - (deno);
|
||||
|
||||
if (sub <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
loc_bsel = (sub / (deno << 1));
|
||||
|
||||
if (loc_bsel >= 4095) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Omit division by 16 get higher accuracy at small baudrates*/
|
||||
calcbaud = (*fper >> loc_bscale) / ((loc_bsel + 1) << (4 - clk2x));
|
||||
|
||||
if (_check_bsel(*baud, calcbaud, &precision)) {
|
||||
*bsel = loc_bsel;
|
||||
*bscale = loc_bscale;
|
||||
}
|
||||
}
|
||||
|
||||
/* More math for the negative equation
|
||||
* bscale is negative so 1/2^bscale = 2^|bscale| which is a factor and
|
||||
* not a division again runding the result before division with
|
||||
* 0.5 * denominator
|
||||
*
|
||||
* bsel = 1/2^bscale *( fcpu / ( (16*baud)-1) )
|
||||
* = ( fcpu*2^|bscale| - (16*baud)*2^|bscale| )/(16*baud)
|
||||
* = ( fcpu*2^|bscale| - (16*baud)*2^|bscale| + 0.5*(16*baud) )/(16*baud)
|
||||
*
|
||||
* deno = (16/2*baud) = (baud<<(3-clk2x))
|
||||
*
|
||||
* bsel = ( (fcpu - (deno<<(1))<<|bscale|) + deno )/(deno<<1)
|
||||
*
|
||||
* Baud = (fper*1/2^bscale)/ (16*(bsel+1/2^bscale))
|
||||
*/
|
||||
for (loc_bscale = -1; loc_bscale >= -7; loc_bscale--) {
|
||||
uint32_t num = 0;
|
||||
|
||||
deno = (*baud << (3 - clk2x));
|
||||
num = ((*fper - (deno << 1)) << (-loc_bscale)) + deno;
|
||||
num = (num / (deno << 1));
|
||||
|
||||
if (num >= 4095) {
|
||||
break;
|
||||
}
|
||||
|
||||
loc_bsel = (uint16_t)(num & 0xFFF);
|
||||
|
||||
/* Omit division by 16 get higher accuracy at small baudrates */
|
||||
calcbaud = (*fper << (-loc_bscale))
|
||||
/ ((loc_bsel + (1 << (-loc_bscale))) << (4 - clk2x));
|
||||
|
||||
if (_check_bsel(*baud, calcbaud, &precision)) {
|
||||
*bsel = loc_bsel;
|
||||
*bscale = loc_bscale;
|
||||
}
|
||||
}
|
||||
|
||||
return precision;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates bsel and bscale for a given periphery clock and baudrate.
|
||||
* Limitation are the periphery clock maximum is 32MHz, unsigned int
|
||||
* overflows if clock is bigger. And the periphery clock has to be not
|
||||
* smaller then 1 when divided by 128.
|
||||
*
|
||||
* fper/128 !=0 must be divide able by 128
|
||||
* fper*128 != uint23_max => 32MHz max fper
|
||||
*/
|
||||
static inline int16_t _xmega_calculate_bsel_bscale(uint32_t fcpu, uint32_t baud,
|
||||
uint8_t *clk2x,
|
||||
uint16_t *bsel,
|
||||
int8_t *bscale)
|
||||
{
|
||||
int16_t precision = 0;
|
||||
|
||||
precision = _xmega_bsel_bscale(&fcpu, &baud, 0, bsel, bscale );
|
||||
|
||||
/* default 2% precision, required precision is at least 2% */
|
||||
if (precision <= (10000 + BAUD_TOL)) {
|
||||
return (precision - 10000);
|
||||
}
|
||||
|
||||
/* Precision goal was not met calculate baudrate with uart frequency doubled */
|
||||
precision = _xmega_bsel_bscale(&fcpu, &baud, 1, bsel, bscale );
|
||||
*clk2x = 1;
|
||||
|
||||
return (precision - 10000);
|
||||
}
|
||||
|
||||
static inline void _configure_pins(uart_t uart)
|
||||
{
|
||||
/* configure RX pin */
|
||||
if (gpio_is_valid(uart_config[uart].rx_pin)) {
|
||||
gpio_init(uart_config[uart].rx_pin, GPIO_IN);
|
||||
}
|
||||
|
||||
/* configure TX pin */
|
||||
if (gpio_is_valid(uart_config[uart].tx_pin)) {
|
||||
gpio_set(uart_config[uart].tx_pin);
|
||||
gpio_init(uart_config[uart].tx_pin, GPIO_OUT);
|
||||
}
|
||||
|
||||
#ifdef MODULE_PERIPH_UART_HW_FC
|
||||
/* TODO */
|
||||
#endif
|
||||
}
|
||||
|
||||
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
||||
{
|
||||
int8_t bscale;
|
||||
uint8_t clk2x;
|
||||
uint16_t bsel;
|
||||
|
||||
/* make sure the given device is valid */
|
||||
if (uart >= UART_NUMOF) {
|
||||
return UART_NODEV;
|
||||
}
|
||||
|
||||
uint16_t count = UINT16_MAX;
|
||||
while (avr8_is_uart_tx_pending() && count--) {}
|
||||
|
||||
/* register interrupt context */
|
||||
isr_ctx[uart].rx_cb = rx_cb;
|
||||
isr_ctx[uart].arg = arg;
|
||||
|
||||
/* disable and reset UART */
|
||||
dev(uart)->CTRLA = 0;
|
||||
dev(uart)->CTRLB = 0;
|
||||
dev(uart)->CTRLC = 0;
|
||||
|
||||
_configure_pins(uart);
|
||||
|
||||
/* configure UART to 8N1 mode */
|
||||
dev(uart)->CTRLC = USART_CMODE_ASYNCHRONOUS_gc
|
||||
| USART_PMODE_DISABLED_gc
|
||||
| USART_CHSIZE_8BIT_gc;
|
||||
|
||||
/* set clock divider */
|
||||
_xmega_calculate_bsel_bscale(CLOCK_CORECLOCK, baudrate, &clk2x,
|
||||
&bsel, &bscale);
|
||||
|
||||
dev(uart)->BAUDCTRLA = (uint8_t)(bsel & 0x00ff);
|
||||
dev(uart)->BAUDCTRLB = (bscale << USART_BSCALE_gp)
|
||||
| ((uint8_t)((bsel & 0x0fff) >> 8));
|
||||
if (clk2x == 1) {
|
||||
dev(uart)->CTRLB |= USART_CLK2X_bm;
|
||||
}
|
||||
|
||||
/* enable RX and TX Interrupts and set level*/
|
||||
if (rx_cb) {
|
||||
dev(uart)->CTRLA = (uart_config[uart].rx_int_lvl << USART_RXCINTLVL_gp)
|
||||
| (uart_config[uart].tx_int_lvl << USART_TXCINTLVL_gp)
|
||||
| (uart_config[uart].dre_int_lvl << USART_DREINTLVL_gp);
|
||||
dev(uart)->CTRLB = USART_RXEN_bm | USART_TXEN_bm;
|
||||
}
|
||||
else {
|
||||
/* only transmit */
|
||||
dev(uart)->CTRLB = USART_TXEN_bm;
|
||||
}
|
||||
|
||||
DEBUG("Set clk2x %" PRIu8 " bsel %" PRIu16 "bscale %" PRIi8 "\n",
|
||||
clk2x, bsel, bscale);
|
||||
|
||||
return UART_OK;
|
||||
}
|
||||
|
||||
void uart_write(uart_t uart, const uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
while (!(dev(uart)->STATUS & USART_DREIF_bm)) {}
|
||||
|
||||
/* start of TX won't finish until no data in DATAn and transmit shift
|
||||
register is empty */
|
||||
uint8_t irq_state = irq_disable();
|
||||
avr8_state |= AVR8_STATE_FLAG_UART_TX(uart);
|
||||
irq_restore(irq_state);
|
||||
|
||||
dev(uart)->DATA = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
void uart_poweron(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
/* not implemented (yet) */
|
||||
}
|
||||
|
||||
void uart_poweroff(uart_t uart)
|
||||
{
|
||||
(void)uart;
|
||||
/* not implemented (yet) */
|
||||
}
|
||||
|
||||
static inline void _rx_isr_handler(int num)
|
||||
{
|
||||
avr8_enter_isr();
|
||||
|
||||
if (isr_ctx[num].rx_cb) {
|
||||
isr_ctx[num].rx_cb(isr_ctx[num].arg, dev(num)->DATA);
|
||||
}
|
||||
|
||||
avr8_exit_isr();
|
||||
}
|
||||
|
||||
static inline void _tx_isr_handler(int num)
|
||||
{
|
||||
avr8_enter_isr();
|
||||
|
||||
/* entire frame in the Transmit Shift Register has been shifted out and
|
||||
there are no new data currently present in the transmit buffer */
|
||||
avr8_state &= ~AVR8_STATE_FLAG_UART_TX(num);
|
||||
|
||||
avr8_exit_isr();
|
||||
}
|
||||
|
||||
#ifdef UART_0_RXC_ISR
|
||||
ISR(UART_0_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(0);
|
||||
}
|
||||
ISR(UART_0_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(0);
|
||||
}
|
||||
#endif /* UART_0_ISR */
|
||||
|
||||
#ifdef UART_1_RXC_ISR
|
||||
ISR(UART_1_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(1);
|
||||
}
|
||||
ISR(UART_1_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(1);
|
||||
}
|
||||
#endif /* UART_1_ISR */
|
||||
|
||||
#ifdef UART_2_RXC_ISR
|
||||
ISR(UART_2_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(2);
|
||||
}
|
||||
ISR(UART_2_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(2);
|
||||
}
|
||||
#endif /* UART_2_ISR */
|
||||
|
||||
#ifdef UART_3_RXC_ISR
|
||||
ISR(UART_3_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(3);
|
||||
}
|
||||
ISR(UART_3_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(3);
|
||||
}
|
||||
#endif /* UART_3_ISR */
|
||||
|
||||
#ifdef UART_4_RXC_ISR
|
||||
ISR(UART_4_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(4);
|
||||
}
|
||||
ISR(UART_4_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(4);
|
||||
}
|
||||
#endif /* UART_4_ISR */
|
||||
|
||||
#ifdef UART_5_RXC_ISR
|
||||
ISR(UART_5_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(5);
|
||||
}
|
||||
ISR(UART_5_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(5);
|
||||
}
|
||||
#endif /* UART_5_ISR */
|
||||
|
||||
#ifdef UART_6_RXC_ISR
|
||||
ISR(UART_6_RXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_rx_isr_handler(6);
|
||||
}
|
||||
ISR(UART_6_TXC_ISR, ISR_BLOCK)
|
||||
{
|
||||
_tx_isr_handler(6);
|
||||
}
|
||||
#endif /* UART_6_ISR */
|
@ -5,15 +5,12 @@
|
||||
# General Public License v2.1. See the file LICENSE in the top level
|
||||
# directory for more details.
|
||||
#
|
||||
|
||||
config CPU_ARCH_AVR8
|
||||
bool
|
||||
select HAS_ARCH_8BIT
|
||||
select HAS_ARCH_AVR8
|
||||
|
||||
config CPU_CORE_AVR
|
||||
bool
|
||||
select CPU_ARCH_AVR8
|
||||
|
||||
## Common CPU symbols
|
||||
config CPU_ARCH
|
||||
default "avr8" if CPU_ARCH_AVR8
|
||||
|
@ -3,4 +3,4 @@ INCLUDES += -I$(RIOTCPU)/avr8_common/include \
|
||||
-isystem$(RIOTCPU)/avr8_common/avr_libc_extra/include \
|
||||
-isystem$(RIOTCPU)/avr8_common/avr_libc_extra/include/vendor
|
||||
|
||||
include $(RIOTMAKE)/arch/atmega.inc.mk
|
||||
include $(RIOTMAKE)/arch/avr8.inc.mk
|
||||
|
@ -31,19 +31,29 @@
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#ifdef CPU_AVR8_HAS_CLOCK_INIT
|
||||
#include "cpu_clock.h"
|
||||
#endif
|
||||
#include "board.h"
|
||||
#include "irq.h"
|
||||
#include "periph/init.h"
|
||||
#include "panic.h"
|
||||
#include "kernel_defines.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef RST
|
||||
/* In ATxmega there is a special register to get reset cause */
|
||||
#define MCUSR RST.STATUS
|
||||
#else
|
||||
#ifndef MCUSR
|
||||
/* In older ATmegas the MCUSR register was still named MCUCSR. Current avrlibc
|
||||
* versions provide the MCUSR macro for those as well, but adding a fallback
|
||||
* here doesn't hurt*/
|
||||
#define MCUSR MCUCSR
|
||||
#endif /* !MCUSR */
|
||||
#endif /* RST */
|
||||
|
||||
/*
|
||||
* Since atmega MCUs do not feature a software reset, the watchdog timer
|
||||
@ -86,6 +96,10 @@ void cpu_init(void)
|
||||
wdt_reset(); /* should not be nececessary as done in bootloader */
|
||||
wdt_disable(); /* but when used without bootloader this is needed */
|
||||
|
||||
#ifdef CPU_AVR8_HAS_CLOCK_INIT
|
||||
avr8_clk_init();
|
||||
#endif
|
||||
|
||||
/* Initialize stdio before periph_init() to allow use of DEBUG() there */
|
||||
#ifdef MODULE_AVR_LIBC_EXTRA
|
||||
avr8_stdio_init();
|
||||
@ -95,6 +109,15 @@ void cpu_init(void)
|
||||
/* rtc_init */
|
||||
/* hwrng_init */
|
||||
periph_init();
|
||||
|
||||
#ifdef CPU_ATXMEGA
|
||||
/* Enable Multilevel Interrupt Controller */
|
||||
PMIC.CTRL |= PMIC_HILVLEN_bm
|
||||
| PMIC_MEDLVLEN_bm
|
||||
| PMIC_LOLVLEN_bm;
|
||||
#endif
|
||||
|
||||
irq_enable();
|
||||
}
|
||||
|
||||
struct __freelist {
|
||||
|
@ -63,6 +63,11 @@ extern "C"
|
||||
#define AVR8_STATE_FLAG_ISR (0x80U) /**< In ISR */
|
||||
#define AVR8_STATE_FLAG_UART0_TX (0x01U) /**< TX pending for UART 0 */
|
||||
#define AVR8_STATE_FLAG_UART1_TX (0x02U) /**< TX pending for UART 1 */
|
||||
#define AVR8_STATE_FLAG_UART2_TX (0x04U) /**< TX pending for UART 2 */
|
||||
#define AVR8_STATE_FLAG_UART3_TX (0x08U) /**< TX pending for UART 3 */
|
||||
#define AVR8_STATE_FLAG_UART4_TX (0x10U) /**< TX pending for UART 4 */
|
||||
#define AVR8_STATE_FLAG_UART5_TX (0x20U) /**< TX pending for UART 5 */
|
||||
#define AVR8_STATE_FLAG_UART6_TX (0x40U) /**< TX pending for UART 6 */
|
||||
#define AVR8_STATE_FLAG_UART_TX(x) (0x01U << x) /**< TX pending for UART x */
|
||||
/** @} */
|
||||
|
||||
@ -77,14 +82,18 @@ extern "C"
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* 7 6 5 4 3 2 1 0
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* |IRQ| unused |TX1|TX0|
|
||||
* |IRQ|TX6|TX5|TX4|TX3|TX2|TX1|TX0|
|
||||
* +---+---+---+---+---+---+---+---+
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* | Label | Description |
|
||||
* |:-------|:--------------------------------------------------------------|
|
||||
* | IRQ | This bit is set when in IRQ context |
|
||||
* | unused | This bits are currently not used |
|
||||
* | TX6 | This bit is set when on UART6 TX is pending |
|
||||
* | TX5 | This bit is set when on UART5 TX is pending |
|
||||
* | TX4 | This bit is set when on UART4 TX is pending |
|
||||
* | TX3 | This bit is set when on UART3 TX is pending |
|
||||
* | TX2 | This bit is set when on UART2 TX is pending |
|
||||
* | TX1 | This bit is set when on UART1 TX is pending |
|
||||
* | TX0 | This bit is set when on UART0 TX is pending |
|
||||
*/
|
||||
@ -138,7 +147,13 @@ static inline void avr8_enter_isr(void)
|
||||
static inline int avr8_is_uart_tx_pending(void)
|
||||
{
|
||||
uint8_t state = avr8_get_state();
|
||||
return (state & (AVR8_STATE_FLAG_UART0_TX | AVR8_STATE_FLAG_UART1_TX));
|
||||
return (state & (AVR8_STATE_FLAG_UART0_TX
|
||||
| AVR8_STATE_FLAG_UART1_TX
|
||||
| AVR8_STATE_FLAG_UART2_TX
|
||||
| AVR8_STATE_FLAG_UART3_TX
|
||||
| AVR8_STATE_FLAG_UART4_TX
|
||||
| AVR8_STATE_FLAG_UART5_TX
|
||||
| AVR8_STATE_FLAG_UART6_TX));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,6 +166,11 @@ void avr8_exit_isr(void);
|
||||
*/
|
||||
void cpu_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initialization of the CPU clock
|
||||
*/
|
||||
void avr8_clk_init(void);
|
||||
|
||||
/**
|
||||
* @brief Print the last instruction's address
|
||||
*/
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2014 Freie Universität Berlin, Hinnerk van Bruinehsen
|
||||
* 2017 Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
* 2018 RWTH Aachen, Josua Arndt <jarndt@ias.rwth-aachen.de>
|
||||
* 2021 Gerson Fernando Budke
|
||||
* 2021 Gerson Fernando Budke <nandojve@gmail.com>
|
||||
*
|
||||
* 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
|
||||
@ -14,7 +14,8 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of the kernel's architecture dependent thread interface
|
||||
* @brief Implementation of the kernel's architecture dependent thread
|
||||
* interface
|
||||
*
|
||||
* @author Hinnerk van Bruinehsen <h.v.bruinehsen@fu-berlin.de>
|
||||
* @author Thomas Perrot <thomas.perrot@tupi.fr>
|
||||
@ -31,14 +32,31 @@
|
||||
#include "irq.h"
|
||||
#include "cpu.h"
|
||||
#include "board.h"
|
||||
#include "macros/xtstr.h"
|
||||
|
||||
#define CHECK_EIND_REG FLASHEND > 0x1ffff
|
||||
|
||||
#if defined(DATAMEM_SIZE)
|
||||
#define CHECK_RAMPZ_REG DATAMEM_SIZE > 0xffff || FLASHEND > 0xffff
|
||||
#define CHECK_RAMPDXY_REG DATAMEM_SIZE > 0xffff
|
||||
#else
|
||||
#define CHECK_RAMPZ_REG FLASHEND > 0xffff
|
||||
#define CHECK_RAMPDXY_REG 0
|
||||
#endif
|
||||
|
||||
#if (CHECK_EIND_REG)
|
||||
#ifndef __EIND__
|
||||
#define __EIND__ 0x3C
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void avr8_context_save(void);
|
||||
static void avr8_context_restore(void);
|
||||
static void avr8_enter_thread_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Since AVR doesn't support direct manipulation of the program counter we
|
||||
* model a stack like it would be left by avr8_context_save().
|
||||
* @brief Since AVR doesn't support direct manipulation of the program counter
|
||||
* we model a stack like it would be left by avr8_context_save().
|
||||
* The resulting layout in memory is the following:
|
||||
* ---------------thread_t (not created by thread_stack_init) ----------
|
||||
* local variables (a temporary value and the stackpointer)
|
||||
@ -46,18 +64,18 @@ static void avr8_enter_thread_mode(void);
|
||||
* a marker (AFFE) - for debugging purposes (helps finding the stack
|
||||
* -----------------------------------------------------------------------
|
||||
* a 16 Bit pointer to sched_task_exit
|
||||
* (Optional 17 bit (bit is set to zero) for devices with > 128kb FLASH)
|
||||
* (Optional EIND bits are set to zero for devices with > 128kb FLASH)
|
||||
* -----------------------------------------------------------------------
|
||||
* a 16 Bit pointer to task_func
|
||||
* this is placed exactly at the place where the program counter would be
|
||||
* stored normally and thus can be returned to when avr8_context_restore()
|
||||
* has been run
|
||||
* (Optional 17 bit (bit is set to zero) for devices with > 128kb FLASH)
|
||||
* (Optional EIND bits are set to zero for devices with > 128kb FLASH)
|
||||
* -----------------------------------------------------------------------
|
||||
* saved registers from context:
|
||||
* r0
|
||||
* status register
|
||||
* (Optional EIND and RAMPZ registers)
|
||||
* (Optional EIND, RAMPZ, RAMPX, RAMPY, RAMPD registers)
|
||||
* r1 - r23
|
||||
* pointer to arg in r24 and r25
|
||||
* r26 - r31
|
||||
@ -91,8 +109,9 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
|
||||
tmp_adress >>= 8;
|
||||
*stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
|
||||
|
||||
#if FLASHEND > 0x1ffff
|
||||
/* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */
|
||||
#if (CHECK_EIND_REG)
|
||||
/* Devices with more than 128kb FLASH use a PC with more than 16bits, we
|
||||
* set whole the top byte forcibly to 0 */
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00;
|
||||
#endif
|
||||
@ -105,8 +124,9 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
|
||||
tmp_adress >>= 8;
|
||||
*stk = (uint8_t)(tmp_adress & (uint16_t)0x00ff);
|
||||
|
||||
#if FLASHEND > 0x1ffff
|
||||
/* Devices with more than 128kb FLASH use a 17 bit PC, we set whole the top byte forcibly to 0 */
|
||||
#if (CHECK_EIND_REG)
|
||||
/* Devices with more than 128kb FLASH use a PC with more than 16bits, we
|
||||
* set whole the top byte forcibly to 0 */
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00;
|
||||
#endif
|
||||
@ -119,13 +139,23 @@ char *thread_stack_init(thread_task_func_t task_func, void *arg,
|
||||
stk--;
|
||||
*stk = (uint8_t)0x80;
|
||||
|
||||
#if defined(EIND)
|
||||
#if (CHECK_RAMPZ_REG)
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00;
|
||||
*stk = (uint8_t)0x00; /* RAMPZ */
|
||||
#endif
|
||||
#if defined(RAMPZ) && !defined(__AVR_ATmega32U4__)
|
||||
|
||||
#if (CHECK_RAMPDXY_REG)
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00;
|
||||
*stk = (uint8_t)0x00; /* RAMPY */
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00; /* RAMPX */
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00; /* RAMPD */
|
||||
#endif
|
||||
|
||||
#if (CHECK_EIND_REG)
|
||||
stk--;
|
||||
*stk = (uint8_t)0x00; /* EIND */
|
||||
#endif
|
||||
|
||||
/* r1 - has always to be 0 */
|
||||
@ -210,7 +240,8 @@ extern char * __malloc_heap_end;
|
||||
extern char *__brkval;
|
||||
|
||||
/**
|
||||
* @brief Set the MCU into Thread-Mode and load the initial task from the stack and run it
|
||||
* @brief Set the MCU into Thread-Mode and load the initial task from the
|
||||
* stack and run it
|
||||
*/
|
||||
void NORETURN avr8_enter_thread_mode(void)
|
||||
{
|
||||
@ -223,6 +254,7 @@ void NORETURN avr8_enter_thread_mode(void)
|
||||
* thread-mode. Therefore, it can be considered as the top of the heap.
|
||||
*/
|
||||
__malloc_heap_end = STACK_POINTER - __malloc_margin;
|
||||
|
||||
/* __brkval has to be initialized if necessary */
|
||||
if (__brkval == NULL) {
|
||||
__brkval = __malloc_heap_start;
|
||||
@ -250,8 +282,10 @@ void thread_yield_higher(void)
|
||||
void avr8_exit_isr(void)
|
||||
{
|
||||
avr8_state &= ~AVR8_STATE_FLAG_ISR;
|
||||
|
||||
/* Force access to avr8_state to take place */
|
||||
__asm__ volatile ("" : : : "memory");
|
||||
|
||||
if (sched_context_switch_request) {
|
||||
avr8_context_save();
|
||||
sched_run();
|
||||
@ -263,108 +297,131 @@ void avr8_exit_isr(void)
|
||||
__attribute__((always_inline)) static inline void avr8_context_save(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"push __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __SREG__ \n\t"
|
||||
"cli \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
#if defined(RAMPZ) && !defined(__AVR_ATmega32U4__)
|
||||
"in __tmp_reg__, __RAMPZ__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __SREG__ \n\t"
|
||||
"cli \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
|
||||
#if (CHECK_RAMPZ_REG)
|
||||
"in __tmp_reg__, __RAMPZ__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
#endif
|
||||
#if defined(EIND)
|
||||
"in __tmp_reg__, 0x3c \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
|
||||
#if (CHECK_RAMPDXY_REG)
|
||||
"in __tmp_reg__, __RAMPY__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __RAMPX__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __RAMPD__ \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
#endif
|
||||
"push r1 \n\t"
|
||||
"clr r1 \n\t"
|
||||
"push r2 \n\t"
|
||||
"push r3 \n\t"
|
||||
"push r4 \n\t"
|
||||
"push r5 \n\t"
|
||||
"push r6 \n\t"
|
||||
"push r7 \n\t"
|
||||
"push r8 \n\t"
|
||||
"push r9 \n\t"
|
||||
"push r10 \n\t"
|
||||
"push r11 \n\t"
|
||||
"push r12 \n\t"
|
||||
"push r13 \n\t"
|
||||
"push r14 \n\t"
|
||||
"push r15 \n\t"
|
||||
"push r16 \n\t"
|
||||
"push r17 \n\t"
|
||||
"push r18 \n\t"
|
||||
"push r19 \n\t"
|
||||
"push r20 \n\t"
|
||||
"push r21 \n\t"
|
||||
"push r22 \n\t"
|
||||
"push r23 \n\t"
|
||||
"push r24 \n\t"
|
||||
"push r25 \n\t"
|
||||
"push r26 \n\t"
|
||||
"push r27 \n\t"
|
||||
"push r28 \n\t"
|
||||
"push r29 \n\t"
|
||||
"push r30 \n\t"
|
||||
"push r31 \n\t"
|
||||
"lds r26, sched_active_thread \n\t"
|
||||
"lds r27, sched_active_thread + 1 \n\t"
|
||||
"in __tmp_reg__, __SP_L__ \n\t"
|
||||
"st x+, __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __SP_H__ \n\t"
|
||||
"st x+, __tmp_reg__ \n\t");
|
||||
|
||||
#if (CHECK_EIND_REG)
|
||||
"in __tmp_reg__, " XTSTR(__EIND__) " \n\t"
|
||||
"push __tmp_reg__ \n\t"
|
||||
#endif
|
||||
|
||||
"push r1 \n\t"
|
||||
"clr r1 \n\t"
|
||||
"push r2 \n\t"
|
||||
"push r3 \n\t"
|
||||
"push r4 \n\t"
|
||||
"push r5 \n\t"
|
||||
"push r6 \n\t"
|
||||
"push r7 \n\t"
|
||||
"push r8 \n\t"
|
||||
"push r9 \n\t"
|
||||
"push r10 \n\t"
|
||||
"push r11 \n\t"
|
||||
"push r12 \n\t"
|
||||
"push r13 \n\t"
|
||||
"push r14 \n\t"
|
||||
"push r15 \n\t"
|
||||
"push r16 \n\t"
|
||||
"push r17 \n\t"
|
||||
"push r18 \n\t"
|
||||
"push r19 \n\t"
|
||||
"push r20 \n\t"
|
||||
"push r21 \n\t"
|
||||
"push r22 \n\t"
|
||||
"push r23 \n\t"
|
||||
"push r24 \n\t"
|
||||
"push r25 \n\t"
|
||||
"push r26 \n\t"
|
||||
"push r27 \n\t"
|
||||
"push r28 \n\t"
|
||||
"push r29 \n\t"
|
||||
"push r30 \n\t"
|
||||
"push r31 \n\t"
|
||||
"lds r26, sched_active_thread \n\t"
|
||||
"lds r27, sched_active_thread + 1 \n\t"
|
||||
"in __tmp_reg__, __SP_L__ \n\t"
|
||||
"st x+, __tmp_reg__ \n\t"
|
||||
"in __tmp_reg__, __SP_H__ \n\t"
|
||||
"st x+, __tmp_reg__ \n\t");
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void avr8_context_restore(void)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"lds r26, sched_active_thread \n\t"
|
||||
"lds r27, sched_active_thread + 1 \n\t"
|
||||
"ld r28, x+ \n\t"
|
||||
"out __SP_L__, r28 \n\t"
|
||||
"ld r29, x+ \n\t"
|
||||
"out __SP_H__, r29 \n\t"
|
||||
"pop r31 \n\t"
|
||||
"pop r30 \n\t"
|
||||
"pop r29 \n\t"
|
||||
"pop r28 \n\t"
|
||||
"pop r27 \n\t"
|
||||
"pop r26 \n\t"
|
||||
"pop r25 \n\t"
|
||||
"pop r24 \n\t"
|
||||
"pop r23 \n\t"
|
||||
"pop r22 \n\t"
|
||||
"pop r21 \n\t"
|
||||
"pop r20 \n\t"
|
||||
"pop r19 \n\t"
|
||||
"pop r18 \n\t"
|
||||
"pop r17 \n\t"
|
||||
"pop r16 \n\t"
|
||||
"pop r15 \n\t"
|
||||
"pop r14 \n\t"
|
||||
"pop r13 \n\t"
|
||||
"pop r12 \n\t"
|
||||
"pop r11 \n\t"
|
||||
"pop r10 \n\t"
|
||||
"pop r9 \n\t"
|
||||
"pop r8 \n\t"
|
||||
"pop r7 \n\t"
|
||||
"pop r6 \n\t"
|
||||
"pop r5 \n\t"
|
||||
"pop r4 \n\t"
|
||||
"pop r3 \n\t"
|
||||
"pop r2 \n\t"
|
||||
"pop r1 \n\t"
|
||||
#if defined(EIND)
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out 0x3c, __tmp_reg__ \n\t"
|
||||
"lds r26, sched_active_thread \n\t"
|
||||
"lds r27, sched_active_thread + 1 \n\t"
|
||||
"ld r28, x+ \n\t"
|
||||
"out __SP_L__, r28 \n\t"
|
||||
"ld r29, x+ \n\t"
|
||||
"out __SP_H__, r29 \n\t"
|
||||
"pop r31 \n\t"
|
||||
"pop r30 \n\t"
|
||||
"pop r29 \n\t"
|
||||
"pop r28 \n\t"
|
||||
"pop r27 \n\t"
|
||||
"pop r26 \n\t"
|
||||
"pop r25 \n\t"
|
||||
"pop r24 \n\t"
|
||||
"pop r23 \n\t"
|
||||
"pop r22 \n\t"
|
||||
"pop r21 \n\t"
|
||||
"pop r20 \n\t"
|
||||
"pop r19 \n\t"
|
||||
"pop r18 \n\t"
|
||||
"pop r17 \n\t"
|
||||
"pop r16 \n\t"
|
||||
"pop r15 \n\t"
|
||||
"pop r14 \n\t"
|
||||
"pop r13 \n\t"
|
||||
"pop r12 \n\t"
|
||||
"pop r11 \n\t"
|
||||
"pop r10 \n\t"
|
||||
"pop r9 \n\t"
|
||||
"pop r8 \n\t"
|
||||
"pop r7 \n\t"
|
||||
"pop r6 \n\t"
|
||||
"pop r5 \n\t"
|
||||
"pop r4 \n\t"
|
||||
"pop r3 \n\t"
|
||||
"pop r2 \n\t"
|
||||
"pop r1 \n\t"
|
||||
|
||||
#if (CHECK_EIND_REG)
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out " XTSTR(__EIND__) ", __tmp_reg__ \n\t"
|
||||
#endif
|
||||
|
||||
#if defined(RAMPZ) && !defined(__AVR_ATmega32U4__)
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __RAMPZ__, __tmp_reg__ \n\t"
|
||||
#if (CHECK_RAMPDXY_REG)
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __RAMPD__, __tmp_reg__ \n\t"
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __RAMPX__, __tmp_reg__ \n\t"
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __RAMPY__, __tmp_reg__ \n\t"
|
||||
#endif
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __SREG__, __tmp_reg__ \n\t"
|
||||
"pop __tmp_reg__ \n\t");
|
||||
|
||||
#if (CHECK_RAMPZ_REG)
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __RAMPZ__, __tmp_reg__ \n\t"
|
||||
#endif
|
||||
|
||||
"pop __tmp_reg__ \n\t"
|
||||
"out __SREG__, __tmp_reg__ \n\t"
|
||||
"pop __tmp_reg__ \n\t");
|
||||
}
|
||||
|
@ -7,16 +7,16 @@
|
||||
|
||||
config MODULE_WS281X
|
||||
bool "WS2812/SK6812 RGB LED (NeoPixel)"
|
||||
depends on HAS_ARCH_AVR8 || HAS_ARCH_ESP32 || HAS_ARCH_NATIVE
|
||||
depends on HAS_CPU_CORE_ATMEGA || HAS_ARCH_ESP32 || HAS_ARCH_NATIVE
|
||||
depends on TEST_KCONFIG
|
||||
select MODULE_XTIMER
|
||||
select MODULE_WS281X_ATMEGA if HAS_ARCH_AVR8
|
||||
select MODULE_WS281X_ATMEGA if HAS_CPU_CORE_ATMEGA
|
||||
select MODULE_WS281X_VT100 if HAS_ARCH_NATIVE
|
||||
select MODULE_WS281X_ESP32 if HAS_ARCH_ESP32
|
||||
|
||||
config MODULE_WS281X_ATMEGA
|
||||
bool
|
||||
depends on HAS_ARCH_AVR8
|
||||
depends on HAS_CPU_CORE_ATMEGA
|
||||
|
||||
config MODULE_WS281X_VT100
|
||||
bool
|
||||
|
@ -1,7 +1,7 @@
|
||||
FEATURES_REQUIRED_ANY += arch_avr8|arch_esp32|arch_native
|
||||
FEATURES_REQUIRED_ANY += cpu_core_atmega|arch_esp32|arch_native
|
||||
|
||||
ifeq (,$(filter ws281x_%,$(USEMODULE)))
|
||||
ifneq (,$(filter arch_avr8,$(FEATURES_USED)))
|
||||
ifneq (,$(filter cpu_core_atmega,$(FEATURES_USED)))
|
||||
USEMODULE += ws281x_atmega
|
||||
endif
|
||||
ifneq (,$(filter arch_native,$(FEATURES_USED)))
|
||||
@ -13,7 +13,7 @@ ifeq (,$(filter ws281x_%,$(USEMODULE)))
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ws281x_atmega,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += arch_avr8
|
||||
FEATURES_REQUIRED += cpu_core_atmega
|
||||
endif
|
||||
|
||||
USEMODULE += xtimer
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
chronos \
|
||||
derfmega128 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill \
|
||||
blackpill-128kib \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
blackpill \
|
||||
bluepill \
|
||||
bluepill-stm32f030c8 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
chronos \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -2,7 +2,14 @@
|
||||
TARGET_ARCH_AVR ?= avr
|
||||
TARGET_ARCH ?= $(TARGET_ARCH_AVR)
|
||||
|
||||
CFLAGS_CPU = -mmcu=$(CPU) $(CFLAGS_FPU)
|
||||
ifeq (atxmega,$(CPU))
|
||||
ifeq (,$(CPU_MODEL))
|
||||
$(error CPU_MODEL must have been defined by the board Makefile.features)
|
||||
endif
|
||||
CFLAGS_CPU ?= -mmcu=$(CPU_MODEL) $(CFLAGS_FPU)
|
||||
else
|
||||
CFLAGS_CPU ?= -mmcu=$(CPU) $(CFLAGS_FPU)
|
||||
endif
|
||||
CFLAGS_LINK = -ffunction-sections -fdata-sections -fno-builtin -fshort-enums
|
||||
CFLAGS_DBG ?= -ggdb -g3
|
||||
CFLAGS_OPT ?= -Os
|
@ -12,14 +12,18 @@ ifneq (,$(filter $(CPU),atmega328p))
|
||||
# Use debugWIRE as protocol for debugging (ATmega328P does not support JTAG)
|
||||
DEBUGPROTO := -w
|
||||
else
|
||||
# Use JTAG as protocol for debugging
|
||||
DEBUGPROTO := -j $(AVR_DEBUGINTERFACE)
|
||||
# Use JTAG as protocol for debugging as default
|
||||
DEBUGPROTO ?= -j $(AVR_DEBUGINTERFACE)
|
||||
endif
|
||||
DEBUGSERVER_FLAGS ?= "$(AVR_DEBUGDEVICE) $(DEBUGPROTO) :$(DEBUGSERVER_PORT)"
|
||||
DEBUGGER_FLAGS ?= "-x $(AVARICE_PATH)/gdb.conf $(ELFFILE)"
|
||||
DEBUGGER = "$(AVARICE_PATH)/debug.sh" $(DEBUGSERVER_FLAGS) $(AVARICE_PATH) $(DEBUGSERVER_PORT)
|
||||
|
||||
AVRDUDE_PROGRAMMER_FLAGS = -p $(subst atmega,m,$(CPU))
|
||||
ifeq (atxmega,$(CPU))
|
||||
AVRDUDE_PROGRAMMER_FLAGS ?= -p $(subst atxmega,x,$(CPU_MODEL))
|
||||
else
|
||||
AVRDUDE_PROGRAMMER_FLAGS = -p $(subst atmega,m,$(CPU))
|
||||
endif
|
||||
|
||||
# Set flasher port only for programmers that require it
|
||||
ifneq (,$(filter $(AVRDUDE_PROGRAMMER),arduino avr109 buspirate stk500v1 stk500v2 wiring))
|
||||
|
@ -3,6 +3,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
im880b \
|
||||
nucleo-l011k4 \
|
||||
|
@ -4,6 +4,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
nucleo-f031k6 \
|
||||
nucleo-l011k4 \
|
||||
samd10-xmini \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
|
@ -4,6 +4,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
nucleo-f030r8 \
|
||||
nucleo-f031k6 \
|
||||
nucleo-f042k6 \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill \
|
||||
blackpill-128kib \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill \
|
||||
blackpill-128kib \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
blackpill \
|
||||
bluepill \
|
||||
bluepill-stm32f030c8 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nucleo-f031k6 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
i-nucleo-lrwan1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
b-l072z-lrwan1 \
|
||||
blackpill \
|
||||
blackpill-128kib \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
hifive1 \
|
||||
hifive1b \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
blackpill \
|
||||
bluepill \
|
||||
bluepill-stm32f030c8 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
msb-430 \
|
||||
msb-430h \
|
||||
nucleo-f031k6 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
derfmega128 \
|
||||
hifive1 \
|
||||
|
@ -6,6 +6,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega1281 \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
msb-430 \
|
||||
|
@ -7,6 +7,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
blackpill \
|
||||
bluepill \
|
||||
bluepill-stm32f030c8 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
mega-xplained \
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
|
@ -2,6 +2,10 @@ include ../Makefile.tests_common
|
||||
|
||||
FEATURES_REQUIRED = periph_timer
|
||||
|
||||
BOARDS_TIMER_500kHz := \
|
||||
atxmega-a1u-xpro \
|
||||
#
|
||||
|
||||
BOARDS_TIMER_250kHz := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
@ -39,7 +43,9 @@ BOARDS_TIMER_CLOCK_CORECLOCK := \
|
||||
waspmote-pro \
|
||||
#
|
||||
|
||||
ifneq (,$(filter $(BOARDS_TIMER_250kHz),$(BOARD)))
|
||||
ifneq (,$(filter $(BOARDS_TIMER_500kHz),$(BOARD)))
|
||||
TIMER_SPEED ?= 500000
|
||||
else ifneq (,$(filter $(BOARDS_TIMER_250kHz),$(BOARD)))
|
||||
TIMER_SPEED ?= 250000
|
||||
else ifneq (,$(filter $(BOARDS_TIMER_32kHz),$(BOARD)))
|
||||
TIMER_SPEED ?= 32768
|
||||
|
@ -5,6 +5,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-uno \
|
||||
atmega1284p \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
blackpill \
|
||||
bluepill \
|
||||
derfmega128 \
|
||||
|
@ -4,6 +4,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atxmega-a1u-xpro \
|
||||
bluepill-stm32f030c8 \
|
||||
i-nucleo-lrwan1 \
|
||||
nucleo-f030r8 \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user