diff --git a/boards/common/atmega/include/periph_conf_atmega_common.h b/boards/common/atmega/include/periph_conf_atmega_common.h index de95f5a303..a6a7049df8 100644 --- a/boards/common/atmega/include/periph_conf_atmega_common.h +++ b/boards/common/atmega/include/periph_conf_atmega_common.h @@ -121,7 +121,7 @@ extern "C" { #define TIMER_1_ISRA TIMER3_COMPA_vect #define TIMER_1_ISRB TIMER3_COMPB_vect #define TIMER_1_ISRC TIMER3_COMPC_vect -#elif defined(CPU_ATMEGA256RFR2) +#elif defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2) #define TIMER_NUMOF (3U) #define TIMER_CHANNELS (3) @@ -203,7 +203,8 @@ extern "C" { */ #ifndef UART_NUMOF -#if defined(CPU_ATMEGA256RFR2) || defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA2560) +#if defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2) || \ + defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA2560) #define UART_NUMOF (2U) /* UART0 is used for stdio */ @@ -295,7 +296,8 @@ extern "C" { * @{ */ #ifndef ADC_NUMOF -#if defined(CPU_ATMEGA256RFR2) || defined(CPU_ATMEGA328P) || defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA32U4) +#if defined(CPU_ATMEGA128RFA1) || defined(CPU_ATMEGA256RFR2) || defined(CPU_ATMEGA328P) || \ + defined(CPU_ATMEGA1281) || defined(CPU_ATMEGA1284P) || defined(CPU_ATMEGA32U4) #define ADC_NUMOF (8U) #elif defined (CPU_ATMEGA2560) #define ADC_NUMOF (16U) diff --git a/cpu/atmega128rfa1/Makefile b/cpu/atmega128rfa1/Makefile new file mode 100644 index 0000000000..bfe7b40097 --- /dev/null +++ b/cpu/atmega128rfa1/Makefile @@ -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)/atmega_common/ + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/atmega128rfa1/Makefile.dep b/cpu/atmega128rfa1/Makefile.dep new file mode 100644 index 0000000000..29a865fd37 --- /dev/null +++ b/cpu/atmega128rfa1/Makefile.dep @@ -0,0 +1,6 @@ +# additional PCINTs for atmega128rfa1 +ifneq (,$(filter atmega_pcint,$(USEMODULE))) + USEMODULE += atmega_pcint1 +endif + +include $(RIOTCPU)/atmega_common/Makefile.dep diff --git a/cpu/atmega128rfa1/Makefile.features b/cpu/atmega128rfa1/Makefile.features new file mode 100644 index 0000000000..4bac718e83 --- /dev/null +++ b/cpu/atmega128rfa1/Makefile.features @@ -0,0 +1,9 @@ +include $(RIOTCPU)/atmega_common/Makefile.features +# common feature are defined in atmega_common/Makefile.features +# Only add Additional features + +# additional PCINT for atmega128rfa1 +FEATURES_PROVIDED += atmega_pcint1 + +# Various other features (if any) +FEATURES_PROVIDED += periph_cpuid diff --git a/cpu/atmega128rfa1/Makefile.include b/cpu/atmega128rfa1/Makefile.include new file mode 100644 index 0000000000..beb154850e --- /dev/null +++ b/cpu/atmega128rfa1/Makefile.include @@ -0,0 +1,16 @@ +# tell the build system that the CPU depends on the atmega common files +USEMODULE += atmega_common + +#include periph module +USEMODULE += periph + +RAM_LEN = 16K +ROM_LEN = 128K + +# expand atmega_pcint for atmega128rfa1 +ifneq (,$(filter atmega_pcint,$(USEMODULE))) + USEMODULE += atmega_pcint1 +endif + +# CPU depends on the atmega common module, so include it +include $(RIOTCPU)/atmega_common/Makefile.include diff --git a/cpu/atmega128rfa1/doc.txt b/cpu/atmega128rfa1/doc.txt new file mode 100644 index 0000000000..28dc3fa949 --- /dev/null +++ b/cpu/atmega128rfa1/doc.txt @@ -0,0 +1,5 @@ +/** + * @defgroup cpu_atmega128rfa1 Atmel ATmega128rfa1 + * @ingroup cpu + * @brief Implementation of Atmel's ATmega128rfa1 MCU + */ diff --git a/cpu/atmega128rfa1/include/atmega_pcint.h b/cpu/atmega128rfa1/include/atmega_pcint.h new file mode 100644 index 0000000000..c25d43c169 --- /dev/null +++ b/cpu/atmega128rfa1/include/atmega_pcint.h @@ -0,0 +1,15 @@ +#ifndef ATMEGA_PCINT_H +#define ATMEGA_PCINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ATMEGA_PCINT_MAP_PCINT0 GPIO_PIN(PORT_B, 0), GPIO_PIN(PORT_B, 1), GPIO_PIN(PORT_B, 2), GPIO_PIN(PORT_B, 3), GPIO_PIN(PORT_B, 4), GPIO_PIN(PORT_B, 5), GPIO_PIN(PORT_B, 6), GPIO_PIN(PORT_B, 7) +#define ATMEGA_PCINT_MAP_PCINT1 GPIO_PIN(PORT_E, 0), GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF, GPIO_UNDEF + +#ifdef __cplusplus +} +#endif + +#endif /* ATMEGA_PCINT_H */ diff --git a/cpu/atmega128rfa1/include/periph_cpu.h b/cpu/atmega128rfa1/include/periph_cpu.h new file mode 100644 index 0000000000..e39b812f3d --- /dev/null +++ b/cpu/atmega128rfa1/include/periph_cpu.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) Josua Arndt, Steffen Robertz 2017 RWTH Aachen + * + * 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_atmega128rfa1 + * @{ + * + * @file + * @brief CPU specific definitions for internal peripheral handling + * + * @author Josua Arndt + * @author Steffen Robertz + */ + +#ifndef PERIPH_CPU_H +#define PERIPH_CPU_H + +#include "periph_cpu_common.h" +#include "atmega_regs_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Length of the CPU_ID in octets + * @{ + */ +#define CPUID_LEN (8U) +/** @} */ + +/** + * @name Available ports on the ATmega128rfa1 MCU + * @{ + */ +enum { + PORT_B = 1, /**< port B */ + PORT_D = 3, /**< port D */ + PORT_E = 4, /**< port E */ + PORT_F = 5, /**< port F */ + PORT_G = 6, /**< port G */ +}; + +/** + * @brief Available external interrupt pins on the ATmega128rfa1 MCU + * + * In order of their interrupt number. + */ +#define CPU_ATMEGA_EXT_INTS { GPIO_PIN(PORT_D, 0), \ + GPIO_PIN(PORT_D, 1), \ + GPIO_PIN(PORT_D, 2), \ + GPIO_PIN(PORT_D, 3), \ + GPIO_PIN(PORT_E, 4), \ + GPIO_PIN(PORT_E, 5), \ + GPIO_PIN(PORT_E, 6), \ + GPIO_PIN(PORT_E, 7) } + +/** + * @name Defines for the I2C interface + * @{ + */ +#define I2C_PORT_REG PORTD +#define I2C_PIN_MASK (1 << PORTD1) | (1 << PORTD0) +/** @} */ + +/** + * @name EEPROM configuration + * @{ + */ +#define EEPROM_SIZE (4096U) /* 4kB */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* PERIPH_CPU_H */ +/** @} */ diff --git a/cpu/atmega128rfa1/ldscripts_compat/README.md b/cpu/atmega128rfa1/ldscripts_compat/README.md new file mode 100644 index 0000000000..31317f0371 --- /dev/null +++ b/cpu/atmega128rfa1/ldscripts_compat/README.md @@ -0,0 +1,14 @@ +avr linkerscript +================ + +Starting from avr-binutils 2.26, the linker defines symbol that can be +overriden to configure ROM and RAM length. + +This ldscript is used for supporting older versions on avr-binutils like on +ubuntu xenial. + +Generated by extracting the output of + + avr-gcc -Wl,--verbose -mmcu=$(CPU) + +With avr-binutils 2.26 diff --git a/cpu/atmega128rfa1/ldscripts_compat/avr_2.26.ld b/cpu/atmega128rfa1/ldscripts_compat/avr_2.26.ld new file mode 100644 index 0000000000..07dcba9a1e --- /dev/null +++ b/cpu/atmega128rfa1/ldscripts_compat/avr_2.26.ld @@ -0,0 +1,262 @@ +/* Script for -n: mix text and data on same page */ +/* Copyright (C) 2014-2015 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr") +OUTPUT_ARCH(avr:51) +__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 128K; +__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xff00; +__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K; +__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K; +__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K; +__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K; +__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K; +MEMORY +{ + text (rx) : ORIGIN = 0, LENGTH = __TEXT_REGION_LENGTH__ + data (rw!x) : ORIGIN = 0x800200, LENGTH = __DATA_REGION_LENGTH__ + eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__ + fuse (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__ + lock (rw!x) : ORIGIN = 0x830000, LENGTH = __LOCK_REGION_LENGTH__ + signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__ + user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__ +} +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : + { + *(.rel.text) + *(.rel.text.*) + *(.rel.gnu.linkonce.t*) + } + .rela.text : + { + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t*) + } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : + { + *(.rel.rodata) + *(.rel.rodata.*) + *(.rel.gnu.linkonce.r*) + } + .rela.rodata : + { + *(.rela.rodata) + *(.rela.rodata.*) + *(.rela.gnu.linkonce.r*) + } + .rel.data : + { + *(.rel.data) + *(.rel.data.*) + *(.rel.gnu.linkonce.d*) + } + .rela.data : + { + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d*) + } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + /* Internal text space or external memory. */ + .text : + { + *(.vectors) + KEEP(*(.vectors)) + /* For data that needs to reside in the lower 64k of progmem. */ + *(.progmem.gcc*) + /* PR 13812: Placing the trampolines here gives a better chance + that they will be in range of the code that uses them. */ + . = ALIGN(2); + __trampolines_start = . ; + /* The jump trampolines for the 16-bit limited relocs will reside here. */ + *(.trampolines) + *(.trampolines*) + __trampolines_end = . ; + /* avr-libc expects these data to reside in lower 64K. */ + *libprintf_flt.a:*(.progmem.data) + *libc.a:*(.progmem.data) + *(.progmem*) + . = ALIGN(2); + /* For future tablejump instruction arrays for 3 byte pc devices. + We don't relax jump/call instructions within these sections. */ + *(.jumptables) + *(.jumptables*) + /* For code that needs to reside in the lower 128k progmem. */ + *(.lowtext) + *(.lowtext*) + __ctors_start = . ; + *(.ctors) + __ctors_end = . ; + __dtors_start = . ; + *(.dtors) + __dtors_end = . ; + KEEP(SORT(*)(.ctors)) + KEEP(SORT(*)(.dtors)) + /* From this point on, we don't bother about wether the insns are + below or above the 16 bits boundary. */ + *(.init0) /* Start here after reset. */ + KEEP (*(.init0)) + *(.init1) + KEEP (*(.init1)) + *(.init2) /* Clear __zero_reg__, set up stack pointer. */ + KEEP (*(.init2)) + *(.init3) + KEEP (*(.init3)) + *(.init4) /* Initialize data and BSS. */ + KEEP (*(.init4)) + *(.init5) + KEEP (*(.init5)) + *(.init6) /* C++ constructors. */ + KEEP (*(.init6)) + *(.init7) + KEEP (*(.init7)) + *(.init8) + KEEP (*(.init8)) + *(.init9) /* Call main(). */ + KEEP (*(.init9)) + *(.text) + . = ALIGN(2); + *(.text.*) + . = ALIGN(2); + *(.fini9) /* _exit() starts here. */ + KEEP (*(.fini9)) + *(.fini8) + KEEP (*(.fini8)) + *(.fini7) + KEEP (*(.fini7)) + *(.fini6) /* C++ destructors. */ + KEEP (*(.fini6)) + *(.fini5) + KEEP (*(.fini5)) + *(.fini4) + KEEP (*(.fini4)) + *(.fini3) + KEEP (*(.fini3)) + *(.fini2) + KEEP (*(.fini2)) + *(.fini1) + KEEP (*(.fini1)) + *(.fini0) /* Infinite loop after program termination. */ + KEEP (*(.fini0)) + _etext = . ; + } > text + .data : + { + PROVIDE (__data_start = .) ; + *(.data) + *(.data*) + *(.rodata) /* We need to include .rodata here if gcc is used */ + *(.rodata*) /* with -fdata-sections. */ + *(.gnu.linkonce.d*) + . = ALIGN(2); + _edata = . ; + PROVIDE (__data_end = .) ; + } > data AT> text + .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) + { + PROVIDE (__bss_start = .) ; + *(.bss) + *(.bss*) + *(COMMON) + PROVIDE (__bss_end = .) ; + } > data + __data_load_start = LOADADDR(.data); + __data_load_end = __data_load_start + SIZEOF(.data); + /* Global data not cleared after reset. */ + .noinit ADDR(.bss) + SIZEOF (.bss) : AT (ADDR (.noinit)) + { + PROVIDE (__noinit_start = .) ; + *(.noinit*) + PROVIDE (__noinit_end = .) ; + _end = . ; + PROVIDE (__heap_start = .) ; + } > data + .eeprom : + { + /* See .data above... */ + KEEP(*(.eeprom*)) + __eeprom_end = . ; + } > eeprom + .fuse : + { + KEEP(*(.fuse)) + KEEP(*(.lfuse)) + KEEP(*(.hfuse)) + KEEP(*(.efuse)) + } > fuse + .lock : + { + KEEP(*(.lock*)) + } > lock + .signature : + { + KEEP(*(.signature*)) + } > signature + .user_signatures : + { + KEEP(*(.user_signatures*)) + } > user_signatures + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } +} diff --git a/cpu/atmega128rfa1/periph/Makefile b/cpu/atmega128rfa1/periph/Makefile new file mode 100644 index 0000000000..a36df249ac --- /dev/null +++ b/cpu/atmega128rfa1/periph/Makefile @@ -0,0 +1 @@ +include $(RIOTMAKE)/periph.mk diff --git a/cpu/atmega128rfa1/periph/cpuid.c b/cpu/atmega128rfa1/periph/cpuid.c new file mode 100644 index 0000000000..c3afe35563 --- /dev/null +++ b/cpu/atmega128rfa1/periph/cpuid.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 RWTH Aachen, Josua Arndt, Steffen Robertz + * + * 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_atmega128rfa1 + * @{ + * + * @file + * @brief Low-level CPUID driver implementation + * + * @author Steffen Robertz + * @author Josua Arndt + * + * @} + */ +#include +#include +#include + +#include "periph/cpuid.h" + +#include "atmega_regs_common.h" +#include "avr/boot.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief CPU_ID build from MCU register + * + * CPIUD is taken from MCU Control Register and Signature bytes. + * CPUID: 1e a8 02 1f 94 03 ff ff + * CPUID: 1e a8 02 1f 94 92 XX XX + * MEGA62/128/256_RFR2 [MANUAL] p.505 + * MEGA62/128/256_RFR2 [MANUAL] p.138 + * MEGA62/128/256_RFR2 [MANUAL] p.492 + * + * usr_sign_0/1 are configurable values on flash page 1. + */ +void cpuid_get(void *id) +{ + uint8_t signature_0 = boot_signature_byte_get(0x00); + uint8_t signature_1 = boot_signature_byte_get(0x02); + uint8_t signature_2 = boot_signature_byte_get(0x04); + + uint8_t usr_sign_0 = boot_signature_byte_get(0x0100); + uint8_t usr_sign_1 = boot_signature_byte_get(0x0102); + + uint8_t addr[CPUID_LEN] = { + signature_0, /* 0x1E Atmel manufacturer ID */ + signature_1, /* 0xA8 Part Number high byte */ + signature_2, /* 0x02 Part Number low byte */ + MAN_ID_0, /* 0x1F Atmel JEDEC manufacturer ID */ + PART_NUM, /* 0x94 PART_NUM Identification */ + VERSION_NUM, /* 0x02 VERSION_NUM Identification */ +/* last two bytes can be set to flash page 1. for differentiation of different boards */ + usr_sign_0, /* user signature 0 */ + usr_sign_1, /* user signature 1 */ + }; + +#if defined(ENABLE_DEBUG) + DEBUG("CPUID: " ); + for (uint8_t i=0; i