From 66f6bb45abddd62c5b914871aa886ad9aa6dcf76 Mon Sep 17 00:00:00 2001 From: Kerogit Date: Mon, 10 Mar 2025 22:23:42 +0100 Subject: [PATCH] arch/avr/avrdx: initial support for AVRnDx chips Initial support adds chip specific files like Kconfig, flags for the compiler, and basic functionality like system timer. Some files are stubs derived from corresponding ATmega files but without the functionality they are supposed to add (to be done in later patches) Part of the work is altered copies of corresponding files for ATMega MCUs. Initially supported is AVR128DA28. --- Documentation/platforms/avr/avrdx/index.rst | 28 ++ .../platforms/avr/context-switch-notes.rst | 118 +++++++ arch/avr/Kconfig | 9 + arch/avr/include/avrdx/irq.h | 143 +++++++++ arch/avr/src/avr/Toolchain.defs | 3 + arch/avr/src/avr/excptmacros.h | 106 ++++++- arch/avr/src/avrdx/Kconfig | 90 ++++++ arch/avr/src/avrdx/Make.defs | 58 ++++ arch/avr/src/avrdx/avrdx.h | 107 +++++++ arch/avr/src/avrdx/avrdx_config.h | 48 +++ arch/avr/src/avrdx/avrdx_exceptions.S | 173 +++++++++++ arch/avr/src/avrdx/avrdx_head.S | 288 ++++++++++++++++++ arch/avr/src/avrdx/avrdx_iodefs.h | 76 +++++ arch/avr/src/avrdx/avrdx_lowconsole.c | 92 ++++++ arch/avr/src/avrdx/avrdx_lowinit.c | 116 +++++++ arch/avr/src/avrdx/avrdx_memorymap.h | 48 +++ arch/avr/src/avrdx/avrdx_serial.c | 50 +++ arch/avr/src/avrdx/avrdx_timerisr.c | 164 ++++++++++ arch/avr/src/avrdx/chip.h | 63 ++++ arch/avr/src/avrdx/iodefs/avr128da28.h | 96 ++++++ arch/avr/src/common/avr_internal.h | 17 +- 21 files changed, 1886 insertions(+), 7 deletions(-) create mode 100644 Documentation/platforms/avr/avrdx/index.rst create mode 100644 Documentation/platforms/avr/context-switch-notes.rst create mode 100644 arch/avr/include/avrdx/irq.h create mode 100644 arch/avr/src/avrdx/Kconfig create mode 100644 arch/avr/src/avrdx/Make.defs create mode 100644 arch/avr/src/avrdx/avrdx.h create mode 100644 arch/avr/src/avrdx/avrdx_config.h create mode 100644 arch/avr/src/avrdx/avrdx_exceptions.S create mode 100644 arch/avr/src/avrdx/avrdx_head.S create mode 100644 arch/avr/src/avrdx/avrdx_iodefs.h create mode 100644 arch/avr/src/avrdx/avrdx_lowconsole.c create mode 100644 arch/avr/src/avrdx/avrdx_lowinit.c create mode 100644 arch/avr/src/avrdx/avrdx_memorymap.h create mode 100644 arch/avr/src/avrdx/avrdx_serial.c create mode 100644 arch/avr/src/avrdx/avrdx_timerisr.c create mode 100644 arch/avr/src/avrdx/chip.h create mode 100644 arch/avr/src/avrdx/iodefs/avr128da28.h diff --git a/Documentation/platforms/avr/avrdx/index.rst b/Documentation/platforms/avr/avrdx/index.rst new file mode 100644 index 00000000000..41fe42550bd --- /dev/null +++ b/Documentation/platforms/avr/avrdx/index.rst @@ -0,0 +1,28 @@ +====================== +Microchip DA/DB family +====================== + +This is an attempt to support AVR DA/DB family of MCUs + +Clock Configuration +=================== + +The chip features internal high frequency oscillator, its frequency +can be set in the Kconfig-based configuration. Clock speed in MHz +is then provided in CONFIG_AVRDX_HFO_CLOCK_FREQ + +System Timer +============ + +System timer is provided by RTC peripheral and takes over it. (In theory, +the Periodic Interrupt - PIT - component of it can be still used +but they share single clock.) + +Supported Boards +================ + +.. toctree:: + :glob: + :maxdepth: 1 + + boards/*/* diff --git a/Documentation/platforms/avr/context-switch-notes.rst b/Documentation/platforms/avr/context-switch-notes.rst new file mode 100644 index 00000000000..fa12c73b7b1 --- /dev/null +++ b/Documentation/platforms/avr/context-switch-notes.rst @@ -0,0 +1,118 @@ +=========================== +Notes on AVR context switch +=========================== + +This document describes the ways and circumstances in which context +switches happen in AVR MCUs. + +Used terms and context switch basics +==================================== + +Context creation +---------------- + +There are two ways context is created when a task is suspended. +Either the task is suspended in response to a hardware interrupt +(context created ``in-interrupt`` in the following text), or it is +suspended voluntarily, eg. by calling sleep(), read() etc. +(``in-task`` context.) + +The resulting context is identical and interchangeable with two differences: + + - ``SREG`` - ``in-interrupt`` context has global interrupt enabled ("I"-flag) set + - position in the program where the task resumes running (arbitrary point for ``in-interrupt`` vs. inside ``up_switch_context()`` for ``in-task`` + +Task resumption +--------------- + +Task can be resumed in two corresponding situations - context switch +in response to a hardware interrupt (``by-interrupt``) or in response +to other task relinquishing the CPU (``by-task``) + +Context switch +============== + +Two ways of context creation combined with two ways of task resumption +give 4 possibilities of context switch process, two of which are +not interesting: + +1st combination +--------------- + +``in-task`` context resumed in ``by-task`` context switch. Context +to be resumed has "I" flag cleared and SREG is restored with that flag cleared. +The ``ret`` instruction is used to resume the task,"returning" to the point +where it gave the CPU up, which is inside ``up_switch_context()``. + +This function is supposed to be executed with interrupt disabled ("This +function is called only from the NuttX scheduling logic. Interrupts +will always be disabled when this function is +called." https://nuttx.apache.org/docs/latest/reference/os/arch.html ) Caller +of the context switch method is therefore responsible +for re-enabling interrupts. + +2nd +--- + +``in-interrupt`` resumed in ``by-interrupt`` context switch. The task +essentially (from its point of view) exits interrupt handler after +it entered it. Instruction ``reti`` is used to return from the handler, +setting "I"-flag in the process. + +3rd +--- + +Third and fourth combinations are more interesting: + +``in-task`` context resumed in ``by-interrupt``. The CPU enters +ISR and regular program flow requires returning from ISR and setting +"I"-flag by ``reti`` which does not happen. Task is resumed with +interrupts disabled. However, it is resumed inside ``up_switch_context()`` +and caller of that function will set the "I"-flag at some point. +Task then runs with interrupts enabled, all is well. + +4th +--- + +``in-interrupt`` resumed in ``by-task``, ie. in ``up_switch_context()``. +``reti`` is used to resume the task, setting "I"-flag in the process. +This would be incorrect for ``up_switch_context()`` - it is supposed +to run with interrupts disabled - but the task resumes running +from the point where it was interrupted, which is not inside +of ``up_switch_context()``. All is well. + + +AVRDx core considerations +========================= + +Now, all of the above holds true for eg. ATmega chips which control +interrupt execution solely by the "I"-flag, allowing the code +to not care about where the context switch was triggered. Regardless +of that, the MCU will always end up in correct state even if the +context switch cause doesn't match the context being restored +(cases 3 and 4.) + +This is not the case for AVR Dx family which behaves differently. +The interrupt controller does respect the "I"-flag in a sense where +it considers interrupts disabled when the flag is cleared. However, +it is possible that interrupts are not enabled when the flag is set. +That depends on a logical AND between "I"-flag and "interrupt handler +is not executing" internal state. (Refer to the documentation +for more precise explanation.) + +What this means is that if eg. ``in-task`` context gets +resumed in ``by-interrupt`` condition (case 3 above), then ``ret`` +instruction is used +to resume the task. As discussed above, the "I"-flag is not set this +way but that is not a problem, it is eventually set later. However, +the internal state "running the interrupt handler" is not cleared. +This means that the task keeps running with "global interrupts are +enabled" but is actually unable to be interrupted. The context switch +code needs to handle this. + +Conversely, there is a similar problem with ``in-interrupt`` context +being resumed in ``by-task`` (case 4). Instruction ``reti`` is used +but there is no internal state to be cleared. Unlike the previous case, +no problem related to this was observed but it still looks like something +the code wants to avoid. It could trigger all sorts of undefined behaviour +in the chip otherwise. diff --git a/arch/avr/Kconfig b/arch/avr/Kconfig index 12980e24981..8766a248d9a 100644 --- a/arch/avr/Kconfig +++ b/arch/avr/Kconfig @@ -23,6 +23,13 @@ config ARCH_CHIP_AT90USB ---help--- Atmel AT90USB family of 8-bit AVRs. +config ARCH_CHIP_AVRDX + bool "AVR 32/64/128 DA/DB core" + select ARCH_FAMILY_AVR + select MM_SMALL + ---help--- + Atmel/Microchip AVR 32/64/128 DA/DB core family. + config ARCH_CHIP_AT32UC3 bool "AVR32 AT32UC3* family" select ARCH_FAMILY_AVR32 @@ -54,6 +61,7 @@ config ARCH_FAMILY config ARCH_CHIP string default "atmega" if ARCH_CHIP_ATMEGA + default "avrdx" if ARCH_CHIP_AVRDX default "at90usb" if ARCH_CHIP_AT90USB default "at32uc3" if ARCH_CHIP_AT32UC3 @@ -63,6 +71,7 @@ if ARCH_FAMILY_AVR source "arch/avr/src/avr/Kconfig" source "arch/avr/src/at90usb/Kconfig" source "arch/avr/src/atmega/Kconfig" +source "arch/avr/src/avrdx/Kconfig" endif if ARCH_FAMILY_AVR32 diff --git a/arch/avr/include/avrdx/irq.h b/arch/avr/include/avrdx/irq.h new file mode 100644 index 00000000000..d41c28213f3 --- /dev/null +++ b/arch/avr/include/avrdx/irq.h @@ -0,0 +1,143 @@ +/**************************************************************************** + * arch/avr/include/avrdx/irq.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_AVR_INCLUDE_AVRDX_IRQ_H +#define __ARCH_AVR_INCLUDE_AVRDX_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* AVRnDx interrupt vectors other than vector 0, the reset vector, are + * assigned here: + */ + +#if defined(CONFIG_ARCH_CHIP_AVR128DA28) + +# define AVRDX_IRQ_NMI 0 /* Non-maskable interrupt */ +# define AVRDX_IRQ_BOD_VLM 1 /* BOD interrupt */ +# define AVRDX_IRQ_RTC_CNT 2 /* RTC and periodic interrupt */ +# define AVRDX_IRQ_RTC_PIT 3 +# define AVRDX_IRQ_CCL_CCL 4 /* CCL */ +# define AVRDX_IRQ_PORTA_PORT 5 /* PORTA interrupts */ +# define AVRDX_IRQ_TCA0_LUNF 6 /* TIMER A0 Low byte underflow */ +# define AVRDX_IRQ_TCA0_OVF 6 +# define AVRDX_IRQ_TCA0_HUNF 7 /* TIMER A0 High byte underflow */ +# define AVRDX_IRQ_TCA0_CMP0 8 /* TIMER A0 compare match 0 */ +# define AVRDX_IRQ_TCA0_LCMP0 8 /* TIMER A0 Low byte compare match 0 */ +# define AVRDX_IRQ_TCA0_CMP1 9 +# define AVRDX_IRQ_TCA0_LCMP1 9 +# define AVRDX_IRQ_TCA0_CMP2 10 +# define AVRDX_IRQ_TCA0_LCMP2 10 +# define AVRDX_IRQ_TCB0_INT 11 +# define AVRDX_IRQ_TCB1_INT 12 +# define AVRDX_IRQ_TCD0_OVF 13 +# define AVRDX_IRQ_TCD0_TRIG 14 +# define AVRDX_IRQ_TWI0_TWIS 15 /* TWI client interrupt */ +# define AVRDX_IRQ_TWI0_TWIM 16 /* TWI host interrupt */ +# define AVRDX_IRQ_SPI0_INT 17 +# define AVRDX_IRQ_USART0_RXC 18 +# define AVRDX_IRQ_USART0_DRE 19 +# define AVRDX_IRQ_USART0_TXC 20 +# define AVRDX_IRQ_PORTD_PORT 21 +# define AVRDX_IRQ_AC0_AC 22 /* AC0 analog comparator interrupt */ +# define AVRDX_IRQ_ADC0_RESRDY 23 /* ADC0 result ready */ +# define AVRDX_IRQ_ADC0_WCMP 24 /* ADC0 Window compare interrupt */ +# define AVRDX_IRQ_ZCD0_ZCD 25 /* Zero-cross interrupt */ +# define AVRDX_IRQ_PTC_PTC 26 /* Peripheral touch controller interrupt */ +# define AVRDX_IRQ_AC1_AC 27 +# define AVRDX_IRQ_PORTC_PORT 28 +# define AVRDX_IRQ_TCB2_INT 29 +# define AVRDX_IRQ_USART1_RXC 30 +# define AVRDX_IRQ_USART1_DRE 31 +# define AVRDX_IRQ_USART1_TXC 32 +# define AVRDX_IRQ_PORTF_PORT 33 +# define AVRDX_IRQ_NVMCTRL_EE 34 /* NVM controller EEPROM ready interrupt */ +# define AVRDX_IRQ_SPI1_INT 35 +# define AVRDX_IRQ_USART2_RXC 36 +# define AVRDX_IRQ_USART2_DRE 37 +# define AVRDX_IRQ_USART2_TXC 38 +# define AVRDX_IRQ_AC2_AC 39 + +# define NR_IRQS 40 +# define AVR_PC_SIZE 16 +# define XCPTCONTEXT_REGS 38 /* Size of the register state save array (in bytes), + * 32B registers + 1B SREG + 2B PC + 2B SP (?) + * +1B RAMPZ + */ + +# if defined(CONFIG_AVR_HAS_RAMPZ) +# define AVR_HAS_RAMPZ +# else +# error CONFIG_AVR_HAS_RAMPZ is supposed to be set for this chip +# endif + +#else + #error "Unrecognized chip" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_AVR_INCLUDE_AVRDX_IRQ_H */ diff --git a/arch/avr/src/avr/Toolchain.defs b/arch/avr/src/avr/Toolchain.defs index 64da7360597..8ec327a615c 100644 --- a/arch/avr/src/avr/Toolchain.defs +++ b/arch/avr/src/avr/Toolchain.defs @@ -67,6 +67,9 @@ ifeq ($(CONFIG_ARCH_CHIP_ATMEGA128),y) else ifeq ($(CONFIG_ARCH_CHIP_ATMEGA1284P),y) ARCHCPUFLAGS += -mmcu=atmega1284p LDFLAGS += -mavr51 +else ifeq ($(CONFIG_ARCH_CHIP_AVR128DA28),y) + ARCHCPUFLAGS += -mmcu=avr128da28 + LDFLAGS += -mavrxmega4 else ifeq ($(CONFIG_ARCH_CHIP_AT90USB646),y) ARCHCPUFLAGS += -mmcu=at90usb646 LDFLAGS += -mavr5 diff --git a/arch/avr/src/avr/excptmacros.h b/arch/avr/src/avr/excptmacros.h index a6046abf873..4ee5d211704 100644 --- a/arch/avr/src/avr/excptmacros.h +++ b/arch/avr/src/avr/excptmacros.h @@ -428,6 +428,19 @@ /* Save the return address that we have saved in r18:19 */ + /* Note - this seems backwards for AVR DA/DB family which + * states in the docs, chapter 6.4.4: The return address + * consists of two bytes and the Least Significant Byte (LSB) + * is pushed on the stack first (at the higher address). + * + * First value is popped into r19 and holds the MSB, store + * ordering is reversed here. + * + * Considering this value is just stored and then restored + * with the same discrepancy, it cancels out. No need to branch + * the code with ifdefs. + */ + #if AVR_PC_SIZE > 16 st x+, r20 #endif /* AVR_PC_SIZE */ @@ -578,12 +591,33 @@ /* If interrupts shall be enabled go to 'restore remaining and reti' code * otherwise just do 'restore remaining and ret' + * + * See Documentation/platforms/avr/context-switch-notes.rst + * for information about context creation and how it interacts + * with ways the context is restored */ ld r24, x+ bst r24, SREG_I brts go_reti +#ifdef CONFIG_ARCH_CHIP_AVRDX + /* Older chips do not care for internal MCU state here but for AVR Dx + * family, we need to do different things based on if we came here + * from interrupt handler or not. + * + * We do all branching now because at this point we are about to restore + * SREG, don't have free registers to preserve it anymore and branching + * would clobber it + * + * Branch away if we came here from interrupt handler + */ + + lds r25, CPUINT_STATUS + and r25, r25 + brne .tcbr_avrdx_ret_reti +#endif + /* Restore the status register, interrupts are disabled */ out _SFR_IO_ADDR(SREG), r24 @@ -602,12 +636,71 @@ pop r26 ret +#ifdef CONFIG_ARCH_CHIP_AVRDX +.tcbr_avrdx_ret_reti: + + /* See branch above for more detailed comments */ + + out _SFR_IO_ADDR(SREG), r24 /* SREG with I-flag cleared */ + + /* Restore r24-r25 - The temporary and IRQ number registers */ + + ld r25, x+ /* restore r24-r25 */ + ld r24, x+ + pop r27 /* recovering R27 then R26 */ + pop r26 + + /* Returning with I-flag cleared (reti does not change that), + * but clearing internal "running in interrupt context" state + */ + + reti +#endif + go_reti: +#ifdef CONFIG_ARCH_CHIP_AVRDX + /* In this case, branch away if we did NOT come here + * from an interrupt handler + */ + + lds r25, CPUINT_STATUS + and r25, r25 + breq .tcbr_avrdx_reti_ret +#endif + +#ifdef CONFIG_ARCH_CHIP_AVRDX + /* restore Status Register with interrupt enabled. Hardware + * knows it is processing an interrupt and will not interrupt + * us even with "I"-flag set (With the exception of high + * priority interrupts but those are not supported.) + */ +#else + /* restore the Status Register with interrupts disabled * and exit with reti (that will set the Interrupt Enable) */ andi r24, ~(1 << SREG_I) +#endif + + out _SFR_IO_ADDR(SREG), r24 + + ld r25, x+ + ld r24, x+ + + pop r27 + pop r26 + + reti + +#ifdef CONFIG_ARCH_CHIP_AVRDX +.tcbr_avrdx_reti_ret: + + /* restore the Status Register with interrupts disabled, + * we don't want to be interrupted until done + */ + + andi r24, ~(1 << SREG_I) out _SFR_IO_ADDR(SREG), r24 ld r25, x+ @@ -616,7 +709,18 @@ go_reti: pop r27 pop r26 - reti + /* Now enable interrupts and exit with ret, not messing with internal + * state of the interrupt controller because from its point of view, + * we are not returning from interrupt (despite the fact that the restored + * context was created in an interrupt) + * + * AVR Instruction Set Manual DS40002198 states: "The instruction + * following SEI will be executed before any pending interrupts." + */ + + sei + ret +#endif .endm diff --git a/arch/avr/src/avrdx/Kconfig b/arch/avr/src/avrdx/Kconfig new file mode 100644 index 00000000000..8f743a5c624 --- /dev/null +++ b/arch/avr/src/avrdx/Kconfig @@ -0,0 +1,90 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_AVRDX +comment "AVR DA/DB Configuration Options" + +choice + prompt "Atmel AVR DA/DB chip selection" + default ARCH_CHIP_AVR128DA28 + +config ARCH_CHIP_AVR128DA28 + bool "AVR128DA28" + select AVR_HAS_RAMPZ + ---help--- + Atmel AVR128DA28 8-bit AVR. + +endchoice # AVR DA/DB Configuration Options + +menu "AVR DA/DB Peripheral Selections" + +# TBD + +endmenu # AVR DA/DB Peripheral Selections + +choice + prompt "Internal High-Frequency Oscillator clock speed" + default AVRDX_HFO_CLOCK_24MHZ + +config AVRDX_HFO_CLOCK_1MHZ + bool "1MHz" + ---help--- + Internal oscillator set to 1MHz + +config AVRDX_HFO_CLOCK_2MHZ + bool "2MHz" + ---help--- + Internal oscillator set to 2MHz + +config AVRDX_HFO_CLOCK_3MHZ + bool "3MHz" + ---help--- + Internal oscillator set to 3MHz + +config AVRDX_HFO_CLOCK_4MHZ + bool "4MHz" + ---help--- + Internal oscillator set to 4MHz + +config AVRDX_HFO_CLOCK_8MHZ + bool "8MHz" + ---help--- + Internal oscillator set to 8MHz + +config AVRDX_HFO_CLOCK_12MHZ + bool "12MHz" + ---help--- + Internal oscillator set to 12MHz + +config AVRDX_HFO_CLOCK_16MHZ + bool "16MHz" + ---help--- + Internal oscillator set to 16MHz + +config AVRDX_HFO_CLOCK_20MHZ + bool "20MHz" + ---help--- + Internal oscillator set to 20MHz + +config AVRDX_HFO_CLOCK_24MHZ + bool "24MHz" + ---help--- + Internal oscillator set to 24MHz + +endchoice + +config AVRDX_HFO_CLOCK_FREQ + int + default 1000000 if AVRDX_HFO_CLOCK_1MHZ + default 2000000 if AVRDX_HFO_CLOCK_2MHZ + default 3000000 if AVRDX_HFO_CLOCK_3MHZ + default 4000000 if AVRDX_HFO_CLOCK_4MHZ + default 8000000 if AVRDX_HFO_CLOCK_8MHZ + default 12000000 if AVRDX_HFO_CLOCK_12MHZ + default 16000000 if AVRDX_HFO_CLOCK_16MHZ + default 20000000 if AVRDX_HFO_CLOCK_20MHZ + default 24000000 if AVRDX_HFO_CLOCK_24MHZ + +endif diff --git a/arch/avr/src/avrdx/Make.defs b/arch/avr/src/avrdx/Make.defs new file mode 100644 index 00000000000..cb3e659ba16 --- /dev/null +++ b/arch/avr/src/avrdx/Make.defs @@ -0,0 +1,58 @@ +############################################################################ +# arch/avr/src/avrdx/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# The start-up, "head", file + +HEAD_ASRC = avrdx_head.S + +# Common AVR files + +CMN_ASRCS = avr_doswitch.S avr_saveusercontext.S +CMN_CSRCS = avr_allocateheap.c avr_copystate.c avr_createstack.c +CMN_CSRCS += avr_doirq.c avr_exit.c avr_idle.c avr_initialize.c +CMN_CSRCS += avr_initialstate.c avr_irq.c avr_lowputs.c avr_mdelay.c +CMN_CSRCS += avr_nputs.c avr_releasestack.c avr_registerdump.c +CMN_CSRCS += avr_schedulesigaction.c avr_sigdeliver.c avr_getintstack.c +CMN_CSRCS += avr_stackframe.c avr_udelay.c avr_switchcontext.c avr_usestack.c + +# Configuration-dependent common files + +ifeq ($(CONFIG_AVR_SPI),y) +CMN_CSRCS += avr_spi.c +endif + +ifeq ($(CONFIG_STACK_COLORATION),y) +CMN_CSRCS += avr_checkstack.c +endif + +ifeq ($(CONFIG_ARCH_ROMGETC),y) +CMN_CSRCS += avr_romgetc.c +endif + +# Required AVRnDx files + +CHIP_ASRCS = avrdx_exceptions.S +CHIP_CSRCS = avrdx_lowconsole.c avrdx_lowinit.c avrdx_serial.c + +ifneq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += avrdx_timerisr.c +endif diff --git a/arch/avr/src/avrdx/avrdx.h b/arch/avr/src/avrdx/avrdx.h new file mode 100644 index 00000000000..7df8bfade16 --- /dev/null +++ b/arch/avr/src/avrdx/avrdx.h @@ -0,0 +1,107 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_AVRDX_H +#define __ARCH_AVR_SRC_AVRDX_AVRDX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "avrdx_config.h" + +#include +#include +#include "avrdx_iodefs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: up_clkinit + * + * Description: + * Initialize clock/PLL settings per the definitions in the board.h file. + * + ****************************************************************************/ + +void up_clkinitialize(void); + +/**************************************************************************** + * Name: up_consoleinit + * + * Description: + * Initialize a console for debug output. This function is called very + * early in the initialization sequence to configure the serial console + * uart (only). + * + ****************************************************************************/ + +void up_consoleinit(void); + +/**************************************************************************** + * Name: avrdx_boardinitialize + * + * Description: + * This function must be provided by the board-specific logic in the + * directory boards/avr/avrdx//src. + * + ****************************************************************************/ + +void avrdx_boardinitialize(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_AVR_SRC_AVRDX_AVRDX_H */ diff --git a/arch/avr/src/avrdx/avrdx_config.h b/arch/avr/src/avrdx/avrdx_config.h new file mode 100644 index 00000000000..33d32ca79ac --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_config.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_config.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_AVRDX_CONFIG_H +#define __ARCH_AVR_SRC_AVRDX_AVRDX_CONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes Prototypes + ****************************************************************************/ + +#endif /* __ARCH_AVR_SRC_AVRDX_AVRDX_CONFIG_H */ diff --git a/arch/avr/src/avrdx/avrdx_exceptions.S b/arch/avr/src/avrdx/avrdx_exceptions.S new file mode 100644 index 00000000000..cbd920b14a9 --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_exceptions.S @@ -0,0 +1,173 @@ +/******************************************************************************************** + * arch/avr/src/avrdx/avrdx_exceptions.S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ********************************************************************************************/ + +/******************************************************************************************** + * Included Files + ********************************************************************************************/ + +#include + +#include + +#include "excptmacros.h" + +/******************************************************************************************** + * External Symbols + ********************************************************************************************/ + + .file "avrdx_exceptions.S" + .global avr_doirq + .global avr_fullcontextrestore + +/******************************************************************************************** + * Macros + ********************************************************************************************/ + +/******************************************************************************************** + * Exception Vector Handlers + ********************************************************************************************/ + + .section .handlers, "ax", @progbits + +#if defined(CONFIG_ARCH_CHIP_AVR128DA28) + HANDLER avrdx_nmi, AVRDX_IRQ_NMI, excpt_common + HANDLER avrdx_bod_vlm, AVRDX_IRQ_BOD_VLM, excpt_common + HANDLER avrdx_rtc_cnt, AVRDX_IRQ_RTC_CNT, excpt_common + HANDLER avrdx_rtc_pit, AVRDX_IRQ_RTC_PIT, excpt_common + HANDLER avrdx_ccl_ccl, AVRDX_IRQ_CCL_CCL, excpt_common + HANDLER avrdx_porta_port, AVRDX_IRQ_PORTA_PORT, excpt_common + HANDLER avrdx_tca0_ovf, AVRDX_IRQ_TCA0_OVF, excpt_common + HANDLER avrdx_tca0_hunf, AVRDX_IRQ_TCA0_HUNF, excpt_common + HANDLER avrdx_tca0_cmp0, AVRDX_IRQ_TCA0_CMP0, excpt_common + HANDLER avrdx_tca0_cmp1, AVRDX_IRQ_TCA0_CMP1, excpt_common + HANDLER avrdx_tca0_cmp2, AVRDX_IRQ_TCA0_CMP2, excpt_common + HANDLER avrdx_tcb0_int, AVRDX_IRQ_TCB0_INT, excpt_common + HANDLER avrdx_tcb1_int, AVRDX_IRQ_TCB1_INT, excpt_common + HANDLER avrdx_tcd0_ovf, AVRDX_IRQ_TCD0_OVF, excpt_common + HANDLER avrdx_tcd0_trig, AVRDX_IRQ_TCD0_TRIG, excpt_common + HANDLER avrdx_twi0_twis, AVRDX_IRQ_TWI0_TWIS, excpt_common + HANDLER avrdx_twi0_twim, AVRDX_IRQ_TWI0_TWIM, excpt_common + HANDLER avrdx_spi0_int, AVRDX_IRQ_SPI0_INT, excpt_common + HANDLER avrdx_usart0_rxc, AVRDX_IRQ_USART0_RXC, excpt_common + HANDLER avrdx_usart0_dre, AVRDX_IRQ_USART0_DRE, excpt_common + HANDLER avrdx_usart0_txc, AVRDX_IRQ_USART0_TXC, excpt_common + HANDLER avrdx_portd_port, AVRDX_IRQ_PORTD_PORT, excpt_common + HANDLER avrdx_ac0_ac, AVRDX_IRQ_AC0_AC, excpt_common + HANDLER avrdx_adc0_resrdy, AVRDX_IRQ_ADC0_RESRDY, excpt_common + HANDLER avrdx_adc0_wcmp, AVRDX_IRQ_ADC0_WCMP, excpt_common + HANDLER avrdx_zcd0_zcd, AVRDX_IRQ_ZCD0_ZCD, excpt_common + HANDLER avrdx_ptc_ptc, AVRDX_IRQ_PTC_PTC, excpt_common + HANDLER avrdx_ac1_ac, AVRDX_IRQ_AC1_AC, excpt_common + HANDLER avrdx_portc_port, AVRDX_IRQ_PORTC_PORT, excpt_common + HANDLER avrdx_tcb2_int, AVRDX_IRQ_TCB2_INT, excpt_common + HANDLER avrdx_usart1_rxc, AVRDX_IRQ_USART1_RXC, excpt_common + HANDLER avrdx_usart1_dre, AVRDX_IRQ_USART1_DRE, excpt_common + HANDLER avrdx_usart1_txc, AVRDX_IRQ_USART1_TXC, excpt_common + HANDLER avrdx_portf_port, AVRDX_IRQ_PORTF_PORT, excpt_common + HANDLER avrdx_nvmctrl_ee, AVRDX_IRQ_NVMCTRL_EE, excpt_common + HANDLER avrdx_spi1_int, AVRDX_IRQ_SPI1_INT, excpt_common + HANDLER avrdx_usart2_rxc, AVRDX_IRQ_USART2_RXC, excpt_common + HANDLER avrdx_usart2_dre, AVRDX_IRQ_USART2_DRE, excpt_common + HANDLER avrdx_usart2_txc, AVRDX_IRQ_USART2_TXC, excpt_common + HANDLER avrdx_ac2_ac, AVRDX_IRQ_AC2_AC, excpt_common +#else +# error "Unrecognized chip" +#endif + +/******************************************************************************************** + * Name: excpt_common + * + * Description: + * Exception Vector Handlers + * + * On Entry: + * The return PC and the saved r24 is on the stack, r24 now contains the IRQ number + * + * PC1 + * PC0 + * R0 + * --- <- SP + * + ********************************************************************************************/ + +excpt_common: + /* Save the remaining registers on the stack, preserving the IRQ number in r14 */ + + EXCPT_PROLOGUE + + /* Call avr_doirq with r24 = IRQ number, r22-23 = Pointer to the save structure. The stack + * pointer currently points to the save structure (or maybe the save structure -1 since + * the push operation post-decrements -- need to REVISIT this). + */ + + in r28, _SFR_IO_ADDR(SPL) /* Get the save structure pointer in a Call-saved register pair */ + in r29, _SFR_IO_ADDR(SPH) /* Pointer can be obtained from the stack pointer */ + adiw r28, 1 /* Remembering that push post-decrements */ + movw r22, r28 /* Pass register save structure as the parameter 2 */ + USE_INTSTACK rx, ry, rz /* Switch to the interrupt stack */ + call avr_doirq /* Dispatch the interrupt */ + RESTORE_STACK rx, ry /* Undo the operations of USE_INTSTACK */ + + /* up_doiq returns with r24-r25 equal to the new save structure. If no context + * switch occurred, this will be the same as the value passed to it in r22-23. + * But if a context switch occurs, then the returned value will point not at a + * stack frame, but at a register save area inside of the new task's TCB. + */ + + cp r28, r24 + cpc r29, r25 + breq .Lnoswitch + + /* A context switch has occurred, jump to avr_fullcontextrestore with r24, r25 + * equal to the address of the new register save ared. + */ + + jmp avr_fullcontextrestore + + /* No context switch occurred.. just return off the stack */ + +.Lnoswitch: + EXCPT_EPILOGUE + + /* Unlike eg. ATmega devices, from which this code is derived, + * Dx cores do not set Interrupt Enable on reti + */ + sei + reti + +/**************************************************************************************************** + * Name: g_intstackalloc + ****************************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 0 + .bss + .align 4 + .globl g_intstackalloc + .type g_intstackalloc, object + .globl g_intstacktop + .type g_intstacktop, object +g_intstackalloc: + .skip CONFIG_ARCH_INTERRUPTSTACK +g_intstacktop: + .size g_intstackalloc, .-g_intstackalloc +#endif + .end diff --git a/arch/avr/src/avrdx/avrdx_head.S b/arch/avr/src/avrdx/avrdx_head.S new file mode 100644 index 00000000000..9b3695d5429 --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_head.S @@ -0,0 +1,288 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_head.S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Stack is allocated just after uninitialized data and just before the heap */ + +#define STACKBASE (_enoinit+CONFIG_IDLETHREAD_STACKSIZE) + +/* The RAMPZ register should be available for all MCUs in this family + * + * - Support for the EPLMX instructions is assumed if RAMPZ is present + * - If RAMPZ is not present, support for LPMX is assumed + */ + +#define HAVE_RAMPZ 1 + +/**************************************************************************** + * External Symbols + ****************************************************************************/ + + .file "up_nommuhead.S" + .global __start /* Entry point */ + .global _sbss /* Start of .bss. Defined by ld.script */ + .global _ebss /* End of .bss. Defined by ld.script */ + .global _sdata /* Start of .data section in RAM */ + .global _edata /* End of .data section in RAM */ + .global _eronly /* Start of .data section in FLASH */ + .global _enoinit /* End of uninitilized data. Defined by ld.script */ + .global avr_lowinit /* Perform low level initialization */ + .global nx_start /* NuttX entry point */ + + .global vectortab +#if defined(CONFIG_ARCH_CHIP_AVR128DA28) + .global avrdx_nmi + .global avrdx_bod_vlm + .global avrdx_rtc_cnt + .global avrdx_rtc_pit + .global avrdx_ccl_ccl + .global avrdx_porta_port + .global avrdx_tca0_ovf + .global avrdx_tca0_hunf + .global avrdx_tca0_cmp0 + .global avrdx_tca0_cmp1 + .global avrdx_tca0_cmp2 + .global avrdx_tcb0_int + .global avrdx_tcb1_int + .global avrdx_tcd0_ovf + .global avrdx_tcd0_trig + .global avrdx_twi0_twis + .global avrdx_twi0_twim + .global avrdx_spi0_int + .global avrdx_usart0_rxc + .global avrdx_usart0_dre + .global avrdx_usart0_txc + .global avrdx_portd_port + .global avrdx_ac0_ac + .global avrdx_adc0_resrdy + .global avrdx_adc0_wcmp + .global avrdx_zcd0_zcd + .global avrdx_ptc_ptc + .global avrdx_ac1_ac + .global avrdx_portc_port + .global avrdx_tcb2_int + .global avrdx_usart1_rxc + .global avrdx_usart1_dre + .global avrdx_usart1_txc + .global avrdx_portf_port + .global avrdx_nvmctrl_ee + .global avrdx_spi1_int + .global avrdx_usart2_rxc + .global avrdx_usart2_dre + .global avrdx_usart2_txc + .global avrdx_ac2_ac +#else +#error "Unrecognized chip" +#endif + +/**************************************************************************** + * Macros + ****************************************************************************/ + + .macro vector name + jmp \name + .endm + +/**************************************************************************** + * Vector Table + ****************************************************************************/ + +/* The AVR128DA28 has 41 interrupt vectors including vector 0, the reset + * vector. + */ + + .section .vectors, "ax", @progbits + .func vectortab +vectortab: + jmp __start /* 0: Vector 0 is the reset vector */ +#if defined(CONFIG_ARCH_CHIP_AVR128DA28) + vector avrdx_nmi + vector avrdx_bod_vlm + vector avrdx_rtc_cnt + vector avrdx_rtc_pit + vector avrdx_ccl_ccl + vector avrdx_porta_port + vector avrdx_tca0_ovf + vector avrdx_tca0_hunf + vector avrdx_tca0_cmp0 + vector avrdx_tca0_cmp1 + vector avrdx_tca0_cmp2 + vector avrdx_tcb0_int + vector avrdx_tcb1_int + vector avrdx_tcd0_ovf + vector avrdx_tcd0_trig + vector avrdx_twi0_twis + vector avrdx_twi0_twim + vector avrdx_spi0_int + vector avrdx_usart0_rxc + vector avrdx_usart0_dre + vector avrdx_usart0_txc + vector avrdx_portd_port + vector avrdx_ac0_ac + vector avrdx_adc0_resrdy + vector avrdx_adc0_wcmp + vector avrdx_zcd0_zcd + vector avrdx_ptc_ptc + vector avrdx_ac1_ac + vector avrdx_portc_port + vector avrdx_tcb2_int + vector avrdx_usart1_rxc + vector avrdx_usart1_dre + vector avrdx_usart1_txc + vector avrdx_portf_port + vector avrdx_nvmctrl_ee + vector avrdx_spi1_int + vector avrdx_usart2_rxc + vector avrdx_usart2_dre + vector avrdx_usart2_txc + vector avrdx_ac2_ac +#else +#error "Unrecognized chip" +#endif + .endfunc + +/**************************************************************************** + * Reset Entry Point + ****************************************************************************/ + + .section .init, "ax", @progbits + .func __start +__start: + + /* no interrupts! Useful for software reset by jumping to address 0 */ + cli + +#if defined(EIND) + /* set EIND to 0, just to be sure we are sane */ + out _SFR_IO_ADDR(EIND), 0 // EIND = 0x3c +#endif /* EIND */ + + /* Clear the zero register, clear the status register and initialize the + * IDLE thread stack + */ + + clr r1 + out _SFR_IO_ADDR(SREG), r1 + ldi r28, lo8(STACKBASE) + ldi r29, hi8(STACKBASE) + out _SFR_IO_ADDR(SPH), r29 + out _SFR_IO_ADDR(SPL), r28 + + /* Copy initial global data values from FLASH into RAM */ + + .global __do_copy_data; /* Required to suppress dragging in logic from libgcc */ +__do_copy_data: + +#ifdef HAVE_RAMPZ + ldi r17, hi8(_edata) + ldi r26, lo8(_sdata) + ldi r27, hi8(_sdata) + ldi r30, lo8(_eronly) + ldi r31, hi8(_eronly) + ldi r16, hh8(_eronly) + out _SFR_IO_ADDR(RAMPZ), r16 + rjmp .Lcopystart + +.Lcopyloop: + elpm r0, Z+ + st X+, r0 + +.Lcopystart: + cpi r26, lo8(_edata) + cpc r27, r17 + brne .Lcopyloop +#else + ldi r17, hi8(_edata) + ldi r26, lo8(_sdata) + ldi r27, hi8(_sdata) + ldi r30, lo8(_eronly) + ldi r31, hi8(_eronly) + rjmp .Lcopystart + +.Lcopyloop: + lpm r0, Z+ + st X+, r0 + +.Lcopystart: + cpi r26, lo8(_edata) + cpc r27, r17 + brne .Lcopyloop +#endif + + /* Clear uninitialized data */ + + .global __do_clear_bss; /* Required to suppress dragging in logic from libgcc */ +__do_clear_bss: + + ldi r17, hi8(_ebss) + ldi r26, lo8(_sbss) + ldi r27, hi8(_sbss) + rjmp .Lclearstart + +.Lclearloop: + st X+, r1 + +.Lclearstart: + cpi r26, lo8(_ebss) + cpc r27, r17 + brne .Lclearloop + + /* Perform any low-level initialization */ + + call avr_lowinit + + /* Now start NuttX */ + + call nx_start + jmp exit + .endfunc + +/**************************************************************************** + * Heap Base + ****************************************************************************/ + + /* This global variable is unsigned long g_idle_topstack and is exported from + * here only because of its coupling to other uses of _enoinit in this file + */ + + .data + .globl g_idle_topstack + .type g_idle_topstack, object +g_idle_topstack: + .word _enoinit+CONFIG_IDLETHREAD_STACKSIZE + .size g_idle_topstack, .-g_idle_topstack + .end diff --git a/arch/avr/src/avrdx/avrdx_iodefs.h b/arch/avr/src/avrdx/avrdx_iodefs.h new file mode 100644 index 00000000000..85d871d7c16 --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_iodefs.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_iodefs.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_AVRDX_IODEFS_H +#define __ARCH_AVR_SRC_AVRDX_AVRDX_IODEFS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "avrdx_config.h" + +#if defined(CONFIG_ARCH_CHIP_AVR128DA28) +# include "iodefs/avr128da28.h" +#else +# error "I/O register definitions for this chip are missing" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_AVR_SRC_AVRDX_AVRDX_H */ diff --git a/arch/avr/src/avrdx/avrdx_lowconsole.c b/arch/avr/src/avrdx/avrdx_lowconsole.c new file mode 100644 index 00000000000..be8337f0c9a --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_lowconsole.c @@ -0,0 +1,92 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_lowconsole.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include +#include "avrdx_config.h" + +#include +#include + +#include +#include +#include + +#include "avr_internal.h" +#include "avrdx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_consoleinit + * + * Description: + * Initialize a console for debug output. This function is called very + * early in the initialization sequence to configure the serial console + * uart (only). + * + ****************************************************************************/ + +void up_consoleinit(void) +{ +} + +/**************************************************************************** + * Name: avr_lowputc + * + * Description: + * Output one byte on the serial console. Currently not implemented + * but required by common code + * + ****************************************************************************/ + +void avr_lowputc(char ch) +{ +} diff --git a/arch/avr/src/avrdx/avrdx_lowinit.c b/arch/avr/src/avrdx/avrdx_lowinit.c new file mode 100644 index 00000000000..9a100e323b4 --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_lowinit.c @@ -0,0 +1,116 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_lowinit.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include "avrdx_config.h" +#include "avr_internal.h" +#include "avrdx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: avr_lowinit + * + * Description: + * This performs basic initialization of the hardware, notably sets main + * clock and configures USART used for the serial console etc. (USART is + * configured early to make the console output available as soon + * as possible.) + * + * + ****************************************************************************/ + +void avr_lowinit(void) +{ + /* Set the system clock */ + +#if (CONFIG_AVRDX_HFO_CLOCK_FREQ == 24000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_24M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 20000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_20M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 16000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_16M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 12000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_12M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 8000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_8M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 4000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_4M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 3000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_3M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 2000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_2M_GC)); +#elif (CONFIG_AVRDX_HFO_CLOCK_FREQ == 1000000) + _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, + ((CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_GM)) | CLKCTRL_FRQSEL_1M_GC)); +#else + /* At some point, add support to have the board supply + * its own clock setting (ie. support external clock) + */ +# error Unsupported frequency +#endif + + /* Perform board-level initialization */ + + avrdx_boardinitialize(); +} diff --git a/arch/avr/src/avrdx/avrdx_memorymap.h b/arch/avr/src/avrdx/avrdx_memorymap.h new file mode 100644 index 00000000000..454e824f7ef --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_memorymap.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_memorymap.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_AVRDX_MEMORYMAP_H +#define __ARCH_AVR_SRC_AVRDX_AVRDX_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_AVR_SRC_AVRDX_AVRDX_MEMORYMAP_H */ diff --git a/arch/avr/src/avrdx/avrdx_serial.c b/arch/avr/src/avrdx/avrdx_serial.c new file mode 100644 index 00000000000..beb0a7c835e --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_serial.c @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_serial.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * (Not yet implemented) + * + ****************************************************************************/ + +void up_putc(int ch) +{ +} diff --git a/arch/avr/src/avrdx/avrdx_timerisr.c b/arch/avr/src/avrdx/avrdx_timerisr.c new file mode 100644 index 00000000000..5f8cba47aea --- /dev/null +++ b/arch/avr/src/avrdx/avrdx_timerisr.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * arch/avr/src/avrdx/avrdx_timerisr.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include "avr_internal.h" +#include "avrdx.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The system timer is clocked from 32kHz internal oscillator + * with a period of 61us. (Using division by 2 in case oscillator + * correction is used at some point.) + * + * For this clock frequency, the shortest period we can support + * with no errors is 15625us, 64Hz. Multiplies of this value will + * also lead to timer with no errors. + */ + +#define RTC_PER_VAL ((CONFIG_USEC_PER_TICK * 16384ul / 1000000ul) - 1) + +/**************************************************************************** + * Forward declarations + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: avrdx_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int avrdx_timerisr(int irq, uint32_t *regs, FAR void *arg) +{ + RTC.INTFLAGS = (RTC_OVF_bm | RTC_CMP_bm); + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Function: avrdx_rtc_await_nobusy + * + * Description: + * RTC peripheral runs asynchronously from main clock, writes to some + * registers take time to synchronize and subsequent writes will + * not take effect. + * + * This method reads RTC.STATUS and spins until the requested register + * isn't busy. + * + * If instructed, it will also enable and disable interrupts while + * spinning so at least something can run, this is otherwise quite + * multitasking-unfriendly + * + ****************************************************************************/ + +void avrdx_rtc_await_nobusy(uint8_t wait_flag, irqstate_t irqstate) +{ + while (RTC.STATUS & wait_flag) + { + up_irq_restore(irqstate); /* Might not actually enable interrupts + * based on irqstate contents */ + asm volatile("nop"); /* Why not, we are waiting for 2 ticks + * of 32768Hz clock anyway */ + up_irq_save(); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize the system timer. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + irqstate_t irqstate; + + /* Setup RTC timer + */ + + irqstate = up_irq_save(); + + /* RTC initialization procedure as per docs: + * 1. Configure desired oscillator in Clock Controller + * (Using OSC32K which is preconfigured. Done.) + * 2. Write RTC.CLKSEL clock select field. + * (Using OSC32K which is preconfigured. Done.) + * 3. Write compare and period registers. + */ + + avrdx_rtc_await_nobusy(RTC_PERBUSY_bm, \ + irqstate); /* Break the line to make nxstyle happy */ + RTC.PER = RTC_PER_VAL; + + /* 4. Enable desired interrupts */ + + RTC.INTCTRL |= (RTC_OVF_bm); + + /* 5. Configure prescaler */ + + avrdx_rtc_await_nobusy(RTC_CTRLABUSY_bm, \ + irqstate); + RTC.CTRLA = (RTC.CTRLA & ~RTC_PRESCALER_GM) | RTC_PRESCALER_DIV2_GC; + + /* 6. Enable the RTC */ + + avrdx_rtc_await_nobusy(RTC_CTRLABUSY_bm, \ + irqstate); + RTC.CTRLA |= RTC_RTCEN_bm; + + irq_attach(AVRDX_IRQ_RTC_CNT, (xcpt_t)avrdx_timerisr, NULL); + + up_irq_restore(irqstate); +} diff --git a/arch/avr/src/avrdx/chip.h b/arch/avr/src/avrdx/chip.h new file mode 100644 index 00000000000..b02843c6ad0 --- /dev/null +++ b/arch/avr/src/avrdx/chip.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/avr/src/avrdx/chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_CHIP_H +#define __ARCH_AVR_SRC_AVRDX_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Define features for supported chip in the AVRnDx family */ + +#if 1 +#else +# error "Unsupported AVR chip" +#endif + +/* Include only the memory map. + * Other chip hardware files should then include this file for the proper + * setup + * + */ + +#include "avrdx_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes Prototypes + ****************************************************************************/ + +#endif /* __ARCH_AVR_SRC_AVRDX_CHIP_H */ diff --git a/arch/avr/src/avrdx/iodefs/avr128da28.h b/arch/avr/src/avrdx/iodefs/avr128da28.h new file mode 100644 index 00000000000..120761fc4f2 --- /dev/null +++ b/arch/avr/src/avrdx/iodefs/avr128da28.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/avr/src/avrdx/iodefs/avr128da28.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_IODEFS_AVR128DA28_H +#define __ARCH_AVR_SRC_AVRDX_IODEFS_AVR128DA28_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ARCH_AVR_SRC_AVRDX_AVRDX_IODEFS_H +# error "Do not include this file directly, use avrdx_iodefs.h instead" +#endif + +/* CLKCTRL.OSCHFCTRLA */ + +#define CLKCTRL_FRQSEL_GM ( CLKCTRL_FRQSEL_0_bm | CLKCTRL_FRQSEL_1_bm | \ + CLKCTRL_FRQSEL_2_bm | CLKCTRL_FRQSEL_3_bm ) + +#define CLKCTRL_FRQSEL_1M_GC (0) +#define CLKCTRL_FRQSEL_2M_GC (CLKCTRL_FRQSEL_0_bm) +#define CLKCTRL_FRQSEL_3M_GC (CLKCTRL_FRQSEL_1_bm) +#define CLKCTRL_FRQSEL_4M_GC (CLKCTRL_FRQSEL_1_bm | CLKCTRL_FRQSEL_0_bm) +#define CLKCTRL_FRQSEL_8M_GC (CLKCTRL_FRQSEL_2_bm | CLKCTRL_FRQSEL_0_bm) +#define CLKCTRL_FRQSEL_12M_GC (CLKCTRL_FRQSEL_2_bm | CLKCTRL_FRQSEL_1_bm) +#define CLKCTRL_FRQSEL_16M_GC (CLKCTRL_FRQSEL_2_bm | CLKCTRL_FRQSEL_1_bm | \ + CLKCTRL_FRQSEL_0_bm ) +#define CLKCTRL_FRQSEL_20M_GC (CLKCTRL_FRQSEL_3_bm) +#define CLKCTRL_FRQSEL_24M_GC (CLKCTRL_FRQSEL_3_bm | CLKCTRL_FRQSEL_0_bm) + +/* RTC.CTRLA */ + +#define RTC_PRESCALER_GM ( RTC_PRESCALER_0_bm | RTC_PRESCALER_1_bm | \ + RTC_PRESCALER_2_bm | RTC_PRESCALER_3_bm ) + +#define RTC_PRESCALER_DIV2_GC (RTC_PRESCALER_0_bm) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_AVR_SRC_AVRDX_AVRDX_H */ diff --git a/arch/avr/src/common/avr_internal.h b/arch/avr/src/common/avr_internal.h index ed10744e29a..872cff4b9e9 100644 --- a/arch/avr/src/common/avr_internal.h +++ b/arch/avr/src/common/avr_internal.h @@ -59,12 +59,17 @@ #define INTSTACK_COLOR 's' #define HEAP_COLOR 'h' -#define getreg8(a) (*(volatile uint8_t *)(a)) -#define putreg8(v,a) (*(volatile uint8_t *)(a) = (v)) -#define getreg16(a) (*(volatile uint16_t *)(a)) -#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v)) -#define getreg32(a) (*(volatile uint32_t *)(a)) -#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v)) +/* ATMega and similar chips have their registers memory-mapped, + * Dx cores don't + */ +#ifndef CONFIG_ARCH_CHIP_AVRDX +# define getreg8(a) (*(volatile uint8_t *)(a)) +# define putreg8(v,a) (*(volatile uint8_t *)(a) = (v)) +# define getreg16(a) (*(volatile uint16_t *)(a)) +# define putreg16(v,a) (*(volatile uint16_t *)(a) = (v)) +# define getreg32(a) (*(volatile uint32_t *)(a)) +# define putreg32(v,a) (*(volatile uint32_t *)(a) = (v)) +#endif /**************************************************************************** * Public Types