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