From 74aeb5d0c5afa1f43a841d162f410072b67ec0b0 Mon Sep 17 00:00:00 2001 From: zouboan Date: Sat, 15 Jan 2022 14:01:10 +0800 Subject: [PATCH] port nuttx to sparc-v8 commit includes following parts: add support of sparc in arch/Kconfig add support of sparc in boards/Kconfig add sparc dir in arch, add sparc dir in boards add support of sparc in libs/libc/machine modify all the coding style problem about saprc --- arch/Kconfig | 9 + arch/sparc/Kconfig | 57 ++ arch/sparc/include/arch.h | 68 ++ arch/sparc/include/bm3803/irq.h | 158 +++ arch/sparc/include/bm3823/irq.h | 160 +++ arch/sparc/include/elf.h | 84 ++ arch/sparc/include/inttypes.h | 119 +++ arch/sparc/include/irq.h | 85 ++ arch/sparc/include/limits.h | 72 ++ arch/sparc/include/sparc_v8/irq.h | 753 ++++++++++++++ arch/sparc/include/sparc_v8/syscall.h | 195 ++++ arch/sparc/include/spinlock.h | 84 ++ arch/sparc/include/syscall.h | 74 ++ arch/sparc/include/types.h | 105 ++ arch/sparc/src/Makefile | 173 ++++ arch/sparc/src/bm3803/Kconfig | 123 +++ arch/sparc/src/bm3803/Make.defs | 77 ++ arch/sparc/src/bm3803/bm3803-config.h | 101 ++ arch/sparc/src/bm3803/bm3803-irq.c | 321 ++++++ arch/sparc/src/bm3803/bm3803-lowconsole.c | 307 ++++++ arch/sparc/src/bm3803/bm3803-lowinit.c | 119 +++ arch/sparc/src/bm3803/bm3803-memorymap.h | 41 + arch/sparc/src/bm3803/bm3803-serial.c | 955 ++++++++++++++++++ arch/sparc/src/bm3803/bm3803-timerisr.c | 138 +++ arch/sparc/src/bm3803/bm3803-uart.h | 235 +++++ arch/sparc/src/bm3803/bm3803.h | 584 +++++++++++ arch/sparc/src/bm3803/bm3803_exceptions.S | 432 ++++++++ arch/sparc/src/bm3803/bm3803_exti.h | 82 ++ arch/sparc/src/bm3803/bm3803_exti_gpio.c | 270 +++++ arch/sparc/src/bm3803/bm3803_freerun.c | 273 +++++ arch/sparc/src/bm3803/bm3803_freerun.h | 143 +++ arch/sparc/src/bm3803/bm3803_head.S | 623 ++++++++++++ arch/sparc/src/bm3803/bm3803_oneshot.c | 401 ++++++++ arch/sparc/src/bm3803/bm3803_oneshot.h | 182 ++++ .../src/bm3803/bm3803_oneshot_lowerhalf.c | 334 ++++++ arch/sparc/src/bm3803/bm3803_tickless.c | 339 +++++++ arch/sparc/src/bm3803/bm3803_tim.c | 648 ++++++++++++ arch/sparc/src/bm3803/bm3803_tim.h | 154 +++ arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c | 464 +++++++++ arch/sparc/src/bm3803/bm3803_wdg.c | 433 ++++++++ arch/sparc/src/bm3803/bm3803_wdg.h | 78 ++ arch/sparc/src/bm3803/chip.h | 48 + arch/sparc/src/bm3823/Kconfig | 42 + arch/sparc/src/bm3823/Make.defs | 59 ++ arch/sparc/src/bm3823/bm3823-config.h | 102 ++ arch/sparc/src/bm3823/bm3823-irq.c | 327 ++++++ arch/sparc/src/bm3823/bm3823-lowconsole.c | 316 ++++++ arch/sparc/src/bm3823/bm3823-lowinit.c | 172 ++++ arch/sparc/src/bm3823/bm3823-memorymap.h | 43 + arch/sparc/src/bm3823/bm3823-serial.c | 947 +++++++++++++++++ arch/sparc/src/bm3823/bm3823-timerisr.c | 139 +++ arch/sparc/src/bm3823/bm3823-uart.h | 230 +++++ arch/sparc/src/bm3823/bm3823.h | 665 ++++++++++++ arch/sparc/src/bm3823/bm3823_exceptions.S | 251 +++++ arch/sparc/src/bm3823/bm3823_head.S | 624 ++++++++++++ arch/sparc/src/bm3823/chip.h | 48 + arch/sparc/src/common/Kconfig | 7 + arch/sparc/src/common/up_allocateheap.c | 72 ++ arch/sparc/src/common/up_arch.h | 76 ++ arch/sparc/src/common/up_assert.c | 168 +++ arch/sparc/src/common/up_checkstack.c | 211 ++++ arch/sparc/src/common/up_createstack.c | 203 ++++ arch/sparc/src/common/up_exit.c | 184 ++++ arch/sparc/src/common/up_idle.c | 72 ++ arch/sparc/src/common/up_initialize.c | 289 ++++++ arch/sparc/src/common/up_internal.h | 252 +++++ arch/sparc/src/common/up_interruptcontext.c | 55 + arch/sparc/src/common/up_lowputs.c | 60 ++ arch/sparc/src/common/up_mdelay.c | 76 ++ arch/sparc/src/common/up_modifyreg16.c | 71 ++ arch/sparc/src/common/up_modifyreg32.c | 71 ++ arch/sparc/src/common/up_modifyreg8.c | 71 ++ arch/sparc/src/common/up_puts.c | 61 ++ arch/sparc/src/common/up_releasestack.c | 114 +++ arch/sparc/src/common/up_stackframe.c | 123 +++ arch/sparc/src/common/up_udelay.c | 119 +++ arch/sparc/src/common/up_usestack.c | 141 +++ arch/sparc/src/sparc_v8/Kconfig | 31 + arch/sparc/src/sparc_v8/Toolchain.defs | 80 ++ arch/sparc/src/sparc_v8/sparc_v8.h | 108 ++ arch/sparc/src/sparc_v8/up_blocktask.c | 165 +++ arch/sparc/src/sparc_v8/up_copystate.c | 98 ++ arch/sparc/src/sparc_v8/up_doirq.c | 125 +++ arch/sparc/src/sparc_v8/up_dumpstate.c | 229 +++++ arch/sparc/src/sparc_v8/up_initialstate.c | 104 ++ arch/sparc/src/sparc_v8/up_irq.c | 130 +++ arch/sparc/src/sparc_v8/up_releasepending.c | 118 +++ arch/sparc/src/sparc_v8/up_reprioritizertr.c | 175 ++++ arch/sparc/src/sparc_v8/up_romgetc.c | 91 ++ .../sparc/src/sparc_v8/up_schedulesigaction.c | 178 ++++ arch/sparc/src/sparc_v8/up_sigdeliver.c | 133 +++ arch/sparc/src/sparc_v8/up_swint1.c | 239 +++++ arch/sparc/src/sparc_v8/up_syscall.S | 173 ++++ arch/sparc/src/sparc_v8/up_systemreset.c | 65 ++ arch/sparc/src/sparc_v8/up_unblocktask.c | 149 +++ boards/Kconfig | 22 + boards/sparc/bm3803/xx3803/Kconfig | 106 ++ .../sparc/bm3803/xx3803/configs/nsh/defconfig | 99 ++ boards/sparc/bm3803/xx3803/include/board.h | 75 ++ boards/sparc/bm3803/xx3803/scripts/Make.defs | 116 +++ boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld | 84 ++ .../sparc/bm3803/xx3803/scripts/linksparc.ld | 208 ++++ boards/sparc/bm3803/xx3803/src/Makefile | 41 + .../sparc/bm3803/xx3803/src/bm3803_am29lv.c | 155 +++ .../sparc/bm3803/xx3803/src/bm3803_appinit.c | 146 +++ boards/sparc/bm3803/xx3803/src/bm3803_boot.c | 75 ++ boards/sparc/bm3803/xx3803/src/bm3803_reset.c | 66 ++ boards/sparc/bm3803/xx3803/src/bm3803_wdt.c | 162 +++ boards/sparc/bm3803/xx3803/src/xx3803.h | 109 ++ boards/sparc/bm3823/xx3823/Kconfig | 65 ++ .../sparc/bm3823/xx3823/configs/nsh/defconfig | 67 ++ boards/sparc/bm3823/xx3823/include/board.h | 132 +++ boards/sparc/bm3823/xx3823/scripts/Make.defs | 89 ++ .../sparc/bm3823/xx3823/scripts/linksparc.ld | 210 ++++ boards/sparc/bm3823/xx3823/src/Makefile | 34 + .../sparc/bm3823/xx3823/src/bm3823_am29lv.c | 112 ++ .../sparc/bm3823/xx3823/src/bm3823_appinit.c | 117 +++ boards/sparc/bm3823/xx3823/src/bm3823_boot.c | 71 ++ boards/sparc/bm3823/xx3823/src/bm3823_leds.c | 71 ++ boards/sparc/bm3823/xx3823/src/xx3823.h | 75 ++ libs/libc/machine/Kconfig | 4 + libs/libc/machine/Make.defs | 4 +- libs/libc/machine/sparc/Kconfig | 4 + libs/libc/machine/sparc/Make.defs | 28 + libs/libc/machine/sparc/arch_elf.c | 252 +++++ 125 files changed, 21751 insertions(+), 1 deletion(-) create mode 100644 arch/sparc/Kconfig create mode 100644 arch/sparc/include/arch.h create mode 100644 arch/sparc/include/bm3803/irq.h create mode 100644 arch/sparc/include/bm3823/irq.h create mode 100644 arch/sparc/include/elf.h create mode 100644 arch/sparc/include/inttypes.h create mode 100644 arch/sparc/include/irq.h create mode 100644 arch/sparc/include/limits.h create mode 100644 arch/sparc/include/sparc_v8/irq.h create mode 100644 arch/sparc/include/sparc_v8/syscall.h create mode 100644 arch/sparc/include/spinlock.h create mode 100644 arch/sparc/include/syscall.h create mode 100644 arch/sparc/include/types.h create mode 100644 arch/sparc/src/Makefile create mode 100644 arch/sparc/src/bm3803/Kconfig create mode 100644 arch/sparc/src/bm3803/Make.defs create mode 100644 arch/sparc/src/bm3803/bm3803-config.h create mode 100644 arch/sparc/src/bm3803/bm3803-irq.c create mode 100644 arch/sparc/src/bm3803/bm3803-lowconsole.c create mode 100644 arch/sparc/src/bm3803/bm3803-lowinit.c create mode 100644 arch/sparc/src/bm3803/bm3803-memorymap.h create mode 100644 arch/sparc/src/bm3803/bm3803-serial.c create mode 100644 arch/sparc/src/bm3803/bm3803-timerisr.c create mode 100644 arch/sparc/src/bm3803/bm3803-uart.h create mode 100644 arch/sparc/src/bm3803/bm3803.h create mode 100644 arch/sparc/src/bm3803/bm3803_exceptions.S create mode 100644 arch/sparc/src/bm3803/bm3803_exti.h create mode 100644 arch/sparc/src/bm3803/bm3803_exti_gpio.c create mode 100644 arch/sparc/src/bm3803/bm3803_freerun.c create mode 100644 arch/sparc/src/bm3803/bm3803_freerun.h create mode 100644 arch/sparc/src/bm3803/bm3803_head.S create mode 100644 arch/sparc/src/bm3803/bm3803_oneshot.c create mode 100644 arch/sparc/src/bm3803/bm3803_oneshot.h create mode 100644 arch/sparc/src/bm3803/bm3803_oneshot_lowerhalf.c create mode 100644 arch/sparc/src/bm3803/bm3803_tickless.c create mode 100644 arch/sparc/src/bm3803/bm3803_tim.c create mode 100644 arch/sparc/src/bm3803/bm3803_tim.h create mode 100644 arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c create mode 100644 arch/sparc/src/bm3803/bm3803_wdg.c create mode 100644 arch/sparc/src/bm3803/bm3803_wdg.h create mode 100644 arch/sparc/src/bm3803/chip.h create mode 100644 arch/sparc/src/bm3823/Kconfig create mode 100644 arch/sparc/src/bm3823/Make.defs create mode 100644 arch/sparc/src/bm3823/bm3823-config.h create mode 100644 arch/sparc/src/bm3823/bm3823-irq.c create mode 100644 arch/sparc/src/bm3823/bm3823-lowconsole.c create mode 100644 arch/sparc/src/bm3823/bm3823-lowinit.c create mode 100644 arch/sparc/src/bm3823/bm3823-memorymap.h create mode 100644 arch/sparc/src/bm3823/bm3823-serial.c create mode 100644 arch/sparc/src/bm3823/bm3823-timerisr.c create mode 100644 arch/sparc/src/bm3823/bm3823-uart.h create mode 100644 arch/sparc/src/bm3823/bm3823.h create mode 100644 arch/sparc/src/bm3823/bm3823_exceptions.S create mode 100644 arch/sparc/src/bm3823/bm3823_head.S create mode 100644 arch/sparc/src/bm3823/chip.h create mode 100644 arch/sparc/src/common/Kconfig create mode 100644 arch/sparc/src/common/up_allocateheap.c create mode 100644 arch/sparc/src/common/up_arch.h create mode 100644 arch/sparc/src/common/up_assert.c create mode 100644 arch/sparc/src/common/up_checkstack.c create mode 100644 arch/sparc/src/common/up_createstack.c create mode 100644 arch/sparc/src/common/up_exit.c create mode 100644 arch/sparc/src/common/up_idle.c create mode 100644 arch/sparc/src/common/up_initialize.c create mode 100644 arch/sparc/src/common/up_internal.h create mode 100644 arch/sparc/src/common/up_interruptcontext.c create mode 100644 arch/sparc/src/common/up_lowputs.c create mode 100644 arch/sparc/src/common/up_mdelay.c create mode 100644 arch/sparc/src/common/up_modifyreg16.c create mode 100644 arch/sparc/src/common/up_modifyreg32.c create mode 100644 arch/sparc/src/common/up_modifyreg8.c create mode 100644 arch/sparc/src/common/up_puts.c create mode 100644 arch/sparc/src/common/up_releasestack.c create mode 100644 arch/sparc/src/common/up_stackframe.c create mode 100644 arch/sparc/src/common/up_udelay.c create mode 100644 arch/sparc/src/common/up_usestack.c create mode 100644 arch/sparc/src/sparc_v8/Kconfig create mode 100644 arch/sparc/src/sparc_v8/Toolchain.defs create mode 100644 arch/sparc/src/sparc_v8/sparc_v8.h create mode 100644 arch/sparc/src/sparc_v8/up_blocktask.c create mode 100644 arch/sparc/src/sparc_v8/up_copystate.c create mode 100644 arch/sparc/src/sparc_v8/up_doirq.c create mode 100644 arch/sparc/src/sparc_v8/up_dumpstate.c create mode 100644 arch/sparc/src/sparc_v8/up_initialstate.c create mode 100644 arch/sparc/src/sparc_v8/up_irq.c create mode 100644 arch/sparc/src/sparc_v8/up_releasepending.c create mode 100644 arch/sparc/src/sparc_v8/up_reprioritizertr.c create mode 100644 arch/sparc/src/sparc_v8/up_romgetc.c create mode 100644 arch/sparc/src/sparc_v8/up_schedulesigaction.c create mode 100644 arch/sparc/src/sparc_v8/up_sigdeliver.c create mode 100644 arch/sparc/src/sparc_v8/up_swint1.c create mode 100644 arch/sparc/src/sparc_v8/up_syscall.S create mode 100644 arch/sparc/src/sparc_v8/up_systemreset.c create mode 100644 arch/sparc/src/sparc_v8/up_unblocktask.c create mode 100644 boards/sparc/bm3803/xx3803/Kconfig create mode 100644 boards/sparc/bm3803/xx3803/configs/nsh/defconfig create mode 100644 boards/sparc/bm3803/xx3803/include/board.h create mode 100644 boards/sparc/bm3803/xx3803/scripts/Make.defs create mode 100644 boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld create mode 100644 boards/sparc/bm3803/xx3803/scripts/linksparc.ld create mode 100644 boards/sparc/bm3803/xx3803/src/Makefile create mode 100644 boards/sparc/bm3803/xx3803/src/bm3803_am29lv.c create mode 100644 boards/sparc/bm3803/xx3803/src/bm3803_appinit.c create mode 100644 boards/sparc/bm3803/xx3803/src/bm3803_boot.c create mode 100644 boards/sparc/bm3803/xx3803/src/bm3803_reset.c create mode 100644 boards/sparc/bm3803/xx3803/src/bm3803_wdt.c create mode 100644 boards/sparc/bm3803/xx3803/src/xx3803.h create mode 100644 boards/sparc/bm3823/xx3823/Kconfig create mode 100644 boards/sparc/bm3823/xx3823/configs/nsh/defconfig create mode 100644 boards/sparc/bm3823/xx3823/include/board.h create mode 100644 boards/sparc/bm3823/xx3823/scripts/Make.defs create mode 100644 boards/sparc/bm3823/xx3823/scripts/linksparc.ld create mode 100644 boards/sparc/bm3823/xx3823/src/Makefile create mode 100644 boards/sparc/bm3823/xx3823/src/bm3823_am29lv.c create mode 100644 boards/sparc/bm3823/xx3823/src/bm3823_appinit.c create mode 100644 boards/sparc/bm3823/xx3823/src/bm3823_boot.c create mode 100644 boards/sparc/bm3823/xx3823/src/bm3823_leds.c create mode 100644 boards/sparc/bm3823/xx3823/src/xx3823.h create mode 100644 libs/libc/machine/sparc/Kconfig create mode 100644 libs/libc/machine/sparc/Make.defs create mode 100644 libs/libc/machine/sparc/arch_elf.c diff --git a/arch/Kconfig b/arch/Kconfig index 6c9af63a968..8e3c340aaa1 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -131,6 +131,13 @@ config ARCH_OR1K ---help--- OpenRISC architectures. +config ARCH_SPARC + bool "SPARC" + select ARCH_HAVE_INTERRUPTSTACK + select ARCH_HAVE_CUSTOMOPT + ---help--- + SPARC architectures (SPARC V8) + endchoice config ARCH @@ -148,6 +155,7 @@ config ARCH default "z16" if ARCH_Z16 default "z80" if ARCH_Z80 default "or1k" if ARCH_OR1K + default "sparc" if ARCH_SPARC source "arch/arm/Kconfig" source "arch/avr/Kconfig" @@ -163,6 +171,7 @@ source "arch/xtensa/Kconfig" source "arch/z16/Kconfig" source "arch/z80/Kconfig" source "arch/or1k/Kconfig" +source "arch/sparc/Kconfig" config ARCH_CHIP_CUSTOM bool diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig new file mode 100644 index 00000000000..b886cf55e65 --- /dev/null +++ b/arch/sparc/Kconfig @@ -0,0 +1,57 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_SPARC +choice + prompt "SPARC chip selection" + default ARCH_CHIP_BM3803 + +config ARCH_CHIP_BM3803 + bool "BM3803" + select ARCH_SPARC_V8 + select ARCH_HAVE_MATH_H + select ARCH_HAVE_RESET + select ARCH_HAVE_IRQPRIO + select ARCH_VECNOTIRQ + select ARCH_HAVE_RAMFUNCS + select ARCH_HAVE_TICKLESS + select ARCH_HAVE_SERIAL_TERMIOS + ---help--- + Microchip BM3803 (ARCH_SPARC_V8) + +config ARCH_CHIP_BM3823 + bool "BM3823" + select ARCH_SPARC_V8 + select ARCH_HAVE_MATH_H + select ARCH_HAVE_IRQPRIO + select ARCH_VECNOTIRQ + select ARCH_HAVE_RAMFUNCS + select ARCH_HAVE_SERIAL_TERMIOS + ---help--- + Microchip BM3823 (ARCH_SPARC_V8) + +endchoice + +config ARCH_SPARC_V8 + bool + default n + select ARCH_HAVE_STACKCHECK + + +config ARCH_FAMILY + string + default "sparc_v8" if ARCH_SPARC_V8 + +config ARCH_CHIP + string + default "bm3803" if ARCH_CHIP_BM3803 + default "bm3823" if ARCH_CHIP_BM3823 + +source arch/sparc/src/common/Kconfig +source arch/sparc/src/sparc_v8/Kconfig +source arch/sparc/src/bm3803/Kconfig +source arch/sparc/src/bm3823/Kconfig + +endif diff --git a/arch/sparc/include/arch.h b/arch/sparc/include/arch.h new file mode 100644 index 00000000000..8a36419ab2a --- /dev/null +++ b/arch/sparc/include/arch.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * arch/sparc/include/arch.h + * + * 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 directed but, rather, + * only indirectly through nuttx/arch.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_ARCH_H +#define __ARCH_SPARC_INCLUDE_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_SPARC_INCLUDE_ARCH_H */ + diff --git a/arch/sparc/include/bm3803/irq.h b/arch/sparc/include/bm3803/irq.h new file mode 100644 index 00000000000..4d3e356a232 --- /dev/null +++ b/arch/sparc/include/bm3803/irq.h @@ -0,0 +1,158 @@ +/**************************************************************************** + * arch/sparc/include/bm3803/irq.h + * + * 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 directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_BM3803_IRQ_H +#define __ARCH_SPARC_INCLUDE_BM3803_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Interrupt Sources The interrupt source numbers directly map to the trap + * type and to the bits used in the Interrupt Clear, Interrupt Force, + * Interrupt Mask, and the Interrupt Pending Registers. + */ + +#if defined(CONFIG_ARCH_CHIP_BM3803) + +#define BM3803_IRQ_FIRST 0x00 + +#define BM3803_IRQ_RESET 0x00 +#define BM3803_IRQ_INST_ACC_EXCEPTION 0x01 +#define BM3803_IRQ_ILL_INST 0x02 +#define BM3803_IRQ_PRIVELEGE_INST 0x03 +#define BM3803_IRQ_FP_DISABLED 0x04 +#define BM3803_IRQ_WINDOW_OVERFLOW 0x05 +#define BM3803_IRQ_WINDOW_UNDERFLOW 0x06 +#define BM3803_IRQ_ADD_NOT_ALIGNED 0x07 +#define BM3803_IRQ_ADD_FP_EXCEPTION 0x08 +#define BM3803_IRQ_DATA_ACC_EXCEPTION 0x09 +#define BM3803_IRQ_TAG_OVERFLOW 0x0A +#define BM3803_IRQ_HW_UNDEFINED_0B 0x0B +#define BM3803_IRQ_HW_UNDEFINED_0C 0x0C +#define BM3803_IRQ_HW_UNDEFINED_0D 0x0D +#define BM3803_IRQ_HW_UNDEFINED_0E 0x0E +#define BM3803_IRQ_HW_UNDEFINED_0F 0x0F +#define BM3803_IRQ_HW_UNDEFINED_10 0x10 + +#define BM3803_IRQ_FIRST_INTERRUPT 0x11 +#define BM3803_IRQ_CORRECTABLE_MEMORY_ERROR 0x11 +#define BM3803_IRQ_UART_2_RX_TX 0x12 +#define BM3803_IRQ_UART_1_RX_TX 0x13 +#define BM3803_IRQ_EXTERNAL_0 0x14 +#define BM3803_IRQ_EXTERNAL_1 0x15 +#define BM3803_IRQ_EXTERNAL_2 0x16 +#define BM3803_IRQ_EXTERNAL_3 0x17 +#define BM3803_IRQ_TIMER1 0x18 +#define BM3803_IRQ_TIMER2 0x19 +#define BM3803_IRQ_EMPTY1 0x1A +#define BM3803_IRQ_EMPTY2 0x1B +#define BM3803_IRQ_UART_3_RX_TX 0x1C +#define BM3803_IRQ_EMPTY4 0x1D +#define BM3803_IRQ_EMPTY5 0x1E +#define BM3803_IRQ_EMPTY6 0x1F +#define BM3803_IRQ_LAST_INTERRUPT 0x1F + +#define BM3803_IRQ_HW_UNDEFINED_20 0x20 +#define BM3803_IRQ_HW_UNDEFINED_21 0x21 +#define BM3803_IRQ_HW_UNDEFINED_22 0x22 +#define BM3803_IRQ_HW_UNDEFINED_23 0x23 + +#define BM3803_IRQ_CP_DISABLED 0x24 + +#define BM3803_IRQ_HW_UNDEFINED_25 0x25 +#define BM3803_IRQ_HW_UNDEFINED_26 0x26 +#define BM3803_IRQ_HW_UNDEFINED_27 0x27 + +#define BM3803_IRQ_CP_EXCEPTION 0x28 + +#define BM3803_IRQ_HW_UNDEFINED_29 0x29 +#define BM3803_IRQ_HW_UNDEFINED_7F 0x7F + +#define BM3803_IRQ_SW_SYSCALL_TA0 0x80 +#define BM3803_IRQ_SW_UNDEFINED_81 0x81 +#define BM3803_IRQ_SW_UNDEFINED_82 0x82 +#define BM3803_IRQ_SW_FLUSH_WINDOWS 0x83 + +#define BM3803_IRQ_SW_UNDEFINED_84 0x84 +#define BM3803_IRQ_SW_UNDEFINED_85 0x85 +#define BM3803_IRQ_SW_UNDEFINED_86 0x86 +#define BM3803_IRQ_SW_UNDEFINED_87 0x87 +#define BM3803_IRQ_SW_SYSCALL_TA8 0x88 + +#define BM3803_IRQ_SW_SYSCALL_IRQDIS 0x89 +#define BM3803_IRQ_SW_SYSCALL_IRQEN 0x8A + +#define BM3803_IRQ_SW_UNDEFINED_8B 0x8B +#define BM3803_IRQ_SW_UNDEFINED_FF 0xFF + +#define BM3803_IRQ_LAST 0xFF + +# define NR_IRQS 256 + +#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_SPARC_INCLUDE_BM3803_IRQ_H */ diff --git a/arch/sparc/include/bm3823/irq.h b/arch/sparc/include/bm3823/irq.h new file mode 100644 index 00000000000..414e8be3a86 --- /dev/null +++ b/arch/sparc/include/bm3823/irq.h @@ -0,0 +1,160 @@ +/**************************************************************************** + * arch/sparc/include/bm3823/irq.h + * + * 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 directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_BM3823_IRQ_H +#define __ARCH_SPARC_INCLUDE_BM3823_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Interrupt Sources + * + * The interrupt source numbers directly map to the trap type and to + * the bits used in the Interrupt Clear, Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + */ + +#if defined(CONFIG_ARCH_CHIP_BM3823) + +#define BM3823_IRQ_FIRST 0x00 + +#define BM3823_IRQ_RESET 0x00 +#define BM3823_IRQ_INST_ACC_EXCEPTION 0x01 +#define BM3823_IRQ_ILL_INST 0x02 +#define BM3823_IRQ_PRIVELEGE_INST 0x03 +#define BM3823_IRQ_FP_DISABLED 0x04 +#define BM3823_IRQ_WINDOW_OVERFLOW 0x05 +#define BM3823_IRQ_WINDOW_UNDERFLOW 0x06 +#define BM3823_IRQ_ADD_NOT_ALIGNED 0x07 +#define BM3823_IRQ_ADD_FP_EXCEPTION 0x08 +#define BM3823_IRQ_DATA_ACC_EXCEPTION 0x09 +#define BM3823_IRQ_TAG_OVERFLOW 0x0A +#define BM3823_IRQ_HW_UNDEFINED_0B 0x0B +#define BM3823_IRQ_HW_UNDEFINED_0C 0x0C +#define BM3823_IRQ_HW_UNDEFINED_0D 0x0D +#define BM3823_IRQ_HW_UNDEFINED_0E 0x0E +#define BM3823_IRQ_HW_UNDEFINED_0F 0x0F +#define BM3823_IRQ_HW_UNDEFINED_10 0x10 + +#define BM3823_IRQ_FIRST_INTERRUPT 0x11 +#define BM3823_IRQ_AHB_ERROR 0x11 +#define BM3823_IRQ_UART_2_RX_TX 0x12 +#define BM3823_IRQ_UART_1_RX_TX 0x13 +#define BM3823_IRQ_EXTERNAL_0 0x14 +#define BM3823_IRQ_EXTERNAL_1 0x15 +#define BM3823_IRQ_EXTERNAL_2 0x16 +#define BM3823_IRQ_EXTERNAL_3 0x17 +#define BM3823_IRQ_EXTERNAL_4 0x18 +#define BM3823_IRQ_EXTERNAL_5 0x19 +#define BM3823_IRQ_SECOND 0x1A +#define BM3823_IRQ_DSUTRACWBUFF 0x1B +#define BM3823_IRQ_PCI 0x1C +#define BM3823_IRQ_TIMER2 0x1D +#define BM3823_IRQ_TIMER1 0x1E +#define BM3823_IRQ_NONMASK 0x1F +#define BM3823_IRQ_LAST_INTERRUPT 0x1F + +#define BM3823_IRQ_HW_UNDEFINED_20 0x20 +#define BM3823_IRQ_HW_UNDEFINED_21 0x21 +#define BM3823_IRQ_HW_UNDEFINED_22 0x22 +#define BM3823_IRQ_HW_UNDEFINED_23 0x23 + +#define BM3823_IRQ_CP_DISABLED 0x24 + +#define BM3823_IRQ_HW_UNDEFINED_25 0x25 +#define BM3823_IRQ_HW_UNDEFINED_26 0x26 +#define BM3823_IRQ_HW_UNDEFINED_27 0x27 + +#define BM3823_IRQ_CP_EXCEPTION 0x28 + +#define BM3823_IRQ_HW_UNDEFINED_29 0x29 +#define BM3823_IRQ_HW_UNDEFINED_7F 0x7F + +#define BM3823_IRQ_SW_SYSCALL_TA0 0x80 +#define BM3823_IRQ_SW_UNDEFINED_81 0x81 +#define BM3823_IRQ_SW_UNDEFINED_82 0x82 +#define BM3823_IRQ_SW_FLUSH_WINDOWS 0x83 + +#define BM3823_IRQ_SW_UNDEFINED_84 0x84 +#define BM3823_IRQ_SW_UNDEFINED_85 0x85 +#define BM3823_IRQ_SW_UNDEFINED_86 0x86 +#define BM3823_IRQ_SW_UNDEFINED_87 0x87 +#define BM3823_IRQ_SW_SYSCALL_TA8 0x88 + +#define BM3823_IRQ_SW_SYSCALL_IRQDIS 0x89 +#define BM3823_IRQ_SW_SYSCALL_IRQEN 0x8A + +#define BM3823_IRQ_SW_UNDEFINED_8B 0x8B +#define BM3823_IRQ_SW_UNDEFINED_FF 0xFF + +#define BM3823_IRQ_LAST 0xFF + +# define NR_IRQS 256 + +#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_SPARC_INCLUDE_BM3823_IRQ_H */ diff --git a/arch/sparc/include/elf.h b/arch/sparc/include/elf.h new file mode 100644 index 00000000000..39a0f6e0ee5 --- /dev/null +++ b/arch/sparc/include/elf.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/sparc/include/elf.h + * + * 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_SPARC_INCLUDE_ELF_H +#define __ARCH_SPARC_INCLUDE_ELF_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Relocation codes */ + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 + +#define OPCODE_NOP 0x01000000 /* nop */ +#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ +#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ +#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ +#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ + +#endif /* __ARCH_SPARC_INCLUDE_ELF_H */ diff --git a/arch/sparc/include/inttypes.h b/arch/sparc/include/inttypes.h new file mode 100644 index 00000000000..f70b0648907 --- /dev/null +++ b/arch/sparc/include/inttypes.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/sparc/include/inttypes.h + * + * 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_MIPS_INCLUDE_INTTYPES_H +#define __ARCH_MIPS_INCLUDE_INTTYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "ld" +#define PRId64 "lld" + +#define PRIdPTR "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "li" +#define PRIi64 "lli" + +#define PRIiPTR "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "lo" +#define PRIo64 "llo" + +#define PRIoPTR "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "lu" +#define PRIu64 "llu" + +#define PRIuPTR "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "lx" +#define PRIx64 "llx" + +#define PRIxPTR "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "lX" +#define PRIX64 "llX" + +#define PRIXPTR "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "ld" +#define SCNd64 "lld" + +#define SCNdPTR "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "li" +#define SCNi64 "lli" + +#define SCNiPTR "i" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "lo" +#define SCNo64 "llo" + +#define SCNoPTR "o" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "lu" +#define SCNu64 "llu" + +#define SCNuPTR "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "lx" +#define SCNx64 "llx" + +#define SCNxPTR "x" + +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x ## l +#define INT64_C(x) x ## ll + +#define UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## ul +#define UINT64_C(x) x ## ull + +#endif /* __ARCH_SPARC_INCLUDE_INTTYPES_H */ diff --git a/arch/sparc/include/irq.h b/arch/sparc/include/irq.h new file mode 100644 index 00000000000..9cd23373ad6 --- /dev/null +++ b/arch/sparc/include/irq.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * arch/sparc/include/irq.h + * + * 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 directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_IRQ_H +#define __ARCH_SPARC_INCLUDE_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include NuttX-specific IRQ definitions */ + +#include + +/* Include chip-specific IRQ definitions (including IRQ numbers) */ + +#include + +/* Include AVR architecture-specific IRQ definitions (including register + * save structure and up_irq_save()/up_irq_restore() macros + */ + +#ifdef CONFIG_ARCH_SPARC_V8 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_INCLUDE_IRQ_H */ + diff --git a/arch/sparc/include/limits.h b/arch/sparc/include/limits.h new file mode 100644 index 00000000000..89c65dffbc0 --- /dev/null +++ b/arch/sparc/include/limits.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/sparc/include/limits.h + * + * 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_SPARC_INCLUDE_LIMITS_H +#define __ARCH_SPARC_INCLUDE_LIMITS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CHAR_BIT 8 +#define SCHAR_MIN (-SCHAR_MAX - 1) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +/* These could be different on machines where char is unsigned */ + +#ifdef __CHAR_UNSIGNED__ +#define CHAR_MIN 0 +#define CHAR_MAX UCHAR_MAX +#else +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-SHRT_MAX - 1) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535U + +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +/* These change on 32-bit and 64-bit platforms */ + +#define LONG_MIN (-LONG_MAX - 1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#define LLONG_MIN (-LLONG_MAX - 1) +#define LLONG_MAX 9223372036854775807LL +#define ULLONG_MAX 18446744073709551615ULL + +/* A pointer is 4 bytes */ + +#define PTR_MIN (-PTR_MAX - 1) +#define PTR_MAX 2147483647 +#define UPTR_MAX 4294967295U + +#endif /* __ARCH_SPARC_INCLUDE_LIMITS_H */ + diff --git a/arch/sparc/include/sparc_v8/irq.h b/arch/sparc/include/sparc_v8/irq.h new file mode 100644 index 00000000000..de77b50199a --- /dev/null +++ b/arch/sparc/include/sparc_v8/irq.h @@ -0,0 +1,753 @@ +/**************************************************************************** + * arch/sparc/include/sparc_v8/irq.h + * + * 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 directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_SPARC_V8_IRQ_H +#define __ARCH_SPARC_INCLUDE_SPARC_V8_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* The global pointer (GP) does not need to be saved in the "normal," flat + * NuttX build. However, it would be necessary to save the GP if this is + * a KERNEL build or if NXFLAT is supported. + */ + +#undef SPARC_V8_SAVE_GP +#if defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NXFLAT) +# define SPARC_V8_SAVE_GP 1 +#endif + +/* If this is a kernel build, how many nested system calls should support? */ + +#ifndef CONFIG_SYS_NNEST +# define CONFIG_SYS_NNEST 2 +#endif + +/* Register save state structure ********************************************/ + +#define REG_R1 (3) /* R1 */ +#define REG_R2 (4) /* R2 */ +#define REG_R3 (5) /* R3 */ +#define REG_R4 (6) /* R4 */ +#define REG_R5 (7) /* R5 */ +#define REG_R6 (8) /* R6 */ +#define REG_R7 (9) /* R7 */ + +#define REG_R8 (10) /* R8 */ +#define REG_R9 (11) /* R9 */ +#define REG_R10 (12) /* R10 */ +#define REG_R11 (13) /* R11 */ +#define REG_R12 (14) /* R12 */ +#define REG_R13 (15) /* R13 */ +#define REG_R14 (16) /* R14 */ +#define REG_R15 (17) /* R15 */ + +#define REG_R16 (52) /* R16 */ +#define REG_R17 (53) /* R17 */ +#define REG_R18 (54) /* R18 */ +#define REG_R19 (55) /* R19 */ +#define REG_R20 (56) /* R20 */ +#define REG_R21 (57) /* R21 */ +#define REG_R22 (58) /* R22 */ +#define REG_R23 (59) /* R23 */ + +#define REG_R24 (60) /* R24 */ +#define REG_R25 (61) /* R25 */ +#define REG_R26 (62) /* R26 */ +#define REG_R27 (63) /* R27 */ +#define REG_R28 (64) /* R28 */ +#define REG_R29 (65) /* R29 */ +#define REG_R30 (66) /* R30 */ +#define REG_R31 (67) /* R31 */ + +#define REG_R32 (0) /* R32 */ +#define REG_R33 (1) /* R33 */ +#define REG_R34 (2) /* R34 */ + +#define REG_R35 (18) /* R35 */ +#define REG_R36 (19) /* R36 */ + +#define XCPTCONTEXT_REGS (52) +/* Alternate register names *************************************************/ + +/* %psr: processor status register */ +#define REG_PSR (0) + +/* %pc: pc register */ +#define REG_PC (1) + +/* %npc: npc register */ +#define REG_NPC (2) + +/* %g1: global 1 */ +#define REG_G1 (3) + +/* %g2: global 2 (reserved for application) */ +#define REG_G2 (4) + +/* %g3: global 3 (reserved for application) */ +#define REG_G3 (5) + +/* %g4: global 4 (reserved for application) */ +#define REG_G4 (6) + +/* %g5: global 5 (reserved for system) */ +#define REG_G5 (7) + +/* %g6: global 5 (reserved for system) */ +#define REG_G6 (8) + +/* %g7: global 5 (reserved for system) */ +#define REG_G7 (9) + +/* %i0: incoming param 0, outgoing return value */ +#define REG_I0 (10) + +/* %i1: incoming param 1 */ +#define REG_I1 (11) + +/* %i2: incoming param 2 */ +#define REG_I2 (12) + +/* %i3: incoming param 3 */ +#define REG_I3 (13) + +/* %i4: incoming param 4 */ +#define REG_I4 (14) + +/* %i5: incoming param 5 */ +#define REG_I5 (15) + +/* %i6: frame pointer */ +#define REG_I6 (16) + +/* %i7: return address - 8 */ +#define REG_I7 (17) + +#define REG_Y (18) +#define REG_FSR (19) + +/* %l0: loacal 0 */ +#define REG_L0 (52) + +/* %l1: loacal 1 */ +#define REG_L1 (53) + +/* %l2: loacal 2 */ +#define REG_L2 (54) + +/* %l3: loacal 3 */ +#define REG_L3 (55) + +/* %l4: loacal 4 */ +#define REG_L4 (56) + +/* %l5: loacal 5 */ +#define REG_L5 (57) + +/* %l6: loacal 6 */ +#define REG_L6 (58) + +/* %l7: loacal 7 */ +#define REG_L7 (59) + +/* %o0: outgoing param 0, incoming return value */ +#define REG_O0 (60) + +/* %o1: outgoing param 1 */ +#define REG_O1 (61) + +/* %o2: outgoing param 2 */ +#define REG_O2 (62) + +/* %o3: outgoing param 3 */ +#define REG_O3 (63) + +/* %o4: outgoing param 4 */ +#define REG_O4 (64) + +/* %o5: outgoing param 5 */ +#define REG_O5 (65) + +/* %o6: stack pointer */ +#define REG_O6 (66) + +/* %o7: address of call instruction, temporary */ +#define REG_O7 (67) + +/* SPARC Software Trap number definitions */ +#define SPARC_SWTRAP_SYSCALL 0 +#define SPARC_SWTRAP_IRQDIS 9 +#define SPARC_SWTRAP_IRQEN 10 +/** + * PSR masks and starting bit positions + * + * NOTE: Reserved bits are ignored. + */ + +#define SPARC_PSR_CWP_MASK 0x00000007 /* bits 0 - 4 */ + +/** This constant is a mask for the ET bits in the PSR. */ +#define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */ + +/** This constant is a mask for the PS bits in the PSR. */ +#define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */ + +/** This constant is a mask for the S bits in the PSR. */ +#define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */ + +/** This constant is a mask for the PIL bits in the PSR. */ +#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */ + +/** This constant is a mask for the EF bits in the PSR. */ +#define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */ + +/** This constant is a mask for the EC bits in the PSR. */ +#define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */ + +/** This constant is a mask for the ICC bits in the PSR. */ +#define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */ + +/** This constant is a mask for the VER bits in the PSR. */ +#define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */ + +/** This constant is a mask for the IMPL bits in the PSR. */ +#define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */ + +/** This constant is the starting bit position of the CWP in the PSR. */ +#define SPARC_PSR_CWP_BIT_POSITION 0 /* bits 0 - 4 */ + +/** This constant is the starting bit position of the ET in the PSR. */ +#define SPARC_PSR_ET_BIT_POSITION 5 /* bit 5 */ + +/** This constant is the starting bit position of the PS in the PSR. */ +#define SPARC_PSR_PS_BIT_POSITION 6 /* bit 6 */ + +/** This constant is the starting bit position of the S in the PSR. */ +#define SPARC_PSR_S_BIT_POSITION 7 /* bit 7 */ + +/** This constant is the starting bit position of the PIL in the PSR. */ +#define SPARC_PSR_PIL_BIT_POSITION 8 /* bits 8 - 11 */ + +/** This constant is the starting bit position of the EF in the PSR. */ +#define SPARC_PSR_EF_BIT_POSITION 12 /* bit 12 */ + +/** This constant is the starting bit position of the EC in the PSR. */ +#define SPARC_PSR_EC_BIT_POSITION 13 /* bit 13 */ + +/** This constant is the starting bit position of the ICC in the PSR. */ +#define SPARC_PSR_ICC_BIT_POSITION 20 /* bits 20 - 23 */ + +/** This constant is the starting bit position of the VER in the PSR. */ +#define SPARC_PSR_VER_BIT_POSITION 24 /* bits 24 - 27 */ + +/** This constant is the starting bit position of the IMPL in the PSR. */ +#define SPARC_PSR_IMPL_BIT_POSITION 28 /* bits 28 - 31 */ + +#define SPARC_NUMBER_OF_REGISTER_WINDOWS 8 + +#define CPU_STACK_FRAME_L0_OFFSET 0x00 +#define CPU_STACK_FRAME_L2_OFFSET 0x08 +#define CPU_STACK_FRAME_L4_OFFSET 0x10 +#define CPU_STACK_FRAME_L6_OFFSET 0x18 +#define CPU_STACK_FRAME_I0_OFFSET 0x20 +#define CPU_STACK_FRAME_I2_OFFSET 0x28 +#define CPU_STACK_FRAME_I4_OFFSET 0x30 +#define CPU_STACK_FRAME_I6_FP_OFFSET 0x38 +#define CPU_STRUCTURE_RETURN_ADDRESS_OFFSET 0x40 +#define CPU_STACK_FRAME_SAVED_ARG0_OFFSET 0x44 +#define CPU_STACK_FRAME_SAVED_ARG1_OFFSET 0x48 +#define CPU_STACK_FRAME_SAVED_ARG2_OFFSET 0x4c +#define CPU_STACK_FRAME_SAVED_ARG3_OFFSET 0x50 +#define CPU_STACK_FRAME_SAVED_ARG4_OFFSET 0x54 +#define CPU_STACK_FRAME_SAVED_ARG5_OFFSET 0x58 +#define CPU_STACK_FRAME_PAD0_OFFSET 0x5c + +#define CPU_MINIMUM_STACK_FRAME_SIZE 0x60 +#define ISF_STACK_FRAME_OFFSET 0x00 + +#define ISF_PSR_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x00) +#define ISF_PC_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x04) +#define ISF_NPC_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x08) +#define ISF_G1_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x0c) +#define ISF_G2_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x10) +#define ISF_G4_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x18) +#define ISF_G6_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x20) +#define ISF_I0_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x28) +#define ISF_I2_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x30) +#define ISF_I4_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x38) +#define ISF_I6_FP_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x40) +#define ISF_Y_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x48) + +#define ISF_FSR_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x4c) + +#define ISF_F0_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x50) +#define ISF_F2_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x58) +#define ISF_F4_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x60) +#define ISF_F6_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x68) + +#define ISF_F8_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x70) +#define ISF_F10_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x78) +#define ISF_F12_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x80) +#define ISF_F14_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x88) + +#define ISF_F16_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x90) +#define ISF_F18_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0x98) +#define ISF_F20_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xa0) +#define ISF_F22_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xa8) + +#define ISF_F24_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xb0) +#define ISF_F26_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xb8) +#define ISF_F28_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xc0) +#define ISF_F30_OFFSET (CPU_MINIMUM_STACK_FRAME_SIZE + 0xc8) + +#define CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE (CPU_MINIMUM_STACK_FRAME_SIZE + 0x50 + 32*4) + +/* Offsets of fields with Context_Control for assembly routines. */ + +/** This macro defines an offset into the context for use in assembly. */ +#define PSR_OFFSET 0x00 + +/** This macro defines an offset into the context for use in assembly. */ +#define PC_OFFSET 0x04 +/** This macro defines an offset into the context for use in assembly. */ +#define NPC_OFFSET 0x08 + +/** This macro defines an offset into the context for use in assembly. */ +#define G1_OFFSET 0x0C +/** This macro defines an offset into the context for use in assembly. */ +#define G2_OFFSET 0x10 +/** This macro defines an offset into the context for use in assembly. */ +#define G3_OFFSET 0x14 +/** This macro defines an offset into the context for use in assembly. */ +#define G4_OFFSET 0x18 +/** This macro defines an offset into the context for use in assembly. */ +#define G5_OFFSET 0x1C +/** This macro defines an offset into the context for use in assembly. */ +#define G6_OFFSET 0x20 +/** This macro defines an offset into the context for use in assembly. */ +#define G7_OFFSET 0x24 + +/** This macro defines an offset into the context for use in assembly. */ +#define O0_OFFSET 0x28 +/** This macro defines an offset into the context for use in assembly. */ +#define O1_OFFSET 0x2C +/** This macro defines an offset into the context for use in assembly. */ +#define O2_OFFSET 0x30 +/** This macro defines an offset into the context for use in assembly. */ +#define O3_OFFSET 0x34 +/** This macro defines an offset into the context for use in assembly. */ +#define O4_OFFSET 0x38 +/** This macro defines an offset into the context for use in assembly. */ +#define O5_OFFSET 0x3C +/** This macro defines an offset into the context for use in assembly. */ +#define O6_SP_OFFSET 0x40 +/** This macro defines an offset into the context for use in assembly. */ +#define O7_OFFSET 0x44 + +#define Y_OFFSET 0x48 +#define FSR_OFFSET 0x4c + +#define F0_OFFSET 0x50 +#define F2_OFFSET 0x58 +#define F4_OFFSET 0x60 +#define F6_OFFSET 0x68 + +#define F8_OFFSET 0x70 +#define F10_OFFSET 0x78 +#define F12_OFFSET 0x80 +#define F14_OFFSET 0x88 + +#define F16_OFFSET 0x90 +#define F18_OFFSET 0x98 +#define F20_OFFSET 0xa0 +#define F22_OFFSET 0xa8 + +#define F24_OFFSET 0xb0 +#define F26_OFFSET 0xb8 +#define F28_OFFSET 0xc0 +#define F30_OFFSET 0xc8 + +#if ( SPARC_HAS_FPU == 1 ) + /** + * @brief Offset of the CPU_Per_CPU_control::fsr field relative to the + * Per_CPU_Control begin. + */ + #define SPARC_PER_CPU_FSR_OFFSET 4 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* This structure represents the return state from a system call */ + +#ifdef CONFIG_BUILD_KERNEL +struct xcpt_syscall_s +{ + uint32_t sysreturn; /* The return PC */ +}; +#endif + +/* The following structure is included in the TCB and defines the complete + * state of the thread. + */ + +struct xcptcontext +{ + /* The following function pointer is non-NULL if there are pending signals + * to be processed. + */ + + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These additional register save locations are used to implement the + * signal delivery trampoline. + * + * REVISIT: Because there is only one copy of these save areas, + * only a single signal handler can be active. This precludes + * queuing of signal actions. As a result, signals received while + * another signal handler is executing will be ignored! + */ + + uint32_t saved_pc; /* Trampoline PC */ + uint32_t saved_npc; /* Trampoline nPC */ + uint32_t saved_status; /* Status with interrupts disabled. */ + +#ifdef CONFIG_BUILD_KERNEL + /* This is the saved address to use when returning from a user-space + * signal handler. + */ + + uint32_t sigreturn; + +#endif + +#ifdef CONFIG_BUILD_KERNEL + /* The following array holds information needed to return from each nested + * system call. + */ + + uint8_t nsyscalls; + struct xcpt_syscall_s syscall[CONFIG_SYS_NNEST]; + +#endif + + /* Register save area */ + + uint32_t regs[XCPTCONTEXT_REGS] + __attribute__((aligned(8))); +}; + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/** + * @brief Macro to set the PSR. + * + * This macro sets the PSR register to the value in @a _psr. + */ +#define sparc_set_psr( _psr ) \ + do { \ + __asm__ volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \ + nop(); \ + nop(); \ + nop(); \ + } while ( 0 ) + +/** + * @brief Macro to obtain the PSR. + * + * This macro returns the current contents of the PSR register in @a _psr. + */ +#define sparc_get_psr( _psr ) \ + do { \ + (_psr) = 0; \ + __asm__ volatile( "rd %%psr, %0" : "=r" (_psr) : "0" (_psr) ); \ + } while ( 0 ) + +/** + * This macro is a standard nop instruction. + */ +#define nop() \ + do { \ + __asm__ volatile ( "nop" ); \ + } while ( 0 ) + +/** + * @brief Macro to obtain the TBR. + * + * This macro returns the current contents of the TBR register in @a _tbr. + */ +#define sparc_get_tbr( _tbr ) \ + do { \ + (_tbr) = 0; /* to avoid unitialized warnings */ \ + __asm__ volatile( "rd %%tbr, %0" : "=r" (_tbr) : "0" (_tbr) ); \ + } while ( 0 ) + +/** + * @brief Macro to set the TBR. + * + * This macro sets the TBR register to the value in @a _tbr. + */ +#define sparc_set_tbr( _tbr ) \ + do { \ + __asm__ volatile( "wr %0, 0, %%tbr" : "=r" (_tbr) : "0" (_tbr) ); \ + } while ( 0 ) + +/** + * @brief Macro to obtain the WIM. + * + * This macro returns the current contents of the WIM field in @a _wim. + */ +#define sparc_get_wim( _wim ) \ + do { \ + __asm__ volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \ + } while ( 0 ) + +/** + * @brief Macro to set the WIM. + * + * This macro sets the WIM field to the value in @a _wim. + */ +#define sparc_set_wim( _wim ) \ + do { \ + __asm__ volatile( "wr %0, %%wim" : "=r" (_wim) : "0" (_wim) ); \ + nop(); \ + nop(); \ + nop(); \ + } while ( 0 ) + +/** + * @brief Macro to obtain the Y register. + * + * This macro returns the current contents of the Y register in @a _y. + */ +#define sparc_get_y( _y ) \ + do { \ + __asm__ volatile( "rd %%y, %0" : "=r" (_y) : "0" (_y) ); \ + } while ( 0 ) + +/** + * @brief Macro to set the Y register. + * + * This macro sets the Y register to the value in @a _y. + */ +#define sparc_set_y( _y ) \ + do { \ + __asm__ volatile( "wr %0, %%y" : "=r" (_y) : "0" (_y) ); \ + } while ( 0 ) + +/** + * @brief Macro to obtain the asr17. + * + * This macro returns the current contents of the asr17 register in _asr17. + */ +#define sparc_get_asr17( _asr17 ) \ + do { \ + (_asr17) = 0; /* to avoid unitialized warnings */ \ + __asm__ volatile( "rd %%asr17, %0" : "=r" (_asr17) : "0" (_asr17) ); \ + } while ( 0 ) + +/** + * @brief SPARC disable processor interrupts. + * + * This method is invoked to disable all maskable interrupts. + * + * @return This method returns the entire PSR contents. + */ + +static inline uint32_t sparc_disable_interrupts(void) +{ + register uint32_t psr __asm__("g1"); /* return value of trap handler */ + __asm__ volatile ("ta %1\n\t" : "=r" (psr) : "i" (SPARC_SWTRAP_IRQDIS)); + return psr; +} + +/** + * @brief SPARC enable processor interrupts. + * + * This method is invoked to enable all maskable interrupts. + * + * @param[in] psr is the PSR returned by @ref sparc_disable_interrupts. + */ + +static inline void sparc_enable_interrupts(uint32_t psr) +{ + register uint32_t _psr __asm__("g1") = psr; /* input to trap handler */ + + /* The trap instruction has a higher trap priority than the interrupts + * according to "The SPARC Architecture Manual: Version 8", Table 7-1 + * "Exception and Interrupt Request Priority and tt Values". Add a nop to + * prevent a trap instruction right after the interrupt enable trap. + */ + + __asm__ volatile ("ta %0\nnop\n" :: "i" (SPARC_SWTRAP_IRQEN), "r" (_psr)); +} + +/** + * @brief SPARC flash processor interrupts. + * + * This method is invoked to temporarily enable all maskable interrupts. + * + * @param[in] _psr is the PSR returned by @ref sparc_disable_interrupts. + */ + +#define sparc_flash_interrupts( _psr ) \ + do { \ + sparc_enable_interrupts( (_psr) ); \ + _psr = sparc_disable_interrupts(); \ + } while ( 0 ) + +/** + * @brief SPARC obtain interrupt level. + * + * This method is invoked to obtain the current interrupt disable level. + * + * @param[in] _level is the PSR returned by @ref sparc_disable_interrupts. + */ + +#define sparc_get_interrupt_level( _level ) \ + do { \ + register uint32_t _psr_level = 0; \ + \ + sparc_get_psr( _psr_level ); \ + (_level) = \ + (_psr_level & SPARC_PSR_PIL_MASK) >> SPARC_PSR_PIL_BIT_POSITION; \ + } while ( 0 ) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_irq_save + * + * Description: + * Save the current interrupt state and disable interrupts. + * + * NOTE: This function should never be called from application code and, + * as a general rule unless you really know what you are doing, this + * function should not be called directly from operation system code : + * Typically, the wrapper functions, enter_critical_section() is probably + * what you really want. + * + * Input Parameters: + * None + * + * Returned Value: + * Interrupt state prior to disabling interrupts. + * + ****************************************************************************/ + +irqstate_t up_irq_save(void); + +/**************************************************************************** + * Name: up_irq_restore + * + * Description: + * Restore the previous interrupt state (i.e., the one previously returned + * by up_irq_save()) + * + * NOTE: This function should never be called from application code and, + * as a general rule unless you really know what you are doing, this + * function should not be called directly from operation system code : + * Typically, the wrapper functions, leave_critical_section() is probably + * what you really want. + * + * Input Parameters: + * state - The interrupt state to be restored. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_irq_restore(irqstate_t irqtate); + +/**************************************************************************** + * Name: up_irq_enable + * + * Description: + * Enable interrupts + * + * Input Parameters: + * None. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_irq_enable(void); + +/**************************************************************************** + * Name: up_irq_disable + * + * Description: + * Disable interrupts + * + * Input Parameters: + * None. + * + * Returned Value: + * the entire PSR contents + * + ****************************************************************************/ + +uint32_t up_irq_disable(void); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY */ +#endif /* __ARCH_SPARC_INCLUDE_SPARC_V8_IRQ_H */ + diff --git a/arch/sparc/include/sparc_v8/syscall.h b/arch/sparc/include/sparc_v8/syscall.h new file mode 100644 index 00000000000..37eef4859ae --- /dev/null +++ b/arch/sparc/include/sparc_v8/syscall.h @@ -0,0 +1,195 @@ +/**************************************************************************** + * arch/sparc/include/sparc_v8/syscall.h + * + * 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 directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_SPARC_V8_SYSCALL_H +#define __ARCH_SPARC_INCLUDE_SPARC_V8_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SYS_syscall 0x80 + +/* Configuration ************************************************************/ + +/* SYS call 1 and 2 are defined for internal use by the RISC-V port (see + * arch/riscv/include/mips32/syscall.h). In addition, SYS call 3 is the + * return from a SYS call in kernel mode. The first four syscall values must + * therefore, be reserved (0 is not used). + */ + +#ifdef CONFIG_BUILD_KERNEL +# ifndef CONFIG_SYS_RESERVED +# error "CONFIG_SYS_RESERVED must be defined to the value 4" +# elif CONFIG_SYS_RESERVED != 4 +# error "CONFIG_SYS_RESERVED must have the value 4" +# endif +#endif + +/* sys_call macros **********************************************************/ + +#ifndef __ASSEMBLY__ + +/* Context switching system calls *******************************************/ + +/* SYS call 0: (not used) */ + +/* SYS call 1: + * + * void up_fullcontextrestore(uint32_t *restoreregs) noreturn_function; + */ + +#define SYS_restore_context (1) +#define up_fullcontextrestore(restoreregs) \ + (void)sys_call1(SYS_restore_context, (uintptr_t)restoreregs) + +/* SYS call 2: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + */ + +#define SYS_switch_context (2) +#define up_switchcontext(saveregs, restoreregs) \ + (void)sys_call2(SYS_switch_context, (uintptr_t)saveregs, (uintptr_t)restoreregs) + +#ifdef CONFIG_BUILD_KERNEL +/* SYS call 3: + * + * void up_syscall_return(void); + */ + +#define SYS_syscall_return (3) +#define up_syscall_return() (void)sys_call0(SYS_syscall_return) + +#endif +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: up_syscall0 + * + * Description: + * System call SYS_ argument and no additional parameters. + * + ****************************************************************************/ + +uintptr_t sys_call0(unsigned int nbr); + +/**************************************************************************** + * Name: up_syscall1 + * + * Description: + * System call SYS_ argument and one additional parameter. + * + ****************************************************************************/ + +uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1); + +/**************************************************************************** + * Name: up_syscall2 + * + * Description: + * System call SYS_ argument and two additional parameters. + * + ****************************************************************************/ + +uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, uintptr_t parm2); + +/**************************************************************************** + * Name: up_syscall3 + * + * Description: + * System call SYS_ argument and three additional parameters. + * + ****************************************************************************/ + +uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3); + +/**************************************************************************** + * Name: up_syscall4 + * + * Description: + * System call SYS_ argument and four additional parameters. + * + ****************************************************************************/ + +uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4); + +/**************************************************************************** + * Name: up_syscall5 + * + * Description: + * System call SYS_ argument and five additional parameters. + * + ****************************************************************************/ + +uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4, uintptr_t parm5); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_SPARC_INCLUDE_SPARC_V8_SYSCALL_H */ + diff --git a/arch/sparc/include/spinlock.h b/arch/sparc/include/spinlock.h new file mode 100644 index 00000000000..50f55b10f9a --- /dev/null +++ b/arch/sparc/include/spinlock.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/sparc/include/spinlock.h + * + * 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_SPARC_INCLUDE_SPINLOCK_H +#define __ARCH_SPARC_INCLUDE_SPINLOCK_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define SP_UNLOCKED 0 /* The Un-locked state */ +#define SP_LOCKED 1 /* The Locked state */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* The Type of a spinlock. + * + * This must be a uint32_ becaue it will be set using S32C1I instruction. + * That instruction atomically stores to a memory location only if its + * current value is the expected one. The state register (SCOMPARE1) is + * used to provide the additional comparison operand. Some implementations + * also have a state register (ATOMCTL) for further control of the atomic + * operation in cache and on the PIF bus. + */ + +typedef uint32_t spinlock_t; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: up_testset + * + * Description: + * Perform an atomic test and set operation on the provided spinlock. + * + * This function must be provided via the architecture-specific logic. + * + * Input Parameters: + * lock - The address of spinlock object. + * + * Returned Value: + * The spinlock is always locked upon return. The value of previous value + * of the spinlock variable is returned, either SP_LOCKED if the spinlock + * as previously locked (meaning that the test-and-set operation failed to + * obtain the lock) or SP_UNLOCKED if the spinlock was previously unlocked + * (meaning that we successfully obtained the lock) + * + ****************************************************************************/ + +/* See prototype in nuttx/include/nuttx/spinlock.h */ + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_INCLUDE_SPINLOCK_H */ diff --git a/arch/sparc/include/syscall.h b/arch/sparc/include/syscall.h new file mode 100644 index 00000000000..d45d462e80b --- /dev/null +++ b/arch/sparc/include/syscall.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * arch/sparc/include/syscall.h + * + * 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 directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_SYSCALL_H +#define __ARCH_SPARC_INCLUDE_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include ARM architecture-specific syscall macros */ + +#ifdef CONFIG_ARCH_SPARC_V8 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * 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_SPARC_INCLUDE_SYSCALL_H */ + diff --git a/arch/sparc/include/types.h b/arch/sparc/include/types.h new file mode 100644 index 00000000000..51555a9474f --- /dev/null +++ b/arch/sparc/include/types.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/sparc/include/types.h + * + * 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 sys/types.h + */ + +#ifndef __ARCH_SPARC_INCLUDE_TYPES_H +#define __ARCH_SPARC_INCLUDE_TYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* These are the sizes of the standard integer types. NOTE that these type + * names have a leading underscore character. This file will be included + * (indirectly) by include/stdint.h and typedef'ed to the final name without + * the underscore character. This roundabout way of doings things allows + * the stdint.h to be removed from the include/ directory in the event that + * the user prefers to use the definitions provided by their toolchain header + * files + */ + +typedef signed char _int8_t; +typedef unsigned char _uint8_t; + +typedef signed short _int16_t; +typedef unsigned short _uint16_t; + +typedef signed int _int32_t; +typedef unsigned int _uint32_t; + +typedef signed long long _int64_t; +typedef unsigned long long _uint64_t; +#define __INT64_DEFINED + +typedef _int64_t _intmax_t; +typedef _uint64_t _uintmax_t; + +#if defined(__WCHAR_TYPE__) +typedef __WCHAR_TYPE__ _wchar_t; +#else +typedef int _wchar_t; +#endif + +/* A size is 4 bytes */ + +#if defined(__SIZE_TYPE__) +/* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. + * We simply change "unsigned" to "signed" for this single definition + * to make sure ssize_t and size_t only differ by their signedness. + */ + +#define unsigned signed +typedef __SIZE_TYPE__ _ssize_t; +#undef unsigned +typedef __SIZE_TYPE__ _size_t; +#elif defined(CONFIG_ARCH_SIZET_LONG) +typedef signed long _ssize_t; +typedef unsigned long _size_t; +#else +typedef signed int _ssize_t; +typedef unsigned int _size_t; +#endif + +/* This is the size of the interrupt state save returned by up_irq_save(). */ + +typedef unsigned int irqstate_t; + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_SPARC_INCLUDE_TYPES_H */ diff --git a/arch/sparc/src/Makefile b/arch/sparc/src/Makefile new file mode 100644 index 00000000000..6965d107f55 --- /dev/null +++ b/arch/sparc/src/Makefile @@ -0,0 +1,173 @@ +############################################################################ +# arch/sparc/src/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs +-include chip/Make.defs + +ARCH_SUBDIR = sparc_v8 + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + ARCH_SRCDIR = $(TOPDIR)\arch\$(CONFIG_ARCH)\src + NUTTX = "$(TOPDIR)\nuttx$(EXEEXT)" + INCLUDES += -I "$(ARCH_SRCDIR)\chip" + INCLUDES += -I "$(ARCH_SRCDIR)\common" + INCLUDES += -I "$(ARCH_SRCDIR)\$(ARCH_SUBDIR)" + INCLUDES += -I "$(TOPDIR)\sched" +else + ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src +ifeq ($(WINTOOL),y) + NUTTX = "${shell cygpath -w $(TOPDIR)/nuttx$(EXEEXT)}" + INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" + INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" + INCLUDES += -I "${shell cygpath -w $(ARCH_SRCDIR)/$(ARCH_SUBDIR)}" + INCLUDES += -I "${shell cygpath -w $(TOPDIR)/sched}" +else + NUTTX = "$(TOPDIR)/nuttx$(EXEEXT)" + INCLUDES += -I "$(ARCH_SRCDIR)/chip" + INCLUDES += -I "$(ARCH_SRCDIR)/common" + INCLUDES += -I "$(ARCH_SRCDIR)/$(ARCH_SUBDIR)" + INCLUDES += -I "$(TOPDIR)/sched" +endif +endif + +CPPFLAGS += $(INCLUDES) $(EXTRADEFINES) +CFLAGS += $(INCLUDES) $(EXTRADEFINES) +CXXFLAGS += $(INCLUDES) $(EXTRADEFINES) +AFLAGS += $(INCLUDES) $(EXTRADEFINES) + +HEAD_OBJ = $(HEAD_ASRC:.S=$(OBJEXT)) +STARTUP_OBJS ?= $(HEAD_OBJ) + +ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +# Override in Make.defs if linker is not 'ld' + +LDSTARTGROUP ?= --start-group +LDENDGROUP ?= --end-group + +LDFLAGS += $(ARCHSCRIPT) +EXTRA_LIBS ?= +LINKLIBS ?= + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BOARDMAKE = $(if $(wildcard .\board\Makefile),y,) + LIBPATHS += -L"$(TOPDIR)\staging" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"$(TOPDIR)\arch\$(CONFIG_ARCH)\src\board" +endif + +else + BOARDMAKE = $(if $(wildcard ./board/Makefile),y,) + +ifeq ($(WINTOOL),y) + LIBPATHS += -L"${shell cygpath -w "$(TOPDIR)/staging"}" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"${shell cygpath -w "$(TOPDIR)/arch/$(CONFIG_ARCH)/src/board"}" +endif + +else + LIBPATHS += -L"$(TOPDIR)/staging" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"$(TOPDIR)/arch/$(CONFIG_ARCH)/src/board" +endif +endif +endif + +LDLIBS = $(patsubst %.a,%,$(patsubst lib%,-l%,$(LINKLIBS))) +ifeq ($(BOARDMAKE),y) + LDLIBS += -lboard +endif + +LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +VPATH = chip:common:$(ARCH_SUBDIR) + +all: $(HEAD_OBJ) libarch$(LIBEXT) + +.PHONY: board/libboard$(LIBEXT) + +$(AOBJS) $(HEAD_OBJ): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +libarch$(LIBEXT): $(OBJS) + $(call ARCHIVE, $@, $(OBJS)) + +board/libboard$(LIBEXT): + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" libboard$(LIBEXT) EXTRADEFINES=$(EXTRADEFINES) + +nuttx$(EXEEXT): $(HEAD_OBJ) board/libboard$(LIBEXT) + @echo "LD: nuttx" + $(Q) $(LD) --entry=__start $(LDFLAGS) $(LIBPATHS) -o $(NUTTX) $(HEAD_OBJ) $(EXTRA_OBJS) \ + $(LDSTARTGROUP) $(LDLIBS) $(EXTRA_LIBS) $(LIBGCC) $(LDENDGROUP) +ifneq ($(CONFIG_WINDOWS_NATIVE),y) + $(Q) $(NM) $(NUTTX) | \ + grep -v '\(compiled\)\|\(\$(OBJEXT)$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ + sort > $(TOPDIR)/System.map +endif + +# This is part of the top-level export target + +export_startup: board/libboard$(LIBEXT) $(STARTUP_OBJS) + $(Q) if [ -d "$(EXPORT_DIR)/startup" ]; then \ + cp -f $(STARTUP_OBJS) "$(EXPORT_DIR)/startup"; \ + else \ + echo "$(EXPORT_DIR)/startup does not exist"; \ + exit 1; \ + fi + +# Dependencies + +.depend: Makefile chip/Make.defs $(SRCS) +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" depend +endif + $(Q) $(MKDEP) --dep-path chip --dep-path common --dep-path $(ARCH_SUBDIR) \ + "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + $(Q) touch $@ + +depend: .depend + +context:: + +clean: +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" clean +endif + $(call DELFILE, libarch$(LIBEXT)) + $(call CLEAN) + +distclean: clean +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" distclean +endif + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/arch/sparc/src/bm3803/Kconfig b/arch/sparc/src/bm3803/Kconfig new file mode 100644 index 00000000000..50b8cf8818d --- /dev/null +++ b/arch/sparc/src/bm3803/Kconfig @@ -0,0 +1,123 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_BM3803 +comment "BM3803 Configuration Options" + +menu "BM3803 Peripheral Support" + +config BM3803_WDG + bool "Watchdog timer (WDT)" + default n + select WATCHDOG + + +config BM3803_TIM1 + bool "Timer 1 (T1)" + default n + +config BM3803_TIM2 + bool "Timer 2 (T2)" + default n + +config BM3803_UART1 + bool "UART1" + default n + select UART1_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config BM3803_UART2 + bool "UART2" + default n + select UART2_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config BM3803_UART3 + bool "UART3" + default n + select UART3_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +endmenu # BM3803 Peripheral Selections + +menuconfig BM3803_GPIOIRQ + bool "GPIO Interrupt Support" + default n + ---help--- + Build in support for interrupts based on GPIO inputs from IOPorts + +if BM3803_GPIOIRQ + +config BM3803_GPIOIRQ_PORT4 + bool "I/O PORT4 Interrupt Support" + default n + +config BM3803_GPIOIRQ_PORT5 + bool "I/O PORT5 Interrupt Support" + default n + +config BM3803_GPIOIRQ_PORT6 + bool "I/O PORT6 Interrupt Support" + default n +config BM3803_GPIOIRQ_PORT7 + bool "I/O PORT7 Interrupt Support" + default n + +endif # BM3803_GPIOIRQ + + +menu "Timer Configuration" + +if SCHED_TICKLESS + +config BM3803_ONESHOT + bool + default y + +config BM3803_FREERUN + bool + default y + +config BM3803_TICKLESS_ONESHOT + int "Tickless one-shot timer channel" + default 1 + range 1 2 + depends on BM3803_ONESHOT + ---help--- + If the Tickless OS feature is enabled, then one clock must be + assigned to provide the one-shot timer needed by the OS. + +config BM3803_TICKLESS_FREERUN + int "Tickless free-running timer channel" + default 2 + range 1 2 + depends on BM3803_FREERUN + ---help--- + If the Tickless OS feature is enabled, then one clock must be + assigned to provide the free-running timer needed by the OS. + +endif # SCHED_TICKLESS + +if !SCHED_TICKLESS + +config BM3803_ONESHOT + bool "TIM one-shot wrapper" + default n + ---help--- + Enable a wrapper around the low level timer/counter functions to + support one-shot timer. + +config BM3803_FREERUN + bool "TIM free-running wrapper" + default n + ---help--- + Enable a wrapper around the low level timer/counter functions to + support a free-running timer. + +endif # !SCHED_TICKLESS + +endmenu # Timer Configuration + +endif diff --git a/arch/sparc/src/bm3803/Make.defs b/arch/sparc/src/bm3803/Make.defs new file mode 100644 index 00000000000..0abec6ecd88 --- /dev/null +++ b/arch/sparc/src/bm3803/Make.defs @@ -0,0 +1,77 @@ +############################################################################ +# arch/sparc/src/bm3803/Make.defs +# +# 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 = bm3803_head.S + +# Common SPARC files + +CMN_ASRCS = up_syscall.S +CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c up_systemreset.c +CMN_CSRCS += up_createstack.c up_doirq.c up_exit.c up_idle.c up_initialize.c +CMN_CSRCS += up_initialstate.c up_interruptcontext.c up_irq.c up_lowputs.c +CMN_CSRCS += up_mdelay.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c +CMN_CSRCS += up_puts.c up_releasepending.c up_releasestack.c +CMN_CSRCS += up_reprioritizertr.c up_schedulesigaction.c up_sigdeliver.c +CMN_CSRCS += up_stackframe.c up_swint1.c up_udelay.c up_unblocktask.c up_usestack.c + +# Configuration-dependent common files + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_dumpstate.c +endif + +ifeq ($(CONFIG_STACK_COLORATION),y) +CMN_CSRCS += up_checkstack.c +endif + +# Required BM3803 files + +CHIP_ASRCS = bm3803_exceptions.S +CHIP_CSRCS = bm3803-lowconsole.c bm3803-lowinit.c bm3803-serial.c bm3803-irq.c bm3803_tim.c + +ifeq ($(CONFIG_TIMER),y) +CHIP_CSRCS += bm3803_tim_lowerhalf.c +endif + +ifeq ($(CONFIG_BM3803_WDG),y) +CHIP_CSRCS += bm3803_wdg.c +endif + +ifneq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += bm3803-timerisr.c +else +CHIP_CSRCS += bm3803_tickless.c +endif + +ifeq ($(CONFIG_BM3803_ONESHOT),y) +CHIP_CSRCS += bm3803_oneshot.c bm3803_oneshot_lowerhalf.c +endif + +ifeq ($(CONFIG_BM3803_FREERUN),y) +CHIP_CSRCS += bm3803_freerun.c +endif + +# Configuration-dependent files + +ifeq ($(CONFIG_BM3803_GPIOIRQ),y) +CHIP_CSRCS += bm3803_exti_gpio.c +endif diff --git a/arch/sparc/src/bm3803/bm3803-config.h b/arch/sparc/src/bm3803/bm3803-config.h new file mode 100644 index 00000000000..aaea4862627 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-config.h @@ -0,0 +1,101 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-config.h + * + * 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_SPARC_SRC_BM3803_CONFIG_H +#define __ARCH_SPARC_SRC_BM3803_CONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +#include "bm3803-memorymap.h" +#include "bm3803-uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SYS calls ****************************************************************/ + +/* SYS call 1 and 2 are defined for internal use by the BM3803 port (see + * arch/sparc/include/sparc32/syscall.h). In addition, SYS call 3 is the + * return from a SYS call in kernel mode. The first four syscall values + * must, therefore, be reserved (0 is not used). + */ + +#ifdef CONFIG_BUILD_KERNEL +# if !defined(CONFIG_SYS_RESERVED) || CONFIG_SYS_RESERVED < 4 +# error "CONFIG_SYS_RESERVED must be defined to be 4 for a kernel build" +# elif CONFIG_SYS_RESERVED > 4 +# warning "CONFIG_SYS_RESERVED should be defined to be 4 for a kernel build" +# endif +#endif + +/* UARTs ********************************************************************/ + +/* Don't enable UARTs not supported by the chip. */ + +#if CHIP_NUARTS < 1 +# undef CONFIG_BM3803_UART1 +# undef CONFIG_BM3803_UART2 +# undef CONFIG_BM3803_UART3 +#elif CHIP_NUARTS < 2 +# undef CONFIG_BM3803_UART2 +# undef CONFIG_BM3803_UART3 +#elif CHIP_NUARTS < 3 +# undef CONFIG_BM3803_UART3 +#endif + +/* Are any UARTs enabled? */ + +#undef HAVE_UART_DEVICE +#if defined(CONFIG_BM3803_UART1) || defined(CONFIG_BM3803_UART2) || defined(CONFIG_BM3803_UART3) +# define HAVE_UART_DEVICE 1 +#endif + +/* Is there a serial console? There should be no more than one defined. It + * could be on any UARTn, n=1,.. CHIP_NUARTS + */ + +#if defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_BM3803_UART1) +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_BM3803_UART2) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_BM3803_UART3) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#else +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef HAVE_SERIAL_CONSOLE +#endif + +#endif /* __ARCH_SPARC_SRC_BM3803_CONFIG_H */ diff --git a/arch/sparc/src/bm3803/bm3803-irq.c b/arch/sparc/src/bm3803/bm3803-irq.c new file mode 100644 index 00000000000..cb5ae27254f --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-irq.c @@ -0,0 +1,321 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-irq.c + * + * 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 + +#include "up_arch.h" +#include "up_internal.h" + +#include "bm3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t *g_current_regs; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_IRQPRIO +static int up_prioritize_irq(int irq, int priority); +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + int irq; + + for (irq = 1; irq < NR_IRQS; irq++) + { + /* Skip window overflow, underflow, and flush as well as software + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ + * enable.Also avoid trap 0x70 - 0x7f which cannot happen and where + * some of the space is used to pass parameters to the program. + */ + + if (((irq >= 0x00) && (irq <= 0x11)) || + ((irq >= 0x20) && (irq <= 0xff))) + { + continue; + } + + /* Set all interrupts to the default (low) priority */ + + up_prioritize_irq(irq, 0); + + /* Disable all interrupts */ + + up_disable_irq(irq); + } + + /* Attach software interrupts */ + + irq_attach(BM3803_IRQ_SW_SYSCALL_TA0, up_swint0, NULL); + irq_attach(BM3803_IRQ_SW_SYSCALL_TA8, up_swint1, NULL); + + /* currents_regs is non-NULL only while processing an interrupt */ + + g_current_regs = NULL; + + /* And finally, enable interrupts */ + + /* Interrupts are enabled by setting the te bit in the psr status + * register + */ + + up_irq_enable(); +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + int bitno; + + /* Disable the interrupt by clearing the associated bit in the IEC + * register + */ + + DEBUGASSERT(irq >= BM3803_IRQ_FIRST_INTERRUPT && + irq <= BM3803_IRQ_LAST_INTERRUPT); + if (irq >= BM3803_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3803_IRQ_LAST_INTERRUPT) + { + /* Disable the interrupt */ + + bitno = irq - BM3803_IRQ_FIRST_INTERRUPT + 1; + BM3803_REG.int_mask &= (~(1 << bitno)); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + int bitno; + + /* Enable the interrupt by setting the associated bit in the Interrupt_Mask + * Register + */ + + DEBUGASSERT(irq >= BM3803_IRQ_FIRST_INTERRUPT && + irq <= BM3803_IRQ_LAST_INTERRUPT); + if (irq >= BM3803_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3803_IRQ_LAST_INTERRUPT) + { + /* Enable the interrupt */ + + bitno = irq - BM3803_IRQ_FIRST_INTERRUPT + 1; + BM3803_REG.int_mask |= (1 << bitno); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_pending_irq + * + * Description: + * Return true if the interrupt is pending and unmasked. + * + ****************************************************************************/ + +bool up_pending_irq(int irq) +{ + int bitno; + uint16_t regval; + uint16_t regval1; + uint16_t regval2; + + /* Test if the interrupt is pending by reading both the IEC and IFS + * register. Return true if the bit associated with the irq is both pending + * the IFs and enabled in the IEC. + */ + + DEBUGASSERT(irq >= BM3803_IRQ_FIRST_INTERRUPT && + irq <= BM3803_IRQ_LAST_INTERRUPT); + if (irq >= BM3803_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3803_IRQ_LAST_INTERRUPT) + { + /* Get the set of unmasked, pending interrupts. */ + + regval1 = BM3803_REG.int_mask; + regval2 = BM3803_REG.int_pend; + regval = regval1 & regval2; + } + else + { + /* Value out of range.. just ignore */ + + return false; + } + + /* Return true if the interrupt is pending and unmask. */ + + bitno = irq - BM3803_IRQ_FIRST_INTERRUPT + 1; + return (regval & (1 << bitno)) != 0; + } + + return false; +} + +/**************************************************************************** + * Name: up_clrpend_irq + * + * Description: + * Clear any pending interrupt + * + ****************************************************************************/ + +void up_clrpend_irq(int irq) +{ + int bitno; + /* Acknowledge the interrupt by clearing the associated bit in the ITP + * register. It is necessary to do this BEFORE lowering the interrupt + * priority level otherwise recursive interrupts would occur. + */ + + DEBUGASSERT(irq >= BM3803_IRQ_FIRST_INTERRUPT && + irq <= BM3803_IRQ_LAST_INTERRUPT); + if (irq >= BM3803_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3803_IRQ_LAST_INTERRUPT) + { + /* written with a ‘1’, in Interrupt Clear Register + * will clear the corresponding bit(s) in the interrupt pending + * register + */ + + bitno = irq - BM3803_IRQ_FIRST_INTERRUPT + 1; + BM3803_REG.int_clear |= (1 << bitno); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * It is possible to change the priority level of an interrupt using the two + * priority levels from the interrupt mask and priority register (ITMP). + * Each interrupt can be assigned to one of two levels as programmed in the + * Interrupt mask and priority register. Level 1 has higher priority than + * level 0. Within each level the interrupts are prioritised + ****************************************************************************/ + +#ifndef CONFIG_ARCH_IRQPRIO +static +#endif +int up_prioritize_irq(int irq, int priority) +{ + int bitno; + int shift; + + /* Don't allow this function to be used for disabling interrupts. */ + + DEBUGASSERT((unsigned)irq < NR_IRQS && (unsigned)(priority) < 2); + if (irq >= BM3803_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3803_IRQ_LAST_INTERRUPT) + { + bitno = irq - BM3803_IRQ_FIRST_INTERRUPT + 1; + shift = bitno + 16; + + /* Set the new interrupt priority (momentarily disabling + * interrupts) + */ + + BM3803_REG.int_mask &= (~(1 << shift)); + BM3803_REG.int_mask |= (priority << shift); + } + else + { + /* Value out of range.. just ignore */ + + return -EINVAL; + } + } + + return OK; +} diff --git a/arch/sparc/src/bm3803/bm3803-lowconsole.c b/arch/sparc/src/bm3803/bm3803-lowconsole.c new file mode 100644 index 00000000000..1e090d88c84 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-lowconsole.c @@ -0,0 +1,307 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-lowconsole.c + * + * 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 "bm3803-config.h" + +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "bm3803-uart.h" +#include "bm3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usart0_reset and usart1_reset + * + * Description: + * Reset USART0 or USART1. + * + ****************************************************************************/ + +#ifdef CONFIG_BM3803_UART1 +void uart1_reset(void) +{ + /* Clear USART configuration */ + + uart1_disable(); + uart1_parity_config(NONE); + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); +} +#endif + +#ifdef CONFIG_BM3803_UART2 +void uart2_reset(void) +{ + /* Clear USART configuration */ + + uart2_disable(); + uart2_parity_config(NONE); + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); +} +#endif + +#ifdef CONFIG_BM3803_UART3 +void uart3_reset(void) +{ + /* Clear USART configuration */ + + uart3_disable(); + uart3_parity_config(NONE); + uart3_flow_ctrl_config(OFF); + uart3_loopback_config(OFF); +} +#endif + +/**************************************************************************** + * Name: bm3803_uartconfigure + * + * Description: + * Configure a UART as a console. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void bm3803_uartconfigure(uintptr_t uart_base, uint32_t baudrate, + unsigned int parity, unsigned int nbits, + bool stop2) +{ + if (uart_base == BM3803_UART1_BASE) + { + /* Select baud. */ + + uart1_set_baudrate(baudrate); + + /* Select parity */ + + if (parity == 1) + { + uart1_parity_config(ODD); /* Odd parity */ + } + else if (parity == 2) + { + uart1_parity_config(EVEN); /* Even parity */ + } + else + { + uart1_parity_config(NONE); /* Even none */ + } + + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); + + uart1_enable(); + } + else if (uart_base == BM3803_UART2_BASE) + { + /* Select baud. */ + + uart2_set_baudrate(baudrate); + + /* Select parity */ + + if (parity == 1) + { + uart2_parity_config(ODD); /* Odd parity */ + } + else if (parity == 2) + { + uart2_parity_config(EVEN); /* Even parity */ + } + else + { + uart2_parity_config(NONE); /* Even none */ + } + + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); + + uart2_enable(); + } + else + { + return; + } +} +#endif + +#ifdef CONFIG_BM3803_UART1 +void uart1_configure(void) +{ + /* Select baud. */ + + uart1_set_baudrate(CONFIG_UART1_BAUD); + + /* Select parity */ + +#if CONFIG_UART1_PARITY == 1 + uart1_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART1_PARITY == 2 + uart1_parity_config(EVEN); /* Even parity */ +#else + uart1_parity_config(NONE); /* Even none */ +#endif + + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); + + uart1_enable(); +} +#endif + +#ifdef CONFIG_BM3803_UART2 +void uart2_configure(void) +{ + /* Select baud. */ + + uart2_set_baudrate(CONFIG_UART2_BAUD); + + /* Select parity */ + +#if CONFIG_UART2_PARITY == 1 + uart2_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART2_PARITY == 2 + uart2_parity_config(EVEN); /* Even parity */ +#else + uart2_parity_config(NONE); /* Even none */ +#endif + + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); + + uart2_enable(); +} +#endif + +#ifdef CONFIG_BM3803_UART3 +void uart3_configure(void) +{ + /* Select baud. */ + + uart3_set_baudrate(CONFIG_UART3_BAUD); + + /* Select parity */ + +#if CONFIG_UART3_PARITY == 1 + uart2_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART3_PARITY == 2 + uart3_parity_config(EVEN); /* Even parity */ +#else + uart3_parity_config(NONE); /* Even none */ +#endif + + uart3_flow_ctrl_config(OFF); + uart3_loopback_config(OFF); + + uart3_enable(); +} +#endif + +/**************************************************************************** + * 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) +{ +#ifdef HAVE_SERIAL_CONSOLE +#if defined(CONFIG_UART1_SERIAL_CONSOLE) + uart1_configure(); +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) + uart2_configure(); +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) + uart3_configure(); +#endif +#endif +} + +/**************************************************************************** + * Name: up_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void up_lowputc(char ch) +{ +#ifdef HAVE_SERIAL_CONSOLE +#if defined(CONFIG_UART1_SERIAL_CONSOLE) + while (!uart1_tx_ready()) + { + } + + uart1_send_byte(ch); +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) + while (!uart2_tx_ready()) + { + } + + uart2_send_byte(ch); +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) + while (!uart3_tx_ready()) + { + } + + uart3_send_byte(ch); +#endif +#endif +} diff --git a/arch/sparc/src/bm3803/bm3803-lowinit.c b/arch/sparc/src/bm3803/bm3803-lowinit.c new file mode 100644 index 00000000000..c125879ba5a --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-lowinit.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-lowinit.c + * + * 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 "bm3803-config.h" +#include "up_internal.h" +#include "bm3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) up_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowinit + * + * Description: + * This performs basic initialization of the USART used for the serial + * console. Its purpose is to get the console output available as soon + * as possible. + * + ****************************************************************************/ + +void up_lowinit(void) +{ + uint32_t *dest; + + /* Initialize a console (probably a serial console) */ + + up_consoleinit(); + + showprogress('A'); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_bss_start; dest < &_end; ) + { + *dest++ = 0; + } + + showprogress('B'); + /* Perform early serial initialization (so that we will have debug output + * available as soon as possible). + */ + +#ifdef USE_EARLYSERIALINIT + up_earlyserialinit(); +#endif + + /* Perform board-level initialization */ + + bm3803_boardinitialize(); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); +} diff --git a/arch/sparc/src/bm3803/bm3803-memorymap.h b/arch/sparc/src/bm3803/bm3803-memorymap.h new file mode 100644 index 00000000000..1cacd58a52d --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-memorymap.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-memorymap.h + * + * 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_SPARC_SRC_BM3803_BM3803_MEMORYMAP_H +#define __ARCH_SPARC_SRC_BM3803_BM3803_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + # define BM3803_REG_BASE 0x80000000 + +/* UART 1-3 Register Base Addresses */ +# define BM3803_UART1_BASE (BM3803_REG_BASE + 0x70) +# define BM3803_UART2_BASE (BM3803_REG_BASE + 0x80) +# define BM3803_UART3_BASE (BM3803_REG_BASE + 0xE0) + +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_MEMORYMAP_H */ + diff --git a/arch/sparc/src/bm3803/bm3803-serial.c b/arch/sparc/src/bm3803/bm3803-serial.c new file mode 100644 index 00000000000..81216543ec1 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-serial.c @@ -0,0 +1,955 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-serial.c + * + * 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 +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "bm3803-config.h" +#include "chip.h" +#include "bm3803-uart.h" +#include "bm3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#ifdef USE_SERIALDRIVER + +/* Which UART with be tty0/console and which tty1? The console will always + * be ttyS0. If there is no console then will use the lowest numbered UART. + */ + +#ifdef HAVE_SERIAL_CONSOLE + +# if defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3803_UART2) +# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */ +# elif defined(CONFIG_BM3803_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart2port /* UART2 is console */ +# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */ +# if defined(CONFIG_BM3803_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart3port /* UART3 is console */ +# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */ +# undef TTYS1_DEV /* No ttyS1 */ +# else +# error "I'm confused... Do we have a serial console or not?" +# endif +#else +# undef CONSOLE_DEV /* No console */ +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# if defined(CONFIG_BM3803_UART1) +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3803_UART2) +# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */ +# elif defined(CONFIG_BM3803_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_BM3803_UART2) +# define TTYS0_DEV g_uart2port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3803_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_BM3803_UART3) +# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */ +# undef TTYS1_DEV /* No ttyS1 */ +# else +# undef TTYS0_DEV +# undef TTYS0_DEV +# endif +#endif + +/* Common initialization logic will not not know that the all of the UARTs + * have been disabled. So, as a result, we may still have to provide + * stub implementations of up_earlyserialinit(), up_serialinit(), and + * up_putc(). + */ + +#ifdef HAVE_UART_DEVICE + +/* These values describe the set of enabled interrupts */ + +#define RX_ENABLED(im) (((im) & MSK_UART_ENABLE_RX) != 0) +#define TX_ENABLED(im) (((im) & MSK_UART_ENABLE_TX) != 0) + +#define ENABLE_RX(im) do { (im) |= MSK_UART_ENABLE_RX; } while (0) +#define ENABLE_TX(im) do { (im) |= MSK_UART_ENABLE_TX; } while (0) + +#define DISABLE_RX(im) do { (im) &= ~MSK_UART_ENABLE_RX; } while (0) +#define DISABLE_TX(im) do { (im) &= ~MSK_UART_ENABLE_TX; } while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + uintptr_t uartbase; /* Base address of UART registers */ + uint32_t baud; /* Configured baud */ + uint8_t irq; /* IRQ associated with this UART (for attachment) */ + uint8_t im; /* Interrupt mask state */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (5, 6, 7 or 8) */ + bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Low-level helpers */ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset); +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value); +static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im); +static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im); + +/* Serial driver methods */ + +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(struct uart_dev_s *dev); +static int up_attach(struct uart_dev_s *dev); +static void up_detach(struct uart_dev_s *dev); +static int up_interrupt(int irq, void *context, void *arg); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); +static int up_receive(struct uart_dev_s *dev, uint32_t *status); +static void up_rxint(struct uart_dev_s *dev, bool enable); +static bool up_rxavailable(struct uart_dev_s *dev); +static void up_send(struct uart_dev_s *dev, int ch); +static void up_txint(struct uart_dev_s *dev, bool enable); +static bool up_txready(struct uart_dev_s *dev); +static bool up_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txempty, +}; + +/* I/O buffers */ + +#ifdef CONFIG_BM3803_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_BM3803_UART2 +static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE]; +static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE]; +#endif +#ifdef CONFIG_BM3803_UART3 +static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE]; +#endif + +/* This describes the state of the BM3803 UART1 port. */ + +#ifdef CONFIG_BM3803_UART1 +static struct up_dev_s g_uart1priv = +{ + .uartbase = BM3803_UART1_BASE, + .baud = CONFIG_UART1_BAUD, + .irq = BM3803_IRQ_UART_1_RX_TX, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, +}; + +static uart_dev_t g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +/* This describes the state of the BM3803 UART2 port. */ + +#ifdef CONFIG_BM3803_UART2 +static struct up_dev_s g_uart2priv = +{ + .uartbase = BM3803_UART2_BASE, + .baud = CONFIG_UART2_BAUD, + .irq = BM3803_IRQ_UART_2_RX_TX, + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, +}; + +static uart_dev_t g_uart2port = +{ + .recv = + { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +/* This describes the state of the BM3803 UART3 port. */ + +#ifdef CONFIG_BM3803_UART3 +static struct up_dev_s g_uart3priv = +{ + .uartbase = BM3803_UART3_BASE, + .baud = CONFIG_UART3_BAUD, + .irq = BM3803_IRQ_UART_3_RX_TX, + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stopbits2 = CONFIG_UART3_2STOP, +}; + +static uart_dev_t g_uart3port = +{ + .recv = + { + .head = 0, + .tail = 0, + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .head = 0, + .tail = 0, + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart3priv, +}; +#endif +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg32(priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_setuartint + ****************************************************************************/ + +static inline void up_setuartint(struct up_dev_s *priv) +{ + uint8_t regval; + + regval = up_serialin(priv, BM3803_UART_CTRLREG_OFFSET); + regval &= ~MSK_UART_ALLINTS; + regval |= priv->im; + up_serialout(priv, BM3803_UART_CTRLREG_OFFSET, regval); +} + +/**************************************************************************** + * Name: up_restoreuartint + ****************************************************************************/ + +static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im) +{ + irqstate_t flags; + + /* Re-enable/re-disable interrupts corresponding to the state of bits + * in im + */ + + flags = enter_critical_section(); + up_rxint(dev, RX_ENABLED(im)); + up_txint(dev, TX_ENABLED(im)); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_disableuartint + ****************************************************************************/ + +static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (im) + { + *im = priv->im; + } + + up_restoreuartint(dev, 0); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_UART_CONFIG + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Configure the UART as an RS-232 UART */ + + bm3803_uartconfigure(priv->uartbase, priv->baud, priv->parity, + priv->bits, priv->stopbits2); +#endif + +#ifdef CONFIG_ARCH_IRQPRIO + /* Set up the interrupt priority */ + + up_prioritize_irq(priv->irq, priv->irqprio); +#endif + + return OK; +} + +/**************************************************************************** + * Name: up_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void up_shutdown(struct uart_dev_s *dev) +{ + /* struct up_dev_s *priv = (struct up_dev_s *)dev->priv; */ + + /* Disable interrupts */ + + up_disableuartint(dev, NULL); + + /* Reset hardware and disable Rx and Tx */ + + /* bm3803_uartreset(priv->uartbase); */ +} + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method is + * called when the serial port is opened. Normally, this is just after the + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are + * called. + * + ****************************************************************************/ + +static int up_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, up_interrupt, dev); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ + + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The exception + * is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void up_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Disable interrupts */ + + up_disableuartint(dev, NULL); + + /* Detach from the interrupt */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * approprite uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int up_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv; + uint32_t mis; + int passes; + bool handled; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + priv = (struct up_dev_s *)dev->priv; + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + handled = true; + for (passes = 0; passes < 256 && handled; passes++) + { + handled = false; + + /* Get the masked UART status and clear the pending interrupts. */ + + mis = up_serialin(priv, BM3803_UART_STATREG_OFFSET); + + /* Handle incoming, receive bytes */ + + if ((mis & MSK_UART_DATA_READY) != 0) + { + /* Rx buffer not empty ... process incoming bytes */ + + uart_recvchars(dev); + handled = true; + } + + /* Handle outgoing, transmit bytes */ + + if ((mis & MSK_UART_TXH_READY) != 0) + { + /* Tx FIFO not full ... process outgoing bytes */ + + /* if (dev->xmit.head != dev->xmit.tail) + * { + */ + + uart_xmitchars(dev); + handled = true; + + /* } */ + } + } + + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#ifdef CONFIG_SERIAL_TERMIOS + struct inode *inode; + struct uart_dev_s *dev; + struct up_dev_s *priv; + int ret = OK; + + DEBUGASSERT(filep, filep->f_inode); + inode = filep->f_inode; + dev = inode->i_private; + + DEBUGASSERT(dev, dev->priv); + priv = (struct up_dev_s *)dev->priv; + + switch (cmd) + { + case xxx: /* Add commands here */ + break; + + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Other termios fields are not yet returned. + * Note that only cfsetospeed is not necessary because we have + * knowledge that only one speed is supported. + */ + + cfsetispeed(termiosp, priv->baud); + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Handle other termios settings. + * Note that only cfgetispeed is used besued we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + bm3803_uartconfigure(priv->uartbase, priv->baud, priv->parity, + priv->bits, priv->stopbits2); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +#else + return -ENOTTY; +#endif +} + +/**************************************************************************** + * Name: up_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int up_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return status information */ + + if (status) + { + *status = 0; /* We are not yet tracking serial errors */ + } + + /* Then return the actual received byte */ + + return (int)(up_serialin(priv, BM3803_UART_RXREG_OFFSET) & + UART_RXREG_MASK); +} + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void up_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + if (enable) + { + /* Receive an interrupt when their is anything in the Rx FIFO (or an Rx + * timeout occurs. + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= MSK_UART_ENABLE_RXIT; +#endif + } + else + { + priv->im &= ~MSK_UART_ENABLE_RXIT; + } + + up_setuartint(priv); +} + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return true is data is available in the receive data buffer */ + + return (up_serialin(priv, BM3803_UART_STATREG_OFFSET) & + MSK_UART_DATA_READY) != 0; +} + +/**************************************************************************** + * Name: up_send + * + * Description: + * This method will send one byte on the UART. + * + ****************************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + up_serialout(priv, BM3803_UART_TXREG_OFFSET, (uint32_t)ch); +} + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void up_txint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Set to receive an interrupt when the TX data register is empty */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= MSK_UART_ENABLE_TXIT; + up_setuartint(priv); + + /* Fake a TX interrupt */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + priv->im &= ~MSK_UART_ENABLE_TXIT; + up_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return TRUE if the Transmit buffer register is not full */ + + return (up_serialin(priv, BM3803_UART_STATREG_OFFSET) & + MSK_UART_TXH_READY) != 0; +} + +/**************************************************************************** + * Name: up_txempty + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool up_txempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return TRUE if the Transmit shift register is empty */ + + return (up_serialin(priv, BM3803_UART_STATREG_OFFSET) & + MSK_UART_TXS_READY) != 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before up_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in up_consoleinit() and main clock iniialization + * performed in up_clkinitialize(). + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ + /* Disable interrupts from all UARTS. The console is enabled in + * bm3803_consoleinit(). + */ + + up_disableuartint(&TTYS0_DEV, NULL); +#ifdef TTYS1_DEV + up_disableuartint(&TTYS1_DEV, NULL); +#endif + + /* Configuration whichever one is the console */ + +#ifdef HAVE_SERIAL_CONSOLE + CONSOLE_DEV.isconsole = true; + up_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ + /* Register the console */ + +#ifdef HAVE_SERIAL_CONSOLE + (void)uart_register("/dev/console", &CONSOLE_DEV); +#endif + + /* Register all UARTs */ + + (void)uart_register("/dev/ttyS0", &TTYS0_DEV); +#ifdef TTYS1_DEV + (void)uart_register("/dev/ttyS1", &TTYS1_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_SERIAL_CONSOLE + struct uart_dev_s *dev = (struct uart_dev_s *)&CONSOLE_DEV; + uint8_t imr = 0; + + up_disableuartint(dev, &imr); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + up_restoreuartint(dev, imr); +#endif + return ch; +} + +/**************************************************************************** + * Name: up_earlyserialinit, up_serialinit, and up_putc + * + * Description: + * stubs that may be needed. These stubs would be used if all UARTs are + * disabled. In that case, the logic in common/up_initialize() is not + * smart enough to know that there are not UARTs and will still expect + * these interfaces to be provided. + * + ****************************************************************************/ +#else /* HAVE_UART_DEVICE */ +void up_earlyserialinit(void) +{ +} + +void up_serialinit(void) +{ +} + +int up_putc(int ch) +{ + return ch; +} + +#endif /* HAVE_UART_DEVICE */ +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_SERIAL_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ + diff --git a/arch/sparc/src/bm3803/bm3803-timerisr.c b/arch/sparc/src/bm3803/bm3803-timerisr.c new file mode 100644 index 00000000000..d5845366e9b --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-timerisr.c @@ -0,0 +1,138 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-timerisr.c + * + * 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 "up_internal.h" +#include "up_arch.h" + +#include "bm3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The CPU frequency is given by BOARD_CPU_CLOCK (defined in board.h). The + * desired interrupt frequency is given by CONFIG_USEC_PER_TICK. An unscaled + * ideal match is given by: + * + * CLOCK = CPU_CLOCK / DIVISOR # CPU clocks/sec + * MATCH = CLOCK / CLOCKS_PER_SEC # CPU clocks/timer tick + * MATCH = CPU_CLOCK / DIVISOR / CLOCKS_PER_SEC # CPU clocks/timer tick + * + * But we only have 16-bits of accuracy so we need to pick the smallest + * divisor using the following brute force calculation: + */ +#define BM3803_TIMER_CLOCK 1000000 +#define MATCH1 (( 1000000 / CLOCKS_PER_SEC) - 1) + +/* Bit 0: enables the timer when set */ +#define TIMCTR_ENABLE_COUNTER (1 << 0) + +/* Bit 1: automatically reloaded with the reload value after each underflow */ +#define TIMCTR_AUTO_RELOAD (1 << 1) + +/* Bit 2: Set 1, will load the timer reload register into the timer counter + * register + */ + +#define TIMCTR_LOAD_COUNTER (1 << 2) + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: bm3803_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int bm3803_timerisr(int irq, uint32_t *regs, FAR void *arg) +{ + /* Clear the pending timer interrupt */ + + up_clrpend_irq(BM3803_IRQ_TIMER1); + + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize the timer + * interrupt. NOTE: This function depends on setup of OSC32 by + * up_clkinitialize(). + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + BM3803_REG.scaler_load = (BOARD_CPU_CLOCK / BM3803_TIMER_CLOCK) - 1; + BM3803_REG.scaler_cnt = (BOARD_CPU_CLOCK / BM3803_TIMER_CLOCK) - 1; + + /* Setup timer 1 compare match A to generate a tick interrupt. + * + * First, setup the match value for compare match A. + */ + + BM3803_REG.timer_cnt1 = (uint32_t)MATCH1; + BM3803_REG.timer_load1 = (uint32_t)MATCH1; + + BM3803_REG.timer_ctrl1 = (TIMCTR_ENABLE_COUNTER | TIMCTR_AUTO_RELOAD | + TIMCTR_LOAD_COUNTER); + + /* Configure the timer interrupt */ + + up_clrpend_irq(BM3803_IRQ_TIMER1); +#ifdef CONFIG_ARCH_IRQPRIO + (void)up_prioritize_irq(BM3803_IRQ_TIMER1, CONFIG_BM3803_TIMER1PRIO); +#endif + + /* Attach the timer interrupt vector */ + + (void)irq_attach(BM3803_IRQ_TIMER1, (xcpt_t)bm3803_timerisr, NULL); + + /* And enable the timer interrupt */ + + up_enable_irq(BM3803_IRQ_TIMER1); +} diff --git a/arch/sparc/src/bm3803/bm3803-uart.h b/arch/sparc/src/bm3803/bm3803-uart.h new file mode 100644 index 00000000000..e93622ac5bc --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803-uart.h @@ -0,0 +1,235 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803-uart.h + * + * 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_SPARC_SRC_BM3803_BM3803_UART_H +#define __ARCH_SPARC_SRC_BM3803_BM3803_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *************************************************^*******/ +#define BM3803_UART_TXREG_OFFSET 0x0000 /* UARTx transmit register */ +#define BM3803_UART_RXREG_OFFSET 0x0000 /* UARTx receive register */ +#define BM3803_UART_STATREG_OFFSET 0x0004 /* UARTx status register */ +#define BM3803_UART_CTRLREG_OFFSET 0x0008 /* UARTx control register */ +#define BM3803_UART_SCALREG_OFFSET 0x000c /* UARTx scaler register */ + +/* Register Addresses *******************************************************/ +#if CHIP_NUARTS > 0 +#define BM3803_UART1_TXREG (BM3803_UART1_BASE+BM3803_UART_TXREG_OFFSET) +#define BM3803_UART1_RXREG (BM3803_UART1_BASE+BM3803_UART_RXREG_OFFSET) +#define BM3803_UART1_STATREG (BM3803_UART1_BASE+BM3803_UART_STATREG_OFFSET) +#define BM3803_UART1_CTRLREG (BM3803_UART1_BASE+BM3803_UART_CTRLREG_OFFSET) +#define BM3803_UART1_SCALREG (BM3803_UART1_BASE+BM3803_UART_SCALREG_OFFSET) +#endif + +#if CHIP_NUARTS > 1 +#define BM3803_UART2_TXREG (BM3803_UART2_BASE+BM3803_UART_TXREG_OFFSET) +#define BM3803_UART2_RXREG (BM3803_UART2_BASE+BM3803_UART_RXREG_OFFSET) +#define BM3803_UART2_STATREG (BM3803_UART2_BASE+BM3803_UART_STATREG_OFFSET) +#define BM3803_UART2_CTRLREG (BM3803_UART2_BASE+BM3803_UART_CTRLREG_OFFSET) +#define BM3803_UART2_SCALREG (BM3803_UART2_BASE+BM3803_UART_SCALREG_OFFSET) +#endif + +#if CHIP_NUARTS > 2 +#define BM3803_UART3_TXREG (BM3803_UART3_BASE+BM3803_UART_TXREG_OFFSET) +#define BM3803_UART3_RXREG (BM3803_UART3_BASE+BM3803_UART_RXREG_OFFSET) +#define BM3803_UART3_STATREG (BM3803_UART3_BASE+BM3803_UART_STATREG_OFFSET) +#define BM3803_UART3_CTRLREG (BM3803_UART3_BASE+BM3803_UART_CTRLREG_OFFSET) +#define BM3803_UART3_SCALREG (BM3803_UART3_BASE+BM3803_UART_SCALREG_OFFSET) +#endif + +/* Register Bit-Field Definitions *******************************************/ + +#define ODD 1 +#define EVEN 0 +#define ON 1 +#define OFF 0 +#define NONE 2 +#define RX 0 +#define TX 1 +#define RXTX 3 + +/** Uart control list - Mask */ + +#define MSK_UART_ENABLE_RX 0x01 +#define MSK_UART_ENABLE_TX 0x02 +#define MSK_UART_ENABLE_RXIT 0x04 +#define MSK_UART_ENABLE_TXIT 0x08 +#define MSK_UART_ENABLE_PAR 0x20 +#define MSK_UART_PAR 0x10 +#define MSK_UART_ENABLE_FLOW 0x40 +#define MSK_UART_LOOPBACK 0x80 +#define MSK_UART_CLOCK 0x100 +#define MSK_UART_ALLINTS 0x0C + +#define MSK_UART_DATA_READY 0x01 +#define MSK_UART_TXS_READY 0x02 +#define MSK_UART_TXH_READY 0x04 +#define MSK_UART_BREAK 0x08 +#define MSK_UART_OVERRUN 0x10 +#define MSK_UART_PAR_ERR 0x20 +#define MSK_UART_FRAME_ERR 0x40 + +/* UARTx transmit register */ + +#define UART_TXREG_MASK 0xff + +/* UARTx receive register */ + +#define UART_RXREG_MASK 0xff + +/* UARTx baud rate register */ + +#define UART_BRG_MASK 0xfff + +#define uart1_set_baudrate(baudrate) (BM3803_REG.uart_scaler1 = (uint32_t)((((BOARD_CPU_CLOCK*10)/(baudrate * 8))-5)/10)) + +#define uart1_parity_config(uart_parity) ( uart_parity == ODD \ + ? (BM3803_REG.uart_ctrl1 = ((BM3803_REG.uart_ctrl1 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (BM3803_REG.uart_ctrl1 = ((BM3803_REG.uart_ctrl1 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (BM3803_REG.uart_ctrl1 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define Uart_interrupt_config(uart_its) ( uart_its == RXTX \ + ? (UART_CONTROL |= (MSK_UART_ENABLE_RXIT | MSK_UART_ENABLE_TXIT))\ + : ( uart_its == RX \ + ? (UART_CONTROL |= (MSK_UART_ENABLE_RXIT & ~MSK_UART_ENABLE_TXIT))\ + : ( uart_its == TX \ + ? (UART_CONTROL |= (MSK_UART_ENABLE_TXIT & ~MSK_UART_ENABLE_RXIT))\ + : (UART_CONTROL &= ~(MSK_UART_ENABLE_RXIT | MSK_UART_ENABLE_TXIT))\ + ) \ + ) \ + ) + +#define uart1_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (BM3803_REG.uart_ctrl1 |= MSK_UART_ENABLE_FLOW) \ + : (BM3803_REG.uart_ctrl1 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart1_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (BM3803_REG.uart_ctrl1 |= MSK_UART_LOOPBACK) \ + : (BM3803_REG.uart_ctrl1 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart1_enable() (BM3803_REG.uart_ctrl1 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart1_disable() (BM3803_REG.uart_ctrl1 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart1_tx_ready() ((BM3803_REG.uart_status1 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart1_rx_ready() ((BM3803_REG.uart_status1 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart1_send_byte(ch) (BM3803_REG.uart_data1 = ch) + +#define uart2_set_baudrate(baudrate) (BM3803_REG.uart_scaler2 = (((BOARD_CPU_CLOCK*10)/(baudrate*8))-5)/10) + +#define uart2_parity_config(uart_parity) ( uart_parity == ODD \ + ? (BM3803_REG.uart_ctrl2 = ((BM3803_REG.uart_ctrl2 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (BM3803_REG.uart_ctrl2 = ((BM3803_REG.uart_ctrl2 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (BM3803_REG.uart_ctrl2 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define uart2_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (BM3803_REG.uart_ctrl2 |= MSK_UART_ENABLE_FLOW) \ + : (BM3803_REG.uart_ctrl2 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart2_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (BM3803_REG.uart_ctrl2 |= MSK_UART_LOOPBACK) \ + : (BM3803_REG.uart_ctrl2 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart2_enable() (BM3803_REG.uart_ctrl2 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart2_disable() (BM3803_REG.uart_ctrl2 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart2_tx_ready() ((BM3803_REG.uart_status2 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart2_rx_ready() ((BM3803_REG.uart_status2 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart2_send_byte(ch) (BM3803_REG.uart_data2 = ch) + +#define uart3_set_baudrate(baudrate) (BM3803_REG.uart_scaler3 = (((BOARD_CPU_CLOCK*10)/(baudrate*8))-5)/10) + +#define uart3_parity_config(uart_parity) ( uart_parity == ODD \ + ? (BM3803_REG.uart_ctrl3 = ((BM3803_REG.uart_ctrl3 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (BM3803_REG.uart_ctrl3 = ((BM3803_REG.uart_ctrl3 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (BM3803_REG.uart_ctrl3 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define uart3_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (BM3803_REG.uart_ctrl3 |= MSK_UART_ENABLE_FLOW) \ + : (BM3803_REG.uart_ctrl3 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart3_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (BM3803_REG.uart_ctrl3 |= MSK_UART_LOOPBACK) \ + : (BM3803_REG.uart_ctrl3 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart3_enable() (BM3803_REG.uart_ctrl3 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart3_disable() (BM3803_REG.uart_ctrl3 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart3_tx_ready() ((BM3803_REG.uart_status3 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart3_rx_ready() ((BM3803_REG.uart_status3 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart3_send_byte(ch) (BM3803_REG.uart_data3 = ch) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_UART_H */ diff --git a/arch/sparc/src/bm3803/bm3803.h b/arch/sparc/src/bm3803/bm3803.h new file mode 100644 index 00000000000..3a80fe99cf2 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803.h @@ -0,0 +1,584 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803.h + * + * 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_SPARC_SRC_BM3803_BM3803_H +#define __ARCH_SARRC_SRC_BM3803_BM3803_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "bm3803-config.h" + +#ifdef CONFIG_BM3803_GPIOIRQ +#include +#include "bm3803_exti.h" +#endif + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The following defines the bits in Memory Configuration Register 1. */ + +#define BM3803_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x0003C000 + +/* The following defines the bits in Memory Configuration Register 1. */ + +#define BM3803_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001E00 + +/* The following defines the bits in the Timer Control Register. */ + +/* 1 = enable counting + * 0 = hold scalar and counter + */ + +#define BM3803_REG_TIMER_CONTROL_EN 0x00000001 + +/* 1 = reload at 0 + * 0 = stop at 0 + */ + +#define BM3803_REG_TIMER_CONTROL_RL 0x00000002 + +/* 1 = load counter + * 0 = no function + */ + +#define BM3803_REG_TIMER_CONTROL_LD 0x00000004 + +/* The following defines the bits in the UART Control Registers. */ + +#define BM3803_REG_UartCtrlRTD 0x000000FF /* RX/TX data */ + +/* The following defines the bits in the BM3803 UART Status Registers. */ + +#define BM3803_REG_UART_STATUS_CLR 0x00000000 /* Clear all status bits */ +#define BM3803_REG_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define BM3803_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define BM3803_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define BM3803_REG_UART_STATUS_BR 0x00000008 /* Break Error */ +#define BM3803_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */ +#define BM3803_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define BM3803_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */ +#define BM3803_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */ + +/* The following defines the bits in the BM3803 UART Status Registers. */ + +#define BM3803_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */ +#define BM3803_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */ +#define BM3803_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */ +#define BM3803_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */ +#define BM3803_REG_UART_CTRL_PS 0x00000010 /* Parity select */ +#define BM3803_REG_UART_CTRL_PE 0x00000020 /* Parity enable */ +#define BM3803_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */ +#define BM3803_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The following constants are intended to be used ONLY in assembly + * language files. + * + * NOTE: The intended style of usage is to load the address of BM3803 REGS + * into a register and then use these as displacements from + * that register. + */ + +#ifdef __ASSEMBLY__ + +#define BM3803_REG_MEMCFG1_OFFSET 0x00 +#define BM3803_REG_MEMCFG2_OFFSET 0x04 +#define BM3803_REG_EDACCTRL_OFFSET 0x08 +#define BM3803_REG_FAILADDR_OFFSET 0x0C +#define BM3803_REG_MEMSTATUS_OFFSET 0x10 +#define BM3803_REG_CACHECTRL_OFFSET 0x14 +#define BM3803_REG_POWERDOWN_OFFSET 0x18 +#define BM3803_REG_WRITEPROT1_OFFSET 0x1C +#define BM3803_REG_WRITEPROT2_OFFSET 0x20 +#define BM3803_REG_BM3803CONF_OFFSET 0x24 +#define BM3803_REG_UNIMPLEMENTED_2_OFFSET 0x28 +#define BM3803_REG_UNIMPLEMENTED_3_OFFSET 0x2C +#define BM3803_REG_UNIMPLEMENTED_4_OFFSET 0x30 +#define BM3803_REG_UNIMPLEMENTED_5_OFFSET 0x34 +#define BM3803_REG_UNIMPLEMENTED_6_OFFSET 0x38 +#define BM3803_REG_UNIMPLEMENTED_7_OFFSET 0x3C +#define BM3803_REG_TIMERCNT1_OFFSET 0x40 +#define BM3803_REG_TIMERLOAD1_OFFSET 0x44 +#define BM3803_REG_TIMERCTRL1_OFFSET 0x48 +#define BM3803_REG_WDOG_OFFSET 0x4C +#define BM3803_REG_TIMERCNT2_OFFSET 0x50 +#define BM3803_REG_TIMERLOAD2_OFFSET 0x54 +#define BM3803_REG_TIMERCTRL2_OFFSET 0x58 +#define BM3803_REG_UNIMPLEMENTED_8_OFFSET 0x5C +#define BM3803_REG_SCALERCNT_OFFSET 0x60 +#define BM3803_REG_SCALER_LOAD_OFFSET 0x64 +#define BM3803_REG_UNIMPLEMENTED_9_OFFSET 0x68 +#define BM3803_REG_UNIMPLEMENTED_10_OFFSET 0x6C +#define BM3803_REG_UARTDATA1_OFFSET 0x70 +#define BM3803_REG_UARTSTATUS1_OFFSET 0x74 +#define BM3803_REG_UARTCTRL1_OFFSET 0x78 +#define BM3803_REG_UARTSCALER1_OFFSET 0x7C +#define BM3803_REG_UARTDATA2_OFFSET 0x80 +#define BM3803_REG_UARTSTATUS2_OFFSET 0x84 +#define BM3803_REG_UARTCTRL2_OFFSET 0x88 +#define BM3803_REG_UARTSCALER2_OFFSET 0x8C +#define BM3803_REG_IRQMASK_OFFSET 0x90 +#define BM3803_REG_IRQPEND_OFFSET 0x94 +#define BM3803_REG_IRQFORCE_OFFSET 0x98 +#define BM3803_REG_IRQCLEAR_OFFSET 0x9C +#define BM3803_REG_PIODATA_OFFSET 0xA0 +#define BM3803_REG_PIODIR_OFFSET 0xA4 +#define BM3803_REG_PIOIRQ_OFFSET 0xA8 +#define BM3803_REG_SIM_RAM_SIZE_OFFSET 0xF4 +#define BM3803_REG_SIM_ROM_SIZE_OFFSET 0xF8 + +#else + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Trap Types for on-chip peripherals + * + * Source: Table 8 - Interrupt Trap Type and Default Priority Assignments + * + * NOTE: The priority level for each source corresponds to the least + * significant nibble of the trap type. + */ + +#define BM3803_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10) + +#define BM3803_TRAP_SOURCE( _trap ) ((_trap) - 0x10) + +#define BM3803_INT_TRAP( _trap ) \ + ( (_trap) >= BM3803_TRAP_TYPE( BM3803_IRQ_CORRECTABLE_MEMORY_ERROR ) && \ + (_trap) <= BM3803_TRAP_TYPE( BM3803_IRQ_EMPTY6 ) ) + +/* Structure for BM3803 memory mapped registers. + * + * Source: Section 6.1 - On-chip registers + * + * NOTE: There is only one of these structures per CPU, its base address + * is 0x80000000, and the variable BM3803_REG is placed there by the + * linkcmds file. + */ + +typedef struct +{ + volatile unsigned int mem_cfg1; /* Memory Configuration Register 1 */ + volatile unsigned int mem_cfg2; /* Memory Configuration Register 2 */ + volatile unsigned int mem_cfg3; /* Memory Configuration Register 3 */ + volatile unsigned int fail_addr; + + volatile unsigned int mem_status; /* 0x10 */ + volatile unsigned int cache_ctrl; /* Cache control register */ + volatile unsigned int power_down; + volatile unsigned int write_prot1; /* Write protection 1 */ + + volatile unsigned int write_prot2; /* Write protection 2 0x20 */ + volatile unsigned int pcr; + volatile unsigned int dummy2; + volatile unsigned int dummy3; + + volatile unsigned int dummy4; /* 0x30 */ + volatile unsigned int dummy5; + volatile unsigned int dummy6; + volatile unsigned int dummy7; + + volatile unsigned int timer_cnt1; /* 0x40 */ + volatile unsigned int timer_load1; + volatile unsigned int timer_ctrl1; + volatile unsigned int wdog; + + volatile unsigned int timer_cnt2; /* 0x50 */ + volatile unsigned int timer_load2; + volatile unsigned int timer_ctrl2; + volatile unsigned int dummy8; + + volatile unsigned int scaler_cnt; /* 0x60 */ + volatile unsigned int scaler_load; + volatile unsigned int dummy9; + volatile unsigned int dummy10; + + volatile unsigned int uart_data1; /* UA1 data */ + volatile unsigned int uart_status1; /* UA1 status register */ + volatile unsigned int uart_ctrl1; /* UA1 control register */ + volatile unsigned int uart_scaler1; /* UA1 scaler register */ + + volatile unsigned int uart_data2; /* UA2 data */ + volatile unsigned int uart_status2; /* UA2 status register */ + volatile unsigned int uart_ctrl2; /* UA2 control register */ + volatile unsigned int uart_scaler2; /* UA2 scaler register */ + + /* Interrupt Mask and Priority Register register */ + + volatile unsigned int int_mask; + volatile unsigned int int_pend; /* Interrupt Pending Register register */ + volatile unsigned int int_force; + volatile unsigned int int_clear; /* Interrupt Clear Register register */ + + volatile unsigned int pio_data; /* 0xA0 */ + volatile unsigned int pio_dir; + volatile unsigned int pio_irq; + volatile unsigned int dummy11; + + volatile unsigned int i_mask2; /* 0xB0 */ + volatile unsigned int i_pend2; + volatile unsigned int i_stat2; + volatile unsigned int dummy12; + + volatile unsigned int dummy13; /* 0xC0 */ + volatile unsigned int dcom_status; + volatile unsigned int dcom_ctrl; + volatile unsigned int dcom_scaler; + + volatile unsigned int pci_reset; /* 0xD0 */ + volatile unsigned int dummy15; + volatile unsigned int dummy16; + volatile unsigned int dummy17; + + volatile unsigned int uart_data3; /* 0xE0 */ + volatile unsigned int uart_status3; + volatile unsigned int uart_ctrl3; + volatile unsigned int uart_scaler3; + + volatile unsigned int reserved1; /* 0xF0 */ + volatile unsigned int reserved2; + volatile unsigned int reserved3; + volatile unsigned int reserved4; + + volatile unsigned int mecfg1; /* 0x100 */ + volatile unsigned int mecfg2; + volatile unsigned int mecfg3; + volatile unsigned int mecfg4; +} bm3803_register_map; + +/* This is used to manipulate the on-chip registers. + * + * The following symbol must be defined in the linkcmds file and point + * to the correct location. + */ + +extern bm3803_register_map BM3803_REG; + +static __inline__ int bsp_irq_fixup(int irq) +{ + return irq; +} + +/* Macros to manipulate the Interrupt Clear, Interrupt Force, Interrupt Mask + * and the Interrupt Pending Registers. + * + * NOTE: For operations which are not atomic, this code disables interrupts + * to guarantee there are no intervening accesses to the same register + * The operations which read the register, modify the value and then + * store the result back are vulnerable. + */ + +#define BM3803_Clear_interrupt( _source ) \ + do { \ + BM3803_REG.Interrupt_Clear = (1 << (_source)); \ + } while (0) + +#define BM3803_Force_interrupt( _source ) \ + do { \ + BM3803_REG.Interrupt_Force = (1 << (_source)); \ + } while (0) + +#define BM3803_Is_interrupt_pending( _source ) \ + (BM3803_REG.Interrupt_Pending & (1 << (_source))) + +#define BM3803_Is_interrupt_masked( _source ) \ + (!(BM3803_REG.Interrupt_Mask & (1 << (_source)))) + +#define BM3803_Mask_interrupt( _source ) \ + do { \ + uint32_t _level; \ + \ + _level = sparc_disable_interrupts(); \ + BM3803_REG.Interrupt_Mask &= ~(1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define BM3803_Unmask_interrupt( _source ) \ + do { \ + uint32_t _level; \ + \ + _level = sparc_disable_interrupts(); \ + BM3803_REG.Interrupt_Mask |= (1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define BM3803_Disable_interrupt( _source, _previous ) \ + do { \ + uint32_t _level; \ + uint32_t _mask = 1 << (_source); \ + \ + _level = sparc_disable_interrupts(); \ + (_previous) = BM3803_REG.Interrupt_Mask; \ + BM3803_REG.Interrupt_Mask = _previous & ~_mask; \ + sparc_enable_interrupts( _level ); \ + (_previous) &= _mask; \ + } while (0) + +#define BM3803_Restore_interrupt( _source, _previous ) \ + do { \ + uint32_t _level; \ + uint32_t _mask = 1 << (_source); \ + \ + _level = sparc_disable_interrupts(); \ + BM3803_REG.Interrupt_Mask = \ + (BM3803_REG.Interrupt_Mask & ~_mask) | (_previous); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +/* Make all SPARC BSPs have common macros for interrupt handling */ +#define BSP_Clear_interrupt(_source) BM3803_Clear_interrupt(_source) +#define BSP_Force_interrupt(_source) BM3803_Force_interrupt(_source) +#define BSP_Is_interrupt_pending(_source) BM3803_Is_interrupt_pending(_source) +#define BSP_Is_interrupt_masked(_source) BM3803_Is_interrupt_masked(_source) +#define BSP_Unmask_interrupt(_source) BM3803_Unmask_interrupt(_source) +#define BSP_Mask_interrupt(_source) BM3803_Mask_interrupt(_source) +#define BSP_Disable_interrupt(_source, _previous) \ + BM3803_Disable_interrupt(_source, _prev) +#define BSP_Restore_interrupt(_source, _previous) \ + BM3803_Restore_interrupt(_source, _previous) + +/* Make all SPARC BSPs have common macros for interrupt handling on any CPU */ +#define BSP_Cpu_Is_interrupt_masked(_source, _cpu) \ + BSP_Is_interrupt_masked(_source) +#define BSP_Cpu_Unmask_interrupt(_source, _cpu) \ + BSP_Unmask_interrupt(_source) +#define BSP_Cpu_Mask_interrupt(_source, _cpu) \ + BSP_Mask_interrupt(_source) +#define BSP_Cpu_Disable_interrupt(_source, _previous, _cpu) \ + BSP_Disable_interrupt(_source, _prev) +#define BSP_Cpu_Restore_interrupt(_source, _previous, _cpu) \ + BSP_Cpu_Restore_interrupt(_source, _previous) + +/* Each timer control register is organized as follows: + * + * D0 - Enable + * 1 = enable counting + * 0 = hold scaler and counter + * + * D1 - Counter Reload + * 1 = reload counter at zero and restart + * 0 = stop counter at zero + * + * D2 - Counter Load + * 1 = load counter with preset value + * 0 = no function + * + */ + +#define BM3803_REG_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000002 +#define BM3803_REG_TIMER_COUNTER_STOP_AT_ZERO 0x00000000 + +#define BM3803_REG_TIMER_COUNTER_LOAD_COUNTER 0x00000004 + +#define BM3803_REG_TIMER_COUNTER_ENABLE_COUNTING 0x00000001 +#define BM3803_REG_TIMER_COUNTER_DISABLE_COUNTING 0x00000000 + +#define BM3803_REG_TIMER_COUNTER_RELOAD_MASK 0x00000002 +#define BM3803_REG_TIMER_COUNTER_ENABLE_MASK 0x00000001 + +#define BM3803_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003 +#define BM3803_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Load 32-bit word by forcing a cache-miss */ + +static inline unsigned int bm3803_r32_no_cache(uintptr_t addr) +{ + unsigned int tmp; + __asm__ volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr)); + return tmp; +} + +/**************************************************************************** + * Name: up_clkinit + * + * Description: + * Initialiaze clock/PLL settings per the definitions in the board.h file. + * + ****************************************************************************/ + +void up_clkinitialize(void); + +/**************************************************************************** + * Name: usart0_reset and usart1_reset + * + * Description: + * Reset USART0 or USART1. + * + ****************************************************************************/ + +void usart1_reset(void); +void usart2_reset(void); +void usart3_reset(void); +/**************************************************************************** + * Name: usart0_configure and usart1_configure + * + * Description: + * Configure USART0 or USART1. + * + ****************************************************************************/ + +void uart1_configure(void); +void uart2_configure(void); +void uart3_configure(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). + * + ****************************************************************************/ + +#ifdef HAVE_SERIAL_CONSOLE +void up_consoleinit(void); +#else +# define up_consoleinit() +#endif + +/**************************************************************************** + * Name: bm3803_uartconfigure + * + * Description: + * Configure a UART as a RS-232 UART. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void bm3803_uartconfigure(uintptr_t uart_base, uint32_t baudrate, + unsigned int parity, unsigned int nbits, bool stop2); +#endif + +/**************************************************************************** + * Name: bm3803_boardinitialize + * + * Description: + * This function must be provided by the board-specific logic in the + * directory boards/sparc/bm3803//src. + * + ****************************************************************************/ + +void bm3803_boardinitialize(void); + +/**************************************************************************** + * Name: gpio_irqinitialize + * + * Description: + * Initialize all vectors to the unexpected interrupt handler + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + * Assumptions: + * Called during the early boot sequence before global interrupts have + * been enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void weak_function gpio_irqinitialize(void); +#endif + +/**************************************************************************** + * Name: gpio_irqattach + * + * Description: + * Attach in GPIO interrupt to the provide 'isr' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +int gpio_irqattach(int irq, xcpt_t newisr, xcpt_t *oldisr); +#endif + +/**************************************************************************** + * Name: gpio_irqenable + * + * Description: + * Enable the GPIO IRQ specified by 'irq' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void gpio_irqenable(int irq); +#endif + +/**************************************************************************** + * Name: gpio_irqdisable + * + * Description: + * Disable the GPIO IRQ specified by 'irq' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void gpio_irqdisable(int irq); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_H */ diff --git a/arch/sparc/src/bm3803/bm3803_exceptions.S b/arch/sparc/src/bm3803/bm3803_exceptions.S new file mode 100644 index 00000000000..8acb66aaa64 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_exceptions.S @@ -0,0 +1,432 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_exceptions.S + * + * 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 + +/**************************************************************************** + * External Symbols + ****************************************************************************/ + + .global _ISR_Handler + .global up_doirq /* Dispatch an IRQ */ + +/* + * void _ISR_Handler() + * + * This routine provides the RTEMS interrupt management. + * + * We enter this handler from the 4 instructions in the trap table with + * the following registers assumed to be set as shown: + * + * l0 = PSR + * l1 = PC + * l2 = nPC + * l3 = trap type + * + * NOTE: By an executive defined convention, trap type is between 0 and 255 if + * it is an asynchonous trap and 256 and 511 if it is synchronous. + */ + + .align 4 + +_ISR_Handler: + + /* + * Fix the return address for synchronous traps. + */ + + and %l3, 0xF0, %l6 + cmp %l6, 0x10 ! Is this a synchronous trap? + be,a win_ovflow ! No, then skip the adjustment + nop ! DELAY + mov %l2, %l1 ! do not return to the instruction + add %l2, 4, %l2 ! indicated + +win_ovflow: + /* + * Save the globals this block uses. + * + * These registers are not restored from the locals. Their contents + * are saved directly from the locals into the ISF below. + */ + + mov %g4, %l4 ! save the globals this block uses + mov %g5, %l5 + /* + * When at a "window overflow" trap, (wim == (1 << cwp)). + * If we get here like that, then process a window overflow. + */ + rd %wim, %g4 + srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP + ! are LS 5 bits ; how convenient :) + cmp %g5, 1 ! Is this an invalid window? + bne dont_do_the_window ! No, then skip all this stuff + nop + ! we are using the delay slot + + /* + * The following is same as a 1 position right rotate of WIM + */ + srl %g4, 1, %g5 ! g5 = WIM >> 1 + sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4 + ! g4 = WIM << (Number Windows - 1) + or %g4, %g5, %g4 ! g4 = (WIM >> 1) | + ! (WIM << (Number Windows - 1)) + + /* + * At this point: + * + * g4 = the new WIM + * g5 is free + */ + + /* + * Since we are tinkering with the register windows, we need to + * make sure that all the required information is in global registers. + */ + save ! Save into the window + wr %g4, 0, %wim ! WIM = new WIM + nop ! delay slots + nop + nop + + /* + * Now save the window just as if we overflowed to it. + */ + +SAVE_WINDOW: + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + restore + nop + +dont_do_the_window: + /* + * Global registers %g4 and %g5 are saved directly from %l4 and + * %l5 directly into the ISF below. + */ + +save_isf: + + /* + * Save the state of the interrupted task -- especially the global + * registers -- in the Interrupt Stack Frame. Note that the ISF + * includes a regular minimum stack frame which will be used if + * needed by register window overflow and underflow handlers. + * + * REGISTERS SAME AS AT _ISR_Handler + */ + + sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp + ! make space for ISF + + std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC + st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC + st %g1, [%sp + ISF_G1_OFFSET] ! save g1 + std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3 + std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above + std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7 + + std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1 + std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3 + std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5 + std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7 + + rd %y, %g1 + st %g1, [%sp + ISF_Y_OFFSET] ! save y + + mov %sp, %o1 ! 2nd arg to ISR Handler + + st %fsr, [%sp + ISF_FSR_OFFSET] + std %f0, [%sp + ISF_F0_OFFSET] + std %f2, [%sp + ISF_F2_OFFSET] + std %f4, [%sp + ISF_F4_OFFSET] + std %f6, [%sp + ISF_F6_OFFSET] + std %f8, [%sp + ISF_F8_OFFSET] + std %f10, [%sp + ISF_F10_OFFSET] + std %f12, [%sp + ISF_F12_OFFSET] + std %f14, [%sp + ISF_F14_OFFSET] + std %f16, [%sp + ISF_F16_OFFSET] + std %f18, [%sp + ISF_F18_OFFSET] + std %f20, [%sp + ISF_F20_OFFSET] + std %f22, [%sp + ISF_F22_OFFSET] + std %f24, [%sp + ISF_F24_OFFSET] + std %f26, [%sp + ISF_F26_OFFSET] + std %f28, [%sp + ISF_F28_OFFSET] + std %f30, [%sp + ISF_F30_OFFSET] ! total 32 word + +fix_pil: + mov %l0, %g5 + or %g5, SPARC_PSR_PIL_MASK, %g5 /* 0x00000F00 */ + wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** /* 0x00000020 */ + nop + nop + nop +/*==========================================================================*/ + ! o1 = 2nd arg = address of the ISF + ! WAS LOADED WHEN ISF WAS SAVED!!! + mov %l3, %o0 ! o0 = 1st arg = vector number + call up_doirq /* call ISR dispatcher */ + nop +/*==========================================================================*/ + mov %l0, %psr ! **** DISABLE TRAPS **** + nop; + nop; + nop; + /* If a context switch occurred while processing the interrupt then + * %o0 may have change value. If we return any value different + * from the input regs %o1, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + mov %o0, %g6 ! g6 = %o0 + cmp %g6, %sp ! Is this a context switch occurred? + be,a simple_return ! No, then skip the window save + nop ! DELAY + + /* + * Flush all windows with valid contents except the current one. + * In examining the set register windows, one may logically divide + * the windows into sets (some of which may be empty) based on their + * current status: + * + * + current (i.e. in use), + * + used (i.e. a restore would not trap) + * + invalid (i.e. 1 in corresponding bit in WIM) + * + unused + * + * Either the used or unused set of windows may be empty. + * + * NOTE: We assume only one bit is set in the WIM at a time. + * + * Given a CWP of 5 and a WIM of 0x1, the registers are divided + * into sets as follows: + * + * + 0 - invalid + * + 1-4 - unused + * + 5 - current + * + 6-7 - used + * + * In this case, we only would save the used windows -- 6 and 7. + * + * Traps are disabled for the same logical period as in a + * flush all windows trap handler. + * + * Register Usage while saving the windows: + * g1 = current PSR + * g2 = current wim + * g3 = CWP + * g4 = wim scratch + * g5 = scratch + */ + + and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP + andn %l0, SPARC_PSR_ET_MASK, %g1 ! g1 = psr with traps disabled + ! mov %g1, %psr ! **** DISABLE TRAPS **** + mov %wim, %g2 ! g2 = wim + mov 1, %g4 + sll %g4, %g3, %g4 ! g4 = WIM mask for CW invalid + +save_frame_loop: + sll %g4, 1, %g5 ! rotate the "wim" left 1 + srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 + or %g4, %g5, %g4 ! g4 = wim if we do one restore + + /* + * If a restore would not underflow, then continue. + */ + + andcc %g4, %g2, %g0 ! Any windows to flush? + bnz done_flushing ! No, then continue + nop + + restore ! back one window + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + ba save_frame_loop + nop + +done_flushing: + + ! Wait three instructions after the write to PSR before using + ! non-global registers or instructions affecting the CWP + ! g1 = psr with traps disabled + ! g3 = CWP (interrupt regs window) + mov %g1, %psr ! restore cwp + add %g3, 1, %g2 ! calculate desired WIM + and %g2, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g2 + mov 1, %g4 + sll %g4, %g2, %g4 ! g4 = new WIM + mov %g4, %wim + + mov %g6, %o0 ! %o0 = sp of context switch to + +simple_return: + ldd [%o0 + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7 + sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp + + ld [%o0 + ISF_Y_OFFSET], %l5 ! restore y + wr %l5, 0, %y + + ldd [%o0 + ISF_PSR_OFFSET], %l0 ! restore psr, PC + + ld [%o0 + ISF_NPC_OFFSET], %l2 ! restore nPC + rd %psr, %l3 + and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP + andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task + or %l3, %l0, %l0 ! install it later... + andn %l0, SPARC_PSR_ET_MASK, %l0 ! **** DISABLE TRAPS **** + + /* + * Restore tasks global and out registers + */ + ld [%o0 + ISF_G1_OFFSET], %g1 ! restore g1 ! g1 is restored later + ldd [%o0 + ISF_G2_OFFSET], %g2 ! restore g2, g3 + ldd [%o0 + ISF_G4_OFFSET], %g4 ! restore g4, g5 + ldd [%o0 + ISF_G6_OFFSET], %g6 ! restore g6, g7 + + ldd [%o0 + ISF_I0_OFFSET], %i0 ! restore i0, i1 + ldd [%o0 + ISF_I2_OFFSET], %i2 ! restore i2, i3 + ldd [%o0 + ISF_I4_OFFSET], %i4 ! restore i4, i5 + + + ldd [%o0 + ISF_F0_OFFSET] ,%f0 + ldd [%o0 + ISF_F2_OFFSET] ,%f2 + ldd [%o0 + ISF_F4_OFFSET] ,%f4 + ldd [%o0 + ISF_F6_OFFSET] ,%f6 + ldd [%o0 + ISF_F8_OFFSET] ,%f8 + ldd [%o0 + ISF_F10_OFFSET],%f10 + ldd [%o0 + ISF_F12_OFFSET],%f12 + ldd [%o0 + ISF_F14_OFFSET],%f14 + ldd [%o0 + ISF_F16_OFFSET],%f16 + ldd [%o0 + ISF_F18_OFFSET],%f18 + ldd [%o0 + ISF_F20_OFFSET],%f20 + ldd [%o0 + ISF_F22_OFFSET],%f22 + ldd [%o0 + ISF_F24_OFFSET],%f24 + ldd [%o0 + ISF_F26_OFFSET],%f26 + ldd [%o0 + ISF_F28_OFFSET],%f28 + ldd [%o0 + ISF_F30_OFFSET],%f30 + ld [%o0 + ISF_FSR_OFFSET],%fsr + nop + nop + nop + + /* + * Registers: + * + * ALL global registers EXCEPT G1 and the input registers have + * already been restored and thuse off limits. + * + * The following is the contents of the local registers: + * + * %l0 = original psr + * %l1 = return address (i.e. PC) + * %l2 = nPC + * %l3 = %tbr + */ + + /* + * if (CWP + 1) is an invalid window then we need to reload it. + * + * WARNING: Traps should now be disabled + */ + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop + nop + nop + rd %wim, %l4 + add %l0, 1, %l6 ! l6 = cwp + 1 + and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it + srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count + ! and CWP are conveniently LS 5 bits + cmp %l5, 1 ! Is tasks window invalid? + bne good_task_window + + /* + * The following code is the same as a 1 position left rotate of WIM. + */ + sll %l4, 1, %l5 ! l5 = WIM << 1 + srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4 + ! l4 = WIM >> (Number Windows - 1) + or %l4, %l5, %l4 ! l4 = (WIM << 1) | + ! (WIM >> (Number Windows - 1)) + /* + * Now restore the window just as if we underflowed to it. + */ + wr %l4, 0, %wim ! WIM = new WIM + nop ! must delay after writing WIM + nop + nop + + restore ! now into the tasks window + + ldd [%sp + CPU_STACK_FRAME_L0_OFFSET], %l0 + ldd [%sp + CPU_STACK_FRAME_L2_OFFSET], %l2 + ldd [%sp + CPU_STACK_FRAME_L4_OFFSET], %l4 + ldd [%sp + CPU_STACK_FRAME_L6_OFFSET], %l6 + ldd [%sp + CPU_STACK_FRAME_I0_OFFSET], %i0 + ldd [%sp + CPU_STACK_FRAME_I2_OFFSET], %i2 + ldd [%sp + CPU_STACK_FRAME_I4_OFFSET], %i4 + ldd [%sp + CPU_STACK_FRAME_I6_FP_OFFSET],%i6 + ! reload of sp clobbers ISF + save ! Back to ISR dispatch window + +good_task_window: + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop; + nop; + nop + ! and restore condition codes. + + jmp %l1 ! transfer control and + rett %l2 ! go back to tasks window + nop + /* isr end */ + + /* trap handler end*/ + diff --git a/arch/sparc/src/bm3803/bm3803_exti.h b/arch/sparc/src/bm3803/bm3803_exti.h new file mode 100644 index 00000000000..2d37cd2e84a --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_exti.h @@ -0,0 +1,82 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_exti.h + * + * 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_SPARC_SRC_BM3803_BM3803_EXTI_H +#define __ARCH_SPARC_SRC_BM3803_BM3803_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_gpioset_irq + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * - pinset: GPIO pin configuration + * - enable: Enables interrupt or not + * - trig: Trig interrupt on level or falling edges + * - edge: Trig interrupt on falling edges or rising edges + * - func: When non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +int bm3803_gpioset_irq(uint32_t pinset, bool enable, bool trig, bool edge, + xcpt_t func, void *arg); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_EXTI_H */ diff --git a/arch/sparc/src/bm3803/bm3803_exti_gpio.c b/arch/sparc/src/bm3803/bm3803_exti_gpio.c new file mode 100644 index 00000000000..955d88041a9 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_exti_gpio.c @@ -0,0 +1,270 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_exti_gpio.c + * + * 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 + +#include "up_internal.h" +#include "up_arch.h" +#include "chip.h" +#include "bm3803.h" +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gpio_callback_s +{ + xcpt_t callback; + void *arg; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to each EXTI */ + +static struct gpio_callback_s g_gpio_callbacks[4]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Interrupt Service Routines - Dispatchers + ****************************************************************************/ + +static int bm3803_exti0_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + up_clrpend_irq(BM3803_IRQ_EXTERNAL_0); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_callbacks[0].callback != NULL) + { + xcpt_t callback = g_gpio_callbacks[0].callback; + void *cbarg = g_gpio_callbacks[0].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +static int bm3803_exti1_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_callbacks[1].callback != NULL) + { + xcpt_t callback = g_gpio_callbacks[1].callback; + void *cbarg = g_gpio_callbacks[1].arg; + + ret = callback(irq, context, cbarg); + } + + /* Clear the pending interrupt */ + + up_clrpend_irq(BM3803_IRQ_EXTERNAL_1); + + return ret; +} + +static int bm3803_exti2_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_callbacks[2].callback != NULL) + { + xcpt_t callback = g_gpio_callbacks[2].callback; + void *cbarg = g_gpio_callbacks[2].arg; + + ret = callback(irq, context, cbarg); + } + + /* Clear the pending interrupt */ + + up_clrpend_irq(BM3803_IRQ_EXTERNAL_2); + + return ret; +} + +static int bm3803_exti3_isr(int irq, void *context, void * arg) +{ + int ret = OK; + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_callbacks[3].callback != NULL) + { + xcpt_t callback = g_gpio_callbacks[3].callback; + void *cbarg = g_gpio_callbacks[3].arg; + + ret = callback(irq, context, cbarg); + } + + /* Clear the pending interrupt */ + + up_clrpend_irq(BM3803_IRQ_EXTERNAL_3); + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_gpioset_irq + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * - pinset: GPIO pin configuration + * - enable: Enables interrupt or not + * - trig: Trig interrupt on level or falling edges + * - edge: Trig interrupt on falling edges or rising edges + * - func: When non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +int bm3803_gpioset_irq(uint32_t pinset, bool enable, bool trig, bool edge, + xcpt_t func, void *arg) +{ + FAR struct gpio_callback_s *shared_cbs; + uint32_t pin = pinset & 0x3; + + uint32_t en = 0x80 << (pin * 8); + uint32_t le = 0x40 << (pin * 8); + uint32_t pl = 0x20 << (pin * 8); + uint32_t isel = (pin + 4) << (pin * 8); + + int irq; + xcpt_t handler; + int nshared; + int i; + + /* Select the interrupt handler for this EXTI pin */ + + if (pin < 4) + { + irq = pin + BM3803_IRQ_EXTERNAL_0; + nshared = 1; + shared_cbs = &g_gpio_callbacks[pin]; + switch (pin) + { + case 0: + handler = bm3803_exti0_isr; + break; + + case 1: + handler = bm3803_exti1_isr; + break; + + case 2: + handler = bm3803_exti2_isr; + break; + + case 3: + handler = bm3803_exti3_isr; + break; + + default: + handler = bm3803_exti3_isr; + break; + } + } + else + { + return ERROR; + } + + /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */ + + g_gpio_callbacks[pin].callback = func; + g_gpio_callbacks[pin].arg = arg; + + /* Install external interrupt handlers */ + + if (func) + { + irq_attach(irq, handler, NULL); + up_enable_irq(irq); + } + else + { + /* Only disable IRQ if shared handler does not have any active + * callbacks + */ + + for (i = 0; i < nshared; i++) + { + if (shared_cbs[i].callback != NULL) + { + break; + } + } + + if (i == nshared) + { + up_disable_irq(irq); + } + } + + /* Configure GPIO, enable EXTI line enabled if event or interrupt + * is enabled + */ + + BM3803_REG.pio_dir = BM3803_REG.pio_dir & ~(1 << (pin + 4)); + + /* Configure rising/falling edges */ + + modifyreg32((uint32_t)&BM3803_REG.pio_irq, le, trig ? le : 0); + modifyreg32((uint32_t)&BM3803_REG.pio_irq, pl, edge ? pl : 0); + modifyreg32((uint32_t)&BM3803_REG.pio_irq, 0x1f << (pin * 8), isel); + modifyreg32((uint32_t)&BM3803_REG.pio_irq, en, enable ? en : 0); + return OK; +} diff --git a/arch/sparc/src/bm3803/bm3803_freerun.c b/arch/sparc/src/bm3803/bm3803_freerun.c new file mode 100644 index 00000000000..a6011b35765 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_freerun.c @@ -0,0 +1,273 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_freerun.c + * + * 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 + +#include "bm3803_freerun.h" + +#ifdef CONFIG_BM3803_FREERUN + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_freerun_handler + * + * Description: + * Timer interrupt callback. When the freerun timer counter overflows, + * this interrupt will occur. We will just increment an overflow count. + * + * Input Parameters: + * tch - The handle that represents the timer state + * arg - An opaque argument provided when the interrupt was registered + * sr - The value of the timer interrupt status register at the time + * that the interrupt occurred. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int bm3803_freerun_handler(int irq, FAR void *context, void *arg) +{ + FAR struct bm3803_freerun_s *freerun = (FAR struct bm3803_freerun_s *) arg; + + DEBUGASSERT(freerun != NULL && freerun->overflow < UINT24_MAX); + freerun->overflow++; + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_freerun_initialize + * + * Description: + * Initialize the freerun timer wrapper + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure + * chan Timer counter channel to be used. + * resolution The required resolution of the timer in units of + * microseconds. NOTE that the range is restricted to the + * range of uint16_t (excluding zero). + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_initialize(FAR struct bm3803_freerun_s *freerun, int chan, + uint16_t resolution) +{ + uint32_t frequency; + + tmrinfo("chan=%d resolution=%d usec\n", chan, resolution); + DEBUGASSERT(freerun != NULL && resolution > 0); + + /* Get the TC frequency the corresponds to the requested resolution */ + + frequency = USEC_PER_SEC / (uint32_t)resolution; + freerun->frequency = frequency; + + freerun->tch = bm3803_tim_init(chan); + if (!freerun->tch) + { + tmrerr("ERROR: Failed to allocate TIM%d\n", chan); + return -EBUSY; + } + + BM3803_TIM_SETCLOCK(freerun->tch, frequency); + + /* Initialize the remaining fields in the state structure and return + * success. + */ + + freerun->chan = chan; + freerun->running = false; + freerun->overflow = 0; + + /* Set up to receive the callback when the counter overflow occurs */ + + BM3803_TIM_SETISR(freerun->tch, bm3803_freerun_handler, freerun, 0); + + /* Set timer period */ + + BM3803_TIM_SETPERIOD(freerun->tch, UINT24_MAX); + + /* Start the counter */ + + BM3803_TIM_SETMODE(freerun->tch, BM3803_TIM_MODE_DOWN); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_freerun_counter + * + * Description: + * Read the counter register of the free-running timer. + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure. This + * structure must have been previously initialized via a call to + * bm3803_freerun_initialize(); + * ts The location in which to return the time from the free-running + * timer. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_counter(FAR struct bm3803_freerun_s *freerun, + FAR struct timespec *ts) +{ + uint64_t usec; + uint32_t counter; + uint32_t verify; + uint32_t overflow; + uint32_t sec; + uint32_t period; + int pending; + irqstate_t flags; + + DEBUGASSERT(freerun && freerun->tch && ts); + + /* Temporarily disable the overflow counter. NOTE that we have to be + * careful here because bm3803_tc_getpending() will reset the pending + * interrupt status. If we do not handle the overflow here then, it will + * be lost. + */ + + flags = enter_critical_section(); + + overflow = freerun->overflow; + counter = BM3803_TIM_GETCOUNTER(freerun->tch); + pending = BM3803_TIM_CHECKINT(freerun->tch, 0); + verify = BM3803_TIM_GETCOUNTER(freerun->tch); + + /* If an interrupt was pending before we re-enabled interrupts, + * then the overflow needs to be incremented. + */ + + if (pending) + { + BM3803_TIM_CLRINT(freerun->tch, 0); + + /* Increment the overflow count and use the value of the + * guaranteed to be AFTER the overflow occurred. + */ + + overflow++; + counter = verify; + + /* Update freerun overflow counter. */ + + freerun->overflow = overflow; + } + + leave_critical_section(flags); + + tmrinfo("counter=%lu (%lu) overflow=%lu, pending=%i\n", + (unsigned long)counter, (unsigned long)verify, + (unsigned long)overflow, pending); + tmrinfo("frequency=%u\n", freerun->frequency); + + /* Set timer period */ + + period = BM3803_TIM_GETPERIOD(freerun->tch); + + /* Convert the whole thing to units of microseconds. + * + * frequency = ticks / second + * seconds = ticks * frequency + * usecs = (ticks * USEC_PER_SEC) / frequency; + */ + + usec = ((((uint64_t)overflow << 24) + (uint64_t)(period - counter)) * + USEC_PER_SEC) / freerun->frequency; + + /* And return the value of the timer */ + + sec = (uint32_t)(usec / USEC_PER_SEC); + ts->tv_sec = sec; + ts->tv_nsec = (usec - (sec * USEC_PER_SEC)) * NSEC_PER_USEC; + + tmrinfo("usec=%llu ts=(%u, %lu)\n", + usec, (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_freerun_uninitialize + * + * Description: + * Stop the free-running timer and release all resources that it uses. + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure. This + * structure must have been previously initialized via a call to + * bm3803_freerun_initialize(); + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_uninitialize(FAR struct bm3803_freerun_s *freerun) +{ + DEBUGASSERT(freerun && freerun->tch); + + /* Now we can disable the timer interrupt and disable the timer. */ + + BM3803_TIM_SETMODE(freerun->tch, BM3803_TIM_MODE_DISABLED); + BM3803_TIM_SETISR(freerun->tch, NULL, NULL, 0); + + /* Free the timer */ + + bm3803_tim_deinit(freerun->tch); + freerun->tch = NULL; + + return OK; +} + +#endif /* CONFIG_BM3803_FREERUN */ diff --git a/arch/sparc/src/bm3803/bm3803_freerun.h b/arch/sparc/src/bm3803/bm3803_freerun.h new file mode 100644 index 00000000000..310cf2a6b71 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_freerun.h @@ -0,0 +1,143 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_freerun.h + * + * 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_SPARC_SRC_BM3803_FREERUN_H +#define __ARCH_SPARC_SRC_BM3803_FREERUN_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "bm3803_tim.h" + +#ifdef CONFIG_BM3803_FREERUN + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The freerun client must allocate an instance of this structure and called + * bm3803_freerun_initialize() before using the freerun facilities.The client + * should not access the contents of this structure directly since the + * contents are subject to change. + */ + +struct bm3803_freerun_s +{ + uint8_t chan; /* The timer/counter in use */ + bool running; /* True: the timer is running */ + uint32_t overflow; /* Timer counter overflow */ + FAR struct bm3803_tim_dev_s *tch; /* Handle returned by bm3803_tim_init() */ + uint32_t frequency; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_freerun_initialize + * + * Description: + * Initialize the freerun timer wrapper + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure + * chan Timer counter channel to be used. + * resolution The required resolution of the timer in units of + * microseconds. NOTE that the range is restricted to the + * range of uint16_t (excluding zero). + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_initialize(struct bm3803_freerun_s *freerun, int chan, + uint16_t resolution); + +/**************************************************************************** + * Name: bm3803_freerun_counter + * + * Description: + * Read the counter register of the free-running timer. + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure. This + * structure must have been previously initialized via a call to + * bm3803_freerun_initialize(); + * ts The location in which to return the time remaining on the + * oneshot timer. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_counter(struct bm3803_freerun_s *freerun, + struct timespec *ts); + +/**************************************************************************** + * Name: bm3803_freerun_uninitialize + * + * Description: + * Stop the free-running timer and release all resources that it uses. + * + * Input Parameters: + * freerun Caller allocated instance of the freerun state structure. This + * structure must have been previously initialized via a call to + * bm3803_freerun_initialize(); + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_freerun_uninitialize(struct bm3803_freerun_s *freerun); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_BM3803_FREERUN */ +#endif /* __ARCH_SPARC_SRC_BM3803_FREERUN_H */ diff --git a/arch/sparc/src/bm3803/bm3803_head.S b/arch/sparc/src/bm3803/bm3803_head.S new file mode 100644 index 00000000000..26ca897d9b6 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_head.S @@ -0,0 +1,623 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_head.S + * + * 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 + + +#define RTRAP(_vector, _handler) mov %g0, %l0 ; sethi %hi(_handler), %l4 ; jmp %l4+%lo(_handler); mov _vector, %l3 +#define TRAP(_vector, _handler) mov %psr, %l0; sethi %hi(_handler), %l4 ; jmp %l4+%lo(_handler); mov _vector, %l3 + +/* Unexcpected trap will halt the processor by forcing it to error state */ +#define BAD_TRAP ta 0; nop; nop; nop; +#define SOFT_TRAP BAD_TRAP /* Software trap. Treat as BAD_TRAP */ + +/* + * System call optimized trap table entry + */ +#define IRQDIS_TRAP(_handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + or %l0, 0x0f00, %l3; ! Set PIL=0xf to disable IRQ + +/* + * System call optimized trap table entry + */ +#define IRQEN_TRAP(_handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + andn %l0, 0xf00, %l3; ! Set PIL=0 to Enable IRQ + +/* + * Window Overflow optimized trap table entry + */ +#define WOTRAP(_vector, _handler) \ + sethi %hi(_handler), %l4; \ + jmp %l4+%lo(_handler); \ + save; \ + nop + +/* + * Window Underflow optimized trap table entry + */ +#define WUTRAP(_vector, _handler) \ + mov %wim, %l3 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + sll %l3, 1, %l4 ! l4 = WIM << 1 + + .text + .global _trap_table, _hardreset + .global __start + .global up_lowinit /* Perform low level initialization */ + .global nx_start /* NuttX entry point */ + .global _userinit, _end + .global _window_overflow, _window_underflow, _flush_windows, _fpdis_enable + .global syscall_irqdis, syscall_irqen + .global _ISR_Handler + + /* Hardware traps */ +_trap_table: +_hardreset: + RTRAP(0,__start); ! 00 reset trap + BAD_TRAP; ! 01 instruction_access_exception + BAD_TRAP; ! 02 illegal_instruction + BAD_TRAP; ! 03 priveleged_instruction + TRAP(4,_fpdis_enable); ! 04 fp_disabled + WOTRAP(5,_window_overflow); ! 05 window_overflow + WUTRAP(6,_window_underflow); ! 06 window_underflow + BAD_TRAP; ! 07 memory_add0ress_not_aligned + BAD_TRAP; ! 08 fp_exception + BAD_TRAP; ! 09 data_access_exception + BAD_TRAP; ! 0A tag_overflow + BAD_TRAP; ! 0B undefined + BAD_TRAP; ! 0C undefined + BAD_TRAP; ! 0D undefined + BAD_TRAP; ! 0E undefined + BAD_TRAP; ! 0F undefined + BAD_TRAP; ! 10 undefined + + /* Interrupt entries */ + TRAP(0x11,_ISR_Handler) ! 11 interrupt level 1 + TRAP(0x12,_ISR_Handler) ! 12 interrupt level 2 + TRAP(0x13,_ISR_Handler) ! 13 interrupt level 3 + TRAP(0x14,_ISR_Handler) ! 14 interrupt level 4 + TRAP(0x15,_ISR_Handler) ! 15 interrupt level 5 + TRAP(0x16,_ISR_Handler) ! 16 interrupt level 6 + TRAP(0x17,_ISR_Handler) ! 17 interrupt level 7 + TRAP(0x18,_ISR_Handler) ! 18 interrupt level 8 + TRAP(0x19,_ISR_Handler) ! 19 interrupt level 9 + TRAP(0x1A,_ISR_Handler) ! 1A interrupt level 1 + TRAP(0x1B,_ISR_Handler) ! 1B interrupt level 11 + TRAP(0x1C,_ISR_Handler) ! 1C interrupt level 12 + TRAP(0x1D,_ISR_Handler) ! 1D interrupt level 13 + TRAP(0x1E,_ISR_Handler) ! 1E interrupt level 14 + TRAP(0x1F,_ISR_Handler) ! 1F interrupt level 15 + + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 undefined + BAD_TRAP; ! 24 cp_disabled + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 25 - 27 undefined + BAD_TRAP; ! 28 cp_exception + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 29 - 2B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F undefined + + /* + * Software traps + * + * NOTE: At the risk of being redundant... this is not a full + * table. The setjmp on the SPARC requires a window flush trap + * handler and RTEMS will preserve the entries that were + * installed before. + */ + + TRAP( 0x80, _ISR_Handler ); ! 80 halt syscall SW trap + SOFT_TRAP; SOFT_TRAP; ! 81 - 82 + TRAP( 0x83, _flush_windows); ! 83 flush windows SW trap + + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87 + TRAP( 0x88, _ISR_Handler ); ! 88 + + /* + * SW Trap 9-15 Reserved for Operating System + * + * SPARC_SWTRAP_IRQDIS + * SPARC_SWTRAP_IRQEN + */ + IRQDIS_TRAP(syscall_irqdis); ! 89 IRQ Disable syscall trap + IRQEN_TRAP(syscall_irqen); ! 8A IRQ Enable syscall trap + + SOFT_TRAP; ! 8B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - AB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! FC - FF + +/* trap table end*/ + +/* + * Init for SPARC-CPU + */ +#define PSR_INIT 0x10c0 /* Disable traps, set s and ps */ +__start: + mov %g0, %asr16 + mov %g0, %asr17 + nop + nop + + ! initial the IU register !disable trap + set 0x10c0, %g1 + mov %g1,%psr + nop + nop + nop + + mov %g0,%wim + nop + nop + nop + + mov %g0,%g1 + mov %g0,%g2 + mov %g0,%g3 + mov %g0,%g4 + mov %g0,%g5 + mov %g0,%g6 + mov %g0,%g7 + + /*Fill local and in/out register*/ + mov 0x8,%g1 +1: mov %g0,%l0 + mov %g0,%l1 + mov %g0,%l2 + mov %g0,%l3 + mov %g0,%l4 + mov %g0,%l5 + mov %g0,%l6 + mov %g0,%l7 + mov %g0,%i0 + mov %g0,%i1 + mov %g0,%i2 + mov %g0,%i3 + mov %g0,%i4 + mov %g0,%i5 + mov %g0,%i6 + mov %g0,%i7 + subcc %g1,1,%g1 + save + bne 1b + flush + nop + + ! initial the WIM register = 2 + set 2, %g1 + mov %g1, %wim + nop + nop + nop + + ! initial the TBR table + sethi %hi(_trap_table), %g1 + mov %g1, %tbr + nop + nop + nop + + ! enable traps,fpu in psr + set 0x10e0, %g1 + mov %g1,%psr + nop + nop + nop + set BM3803_REG,%g1 + ld [%g1+4], %g2 + or %g2, 0x4f, %g2 + st %g2, [%g1+4] + nop + nop + + ! initial the FSR register + set _fsrinit,%g1 + ld [%g1] , %fsr + nop + nop + nop + + ! initial the FPU %f register + set _fpdata,%g1 + ldd [%g1], %f0 + ldd [%g1], %f2 + ldd [%g1], %f4 + ldd [%g1], %f6 + ldd [%g1], %f8 + ldd [%g1], %f10 + ldd [%g1], %f12 + ldd [%g1], %f14 + ldd [%g1], %f16 + ldd [%g1], %f18 + ldd [%g1], %f20 + ldd [%g1], %f22 + ldd [%g1], %f24 + ldd [%g1], %f26 + ldd [%g1], %f28 + ldd [%g1], %f30 + nop + + ! initial cache controler + set BM3803_REG, %g1 + set 0x81000f,%g2 !open dcache,icache, dcache snoop,icache burst + ! set 0x80000f,%g2 !open dcache,icache, dcache snoop + ! set 0x01000f,%g2 !open dcache,icache, icache burst + ! set 0x00000f,%g2 !open dcache,icache + ! set 0x000000,%g2 !close dcache,icache + st %g2, [%g1 + 0x14] + nop + + set BM3803_REG,%g1 + ld [%g1+4], %g2 + or %g2, 0x4f, %g2 /*将存储器配置为读改写(区别于写选通),等待后期设置为最大*/ + st %g2, [%g1+4] + nop + + ! initial the stack point + sethi %hi(__stack), %g1 + or %g1, %lo(__stack), %g1 + subcc %g1, 16, %g1 + mov %g1, %sp + nop + + call _userinit + nop + + call up_lowinit ! bm3803_lowinit.c + nop + + call nx_start ! sched/init/nx_start.c + nop + +_exit: + ta 0 + nop + nop + +_userinit: /* clear the bss */ + save %sp, -64, %sp + sethi %hi(__bss_start),%g2 + or %g2,%lo(__bss_start),%g2 ! g2 = start of bss + !sethi %hi(__stack),%g3 + !or %g3,%lo(__stack),%g3 ! g3 = end of bss + set 0x40200000, %g3 + mov %g0,%g1 ! so std has two zeros + sub %g3, %g2, %g3 +zerobss: + subcc %g3, 8, %g3 + bge,a zerobss + std %g0,[%g2+%g3] + set _end, %o0 + st %g0,[%o0] + nop + + ret + restore + + +/* + * Init END + */ + +/* Number of register windows */ +#define NWINDOWS 8 + + /* + * Window overflow trap handler. + * + * On entry: + * + * prev regwin l1 = pc + * prev regwin l2 = npc + */ + .global _window_overflow +_window_overflow: + + /* + * Calculate new WIM by "rotating" the valid bits in the WIM right + * by one position. The following shows how the bits move for a SPARC + * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. + * + * OLD WIM = 76543210 + * NEW WIM = 07654321 + * + * NOTE: New WIM must be stored in a global register since the + * "save" instruction just prior to the load of the wim + * register will result in the local register set changing. + */ + + std %l0, [%sp + 0x00] ! save local register set + std %l2, [%sp + 0x08] + mov %wim, %l3 + sll %l3, NWINDOWS-1 , %l2 + ! l2 = WIM << (Number Windows - 1) + std %l4, [%sp + 0x10] + std %l6, [%sp + 0x18] + srl %l3, 1, %l3 ! l3 = WIM >> 1 + wr %l3, %l2, %wim ! WIM = (WIM >> 1) ^ + ! (WIM << (Number Windows - 1)) + ! 3 instruction delay not needed here + std %i0, [%sp + 0x20] ! save input register set + std %i2, [%sp + 0x28] + std %i4, [%sp + 0x30] + std %i6, [%sp + 0x38] + restore ! Go back to trap window. + jmp %l1 ! Re-execute save. + rett %l2 + + + /* + * Window underflow trap handler. + * + * On entry: + * + * l1 = pc + * l2 = npc + * l3 = wim (from trap vector) + * l4 = wim << 1 (from trap vector) + */ + .global _window_underflow +_window_underflow: + + /* + * Calculate new WIM by "rotating" the valid bits in the WIM left + * by one position. The following shows how the bits move for a SPARC + * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. + * + * OLD WIM = 76543210 + * NEW WIM = 07654321 + * + * NOTE: New WIM must be stored in a global register since the + * "save" instruction just prior to the load of the wim + * register will result in the local register set changing. + */ + + srl %l3, NWINDOWS-1, %l5 + or %l5, %l4, %l5 ! l5 = (WIM << 1) | + ! (WIM >> (Number Windows-1)) + mov %l5, %wim ! load the new WIM + nop; nop; nop ! 3 slot delay + restore ! Two restores to get into the + restore ! window to restore + ldd [%sp + 0x00], %l0 ! First the local register set + ldd [%sp + 0x08], %l2 + ldd [%sp + 0x10], %l4 + ldd [%sp + 0x18], %l6 + ldd [%sp + 0x20], %i0 ! Then the input registers + ldd [%sp + 0x28], %i2 + ldd [%sp + 0x30], %i4 + ldd [%sp + 0x38], %i6 + save ! Get back to the trap window. + save + jmp %l1 ! Re-execute restore. + rett %l2 + + + /* + * Flush All Windows trap handler. + * + * Flush all windows with valid contents except the current one + * and the one we will be returning to. + * + * In examining the set register windows, one may logically divide + * the windows into sets (some of which may be empty) based on their + * current status: + * + * + current (i.e. in use), + * + used (i.e. a restore would not trap) + * + invalid (i.e. 1 in corresponding bit in WIM) + * + unused + * + * Either the used or unused set of windows may be empty. + * + * NOTE: We assume only one bit is set in the WIM at a time. + * + * Given a CWP of 5 and a WIM of 0x1, the registers are divided + * into sets as follows: + * + * + 0 - invalid + * + 1-4 - unused + * + 5 - current + * + 6-7 - used + * + * In this case, we only would save the used windows which we + * will not be returning to -- 6. + * + * Register Usage while saving the windows: + * g1 = current PSR + * g2 = current wim + * g3 = CWP + * g4 = wim scratch + * g5 = scratch + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + */ + .global _flush_windows +_flush_windows: + /* + * Save the global registers we will be using + */ + + mov %g1, %l3 + mov %g2, %l4 + mov %g3, %l5 + mov %g4, %l6 + mov %g5, %l7 + + mov %l0, %g1 ! g1 = psr + mov %wim, %g2 ! g2 = wim + and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP + + add %g3, 1, %g5 ! g5 = CWP + 1 + and %g5, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g5 + + mov 1, %g4 + sll %g4, %g5, %g4 ! g4 = WIM mask for CWP+1 invalid + + restore ! go back one register window + +save_frame_loop: + sll %g4, 1, %g5 ! rotate the "wim" left 1 + srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 + or %g4, %g5, %g4 ! g4 = wim if we do one restore + + /* + * If a restore would not underflow, then continue. + */ + + andcc %g4, %g2, %g0 ! Any windows to flush? + bnz done_flushing ! No, then continue + nop + + restore ! back one window + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + ba save_frame_loop + nop + +done_flushing: + + add %g3, 2, %g3 ! calculate desired WIM + and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3 + mov 1, %g4 + sll %g4, %g3, %g4 ! g4 = new WIM + mov %g4, %wim + + mov %g1, %psr ! restore PSR + nop + nop + nop + + /* + * Restore the global registers we used + */ + + mov %l3, %g1 + mov %l4, %g2 + mov %l5, %g3 + mov %l6, %g4 + mov %l7, %g5 + + jmpl %l2, %g0 + rett %l2 + 4 + +/* fpdis_enable */ + .global _fpdis_enable +_fpdis_enable: + + jmpl %l2, %g0 + rett %l2 + 4 + nop + nop +/*************************************************/ + + +/*************************************************/ + .data + .global _fsrinit, _fpdata, g_idle_topstack + .type g_idle_topstack, object +.align 8 +_fsrinit: + .word 0x0,0 + +.align 8 +_fpdata: + .word 0,0 + +.align 8 +g_idle_topstack: + .long _end + CONFIG_IDLETHREAD_STACKSIZE + .size g_idle_topstack, .-g_idle_topstack + .end + diff --git a/arch/sparc/src/bm3803/bm3803_oneshot.c b/arch/sparc/src/bm3803/bm3803_oneshot.c new file mode 100644 index 00000000000..abbbce189fe --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_oneshot.c @@ -0,0 +1,401 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_oneshot.c + * + * 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 + +#include +#include + +#include "bm3803_oneshot.h" + +#ifdef CONFIG_BM3803_ONESHOT + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int bm3803_oneshot_handler(int irq, void *context, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_oneshot_handler + * + * Description: + * Common timer interrupt callback. When any oneshot timer interrupt + * expires, this function will be called. It will forward the call to + * the next level up. + * + * Input Parameters: + * oneshot - The state associated with the expired timer + * + * Returned Value: + * Always returns OK + * + ****************************************************************************/ + +static int bm3803_oneshot_handler(int irq, void *context, void *arg) +{ + struct bm3803_oneshot_s *oneshot = (struct bm3803_oneshot_s *) arg; + oneshot_handler_t oneshot_handler; + FAR void *oneshot_arg; + + tmrinfo("Expired...\n"); + DEBUGASSERT(oneshot != NULL && oneshot->handler); + + /* The clock was stopped, but not disabled when the RC match occurred. + * Disable the TC now and disable any further interrupts. + */ + + BM3803_TIM_SETISR(oneshot->tch, NULL, NULL, 0); + BM3803_TIM_SETMODE(oneshot->tch, BM3803_TIM_MODE_DISABLED); + BM3803_TIM_CLRINT(oneshot->tch, 0); + + /* The timer is no longer running */ + + oneshot->running = false; + + /* Forward the event, clearing out any vestiges */ + + oneshot_handler = (oneshot_handler_t)oneshot->handler; + oneshot->handler = NULL; + oneshot_arg = (void *)oneshot->arg; + oneshot->arg = NULL; + + oneshot_handler(oneshot_arg); + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_oneshot_initialize + * + * Description: + * Initialize the oneshot timer wrapper + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure + * chan Timer counter channel to be used. + * resolution The required resolution of the timer in units of + * microseconds. NOTE that the range is restricted to the + * range of uint16_t (excluding zero). + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_oneshot_initialize(FAR struct bm3803_oneshot_s *oneshot, + int chan, uint16_t resolution) +{ + uint32_t frequency; + + tmrinfo("chan=%d resolution=%d usec\n", chan, resolution); + DEBUGASSERT(oneshot && resolution > 0); + + /* Get the TC frequency the corresponds to the requested resolution */ + + frequency = USEC_PER_SEC / (uint32_t)resolution; + oneshot->frequency = frequency; + + oneshot->tch = bm3803_tim_init(chan); + if (!oneshot->tch) + { + tmrerr("ERROR: Failed to allocate TIM%d\n", chan); + return -EBUSY; + } + + BM3803_TIM_SETCLOCK(oneshot->tch, frequency); + + /* Initialize the remaining fields in the state structure. */ + + oneshot->chan = chan; + oneshot->running = false; + oneshot->handler = NULL; + oneshot->arg = NULL; + + /* Assign a callback handler to the oneshot */ + + return OK; +} + +/**************************************************************************** + * Name: bm3803_oneshot_max_delay + * + * Description: + * Determine the maximum delay of the one-shot timer (in microseconds) + * + ****************************************************************************/ + +int bm3803_oneshot_max_delay(FAR struct bm3803_oneshot_s *oneshot, + FAR uint64_t *usec) +{ + DEBUGASSERT(oneshot != NULL && usec != NULL); + + *usec = (uint64_t)(UINT24_MAX / oneshot->frequency) * + (uint64_t)USEC_PER_SEC; + return OK; +} + +/**************************************************************************** + * Name: bm3803_oneshot_start + * + * Description: + * Start the oneshot timer + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure. This + * structure must have been previously initialized via a call to + * bm3803_oneshot_initialize(); + * handler The function to call when when the oneshot timer expires. + * arg An opaque argument that will accompany the callback. + * ts Provides the duration of the one shot timer. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_oneshot_start(FAR struct bm3803_oneshot_s *oneshot, + oneshot_handler_t handler, FAR void *arg, + FAR const struct timespec *ts) +{ + uint64_t usec; + uint64_t period; + irqstate_t flags; + + tmrinfo("handler=%p arg=%p, ts=(%lu, %lu)\n", handler, arg, + (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec); + DEBUGASSERT(oneshot && handler && ts); + DEBUGASSERT(oneshot->tch); + + /* Was the oneshot already running? */ + + flags = enter_critical_section(); + if (oneshot->running) + { + /* Yes.. then cancel it */ + + tmrinfo("Already running... cancelling\n"); + (void)bm3803_oneshot_cancel(oneshot, NULL); + } + + /* Save the new handler and its argument */ + + oneshot->handler = handler; + oneshot->arg = arg; + + /* Express the delay in microseconds */ + + usec = (uint64_t)ts->tv_sec * USEC_PER_SEC + + (uint64_t)(ts->tv_nsec / NSEC_PER_USEC); + + /* Get the timer counter frequency and determine the number of counts need + * to achieve the requested delay. + * + * frequency = ticks / second + * ticks = seconds * frequency + * = (usecs * frequency) / USEC_PER_SEC; + */ + + period = (usec * (uint64_t)oneshot->frequency) / USEC_PER_SEC; + + tmrinfo("usec=%llu period=%08llx\n", usec, period); + DEBUGASSERT(period <= UINT24_MAX); + + /* Set up to receive the callback when the interrupt occurs */ + + BM3803_TIM_SETISR(oneshot->tch, bm3803_oneshot_handler, oneshot, 0); + + /* Set timer period */ + + oneshot->period = (uint32_t)period; + BM3803_TIM_SETPERIOD(oneshot->tch, (uint32_t)period); + + BM3803_TIM_CLRINT(oneshot->tch, 0); + + /* Start the counter */ + + BM3803_TIM_SETMODE(oneshot->tch, BM3803_TIM_MODE_DOWN); + + /* Enable interrupts. We should get the callback when the interrupt + * occurs. + */ + + oneshot->running = true; + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: bm3803_oneshot_cancel + * + * Description: + * Cancel the oneshot timer and return the time remaining on the timer. + * + * NOTE: This function may execute at a high rate with no timer running (as + * when pre-emption is enabled and disabled). + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure. This + * structure must have been previously initialized via a call to + * bm3803_oneshot_initialize(); + * ts The location in which to return the time remaining on the + * oneshot timer. A time of zero is returned if the timer is + * not running. ts may be zero in which case the time remaining + * is not returned. + * + * Returned Value: + * Zero (OK) is returned on success. A call to up_timer_cancel() when + * the timer is not active should also return success; a negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +int bm3803_oneshot_cancel(FAR struct bm3803_oneshot_s *oneshot, + FAR struct timespec *ts) +{ + irqstate_t flags; + uint64_t usec; + uint64_t sec; + uint64_t nsec; + uint32_t count; + uint32_t period; + + /* Was the timer running? */ + + flags = enter_critical_section(); + if (!oneshot->running) + { + /* No.. Just return zero timer remaining and successful cancellation. + * This function may execute at a high rate with no timer running + * (as when pre-emption is enabled and disabled). + */ + + ts->tv_sec = 0; + ts->tv_nsec = 0; + leave_critical_section(flags); + return OK; + } + + /* Yes.. Get the timer counter and period registers and stop the counter. + * If the counter expires while we are doing this, the counter clock will + * be stopped, but the clock will not be disabled. + * + * The expected behavior is that the counter register will freezes at + * a value equal to the RC register when the timer expires. The counter + * should have values between 0 and RC in all other cased. + * + * REVISIT: This does not appear to be the case. + */ + + tmrinfo("Cancelling...\n"); + + count = BM3803_TIM_GETCOUNTER(oneshot->tch); + period = oneshot->period; + + /* Now we can disable the interrupt and stop the timer. */ + + BM3803_TIM_SETISR(oneshot->tch, NULL, NULL, 0); + BM3803_TIM_SETMODE(oneshot->tch, BM3803_TIM_MODE_DISABLED); + + oneshot->running = false; + oneshot->handler = NULL; + oneshot->arg = NULL; + leave_critical_section(flags); + + /* Did the caller provide us with a location to return the time + * remaining? + */ + + if (ts) + { + /* Yes.. then calculate and return the time remaining on the + * oneshot timer. + */ + + tmrinfo("period=%lu count=%lu\n", + (unsigned long)period, (unsigned long)count); + + /* REVISIT: I am not certain why the timer counter value sometimes + * exceeds RC. Might be a bug, or perhaps the counter does not stop + * in all cases. + */ + + if (count >= period) + { + /* No time remaining (?) */ + + ts->tv_sec = 0; + ts->tv_nsec = 0; + } + else + { + /* The total time remaining is the difference. Convert the that + * to units of microseconds. + * + * frequency = ticks / second + * seconds = ticks * frequency + * usecs = (ticks * USEC_PER_SEC) / frequency; + */ + + usec = (((uint64_t)count) * USEC_PER_SEC) / + oneshot->frequency; + + /* Return the time remaining in the correct form */ + + sec = usec / USEC_PER_SEC; + nsec = ((usec) - (sec * USEC_PER_SEC)) * NSEC_PER_USEC; + + ts->tv_sec = (time_t)sec; + ts->tv_nsec = (unsigned long)nsec; + } + + tmrinfo("remaining (%lu, %lu)\n", + (unsigned long)ts->tv_sec, (unsigned long)ts->tv_nsec); + } + + return OK; +} + +#endif /* CONFIG_BM3803_ONESHOT */ diff --git a/arch/sparc/src/bm3803/bm3803_oneshot.h b/arch/sparc/src/bm3803/bm3803_oneshot.h new file mode 100644 index 00000000000..6c80ebf8652 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_oneshot.h @@ -0,0 +1,182 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_oneshot.h + * + * 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_SPARC_SRC_BM3803_ONESHOT_H +#define __ARCH_SPARC_SRC_BM3803_ONESHOT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "bm3803_tim.h" + +#ifdef CONFIG_BM3803_ONESHOT + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This describes the callback function that will be invoked when the oneshot + * timer expires. The oneshot fires, the client will receive: + * + * arg - The opaque argument provided when the interrupt was registered + */ + +typedef void (*oneshot_handler_t)(void *arg); + +/* The oneshot client must allocate an instance of this structure and called + * bm3803_oneshot_initialize() before using the oneshot facilities.The client + * should not access the contents of this structure directly since the + * contents are subject to change. + */ + +struct bm3803_oneshot_s +{ + uint8_t chan; /* The timer/counter in use */ + + volatile bool running; /* True: the timer is running */ + FAR struct bm3803_tim_dev_s *tch; /* Pointer returned by + * bm3803_tim_init() */ + volatile oneshot_handler_t handler; /* Oneshot expiration callback */ + volatile void *arg; /* The argument that will accompany + * the callback */ + uint32_t frequency; + uint32_t period; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_oneshot_initialize + * + * Description: + * Initialize the oneshot timer wrapper + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure + * chan Timer counter channel to be used. + * resolution The required resolution of the timer in units of + * microseconds. NOTE that the range is restricted to the + * range of uint16_t (excluding zero). + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_oneshot_initialize(struct bm3803_oneshot_s *oneshot, int chan, + uint16_t resolution); + +/**************************************************************************** + * Name: bm3803_oneshot_max_delay + * + * Description: + * Determine the maximum delay of the one-shot timer (in microseconds) + * + ****************************************************************************/ + +int bm3803_oneshot_max_delay(struct bm3803_oneshot_s *oneshot, + uint64_t *usec); + +/**************************************************************************** + * Name: bm3803_oneshot_start + * + * Description: + * Start the oneshot timer + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure. This + * structure must have been previously initialized via a call to + * bm3803_oneshot_initialize(); + * handler The function to call when when the oneshot timer expires. + * arg An opaque argument that will accompany the callback. + * ts Provides the duration of the one shot timer. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +int bm3803_oneshot_start(struct bm3803_oneshot_s *oneshot, + oneshot_handler_t handler, void *arg, + const struct timespec *ts); + +/**************************************************************************** + * Name: bm3803_oneshot_cancel + * + * Description: + * Cancel the oneshot timer and return the time remaining on the timer. + * + * NOTE: This function may execute at a high rate with no timer running (as + * when pre-emption is enabled and disabled). + * + * Input Parameters: + * oneshot Caller allocated instance of the oneshot state structure. This + * structure must have been previously initialized via a call to + * bm3803_oneshot_initialize(); + * ts The location in which to return the time remaining on the + * oneshot timer. A time of zero is returned if the timer is + * not running. + * + * Returned Value: + * Zero (OK) is returned on success. A call to up_timer_cancel() when + * the timer is not active should also return success; a negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +int bm3803_oneshot_cancel(struct bm3803_oneshot_s *oneshot, + struct timespec *ts); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* CONFIG_BM3803_ONESHOT */ +#endif /* __ARCH_SPARC_SRC_BM3803_ONESHOT_H */ diff --git a/arch/sparc/src/bm3803/bm3803_oneshot_lowerhalf.c b/arch/sparc/src/bm3803/bm3803_oneshot_lowerhalf.c new file mode 100644 index 00000000000..b188c66b313 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_oneshot_lowerhalf.c @@ -0,0 +1,334 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_oneshot_lowerhalf.c + * + * 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 + +#include "bm3803_oneshot.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure describes the state of the oneshot timer lower-half + * driver + */ + +struct bm3803_oneshot_lowerhalf_s +{ + /* This is the part of the lower half driver that is visible to the upper- + * half client of the driver. This must be the first thing in this + * structure so that pointers to struct oneshot_lowerhalf_s are cast + * compatible to struct bm3803_oneshot_lowerhalf_s and vice versa. + */ + + struct oneshot_lowerhalf_s lh; /* Common lower-half driver fields */ + + /* Private lower half data follows */ + + /* STM32-specific oneshot state */ + + struct bm3803_oneshot_s oneshot; + oneshot_callback_t callback; /* internal handler that receives callback */ + FAR void *arg; /* Argument that is passed to the handler */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void bm3803_oneshot_handler(void *arg); + +static int bm3803_max_delay(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts); +static int bm3803_start(FAR struct oneshot_lowerhalf_s *lower, + oneshot_callback_t callback, FAR void *arg, + FAR const struct timespec *ts); +static int bm3803_cancel(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Lower half operations */ + +static const struct oneshot_operations_s g_oneshot_ops = +{ + .max_delay = bm3803_max_delay, + .start = bm3803_start, + .cancel = bm3803_cancel, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_oneshot_handler + * + * Description: + * Timer expiration handler + * + * Input Parameters: + * arg - Should be the same argument provided when bm3803_oneshot_start() + * was called. + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void bm3803_oneshot_handler(void *arg) +{ + FAR struct bm3803_oneshot_lowerhalf_s *priv = + (FAR struct bm3803_oneshot_lowerhalf_s *)arg; + oneshot_callback_t callback; + FAR void *cbarg; + + DEBUGASSERT(priv != NULL); + + /* Perhaps the callback was nullified in a race condition with + * bm3803_cancel? + */ + + if (priv->callback) + { + /* Sample and nullify BEFORE executing callback (in case the callback + * restarts the oneshot). + */ + + callback = priv->callback; + cbarg = priv->arg; + priv->callback = NULL; + priv->arg = NULL; + + /* Then perform the callback */ + + callback(&priv->lh, cbarg); + } +} + +/**************************************************************************** + * Name: bm3803_max_delay + * + * Description: + * Determine the maximum delay of the one-shot timer (in microseconds) + * + * Input Parameters: + * lower An instance of the lower-half oneshot state structure. This + * structure must have been previously initialized via a call to + * oneshot_initialize(); + * ts The location in which to return the maxumum delay. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int bm3803_max_delay(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts) +{ + FAR struct bm3803_oneshot_lowerhalf_s *priv = + (FAR struct bm3803_oneshot_lowerhalf_s *)lower; + uint64_t usecs; + int ret; + + DEBUGASSERT(priv != NULL && ts != NULL); + ret = bm3803_oneshot_max_delay(&priv->oneshot, &usecs); + if (ret >= 0) + { + uint64_t sec = usecs / 1000000; + usecs -= 1000000 * sec; + + ts->tv_sec = (time_t)sec; + ts->tv_nsec = (long)(usecs * 1000); + } + + return ret; +} + +/**************************************************************************** + * Name: bm3803_start + * + * Description: + * Start the oneshot timer + * + * Input Parameters: + * lower An instance of the lower-half oneshot state structure. This + * structure must have been previously initialized via a call to + * oneshot_initialize(); + * handler The function to call when when the oneshot timer expires. + * arg An opaque argument that will accompany the callback. + * ts Provides the duration of the one shot timer. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned + * on failure. + * + ****************************************************************************/ + +static int bm3803_start(FAR struct oneshot_lowerhalf_s *lower, + oneshot_callback_t callback, FAR void *arg, + FAR const struct timespec *ts) +{ + FAR struct bm3803_oneshot_lowerhalf_s *priv = + (FAR struct bm3803_oneshot_lowerhalf_s *)lower; + irqstate_t flags; + int ret; + + DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL); + + /* Save the callback information and start the timer */ + + flags = enter_critical_section(); + priv->callback = callback; + priv->arg = arg; + ret = bm3803_oneshot_start(&priv->oneshot, + bm3803_oneshot_handler, priv, ts); + leave_critical_section(flags); + + if (ret < 0) + { + tmrerr("ERROR: bm3803_oneshot_start failed: %d\n", flags); + } + + return ret; +} + +/**************************************************************************** + * Name: bm3803_cancel + * + * Description: + * Cancel the oneshot timer and return the time remaining on the timer. + * + * NOTE: This function may execute at a high rate with no timer running (as + * when pre-emption is enabled and disabled). + * + * Input Parameters: + * lower Caller allocated instance of the oneshot state structure. This + * structure must have been previously initialized via a call to + * oneshot_initialize(); + * ts The location in which to return the time remaining on the + * oneshot timer. A time of zero is returned if the timer is + * not running. + * + * Returned Value: + * Zero (OK) is returned on success. A call to up_timer_cancel() when + * the timer is not active should also return success; a negated errno + * value is returned on any failure. + * + ****************************************************************************/ + +static int bm3803_cancel(FAR struct oneshot_lowerhalf_s *lower, + FAR struct timespec *ts) +{ + FAR struct bm3803_oneshot_lowerhalf_s *priv = + (FAR struct bm3803_oneshot_lowerhalf_s *)lower; + irqstate_t flags; + int ret; + + DEBUGASSERT(priv != NULL); + + /* Cancel the timer */ + + flags = enter_critical_section(); + ret = bm3803_oneshot_cancel(&priv->oneshot, ts); + priv->callback = NULL; + priv->arg = NULL; + leave_critical_section(flags); + + if (ret < 0) + { + tmrerr("ERROR: bm3803_oneshot_cancel failed: %d\n", flags); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: oneshot_initialize + * + * Description: + * Initialize the oneshot timer and return a oneshot lower half driver + * instance. + * + * Input Parameters: + * chan Timer counter channel to be used. + * resolution The required resolution of the timer in units of + * microseconds. NOTE that the range is restricted to the + * range of uint16_t (excluding zero). + * + * Returned Value: + * On success, a non-NULL instance of the oneshot lower-half driver is + * returned. NULL is return on any failure. + * + ****************************************************************************/ + +FAR struct oneshot_lowerhalf_s *oneshot_initialize(int chan, + uint16_t resolution) +{ + FAR struct bm3803_oneshot_lowerhalf_s *priv; + int ret; + + /* Allocate an instance of the lower half driver */ + + priv = (FAR struct bm3803_oneshot_lowerhalf_s *) + kmm_zalloc(sizeof(struct bm3803_oneshot_lowerhalf_s)); + + if (priv == NULL) + { + tmrerr("ERROR: Failed to initialized state structure\n"); + return NULL; + } + + /* Initialize the lower-half driver structure */ + + priv->lh.ops = &g_oneshot_ops; + + /* Initialize the contained STM32 oneshot timer */ + + ret = bm3803_oneshot_initialize(&priv->oneshot, chan, resolution); + if (ret < 0) + { + tmrerr("ERROR: bm3803_oneshot_initialize failed: %d\n", ret); + kmm_free(priv); + return NULL; + } + + return &priv->lh; +} diff --git a/arch/sparc/src/bm3803/bm3803_tickless.c b/arch/sparc/src/bm3803/bm3803_tickless.c new file mode 100644 index 00000000000..25cfa43b58f --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_tickless.c @@ -0,0 +1,339 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_tickless.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Tickless OS Support. + * + * When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts + * is suppressed and the platform specific code is expected to provide the + * following custom functions. + * + * void up_timer_initialize(void): Initializes the timer facilities. + * Called early in the initialization sequence (by up_initialize()). + * int up_timer_gettime(FAR struct timespec *ts): Returns the current + * time from the platform specific time source. + * int up_timer_cancel(void): Cancels the interval timer. + * int up_timer_start(FAR const struct timespec *ts): Start (or re-starts) + * the interval timer. + * + * The RTOS will provide the following interfaces for use by the platform- + * specific interval timer implementation: + * + * void nxsched_timer_expiration(void): Called by the platform-specific + * logic when the interval timer expires. + * + ****************************************************************************/ + +/**************************************************************************** + * BM3803 Timer Usage + * + * This current implementation uses two timers: A one-shot timer to provide + * the timed events and a free running timer to provide the current time. + * Since timers are a limited resource, that could be an issue on some + * systems. + * + * We could do the job with a single timer if we were to keep the single + * timer in a free-running at all times. The STM32 timer/counters have + * 16-bit/32-bit counters with the capability to generate a compare interrupt + * when the timer matches a compare value but also to continue counting + * without stopping (giving another, different interrupt when the timer + * rolls over from 0xffffffff to zero). So we could potentially just set + * the compare at the number of ticks you want PLUS the current value of + * timer. Then you could have both with a single timer: An interval timer + * and a free-running counter with the same timer! + * + * Patches are welcome! + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include +#include +#include + +#include "bm3803_oneshot.h" +#include "bm3803_freerun.h" + +#ifdef CONFIG_SCHED_TICKLESS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_BM3803_ONESHOT +# error CONFIG_BM3803_ONESHOT must be selected for the Tickless OS option +#endif + +#ifndef CONFIG_BM3803_FREERUN +# error CONFIG_BM3803_FREERUN must be selected for the Tickless OS option +#endif + +#ifndef CONFIG_BM3803_TICKLESS_FREERUN +# error CONFIG_BM3803_TICKLESS_FREERUN must be selected for the Tickless OS option +#endif + +#ifndef CONFIG_BM3803_TICKLESS_ONESHOT +# error CONFIG_BM3803_TICKLESS_ONESHOT must be selected for the Tickless OS option +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct bm3803_tickless_s +{ + struct bm3803_oneshot_s oneshot; + struct bm3803_freerun_s freerun; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct bm3803_tickless_s g_tickless; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_oneshot_handler + * + * Description: + * Called when the one shot timer expires + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called early in the initialization sequence before any special + * concurrency protections are required. + * + ****************************************************************************/ + +static void bm3803_oneshot_handler(FAR void *arg) +{ + tmrinfo("Expired...\n"); + nxsched_timer_expiration(); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_timer_initialize + * + * Description: + * Initializes all platform-specific timer facilities. This function is + * called early in the initialization sequence by up_initialize(). + * On return, the current up-time should be available from + * up_timer_gettime() and the interval timer is ready for use (but not + * actively timing. + * + * Provided by platform-specific code and called from the architecture- + * specific logic. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called early in the initialization sequence before any special + * concurrency protections are required. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ +#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP + uint64_t max_delay; +#endif + int ret; + + /* Initialize the one-shot timer */ + + ret = bm3803_oneshot_initialize(&g_tickless.oneshot, + CONFIG_BM3803_TICKLESS_ONESHOT, + CONFIG_USEC_PER_TICK); + if (ret < 0) + { + tmrerr("ERROR: bm3803_oneshot_initialize failed\n"); + DEBUGASSERT(0); + } + +#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP + /* Get the maximum delay of the one-shot timer in microseconds */ + + ret = bm3803_oneshot_max_delay(&g_tickless.oneshot, &max_delay); + if (ret < 0) + { + tmrerr("ERROR: bm3803_oneshot_max_delay failed\n"); + DEBUGASSERT(0); + } + + /* Convert this to configured clock ticks for use by the OS timer logic */ + + max_delay /= CONFIG_USEC_PER_TICK; + if (max_delay > UINT24_MAX) + { + g_oneshot_maxticks = UINT24_MAX; + } + else + { + g_oneshot_maxticks = max_delay; + } +#endif + + /* Initialize the free-running timer */ + + ret = bm3803_freerun_initialize(&g_tickless.freerun, + CONFIG_BM3803_TICKLESS_FREERUN, + CONFIG_USEC_PER_TICK); + if (ret < 0) + { + tmrerr("ERROR: bm3803_freerun_initialize failed\n"); + DEBUGASSERT(0); + } +} + +/**************************************************************************** + * Name: up_timer_gettime + * + * Description: + * Return the elapsed time since power-up (or, more correctly, since + * up_timer_initialize() was called). This function is functionally + * equivalent to: + * + * int clock_gettime(clockid_t clockid, FAR struct timespec *ts); + * + * when clockid is CLOCK_MONOTONIC. + * + * This function provides the basis for reporting the current time and + * also is used to eliminate error build-up from small errors in interval + * time calculations. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Provides the location in which to return the up-time. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * Called from the normal tasking context. The implementation must + * provide whatever mutual exclusion is necessary for correct operation. + * This can include disabling interrupts in order to assure atomic register + * operations. + * + ****************************************************************************/ + +int up_timer_gettime(FAR struct timespec *ts) +{ + return bm3803_freerun_counter(&g_tickless.freerun, ts); +} + +/**************************************************************************** + * Name: up_timer_cancel + * + * Description: + * Cancel the interval timer and return the time remaining on the timer. + * These two steps need to be as nearly atomic as possible. + * nxsched_timer_expiration() will not be called unless the timer is + * restarted with up_timer_start(). + * + * If, as a race condition, the timer has already expired when this + * function is called, then that pending interrupt must be cleared so + * that up_timer_start() and the remaining time of zero should be + * returned. + * + * NOTE: This function may execute at a high rate with no timer running (as + * when pre-emption is enabled and disabled). + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Location to return the remaining time. Zero should be returned + * if the timer is not active. ts may be zero in which case the + * time remaining is not returned. + * + * Returned Value: + * Zero (OK) is returned on success. A call to up_timer_cancel() when + * the timer is not active should also return success; a negated errno + * value is returned on any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_timer_cancel(FAR struct timespec *ts) +{ + return bm3803_oneshot_cancel(&g_tickless.oneshot, ts); +} + +/**************************************************************************** + * Name: up_timer_start + * + * Description: + * Start the interval timer. nxsched_timer_expiration() will be + * called at the completion of the timeout (unless up_timer_cancel + * is called to stop the timing. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Provides the time interval until nxsched_timer_expiration() is + * called. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_timer_start(FAR const struct timespec *ts) +{ + return bm3803_oneshot_start(&g_tickless.oneshot, bm3803_oneshot_handler, + NULL, ts); +} +#endif /* CONFIG_SCHED_TICKLESS */ diff --git a/arch/sparc/src/bm3803/bm3803_tim.c b/arch/sparc/src/bm3803/bm3803_tim.c new file mode 100644 index 00000000000..a2d7c2cc634 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_tim.c @@ -0,0 +1,648 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_tim.c + * + * 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 +#include +#include + +#include + +#include "chip.h" +#include "up_internal.h" +#include "up_arch.h" + +#include "bm3803.h" +#include "bm3803_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This module then only compiles if there are enabled timers that are not + * intended for some other purpose. + */ + +#if defined(CONFIG_BM3803_TIM1) || defined(CONFIG_BM3803_TIM2) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* TIM Device Structure */ + +struct bm3803_tim_priv_s +{ + FAR const struct bm3803_tim_ops_s *ops; + enum bm3803_tim_mode_e mode; + uint32_t base; /* TIMn base address */ +}; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +/* Register helpers */ + +static inline uint16_t bm3803_getreg16(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset); +static inline void bm3803_putreg16(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint16_t value); +static inline void bm3803_modifyreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint32_t clearbits, + uint32_t setbits); +static inline uint32_t bm3803_getreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset); +static inline void bm3803_putreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint32_t value); + +/* Timer helpers */ + +static void bm3803_tim_reload_counter(FAR struct bm3803_tim_dev_s *dev); +static void bm3803_tim_enable(FAR struct bm3803_tim_dev_s *dev); +static void bm3803_tim_disable(FAR struct bm3803_tim_dev_s *dev); +static void bm3803_tim_reset(FAR struct bm3803_tim_dev_s *dev); + +/* Timer methods */ + +static int bm3803_tim_setmode(FAR struct bm3803_tim_dev_s *dev, + enum bm3803_tim_mode_e mode); + +static int bm3803_tim_setclock(FAR struct bm3803_tim_dev_s *dev, + uint32_t freq); +static uint32_t bm3803_tim_getclock(FAR struct bm3803_tim_dev_s *dev); +static void bm3803_tim_setperiod(FAR struct bm3803_tim_dev_s *dev, + uint32_t period); +static uint32_t bm3803_tim_getperiod(FAR struct bm3803_tim_dev_s *dev); +static uint32_t bm3803_tim_getcounter(FAR struct bm3803_tim_dev_s *dev); + +static int bm3803_tim_setisr(FAR struct bm3803_tim_dev_s *dev, + xcpt_t handler, void *arg, int source); + +static int bm3803_tim_checkint(FAR struct bm3803_tim_dev_s *dev, int source); +static void bm3803_tim_clrint(FAR struct bm3803_tim_dev_s *dev, int source); +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct bm3803_tim_ops_s bm3803_tim_ops = +{ + .setmode = bm3803_tim_setmode, + .setclock = bm3803_tim_setclock, + .getclock = bm3803_tim_getclock, + .setperiod = bm3803_tim_setperiod, + .getperiod = bm3803_tim_getperiod, + .getcounter = bm3803_tim_getcounter, + .setisr = bm3803_tim_setisr, + .clrint = bm3803_tim_clrint, + .checkint = bm3803_tim_checkint, +}; + +#ifdef CONFIG_BM3803_TIM1 +struct bm3803_tim_priv_s bm3803_tim1_priv = +{ + .ops = &bm3803_tim_ops, + .mode = BM3803_TIM_MODE_UNUSED, + .base = BM3803_TIM1_BASE, +}; +#endif +#ifdef CONFIG_BM3803_TIM2 +struct bm3803_tim_priv_s bm3803_tim2_priv = +{ + .ops = &bm3803_tim_ops, + .mode = BM3803_TIM_MODE_UNUSED, + .base = BM3803_TIM2_BASE, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_getreg16 + * + * Description: + * Get a 16-bit register value by offset + * + ****************************************************************************/ + +static inline uint16_t bm3803_getreg16(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset) +{ + return getreg16(((struct bm3803_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: bm3803_putreg16 + * + * Description: + * Put a 16-bit register value by offset + * + ****************************************************************************/ + +static inline void bm3803_putreg16(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint16_t value) +{ + putreg16(value, ((struct bm3803_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: bm3803_modifyreg32 + * + * Description: + * Modify a 16-bit register value by offset + * + ****************************************************************************/ + +static inline void bm3803_modifyreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint32_t clearbits, + uint32_t setbits) +{ + modifyreg32(((struct bm3803_tim_priv_s *)dev)->base + offset, clearbits, + setbits); +} + +/**************************************************************************** + * Name: bm3803_getreg32 + * + * Description: + * Get a 24-bit register value by offset. This applies only for the bm3803 + * 24-bit registers (CNT, ARR, CRR1-4) in the 24-bit timers TIM2-5. + * + ****************************************************************************/ + +static inline uint32_t bm3803_getreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset) +{ + return getreg32(((struct bm3803_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: bm3803_putreg32 + * + * Description: + * Put a 24-bit register value by offset. This applies only for the bm3803 + * 24-bit registers (CNT, ARR, CRR1-4) in the 24-bit timers TIM2-5. + * + ****************************************************************************/ + +static inline void bm3803_putreg32(FAR struct bm3803_tim_dev_s *dev, + uint8_t offset, uint32_t value) +{ + putreg32(value, ((struct bm3803_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: bm3803_tim_reload_counter + ****************************************************************************/ + +static void bm3803_tim_reload_counter(FAR struct bm3803_tim_dev_s *dev) +{ + uint32_t val = bm3803_getreg32(dev, BM3803_TIM_CR_OFFSET); + val |= TIMER_LOADCOUNT; + bm3803_putreg32(dev, BM3803_TIM_CR_OFFSET, val); +} + +/**************************************************************************** + * Name: bm3803_tim_enable + ****************************************************************************/ + +static void bm3803_tim_enable(FAR struct bm3803_tim_dev_s *dev) +{ + uint32_t val = bm3803_getreg32(dev, BM3803_TIM_CR_OFFSET); + val |= TIMER_ENABLE | TIMER_RELOADCOUNT; + bm3803_tim_reload_counter(dev); + bm3803_putreg32(dev, BM3803_TIM_CR_OFFSET, val); +} + +/**************************************************************************** + * Name: bm3803_tim_disable + ****************************************************************************/ + +static void bm3803_tim_disable(FAR struct bm3803_tim_dev_s *dev) +{ + uint32_t val = bm3803_getreg32(dev, BM3803_TIM_CR_OFFSET); + val &= ~TIMER_ENABLE; + bm3803_putreg32(dev, BM3803_TIM_CR_OFFSET, val); +} + +/**************************************************************************** + * Name: bm3803_tim_reset + * + * Description: + * Reset timer into system default state, but do not affect output/input pins + * + ****************************************************************************/ + +static void bm3803_tim_reset(FAR struct bm3803_tim_dev_s *dev) +{ + ((struct bm3803_tim_priv_s *)dev)->mode = BM3803_TIM_MODE_DISABLED; + bm3803_tim_disable(dev); +} + +/**************************************************************************** + * Name: bm3803_tim_setmode + ****************************************************************************/ + +static int bm3803_tim_setmode(FAR struct bm3803_tim_dev_s *dev, + enum bm3803_tim_mode_e mode) +{ + uint32_t val = bm3803_getreg32(dev, BM3803_TIM_CR_OFFSET); + + DEBUGASSERT(dev != NULL); + + /* Decode operational modes */ + + switch (mode & BM3803_TIM_MODE_MASK) + { + case BM3803_TIM_MODE_DISABLED: + val &= (~TIMER_LOADCOUNT) & (~TIMER_RELOADCOUNT) & (~TIMER_ENABLE); + break; + + case BM3803_TIM_MODE_DOWN: + val |= (TIMER_LOADCOUNT | TIMER_RELOADCOUNT | TIMER_ENABLE); + break; + + default: + return -EINVAL; + } + + bm3803_tim_reload_counter(dev); + bm3803_putreg32(dev, BM3803_TIM_CR_OFFSET, val); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_tim_setclock + ****************************************************************************/ + +static int bm3803_tim_setclock(FAR struct bm3803_tim_dev_s *dev, + uint32_t freq) +{ + uint32_t freqin; + int prescaler; + + DEBUGASSERT(dev != NULL); + + /* Disable Timer? */ + + if (freq == 0) + { + bm3803_tim_disable(dev); + return 0; + } + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + freqin = BOARD_TIM1_FREQUENCY; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + freqin = BOARD_TIM2_FREQUENCY; + break; +#endif + + default: + return -EINVAL; + } + + /* Select a pre-scaler value for this timer using the input clock + * frequency. + */ + + prescaler = freqin / freq; + + /* We need to decrement value for '1', but only, if that will not to + * cause underflow. + */ + + if (prescaler > 0) + { + prescaler--; + } + + /* Check for overflow as well. */ + + if (prescaler > 0x3ff) + { + prescaler = 0x3ff; + } + + putreg32(prescaler, BM3803_TIM12PRE_BASE + BM3803_TIM_PSCLOAD_OFFSET); + putreg32(prescaler, BM3803_TIM12PRE_BASE + BM3803_TIM_PSCCONT_OFFSET); + bm3803_tim_enable(dev); + + return prescaler; +} + +/**************************************************************************** + * Name: bm3803_tim_getclock + ****************************************************************************/ + +static uint32_t bm3803_tim_getclock(FAR struct bm3803_tim_dev_s *dev) +{ + uint32_t freqin; + uint32_t clock; + DEBUGASSERT(dev != NULL); + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + freqin = BOARD_TIM1_FREQUENCY; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + freqin = BOARD_TIM2_FREQUENCY; + break; +#endif + default: + return -EINVAL; + } + + /* From chip datasheet, at page 1179. */ + + clock = freqin / ((0x3ff & getreg32(BM3803_TIM12PRE_BASE + + BM3803_TIM_PSCLOAD_OFFSET)) + 1); + + return clock; +} + +/**************************************************************************** + * Name: bm3803_tim_setperiod + ****************************************************************************/ + +static void bm3803_tim_setperiod(FAR struct bm3803_tim_dev_s *dev, + uint32_t period) +{ + DEBUGASSERT(dev != NULL); + bm3803_putreg32(dev, BM3803_TIM_ARR_OFFSET, period); + bm3803_putreg32(dev, BM3803_TIM_CNT_OFFSET, period); +} + +/**************************************************************************** + * Name: bm3803_tim_getperiod + ****************************************************************************/ + +static uint32_t bm3803_tim_getperiod (FAR struct bm3803_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + return 0xffffff & bm3803_getreg32(dev, BM3803_TIM_ARR_OFFSET); +} + +/**************************************************************************** + * Name: bm3803_tim_getcounter + ****************************************************************************/ + +static uint32_t bm3803_tim_getcounter(FAR struct bm3803_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + uint32_t counter = bm3803_getreg32(dev, BM3803_TIM_CNT_OFFSET); + + return counter & 0x00ffffff; +} + +/**************************************************************************** + * Name: bm3803_tim_setisr + ****************************************************************************/ + +static int bm3803_tim_setisr(FAR struct bm3803_tim_dev_s *dev, + xcpt_t handler, void *arg, int source) +{ + int vectorno; + + DEBUGASSERT(dev != NULL); + DEBUGASSERT(source == 0); + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + vectorno = BM3803_IRQ_TIMER1; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + vectorno = BM3803_IRQ_TIMER2; + break; +#endif + + default: + vectorno = BM3803_IRQ_TIMER1; + return -EINVAL; + } + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(vectorno); + irq_detach(vectorno); + return OK; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(vectorno, handler, arg); + up_enable_irq(vectorno); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_tim_clrint + ****************************************************************************/ + +static void bm3803_tim_clrint(FAR struct bm3803_tim_dev_s *dev, int source) +{ + int vectorno; + + DEBUGASSERT(dev != NULL); + DEBUGASSERT(source == 0); + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + vectorno = BM3803_IRQ_TIMER1; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + vectorno = BM3803_IRQ_TIMER2; + break; +#endif + + default: + break; + } + + up_clrpend_irq(vectorno); +} + +/**************************************************************************** + * Name: bm3803_tim_checkint + ****************************************************************************/ + +static int bm3803_tim_checkint(FAR struct bm3803_tim_dev_s *dev, int source) +{ + int vectorno; + + DEBUGASSERT(dev != NULL); + DEBUGASSERT(source == 0); + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + vectorno = BM3803_IRQ_TIMER1; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + vectorno = BM3803_IRQ_TIMER2; + break; +#endif + + default: + return -EINVAL; + } + + return up_pending_irq(vectorno); +} + +/**************************************************************************** + * Pubic Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_tim_init + ****************************************************************************/ + +FAR struct bm3803_tim_dev_s *bm3803_tim_init(int timer) +{ + struct bm3803_tim_dev_s *dev = NULL; + + /* Get structure and enable power */ + + switch (timer) + { +#ifdef CONFIG_BM3803_TIM1 + case 1: + dev = (struct bm3803_tim_dev_s *)&bm3803_tim1_priv; + + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case 2: + dev = (struct bm3803_tim_dev_s *)&bm3803_tim2_priv; + + break; +#endif + + default: + return NULL; + } + + /* Is device already allocated */ + + if (((struct bm3803_tim_priv_s *)dev)->mode != BM3803_TIM_MODE_UNUSED) + { + return NULL; + } + + bm3803_tim_reset(dev); + + return dev; +} + +/**************************************************************************** + * Name: bm3803_tim_deinit + * + * TODO: Detach interrupts, and close down all TIM Channels + * + ****************************************************************************/ + +int bm3803_tim_deinit(FAR struct bm3803_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + + /* Disable power */ + + switch (((struct bm3803_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_BM3803_TIM1 + case BM3803_TIM1_BASE: + + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case BM3803_TIM2_BASE: + + break; +#endif + default: + return -EINVAL; + } + + /* Mark it as free */ + + ((struct bm3803_tim_priv_s *)dev)->mode = BM3803_TIM_MODE_UNUSED; + + return OK; +} + +#endif /* defined(CONFIG_BM3803_TIM1 || CONFIG_BM3803_TIM2) */ diff --git a/arch/sparc/src/bm3803/bm3803_tim.h b/arch/sparc/src/bm3803/bm3803_tim.h new file mode 100644 index 00000000000..449788c024c --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_tim.h @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_tim.h + * + * 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_SPARC_SRC_BM3803_BM3803_TIM_H +#define __ARCH_SPARC_SRC_BM3803_BM3803_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define BM3803_TIM1_BASE 0x80000040 +#define BM3803_TIM2_BASE 0x80000050 +#define BM3803_TIM12PRE_BASE 0x80000060 + +#define BM3803_TIM_WDG_OFFSET 0x000C /* wdg register 1 (16-bit) */ +#define BM3803_TIM_CR_OFFSET 0x0008 /* Control register 1 (16-bit) */ +#define BM3803_TIM_CNT_OFFSET 0x0000 /* Counter (16-bit) */ +#define BM3803_TIM_ARR_OFFSET 0x0004 /* Auto-reload register (16-bit) */ + +#define BM3803_TIM_PSCLOAD_OFFSET 0x0004 /* Prescaler load (16-bit) */ +#define BM3803_TIM_PSCCONT_OFFSET 0x0000 /* Prescaler count (16-bit) */ + +#define TIMER_WDG 0x10 +#define TIMER_LOADCOUNT 0x4 +#define TIMER_RELOADCOUNT 0x2 +#define TIMER_ENABLE 0x1 + +# define UINT24_MAX 16777215u +/* Helpers ******************************************************************/ +#define BM3803_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define BM3803_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define BM3803_TIM_GETCLOCK(d) ((d)->ops->getclock(d)) +#define BM3803_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define BM3803_TIM_GETPERIOD(d) ((d)->ops->getperiod(d)) +#define BM3803_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d)) +#define BM3803_TIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s)) +#define BM3803_TIM_CLRINT(d,s) ((d)->ops->clrint(d,s)) +#define BM3803_TIM_CHECKINT(d,s) ((d)->ops->checkint(d,s)) +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* TIM Device Structure */ + +struct bm3803_tim_dev_s +{ + struct bm3803_tim_ops_s *ops; +}; + +enum bm3803_tim_mode_e +{ + BM3803_TIM_MODE_UNUSED = -1, + + /* One of the following */ + + BM3803_TIM_MODE_MASK = 0x3, + BM3803_TIM_MODE_DISABLED = 0x1, + BM3803_TIM_MODE_DOWN = 0x2, +}; + +/* TIM Operations */ + +struct bm3803_tim_ops_s +{ + /* Basic Timers */ + + int (*setmode)(FAR struct bm3803_tim_dev_s *dev, + enum bm3803_tim_mode_e mode); + int (*setclock)(FAR struct bm3803_tim_dev_s *dev, uint32_t freq); + uint32_t (*getclock)(FAR struct bm3803_tim_dev_s *dev); + void (*setperiod)(FAR struct bm3803_tim_dev_s *dev, uint32_t period); + uint32_t (*getperiod)(FAR struct bm3803_tim_dev_s *dev); + uint32_t (*getcounter)(FAR struct bm3803_tim_dev_s *dev); + + /* Timer interrupts */ + + int (*setisr)(FAR struct bm3803_tim_dev_s *dev, + xcpt_t handler, void *arg, int source); + void (*clrint)(FAR struct bm3803_tim_dev_s *dev, int source); + int (*checkint)(FAR struct bm3803_tim_dev_s *dev, int source); +}; + +/* Power-up timer and get its structure */ + +FAR struct bm3803_tim_dev_s *bm3803_tim_init(int timer); + +/* Power-down timer, mark it as unused */ + +int bm3803_tim_deinit(FAR struct bm3803_tim_dev_s *dev); + +/**************************************************************************** + * Name: bm3803_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the form + * /dev/timer0 + * timer - the timer number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_TIMER +int bm3803_timer_initialize(FAR const char *devpath, int timer); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_TIM_H */ diff --git a/arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c b/arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c new file mode 100644 index 00000000000..9a256c6d1a1 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c @@ -0,0 +1,464 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_tim_lowerhalf.c + * + * 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 + +#include "bm3803_tim.h" + +#if defined(CONFIG_TIMER) && \ + (defined(CONFIG_BM3803_TIM1) || defined(CONFIG_BM3803_TIM2)) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BM3803_TIM1_RES 24 +#define BM3803_TIM2_RES 24 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * timer_lowerhalf_s structure. + */ + +struct bm3803_lowerhalf_s +{ + FAR const struct timer_ops_s *ops; /* Lower half operations */ + FAR struct bm3803_tim_dev_s *tim; /* stm32 timer driver */ + tccb_t callback; /* Current upper half interrupt + * callback */ + FAR void *arg; /* Argument passed to upper half + * callback */ + bool started; /* True: Timer has been started */ + const uint8_t resolution; /* Number of bits in the timer + * (16 or 32 bits) */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Interrupt handling *******************************************************/ + +static int bm3803_timer_handler(int irq, void *context, void *arg); + +/* "Lower half" driver methods **********************************************/ + +static int bm3803_start(FAR struct timer_lowerhalf_s *lower); +static int bm3803_stop(FAR struct timer_lowerhalf_s *lower); +static int bm3803_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +static int bm3803_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void bm3803_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_timer_ops = +{ + .start = bm3803_start, + .stop = bm3803_stop, + .getstatus = bm3803_getstatus, + .settimeout = bm3803_settimeout, + .setcallback = bm3803_setcallback, + .ioctl = NULL, +}; + +#ifdef CONFIG_BM3803_TIM1 +static struct bm3803_lowerhalf_s g_tim1_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = BM3803_TIM1_RES, +}; +#endif + +#ifdef CONFIG_BM3803_TIM2 +static struct bm3803_lowerhalf_s g_tim2_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = BM3803_TIM2_RES, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_timer_handler + * + * Description: + * timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int bm3803_timer_handler(int irq, void *context, void *arg) +{ + FAR struct bm3803_lowerhalf_s *lower = + (FAR struct bm3803_lowerhalf_s *)arg; + uint32_t next_interval_us = 0; + + BM3803_TIM_ACKINT(lower->tim, 0); + + if (lower->callback(&next_interval_us, lower->arg)) + { + if (next_interval_us > 0) + { + BM3803_TIM_SETPERIOD(lower->tim, next_interval_us); + } + } + else + { + bm3803_stop((struct timer_lowerhalf_s *)lower); + } + + return OK; +} + +/**************************************************************************** + * Name: bm3803_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_start(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + + if (!priv->started) + { + BM3803_TIM_SETMODE(priv->tim, BM3803_TIM_MODE_DOWN); + + if (priv->callback != NULL) + { + BM3803_TIM_SETISR(priv->tim, bm3803_timer_handler, priv, 0); + } + + priv->started = true; + return OK; + } + + /* Return EBUSY to indicate that the timer was already running */ + + return -EBUSY; +} + +/**************************************************************************** + * Name: bm3803_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_stop(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + + if (priv->started) + { + BM3803_TIM_SETMODE(priv->tim, BM3803_TIM_MODE_DISABLED); + BM3803_TIM_SETISR(priv->tim, NULL, NULL, 0); + priv->started = false; + return OK; + } + + /* Return ENODEV to indicate that the timer was not running */ + + return -ENODEV; +} + +/**************************************************************************** + * Name: bm3803_getstatus + * + * Description: + * get timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + uint64_t maxtimeout; + uint32_t timeout; + uint32_t clock; + uint32_t period; + uint32_t clock_factor; + + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = 0; + if (priv->started) + { + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback) + { + status->flags |= TCFLAGS_HANDLER; + } + + /* Get timeout */ + + maxtimeout = (1 << priv->resolution) - 1; + clock = BM3803_TIM_GETCLOCK(priv->tim); + period = BM3803_TIM_GETPERIOD(priv->tim); + + if (clock == 1000000) + { + timeout = period; + } + else + { + timeout = (maxtimeout * 1000000) / clock; + } + + status->timeout = timeout; + + /* Get the time remaining until the timer expires (in microseconds) */ + + clock_factor = (clock == 1000000)? 1: (clock / 1000000); + status->timeleft = (timeout - BM3803_TIM_GETCOUNTER(priv->tim)) * + clock_factor; + return OK; +} + +/**************************************************************************** + * Name: bm3803_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + uint64_t maxtimeout; + + if (priv->started) + { + return -EPERM; + } + + maxtimeout = (1 << priv->resolution) - 1; + if (timeout > maxtimeout) + { + uint64_t freq = (maxtimeout * 1000000) / timeout; + BM3803_TIM_SETCLOCK(priv->tim, freq); + BM3803_TIM_SETPERIOD(priv->tim, maxtimeout); + } + else + { + BM3803_TIM_SETCLOCK(priv->tim, 1000000); + BM3803_TIM_SETPERIOD(priv->tim, timeout); + } + + return OK; +} + +/**************************************************************************** + * Name: bm3803_sethandler + * + * Description: + * Call this user provided timeout handler. + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void bm3803_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + irqstate_t flags = enter_critical_section(); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + if (callback != NULL && priv->started) + { + BM3803_TIM_SETISR(priv->tim, bm3803_timer_handler, priv, 0); + } + else + { + BM3803_TIM_SETISR(priv->tim, NULL, NULL, 0); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int bm3803_timer_initialize(FAR const char *devpath, int timer) +{ + FAR struct bm3803_lowerhalf_s *lower; + + switch (timer) + { +#ifdef CONFIG_BM3803_TIM1 + case 1: + lower = &g_tim1_lowerhalf; + break; +#endif + +#ifdef CONFIG_BM3803_TIM2 + case 2: + lower = &g_tim2_lowerhalf; + break; +#endif + + default: + return -ENODEV; + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = bm3803_tim_init(timer); + + if (lower->tim == NULL) + { + return -EINVAL; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discard here. + */ + + FAR void *drvr = timer_register(devpath, + (FAR struct timer_lowerhalf_s *)lower); + if (drvr == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'depath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + return -EEXIST; + } + + return OK; +} + +#endif /* CONFIG_TIMER */ diff --git a/arch/sparc/src/bm3803/bm3803_wdg.c b/arch/sparc/src/bm3803/bm3803_wdg.c new file mode 100644 index 00000000000..615eec7b746 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_wdg.c @@ -0,0 +1,433 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_wdg.c + * + * 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 +#include +#include + +#include "up_arch.h" +#include "bm3803_wdg.h" + +#if defined(CONFIG_WATCHDOG) && defined(CONFIG_BM3803_WDG) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +#ifndef CONFIG_BM3803_WDG_DEFTIMOUT +# define CONFIG_BM3803_WDG_DEFTIMOUT 1000 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * well-known watchdog_lowerhalf_s structure. + */ + +struct bm3803_lowerhalf_s +{ + /* Lower half operations */ + + FAR const struct watchdog_ops_s *ops; + uint32_t timeout; /* The (actual) selected timeout */ + uint32_t lastreset; /* The last reset time */ + bool started; /* true: The watchdog timer has been started */ + uint16_t prescaler; /* Clock prescaler value */ + uint32_t reload; /* Timer reload value */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Register operations ******************************************************/ + +# define bm3803_getreg(addr) getreg32(addr) +# define bm3803_putreg(val,addr) putreg32(val,addr) + +static inline void bm3803_setreload(FAR struct bm3803_lowerhalf_s *priv); + +/* "Lower half" driver methods **********************************************/ + +static int bm3803_start(FAR struct watchdog_lowerhalf_s *lower); +static int bm3803_stop(FAR struct watchdog_lowerhalf_s *lower); +static int bm3803_keepalive(FAR struct watchdog_lowerhalf_s *lower); +static int bm3803_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status); +static int bm3803_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct watchdog_ops_s g_wdgops = +{ + .start = bm3803_start, + .stop = bm3803_stop, + .keepalive = bm3803_keepalive, + .getstatus = bm3803_getstatus, + .settimeout = bm3803_settimeout, + .capture = NULL, + .ioctl = NULL, +}; + +/* "Lower half" driver state */ + +static struct bm3803_lowerhalf_s g_wdgdev; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_setreload + * + * Description: + * Set up the prescaler and reload values. + * + * Input Parameters: + * priv - A pointer the internal representation of the "lower-half" + * driver state structure. + * + ****************************************************************************/ + +static inline void bm3803_setreload(FAR struct bm3803_lowerhalf_s *priv) +{ + /* Set the reload value */ + + bm3803_putreg(priv->reload, BM3803_TIM1_BASE + BM3803_TIM_WDG_OFFSET); +} + +/**************************************************************************** + * Name: bm3803_start + * + * Description: + * Start the watchdog timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_start(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + irqstate_t flags; + uint32_t val = bm3803_getreg(BM3803_TIM1_BASE + BM3803_TIM_CR_OFFSET); + val |= TIMER_WDG; + + wdinfo("Entry: started=%d\n"); + DEBUGASSERT(priv); + + /* Have we already been started? */ + + if (!priv->started) + { + /* Set up prescaler and reload value for the selected timeout before + * starting the watchdog timer. + */ + + bm3803_setreload(priv); + + /* Enable WDG (the LSI oscillator will be enabled by hardware). NOTE: + * If the "Hardware watchdog" feature is enabled through the device + * option bits, the watchdog is automatically enabled at power-on. + */ + + flags = enter_critical_section(); + bm3803_putreg(val, BM3803_TIM1_BASE + BM3803_TIM_CR_OFFSET); + priv->lastreset = clock_systime_ticks(); + priv->started = true; + leave_critical_section(flags); + } + + return OK; +} + +/**************************************************************************** + * Name: bm3803_stop + * + * Description: + * Stop the watchdog timer + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_stop(FAR struct watchdog_lowerhalf_s *lower) +{ + uint32_t val = bm3803_getreg(BM3803_TIM1_BASE + BM3803_TIM_CR_OFFSET); + + wdinfo("Entry\n"); + + val &= ~TIMER_WDG; + + bm3803_putreg(val, BM3803_TIM1_BASE + BM3803_TIM_CR_OFFSET); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_keepalive + * + * Description: + * Reset the watchdog timer to the current timeout value, prevent any + * imminent watchdog timeouts. This is sometimes referred as "pinging" + * the watchdog timer or "petting the dog". + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_keepalive(FAR struct watchdog_lowerhalf_s *lower) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + irqstate_t flags; + + wdinfo("Entry\n"); + + /* Reload the WDG timer */ + + flags = enter_critical_section(); + bm3803_setreload(priv); + priv->lastreset = clock_systime_ticks(); + leave_critical_section(flags); + + return OK; +} + +/**************************************************************************** + * Name: bm3803_getstatus + * + * Description: + * Get the current watchdog timer status + *putreg32(value, ((struct bm3803_tim_priv_s *)dev)->base + offset); + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * status - The location to return the watchdog status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_getstatus(FAR struct watchdog_lowerhalf_s *lower, + FAR struct watchdog_status_s *status) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + uint32_t ticks; + uint32_t elapsed; + + wdinfo("Entry\n"); + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = WDFLAGS_RESET; + if (priv->started) + { + status->flags |= WDFLAGS_ACTIVE; + } + + /* Return the actual timeout in milliseconds */ + + status->timeout = priv->timeout; + + /* Get the elapsed time since the last ping */ + + ticks = clock_systime_ticks() - priv->lastreset; + elapsed = (int32_t)TICK2MSEC(ticks); + + if (elapsed > priv->timeout) + { + elapsed = priv->timeout; + } + + /* Return the approximate time until the watchdog timer expiration */ + + status->timeleft = priv->timeout - elapsed; + + wdinfo("Status :\n"); + wdinfo(" flags : %08x\n", status->flags); + wdinfo(" timeout : %d\n", status->timeout); + wdinfo(" timeleft : %d\n", status->timeleft); + return OK; +} + +/**************************************************************************** + * Name: bm3803_settimeout + * + * Description: + * Set a new timeout value (and reset the watchdog timer) + * + * Input Parameters: + * lower- A pointer the publicly visible representation of the "lower-half" + * driver state structure. + * timeout - The new timeout value in milliseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int bm3803_settimeout(FAR struct watchdog_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct bm3803_lowerhalf_s *priv = + (FAR struct bm3803_lowerhalf_s *)lower; + uint32_t reload; + uint16_t prescaler; + uint32_t freqin; + uint32_t clock; + + wdinfo("Entry: timeout=%d\n", timeout); + DEBUGASSERT(priv); + + /* Can this timeout be represented? */ + + if (timeout < 1) + { + wderr("ERROR: Cannot represent timeout=%d \n", timeout); + return -ERANGE; + } + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + freqin = BOARD_TIM1_FREQUENCY; + + prescaler = 0x3ff & bm3803_getreg(BM3803_TIM12PRE_BASE + + BM3803_TIM_PSCLOAD_OFFSET); + + clock = freqin / (prescaler + 1); + + reload = (timeout / 1000) * clock; + + priv->timeout = timeout; + + /* Save setup values for later use */ + + priv->prescaler = prescaler; + priv->reload = reload; + + /* Write the prescaler and reload values to the WDG registers. */ + + if (priv->started) + { + bm3803_setreload(priv); + } + + wdinfo("reload=%d\n", reload); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_wdginitialize + * + * Description: + * Initialize the WDG watchdog timer.The watchdog timer is initialized and + * registers as 'devpath'. The initial state of the watchdog timer is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * + * Returned Value: + * None + * + ****************************************************************************/ + +void bm3803_wdginitialize(FAR const char *devpath) +{ + FAR struct bm3803_lowerhalf_s *priv = &g_wdgdev; + + wdinfo("Entry: devpath=%s \n", devpath); + + /* NOTE we assume that clocking to the WDG has already been provided by + * the RCC initialization logic. + */ + + /* Initialize the driver state structure. */ + + priv->ops = &g_wdgops; + priv->started = false; + + /* Select an arbitrary initial timeout value. But don't start the watchdog + * yet. NOTE: If the "Hardware watchdog" feature is enabled through the + * device option bits, the watchdog is automatically enabled at power-on. + */ + + bm3803_settimeout((FAR struct watchdog_lowerhalf_s *)priv, + CONFIG_BM3803_WDG_DEFTIMOUT); + + /* Register the watchdog driver as /dev/watchdog0 */ + + (void)watchdog_register(devpath, (FAR struct watchdog_lowerhalf_s *)priv); +} + +#endif /* CONFIG_WATCHDOG && CONFIG_BM3803_WDG */ diff --git a/arch/sparc/src/bm3803/bm3803_wdg.h b/arch/sparc/src/bm3803/bm3803_wdg.h new file mode 100644 index 00000000000..cb60b7a6f82 --- /dev/null +++ b/arch/sparc/src/bm3803/bm3803_wdg.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/bm3803_wdg.h + * + * 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_SPARC_SRC_BM3803_BM3803_WDG_H +#define __ARCH_SPARC_SRC_BM3803_BM3803_WDG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "bm3803_tim.h" + +#ifdef CONFIG_WATCHDOG + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: bm3803_wdginitialize + * + * Description: + * Initialize the IWDG watchdog time. The watchdog timer is initialized + * and registers as 'devpath. The initial state of the watchdog time is + * disabled. + * + * Input Parameters: + * devpath - The full path to the watchdog. This should be of the form + * /dev/watchdog0 + * lsifreq - The calibrated LSI clock frequency + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_BM3803_WDG +void bm3803_wdginitialize(FAR const char *devpath); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* CONFIG_WATCHDOG */ +#endif /* __ARCH_SPARC_SRC_BM3803_BM3803_WDG_H */ diff --git a/arch/sparc/src/bm3803/chip.h b/arch/sparc/src/bm3803/chip.h new file mode 100644 index 00000000000..dfe3f2d2075 --- /dev/null +++ b/arch/sparc/src/bm3803/chip.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * arch/sparc/src/bm3803/chip.h + * + * 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_SPARC_SRC_BM3803_CHIP_H +#define __ARCH_SPARC_SRC_BM3803_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include only the memory map. Other chip hardware files should then + * include this file for the proper setup + */ + +#include "bm3803-memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Define features for supported chip in the SPARC family */ + +#if 1 +#else +# error "Unsupported SPARC chip" +#endif + +#endif /* __ARCH_SPARC_SRC_BM3803_CHIP_H */ + diff --git a/arch/sparc/src/bm3823/Kconfig b/arch/sparc/src/bm3823/Kconfig new file mode 100644 index 00000000000..18e415fef50 --- /dev/null +++ b/arch/sparc/src/bm3823/Kconfig @@ -0,0 +1,42 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_BM3823 +comment "BM3823 Configuration Options" + +menu "BM3823 Peripheral Support" + +config BM3823_WDT + bool "Watchdog timer (WDT)" + default n + +config BM3823_T1 + bool "Timer 1 (T1)" + default n + +config BM3823_T2 + bool "Timer 2 (T2)" + default n + +config BM3823_UART1 + bool "UART1" + default n + select UART1_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config BM3823_UART2 + bool "UART2" + default n + select UART2_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +config BM3823_UART3 + bool "UART3" + default n + select UART3_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + +endmenu # BM3823 Peripheral Selections +endif diff --git a/arch/sparc/src/bm3823/Make.defs b/arch/sparc/src/bm3823/Make.defs new file mode 100644 index 00000000000..5b380c53615 --- /dev/null +++ b/arch/sparc/src/bm3823/Make.defs @@ -0,0 +1,59 @@ +############################################################################ +# arch/sparc/src/bm3823/Make.defs +# +# 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 = bm3823_head.S + +# Common SPARC files + +CMN_ASRCS = up_syscall.S +CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c +CMN_CSRCS += up_createstack.c up_doirq.c up_exit.c up_idle.c up_initialize.c +CMN_CSRCS += up_initialstate.c up_interruptcontext.c up_irq.c up_lowputs.c +CMN_CSRCS += up_mdelay.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c +CMN_CSRCS += up_puts.c up_releasepending.c up_releasestack.c +CMN_CSRCS += up_reprioritizertr.c up_schedulesigaction.c up_sigdeliver.c +CMN_CSRCS += up_stackframe.c up_swint1.c up_udelay.c up_unblocktask.c up_usestack.c + +# Configuration-dependent common files + +ifeq ($(CONFIG_ARCH_STACKDUMP),y) +CMN_CSRCS += up_dumpstate.c +endif + +ifeq ($(CONFIG_STACK_COLORATION),y) +CMN_CSRCS += up_checkstack.c +endif + +# Required bm3823 files + +CHIP_ASRCS = bm3823_exceptions.S +CHIP_CSRCS = bm3823-lowconsole.c bm3823-lowinit.c bm3823-serial.c bm3823-irq.c + +ifneq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += bm3823-timerisr.c +endif + +# Configuration-dependent files + +ifeq ($(CONFIG_SPARC_GPIOIRQ),y) +CHIP_CSRCS += +endif diff --git a/arch/sparc/src/bm3823/bm3823-config.h b/arch/sparc/src/bm3823/bm3823-config.h new file mode 100644 index 00000000000..fe9fe57ed4d --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-config.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-config.h + * + * 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_SPARC_SRC_BM3823_CONFIG_H +#define __ARCH_SPARC_SRC_BM3823_CONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +#include "bm3823-memorymap.h" +#include "bm3823-uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SYS calls ****************************************************************/ + +/* SYS call 1 and 2 are defined for internal use by the BM3823 port (see + * arch/sparc/include/sparc32/syscall.h). In addition, SYS call 3 is the + * return from a SYS call in kernel mode. The first four syscall values must + * therefore, be + * reserved (0 is not used). + */ + +#ifdef CONFIG_BUILD_KERNEL +# if !defined(CONFIG_SYS_RESERVED) || CONFIG_SYS_RESERVED < 4 +# error "CONFIG_SYS_RESERVED must be defined to be 4 for a kernel build" +# elif CONFIG_SYS_RESERVED > 4 +# warning "CONFIG_SYS_RESERVED should be defined to be 4 for a kernel build" +# endif +#endif + +/* UARTs ********************************************************************/ + +/* Don't enable UARTs not supported by the chip. */ + +#if CHIP_NUARTS < 1 +# undef CONFIG_BM3823_UART1 +# undef CONFIG_BM3823_UART2 +# undef CONFIG_BM3823_UART3 +#elif CHIP_NUARTS < 2 +# undef CONFIG_BM3823_UART2 +# undef CONFIG_BM3823_UART3 +#elif CHIP_NUARTS < 3 +# undef CONFIG_BM3823_UART3 +#endif + +/* Are any UARTs enabled? */ + +#undef HAVE_UART_DEVICE +#if defined(CONFIG_BM3823_UART1) || defined(CONFIG_BM3823_UART2) || defined(CONFIG_BM3823_UART3) +# define HAVE_UART_DEVICE 1 +#endif + +/* Is there a serial console? There should be no more than one defined. It + * could be on any UARTn, n=1,.. CHIP_NUARTS + */ + +#if defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_BM3823_UART1) +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_BM3823_UART2) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_BM3823_UART3) +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# define HAVE_SERIAL_CONSOLE 1 +#else +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# undef HAVE_SERIAL_CONSOLE +#endif + +#endif /* __ARCH_SPARC_SRC_BM3823_CONFIG_H */ diff --git a/arch/sparc/src/bm3823/bm3823-irq.c b/arch/sparc/src/bm3823/bm3823-irq.c new file mode 100644 index 00000000000..32ff02938e3 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-irq.c @@ -0,0 +1,327 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-irq.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +#include "bm3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint32_t *g_current_regs; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifndef CONFIG_ARCH_IRQPRIO +static int up_prioritize_irq(int irq, int priority); +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + int irq; + + for (irq = 1; irq < NR_IRQS; irq++) + { + /* Skip window overflow, underflow, and flush as well as software + * trap 0,9,10 which we will use as a shutdown, IRQ disable, IRQ enable. + * Also avoid trap 0x70 - 0x7f which cannot happen and where some of the + * space is used to pass parameters to the program. + */ + + if (((irq >= 0x00) && (irq <= 0x11)) || ((irq >= 0x20) && + (irq <= 0xff))) + { + continue; + } + + /* Set all interrupts to the default (low) priority */ + + up_prioritize_irq(irq, 0); + + /* Disable all interrupts */ + + up_disable_irq(irq); + } + + /* Initialize GPIO change notification handling */ + +#ifdef CONFIG_BM3823_GPIOIRQ + bm3823_gpioirqinitialize(); +#endif + + /* Attach software interrupts */ + + irq_attach(BM3823_IRQ_SW_SYSCALL_TA0, up_swint0, NULL); + irq_attach(BM3823_IRQ_SW_SYSCALL_TA8, up_swint1, NULL); + + /* currents_regs is non-NULL only while processing an interrupt */ + + g_current_regs = NULL; + + /* And finally, enable interrupts */ + + /* Interrupts are enabled by setting the te bit in the psr status + * register + */ + + up_irq_enable(); +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + int bitno; + + /* Disable the interrupt by clearing the associated bit in the IEC + * register + */ + + DEBUGASSERT(irq >= BM3823_IRQ_FIRST_INTERRUPT && + irq <= BM3823_IRQ_LAST_INTERRUPT); + if (irq >= BM3823_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3823_IRQ_LAST_INTERRUPT) + { + /* Disable the interrupt */ + + bitno = irq - BM3823_IRQ_FIRST_INTERRUPT - 1; + INTER_REG.int_mask &= (~(1 << bitno)); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + int bitno; + + /* Enable the interrupt by setting the associated bit in the Interrupt_Mask + * Register + */ + + DEBUGASSERT(irq >= BM3823_IRQ_FIRST_INTERRUPT && + irq <= BM3823_IRQ_LAST_INTERRUPT); + if (irq >= BM3823_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3823_IRQ_LAST_INTERRUPT) + { + /* Enable the interrupt */ + + bitno = irq - BM3823_IRQ_FIRST_INTERRUPT + 1; + INTER_REG.int_mask |= (1 << bitno); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_pending_irq + * + * Description: + * Return true if the interrupt is pending and unmasked. + * + ****************************************************************************/ + +bool up_pending_irq(int irq) +{ + int bitno; + uint16_t regval; + uint16_t regval1; + uint16_t regval2; + + /* Test if the interrupt is pending by reading both the IEC and IFS + * register. Return true if the bit associated with the irq is both pending + * the IFs and enabled in the IEC. + */ + + DEBUGASSERT(irq >= BM3823_IRQ_FIRST_INTERRUPT && + irq <= BM3823_IRQ_LAST_INTERRUPT); + if (irq >= BM3823_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3823_IRQ_LAST_INTERRUPT) + { + /* Get the set of unmasked, pending interrupts. */ + + regval1 = INTER_REG.int_mask; + regval2 = INTER_REG.int_pend_force; + regval = regval1 & regval2; + } + else + { + /* Value out of range.. just ignore */ + + return false; + } + + /* Return true if the interrupt is pending and unmask. */ + + bitno = irq - BM3823_IRQ_FIRST_INTERRUPT - 1; + return (regval & (1 << bitno)) != 0; + } + + return false; +} + +/**************************************************************************** + * Name: up_clrpend_irq + * + * Description: + * Clear any pending interrupt + * + ****************************************************************************/ + +void up_clrpend_irq(int irq) +{ + int bitno; + /* Acknowledge the interrupt by clearing the associated bit in the ITP + * register. It is necessary to do this BEFORE lowering the interrupt + * priority level otherwise recursive interrupts would occur. + */ + + DEBUGASSERT(irq >= BM3823_IRQ_FIRST_INTERRUPT && + irq <= BM3823_IRQ_LAST_INTERRUPT); + if (irq >= BM3823_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3823_IRQ_LAST_INTERRUPT) + { + /* written with a ‘1’, in Interrupt Clear Register + * will clear the corresponding bit(s) in the interrupt pending + * register + */ + + bitno = irq - BM3823_IRQ_FIRST_INTERRUPT - 1; + INTER_REG.int_clear |= (1 << bitno); + } + else + { + /* Value out of range.. just ignore */ + + return; + } + } +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * It is possible to change the priority level of an interrupt using the two + * priority levels from the interrupt mask and priority register (ITMP). + * Each interrupt can be assigned to one of two levels as programmed in the + * Interrupt mask and priority register. Level 1 has higher priority than + * level 0. Within each level the interrupts are prioritised + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_IRQPRIO +static +#endif +int up_prioritize_irq(int irq, int priority) +{ + int bitno; + int shift; + + /* Don't allow this function to be used for disabling interrupts. */ + + DEBUGASSERT((unsigned)irq < NR_IRQS && (unsigned)(priority) < 2); + if (irq >= BM3823_IRQ_FIRST_INTERRUPT) + { + if (irq <= BM3823_IRQ_LAST_INTERRUPT) + { + bitno = irq - BM3823_IRQ_FIRST_INTERRUPT - 1; + shift = bitno + 16; + + /* Set the new interrupt priority + * (momentarily disabling interrupts) + */ + + INTER_REG.int_mask &= (~(1 << shift)); + INTER_REG.int_mask |= (priority << shift); + } + else + { + /* Value out of range.. just ignore */ + + return -EINVAL; + } + } + + return OK; +} diff --git a/arch/sparc/src/bm3823/bm3823-lowconsole.c b/arch/sparc/src/bm3823/bm3823-lowconsole.c new file mode 100644 index 00000000000..317da522359 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-lowconsole.c @@ -0,0 +1,316 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-lowconsole.c + * + * 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 "bm3823-config.h" + +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" +#include "bm3823-uart.h" +#include "bm3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: usart0_reset and usart1_reset + * + * Description: + * Reset USART0 or USART1. + * + ****************************************************************************/ + +#ifdef CONFIG_BM3823_UART1 +void uart1_reset(void) +{ + /* Clear USART configuration */ + + uart1_disable(); + uart1_parity_config(NONE); + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); +} +#endif + +#ifdef CONFIG_BM3823_UART2 +void uart2_reset(void) +{ + /* Clear USART configuration */ + + uart2_disable(); + uart2_parity_config(NONE); + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); +} +#endif + +#ifdef CONFIG_BM3823_UART3 +void uart3_reset(void) +{ + /* Clear USART configuration */ + + uart3_disable(); + uart3_parity_config(NONE); + uart3_flow_ctrl_config(OFF); + uart3_loopback_config(OFF); +} +#endif + +/**************************************************************************** + * Name: bm3823_uartconfigure + * + * Description: + * Configure a UART as a console. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void bm3823_uartconfigure(uintptr_t uart_base, uint32_t baudrate, + unsigned int parity, unsigned int nbits, bool stop2) +{ + if (uart_base == BM3823_UART1_BASE) + { + /* Select baud. */ + + uart1_set_baudrate(baudrate); + + /* Select parity */ + + if (parity == 1) + { + uart1_parity_config(ODD); /* Odd parity */ + } + else if (parity == 2) + { + uart1_parity_config(EVEN); /* Even parity */ + } + else + { + uart1_parity_config(NONE); /* Even none */ + } + + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); + + uart1_enable(); + } + else if (uart_base == BM3823_UART2_BASE) + { + /* Select baud. */ + + uart2_set_baudrate(baudrate); + + /* Select parity */ + + if (parity == 1) + { + uart2_parity_config(ODD); /* Odd parity */ + } + else if (parity == 2) + { + uart2_parity_config(EVEN); /* Even parity */ + } + else + { + uart2_parity_config(NONE); /* Even none */ + } + + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); + + uart2_enable(); + } + else + { + return; + } +} +#endif + +#ifdef CONFIG_BM3823_UART1 +void uart1_configure(void) +{ + uint32_t i = 0; + + /* Select baud. */ + + uart1_set_baudrate(CONFIG_UART1_BAUD); + + i = EXTER_REG.uart_data1; + i = EXTER_REG.uart_data1; + i = i; + EXTER_REG.uart_status1 = 0; + + /* Select parity */ + +#if CONFIG_UART1_PARITY == 1 + uart1_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART1_PARITY == 2 + uart1_parity_config(EVEN); /* Even parity */ +#else + uart1_parity_config(NONE); /* Even none */ +#endif + + uart1_flow_ctrl_config(OFF); + uart1_loopback_config(OFF); + + uart1_enable(); + + GPIO_DIR = GPIO_DIR | 0x8000; + GPIO_DIR = GPIO_DIR & 0xffffbfff; +} +#endif + +#ifdef CONFIG_BM3823_UART2 +void uart2_configure(void) +{ + /* Select baud. */ + + uart2_set_baudrate(CONFIG_UART2_BAUD); + + /* Select parity */ + +#if CONFIG_UART2_PARITY == 1 + uart2_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART2_PARITY == 2 + uart2_parity_config(EVEN); /* Even parity */ +#else + uart2_parity_config(NONE); /* Even none */ +#endif + + uart2_flow_ctrl_config(OFF); + uart2_loopback_config(OFF); + + uart2_enable(); +} +#endif + +#ifdef CONFIG_BM3823_UART3 +void uart3_configure(void) +{ + /* Select baud. */ + + uart3_set_baudrate(CONFIG_UART3_BAUD); + + /* Select parity */ + +#if CONFIG_UART3_PARITY == 1 + uart2_parity_config(ODD); /* Odd parity */ +#elif CONFIG_UART3_PARITY == 2 + uart3_parity_config(EVEN); /* Even parity */ +#else + uart3_parity_config(NONE); /* Even none */ +#endif + + uart3_flow_ctrl_config(OFF); + uart3_loopback_config(OFF); + + uart3_enable(); +} +#endif + +/**************************************************************************** + * 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) +{ +#ifdef HAVE_SERIAL_CONSOLE +# if defined(CONFIG_UART1_SERIAL_CONSOLE) + uart1_configure(); +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) + uart2_configure(); +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) + uart3_configure(); +# endif +#endif +} + +/**************************************************************************** + * Name: up_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void up_lowputc(char ch) +{ +#ifdef HAVE_SERIAL_CONSOLE +# if defined(CONFIG_UART1_SERIAL_CONSOLE) + while (!uart1_tx_ready()) + { + } + + uart1_send_byte(ch); + +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) + while (!uart2_tx_ready()) + { + } + + uart2_send_byte(ch); +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) + while (!uart3_tx_ready()) + { + } + + uart3_send_byte(ch); +# endif +#endif +} diff --git a/arch/sparc/src/bm3823/bm3823-lowinit.c b/arch/sparc/src/bm3823/bm3823-lowinit.c new file mode 100644 index 00000000000..54173b35157 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-lowinit.c @@ -0,0 +1,172 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-lowinit.c + * + * 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 "bm3823-config.h" +#include "up_internal.h" +#include "bm3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_WDTO_15MS) +# define WDTO_VALUE WDTO_15MS +#elif defined(CONFIG_WDTO_30MS) +# define WDTO_VALUE WDTO_30MS +#elif defined(CONFIG_WDTO_60MS) +# define WDTO_VALUE WDTO_60MS +#elif defined(CONFIG_WDTO_120MS) +# define WDTO_VALUE WDTO_120MS +#elif defined(CONFIG_WDTO_1250MS) +# define WDTO_VALUE WDTO_250MS +#elif defined(CONFIG_WDTO_500MS) +# define WDTO_VALUE WDTO_500MS +#elif defined(CONFIG_WDTO_1S) +# define WDTO_VALUE WDTO_1S +#elif defined(CONFIG_WDTO_2S) +# define WDTO_VALUE WDTO_2S +#elif defined(CONFIG_WDTO_4S) +# define WDTO_VALUE WDTO_4S +#else /* if defined(CONFIG_WDTO_8S) */ +# define WDTO_VALUE WDTO_8S +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) up_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Name: up_wdtinit + * + * Description: + * Initialize the watchdog per the NuttX configuration. + * + ****************************************************************************/ + +void wdt_disable(void) +{ +} + +void wdt_enable(uint32_t wdt) +{ +} + +static inline void up_wdtinit(void) +{ +#ifdef CONFIG_SPARC_WDT + wdt_enable(WDTO_VALUE); +#endif +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowinit + * + * Description: + * This performs basic initialization of the USART used for the serial + * console. Its purpose is to get the console output available as soon + * as possible. + * + ****************************************************************************/ + +void up_lowinit(void) +{ + uint32_t *dest; + + /* Disable the watchdog timer */ + + wdt_disable(); + + /* Initialize the watchdog timer */ + + up_wdtinit(); + + /* Initialize a console (probably a serial console) */ + + up_consoleinit(); + + showprogress('A'); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_bss_start; dest < &_end; ) + { + *dest++ = 0; + } + + showprogress('B'); + /* Perform early serial initialization (so that we will have debug output + * available as soon as possible). + */ + +#ifdef USE_EARLYSERIALINIT + up_earlyserialinit(); +#endif + + /* Perform board-level initialization */ + + bm3823_boardinitialize(); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); +} diff --git a/arch/sparc/src/bm3823/bm3823-memorymap.h b/arch/sparc/src/bm3823/bm3823-memorymap.h new file mode 100644 index 00000000000..3610ec32253 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-memorymap.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-memorymap.h + * + * 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_SPARC_SRC_BM3823_BM3823_MEMORYMAP_H +#define __ARCH_SPARC_SRC_BM3823_BM3823_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +# define BM3823_INTER_REG_BASE 0x80000000 +# define BM3823_EXTER_REG_BASE 0x81000000 + +/* UART 1-3 Register Base Addresses */ +# define BM3823_UART1_BASE (BM3823_EXTER_REG_BASE + 0x70) +# define BM3823_UART2_BASE (BM3823_EXTER_REG_BASE + 0x80) +# define BM3823_UART3_BASE (BM3823_EXTER_REG_BASE + 0x1C0) +# define BM3823_UART4_BASE (BM3823_EXTER_REG_BASE + 0x1E0) + +#endif /* __ARCH_SPARC_SRC_BM3823_BM3823_MEMORYMAP_H */ + diff --git a/arch/sparc/src/bm3823/bm3823-serial.c b/arch/sparc/src/bm3823/bm3823-serial.c new file mode 100644 index 00000000000..1ec6bb506f3 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-serial.c @@ -0,0 +1,947 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-serial.c + * + * 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 +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +#include "bm3823-config.h" +#include "chip.h" +#include "bm3823-uart.h" +#include "bm3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If we are not using the serial driver for the console, then we still must + * provide some minimal implementation of up_putc. + */ + +#ifdef USE_SERIALDRIVER + +/* Which UART with be tty0/console and which tty1? The console will always + * be ttyS0. If there is no console then will use the lowest numbered UART. + */ + +#ifdef HAVE_SERIAL_CONSOLE + +# if defined(CONFIG_UART1_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart1port /* UART1 is console */ +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3823_UART2) +# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */ +# elif defined(CONFIG_BM3823_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_UART2_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart2port /* UART2 is console */ +# define TTYS0_DEV g_uart2port /* UART2 is ttyS0 */ +# if defined(CONFIG_BM3823_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_UART3_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart3port /* UART3 is console */ +# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */ +# undef TTYS1_DEV /* No ttyS1 */ +# else +# error "I'm confused... Do we have a serial console or not?" +# endif +#else +# undef CONSOLE_DEV /* No console */ +# undef CONFIG_UART1_SERIAL_CONSOLE +# undef CONFIG_UART2_SERIAL_CONSOLE +# undef CONFIG_UART3_SERIAL_CONSOLE +# if defined(CONFIG_BM3823_UART1) +# define TTYS0_DEV g_uart1port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3823_UART2) +# define TTYS1_DEV g_uart2port /* UART2 is ttyS1 */ +# elif defined(CONFIG_BM3823_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_BM3823_UART2) +# define TTYS0_DEV g_uart2port /* UART1 is ttyS0 */ +# if defined(CONFIG_BM3823_UART3) +# define TTYS1_DEV g_uart3port /* UART3 is ttyS1 */ +# else +# undef TTYS1_DEV /* No ttyS1 */ +# endif +# elif defined(CONFIG_BM3823_UART3) +# define TTYS0_DEV g_uart3port /* UART3 is ttyS0 */ +# undef TTYS1_DEV /* No ttyS1 */ +# else +# undef TTYS0_DEV +# undef TTYS0_DEV +# endif +#endif + +/* Common initialization logic will not not know that the all of the UARTs + * have been disabled. So, as a result, we may still have to provide + * stub implementations of up_earlyserialinit(), up_serialinit(), and + * up_putc(). + */ + +#ifdef HAVE_UART_DEVICE + +/* These values describe the set of enabled interrupts */ + +#define RX_ENABLED(im) (((im) & MSK_UART_ENABLE_RX) != 0) +#define TX_ENABLED(im) (((im) & MSK_UART_ENABLE_TX) != 0) + +#define ENABLE_RX(im) do { (im) |= MSK_UART_ENABLE_RX; } while (0) +#define ENABLE_TX(im) do { (im) |= MSK_UART_ENABLE_TX; } while (0) + +#define DISABLE_RX(im) do { (im) &= ~MSK_UART_ENABLE_RX; } while (0) +#define DISABLE_TX(im) do { (im) &= ~MSK_UART_ENABLE_TX; } while (0) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + uintptr_t uartbase; /* Base address of UART registers */ + uint32_t baud; /* Configured baud */ + uint8_t irq; /* IRQ associated with this UART (for attachment) */ + uint8_t im; /* Interrupt mask state */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (5, 6, 7 or 8) */ + bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Low-level helpers */ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset); +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value); +static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im); +static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im); + +/* Serial driver methods */ + +static int up_setup(struct uart_dev_s *dev); +static void up_shutdown(struct uart_dev_s *dev); +static int up_attach(struct uart_dev_s *dev); +static void up_detach(struct uart_dev_s *dev); +static int up_interrupt(int irq, void *context, void *arg); +static int up_ioctl(struct file *filep, int cmd, unsigned long arg); +static int up_receive(struct uart_dev_s *dev, uint32_t *status); +static void up_rxint(struct uart_dev_s *dev, bool enable); +static bool up_rxavailable(struct uart_dev_s *dev); +static void up_send(struct uart_dev_s *dev, int ch); +static void up_txint(struct uart_dev_s *dev, bool enable); +static bool up_txready(struct uart_dev_s *dev); +static bool up_txempty(struct uart_dev_s *dev); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uart_ops_s g_uart_ops = +{ + .setup = up_setup, + .shutdown = up_shutdown, + .attach = up_attach, + .detach = up_detach, + .ioctl = up_ioctl, + .receive = up_receive, + .rxint = up_rxint, + .rxavailable = up_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = NULL, +#endif + .send = up_send, + .txint = up_txint, + .txready = up_txready, + .txempty = up_txempty, +}; + +/* I/O buffers */ + +#ifdef CONFIG_BM3823_UART1 +static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE]; +static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE]; +#endif +#ifdef CONFIG_BM3823_UART2 +static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE]; +static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE]; +#endif +#ifdef CONFIG_BM3823_UART3 +static char g_uart3rxbuffer[CONFIG_UART3_RXBUFSIZE]; +static char g_uart3txbuffer[CONFIG_UART3_TXBUFSIZE]; +#endif +/* This describes the state of the BM3823 UART1 port. */ + +#ifdef CONFIG_BM3823_UART1 +static struct up_dev_s g_uart1priv = +{ + .uartbase = BM3823_UART1_BASE, + .baud = CONFIG_UART1_BAUD, + .irq = BM3823_IRQ_UART_1_RX_TX, + .parity = CONFIG_UART1_PARITY, + .bits = CONFIG_UART1_BITS, + .stopbits2 = CONFIG_UART1_2STOP, +}; + +static uart_dev_t g_uart1port = +{ + .recv = + { + .size = CONFIG_UART1_RXBUFSIZE, + .buffer = g_uart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART1_TXBUFSIZE, + .buffer = g_uart1txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart1priv, +}; +#endif + +/* This describes the state of the BM3823 UART2 port. */ + +#ifdef CONFIG_BM3823_UART2 +static struct up_dev_s g_uart2priv = +{ + .uartbase = BM3823_UART2_BASE, + .baud = CONFIG_UART2_BAUD, + .irq = BM3823_IRQ_UART_2_RX_TX, + .parity = CONFIG_UART2_PARITY, + .bits = CONFIG_UART2_BITS, + .stopbits2 = CONFIG_UART2_2STOP, +}; + +static uart_dev_t g_uart2port = +{ + .recv = + { + .size = CONFIG_UART2_RXBUFSIZE, + .buffer = g_uart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART2_TXBUFSIZE, + .buffer = g_uart2txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart2priv, +}; +#endif + +/* This describes the state of the BM3823 UART3 port. */ + +#ifdef CONFIG_BM3823_UART3 +static struct up_dev_s g_uart3priv = +{ + .uartbase = BM3823_UART3_BASE, + .baud = CONFIG_UART3_BAUD, + .irq = BM3823_IRQ_UART_3_RX_TX, + .parity = CONFIG_UART3_PARITY, + .bits = CONFIG_UART3_BITS, + .stopbits2 = CONFIG_UART3_2STOP, +}; + +static uart_dev_t g_uart3port = +{ + .recv = + { + .head = 0, + .tail = 0, + .size = CONFIG_UART3_RXBUFSIZE, + .buffer = g_uart3rxbuffer, + }, + .xmit = + { + .head = 0, + .tail = 0, + .size = CONFIG_UART3_TXBUFSIZE, + .buffer = g_uart3txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart3priv, +}; +#endif +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_serialin + ****************************************************************************/ + +static inline uint32_t up_serialin(struct up_dev_s *priv, int offset) +{ + return getreg32(priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_serialout + ****************************************************************************/ + +static inline void up_serialout(struct up_dev_s *priv, int offset, + uint32_t value) +{ + putreg32(value, priv->uartbase + offset); +} + +/**************************************************************************** + * Name: up_setuartint + ****************************************************************************/ + +static inline void up_setuartint(struct up_dev_s *priv) +{ + uint8_t regval; + + regval = up_serialin(priv, BM3823_UART_CTRLREG_OFFSET); + regval &= ~MSK_UART_ALLINTS; + regval |= priv->im; + up_serialout(priv, BM3823_UART_CTRLREG_OFFSET, regval); +} + +/**************************************************************************** + * Name: up_restoreuartint + ****************************************************************************/ + +static void up_restoreuartint(struct uart_dev_s *dev, uint8_t im) +{ + irqstate_t flags; + + /* Re-enable/re-disable interrupts corresponding to the state of bits in + * im + */ + + flags = enter_critical_section(); + up_rxint(dev, RX_ENABLED(im)); + up_txint(dev, TX_ENABLED(im)); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_disableuartint + ****************************************************************************/ + +static void up_disableuartint(struct uart_dev_s *dev, uint8_t *im) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (im) + { + *im = priv->im; + } + + up_restoreuartint(dev, 0); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the UART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int up_setup(struct uart_dev_s *dev) +{ +#ifndef CONFIG_SUPPRESS_UART_CONFIG + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Configure the UART as an RS-232 UART */ + + bm3823_uartconfigure(priv->uartbase, priv->baud, priv->parity, + priv->bits, priv->stopbits2); +#endif + +#ifdef CONFIG_ARCH_IRQPRIO + /* Set up the interrupt priority */ + + up_prioritize_irq(priv->irq, priv->irqprio); +#endif + + return OK; +} + +/**************************************************************************** + * Name: up_shutdown + * + * Description: + * Disable the UART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void up_shutdown(struct uart_dev_s *dev) +{ + /* struct up_dev_s *priv = (struct up_dev_s *)dev->priv; */ + + /* Disable interrupts */ + + up_disableuartint(dev, NULL); + + /* Reset hardware and disable Rx and Tx */ + + /* bm3823_uartreset(priv->uartbase); */ +} + +/**************************************************************************** + * Name: up_attach + * + * Description: + * Configure the UART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the the setup() method is called, however, the serial console may + * operate in a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled by the attach method (unless the + * hardware supports multiple levels of interrupt enabling). The RX and TX + * interrupts are not enabled until the txint() and rxint() methods are + * called. + * + ****************************************************************************/ + +static int up_attach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, up_interrupt, dev); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ + + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: up_detach + * + * Description: + * Detach UART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called.The exception + * is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void up_detach(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Disable interrupts */ + + up_disableuartint(dev, NULL); + + /* Detach from the interrupt */ + + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * approprite uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int up_interrupt(int irq, void *context, void *arg) +{ + struct uart_dev_s *dev = (struct uart_dev_s *)arg; + struct up_dev_s *priv; + uint32_t mis; + int passes; + bool handled; + + DEBUGASSERT(dev != NULL && dev->priv != NULL); + priv = (struct up_dev_s *)dev->priv; + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + handled = true; + for (passes = 0; passes < 256 && handled; passes++) + { + handled = false; + + /* Get the masked UART status and clear the pending interrupts. */ + + mis = up_serialin(priv, BM3823_UART_STATREG_OFFSET); + + /* Handle incoming, receive bytes */ + + if ((mis & MSK_UART_DATA_READY) != 0) + { + /* Rx buffer not empty ... process incoming bytes */ + + uart_recvchars(dev); + handled = true; + } + + /* Handle outgoing, transmit bytes */ + + if ((mis & MSK_UART_TXH_READY) != 0) + { + /* Tx FIFO not full ... process outgoing bytes */ + + uart_xmitchars(dev); + handled = true; + } + } + + return OK; +} + +/**************************************************************************** + * Name: up_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int up_ioctl(struct file *filep, int cmd, unsigned long arg) +{ +#ifdef CONFIG_SERIAL_TERMIOS + struct inode *inode; + struct uart_dev_s *dev; + struct up_dev_s *priv; + int ret = OK; + + DEBUGASSERT(filep, filep->f_inode); + inode = filep->f_inode; + dev = inode->i_private; + + DEBUGASSERT(dev, dev->priv); + priv = (struct up_dev_s *)dev->priv; + + switch (cmd) + { + case xxx: /* Add commands here */ + break; + + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Other termios fields are not yet returned. + * Note that only cfsetospeed is not necessary because we have + * knowledge that only one speed is supported. + */ + + cfsetispeed(termiosp, priv->baud); + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Handle other termios settings. + * Note that only cfgetispeed is used besued we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + bm3823_uartconfigure(priv->uartbase, priv->baud, priv->parity, + priv->bits, priv->stopbits2); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +#else + return -ENOTTY; +#endif +} + +/**************************************************************************** + * Name: up_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the UART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +static int up_receive(struct uart_dev_s *dev, uint32_t *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return status information */ + + if (status) + { + *status = 0; /* We are not yet tracking serial errors */ + } + + /* Then return the actual received byte */ + + return (int)(up_serialin(priv, BM3823_UART_RXREG_OFFSET) & + UART_RXREG_MASK); +} + +/**************************************************************************** + * Name: up_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +static void up_rxint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + if (enable) + { + /* Receive an interrupt when their is anything in the Rx FIFO (or an Rx + * timeout occurs. + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= MSK_UART_ENABLE_RXIT; +#endif + } + else + { + priv->im &= ~MSK_UART_ENABLE_RXIT; + } + + up_setuartint(priv); +} + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return true is data is available in the receive data buffer */ + + return (up_serialin(priv, BM3823_UART_STATREG_OFFSET) & + MSK_UART_DATA_READY) != 0; +} + +/**************************************************************************** + * Name: up_send + * + * Description: + * This method will send one byte on the UART. + * + ****************************************************************************/ + +static void up_send(struct uart_dev_s *dev, int ch) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + up_serialout(priv, BM3823_UART_TXREG_OFFSET, (uint32_t)ch); +} + +/**************************************************************************** + * Name: up_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void up_txint(struct uart_dev_s *dev, bool enable) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + irqstate_t flags; + + flags = enter_critical_section(); + if (enable) + { + /* Set to receive an interrupt when the TX data register is empty */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->im |= MSK_UART_ENABLE_TXIT; + up_setuartint(priv); + + /* Fake a TX interrupt */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + priv->im &= ~MSK_UART_ENABLE_TXIT; + up_setuartint(priv); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return TRUE if the Transmit buffer register is not full */ + + return (up_serialin(priv, BM3823_UART_STATREG_OFFSET) & + MSK_UART_TXH_READY) != 0; +} + +/**************************************************************************** + * Name: up_txempty + * + * Description: + * Return true if the tranmsit data register is empty + * + ****************************************************************************/ + +static bool up_txempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + + /* Return TRUE if the Transmit shift register is empty */ + + return (up_serialin(priv, BM3823_UART_STATREG_OFFSET) & + MSK_UART_TXS_READY) != 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_earlyserialinit + * + * Description: + * Performs the low level UART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before up_serialinit. NOTE: This function depends on GPIO pin + * configuration performed in up_consoleinit() and main clock iniialization + * performed in up_clkinitialize(). + * + ****************************************************************************/ + +void up_earlyserialinit(void) +{ + /* Disable interrupts from all UARTS. The console is enabled in + * bm3823_consoleinit(). + */ + + up_disableuartint(&TTYS0_DEV, NULL); +#ifdef TTYS1_DEV + up_disableuartint(&TTYS1_DEV, NULL); +#endif + + /* Configuration whichever one is the console */ + +#ifdef HAVE_SERIAL_CONSOLE + CONSOLE_DEV.isconsole = true; + up_setup(&CONSOLE_DEV); +#endif +} + +/**************************************************************************** + * Name: up_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that up_earlyserialinit was called previously. + * + ****************************************************************************/ + +void up_serialinit(void) +{ + /* Register the console */ + +#ifdef HAVE_SERIAL_CONSOLE + (void)uart_register("/dev/console", &CONSOLE_DEV); +#endif + + /* Register all UARTs */ + + (void)uart_register("/dev/ttyS0", &TTYS0_DEV); +#ifdef TTYS1_DEV + (void)uart_register("/dev/ttyS1", &TTYS1_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_SERIAL_CONSOLE + struct uart_dev_s *dev = (struct uart_dev_s *)&CONSOLE_DEV; + uint8_t imr = 0; + + up_disableuartint(dev, &imr); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + up_restoreuartint(dev, imr); +#endif + return ch; +} + +/**************************************************************************** + * Name: up_earlyserialinit, up_serialinit, and up_putc + * + * Description: + * stubs that may be needed. These stubs would be used if all UARTs are + * disabled. In that case, the logic in common/up_initialize() is not + * smart enough to know that there are not UARTs and will still expect + * these interfaces to be provided. + * + ****************************************************************************/ +#else /* HAVE_UART_DEVICE */ +void up_earlyserialinit(void) +{ +} + +void up_serialinit(void) +{ +} + +int up_putc(int ch) +{ + return ch; +} + +#endif /* HAVE_UART_DEVICE */ +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_SERIAL_CONSOLE + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ + diff --git a/arch/sparc/src/bm3823/bm3823-timerisr.c b/arch/sparc/src/bm3823/bm3823-timerisr.c new file mode 100644 index 00000000000..80c984a1ea4 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-timerisr.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-timerisr.c + * + * 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 "up_internal.h" +#include "up_arch.h" + +#include "bm3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The CPU frequency is given by BOARD_CPU_CLOCK (defined in board.h). The + * desired interrupt frequency is given by CONFIG_USEC_PER_TICK. An unscaled + * ideal match is given by: + * + * CLOCK = CPU_CLOCK / DIVISOR # CPU clocks/sec + * MATCH = CLOCK / CLOCKS_PER_SEC # CPU clocks/timer tick + * MATCH = CPU_CLOCK / DIVISOR / CLOCKS_PER_SEC # CPU clocks/timer tick + * + * But we only have 16-bits of accuracy so we need to pick the smallest + * divisor using the following brute force calculation: + */ +#define BM3823_TIMER_CLOCK 1000000 +#define MATCH1 (( 1000000 / CLOCKS_PER_SEC) - 1) + +#define TIMCTR_ENABLE_COUNTER (1 << 0) /* Bit 0: enables the + * timer when set + */ + +#define TIMCTR_AUTO_RELOAD (1 << 1) /* Bit 1: automatically + * reloaded with the reload + * value after each underflow + */ +#define TIMCTR_LOAD_COUNTER (1 << 2) /* Bit 2: Set 1, will load the + * timer reload register into + * the timer counter register + */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: bm3823_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int bm3823_timerisr(int irq, uint32_t *regs, FAR void *arg) +{ + /* Clear the pending timer interrupt */ + + up_clrpend_irq(BM3823_IRQ_TIMER1); + + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize the timer + * interrupt. NOTE: This function depends on setup of OSC32 by + * up_clkinitialize(). + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + EXTER_REG.scaler_load = (BOARD_PERIPH_CLOCK / BM3823_TIMER_CLOCK) - 1; + EXTER_REG.scaler_cnt = (BOARD_PERIPH_CLOCK / BM3823_TIMER_CLOCK) - 1; + + /* Setup timer 1 compare match A to generate a tick interrupt. + * + * First, setup the match value for compare match A. + */ + + EXTER_REG.timer_cnt1 = (uint32_t)MATCH1; + EXTER_REG.timer_load1 = (uint32_t)MATCH1; + + EXTER_REG.timer_ctrl1 = (TIMCTR_ENABLE_COUNTER | TIMCTR_AUTO_RELOAD | + TIMCTR_LOAD_COUNTER); + + /* Configure the timer interrupt */ + + up_clrpend_irq(BM3823_IRQ_TIMER1); +#ifdef CONFIG_ARCH_IRQPRIO + (void)up_prioritize_irq(BM3823_IRQ_TIMER1, CONFIG_BM3823_TIMER1PRIO); +#endif + + /* Attach the timer interrupt vector */ + + (void)irq_attach(BM3823_IRQ_TIMER1, (xcpt_t)bm3823_timerisr, NULL); + + /* And enable the timer interrupt */ + + up_enable_irq(BM3823_IRQ_TIMER1); +} diff --git a/arch/sparc/src/bm3823/bm3823-uart.h b/arch/sparc/src/bm3823/bm3823-uart.h new file mode 100644 index 00000000000..dce243dd512 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823-uart.h @@ -0,0 +1,230 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823-uart.h + * + * 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_SPARC_SRC_BM3823_BM3823_UART_H +#define __ARCH_SPARC_SRC_BM3823_BM3823_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define BM3823_UART_TXREG_OFFSET 0x0000 /* UARTx transmit register */ +#define BM3823_UART_RXREG_OFFSET 0x0000 /* UARTx receive register */ +#define BM3823_UART_STATREG_OFFSET 0x0004 /* UARTx status register */ +#define BM3823_UART_CTRLREG_OFFSET 0x0008 /* UARTx control register */ +#define BM3823_UART_SCALREG_OFFSET 0x000c /* UARTx scaler register */ + +/* Register Addresses *******************************************************/ + +#if CHIP_NUARTS > 0 +#define BM3823_UART1_TXREG (BM3823_UART1_BASE+BM3823_UART_TXREG_OFFSET) +#define BM3823_UART1_RXREG (BM3823_UART1_BASE+BM3823_UART_RXREG_OFFSET) +#define BM3823_UART1_STATREG (BM3823_UART1_BASE+BM3823_UART_STATREG_OFFSET) +#define BM3823_UART1_CTRLREG (BM3823_UART1_BASE+BM3823_UART_CTRLREG_OFFSET) +#define BM3823_UART1_SCALREG (BM3823_UART1_BASE+BM3823_UART_SCALREG_OFFSET) +#endif + +#if CHIP_NUARTS > 1 +#define BM3823_UART2_TXREG (BM3823_UART2_BASE+BM3823_UART_TXREG_OFFSET) +#define BM3823_UART2_RXREG (BM3823_UART2_BASE+BM3823_UART_RXREG_OFFSET) +#define BM3823_UART2_STATREG (BM3823_UART2_BASE+BM3823_UART_STATREG_OFFSET) +#define BM3823_UART2_CTRLREG (BM3823_UART2_BASE+BM3823_UART_CTRLREG_OFFSET) +#define BM3823_UART2_SCALREG (BM3823_UART2_BASE+BM3823_UART_SCALREG_OFFSET) +#endif + +#if CHIP_NUARTS > 2 +#define BM3823_UART3_TXREG (BM3823_UART3_BASE+BM3823_UART_TXREG_OFFSET) +#define BM3823_UART3_RXREG (BM3823_UART3_BASE+BM3823_UART_RXREG_OFFSET) +#define BM3823_UART3_STATREG (BM3823_UART3_BASE+BM3823_UART_STATREG_OFFSET) +#define BM3823_UART3_CTRLREG (BM3823_UART3_BASE+BM3823_UART_CTRLREG_OFFSET) +#define BM3823_UART3_SCALREG (BM3823_UART3_BASE+BM3823_UART_SCALREG_OFFSET) +#endif + +/* Register Bit-Field Definitions *******************************************/ + +#define ODD 1 +#define EVEN 0 +#define ON 1 +#define OFF 0 +#define NONE 2 +#define RX 0 +#define TX 1 +#define RXTX 3 + +/* Uart control list - Mask */ + +#define MSK_UART_ENABLE_RX 0x01 +#define MSK_UART_ENABLE_TX 0x02 +#define MSK_UART_ENABLE_RXIT 0x04 +#define MSK_UART_ENABLE_TXIT 0x08 +#define MSK_UART_ENABLE_PAR 0x20 +#define MSK_UART_PAR 0x10 +#define MSK_UART_ENABLE_FLOW 0x40 +#define MSK_UART_LOOPBACK 0x80 +#define MSK_UART_CLOCK 0x100 +#define MSK_UART_ALLINTS 0x0C + +#define MSK_UART_DATA_READY 0x01 +#define MSK_UART_TXS_READY 0x02 +#define MSK_UART_TXH_READY 0x04 +#define MSK_UART_BREAK 0x08 +#define MSK_UART_OVERRUN 0x10 +#define MSK_UART_PAR_ERR 0x20 +#define MSK_UART_FRAME_ERR 0x40 + +/* UARTx transmit register */ + +#define UART_TXREG_MASK 0xff + +/* UARTx receive register */ + +#define UART_RXREG_MASK 0xff + +/* UARTx baud rate register */ + +#define UART_BRG_MASK 0xfff + +#define uart1_set_baudrate(baudrate) (EXTER_REG.uart_scaler1 = (uint32_t)((((BOARD_PERIPH_CLOCK*10)/(baudrate * 8))-5)/10)) + +#define uart1_parity_config(uart_parity) ( uart_parity == ODD \ + ? (EXTER_REG.uart_ctrl1 = ((EXTER_REG.uart_ctrl1 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (EXTER_REG.uart_ctrl1 = ((EXTER_REG.uart_ctrl1 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (EXTER_REG.uart_ctrl1 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define uart1_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (EXTER_REG.uart_ctrl1 |= MSK_UART_ENABLE_FLOW) \ + : (EXTER_REG.uart_ctrl1 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart1_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (EXTER_REG.uart_ctrl1 |= MSK_UART_LOOPBACK) \ + : (EXTER_REG.uart_ctrl1 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart1_enable() (EXTER_REG.uart_ctrl1 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart1_disable() (EXTER_REG.uart_ctrl1 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart1_tx_ready() ((EXTER_REG.uart_status1 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart1_rx_ready() ((EXTER_REG.uart_status1 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart1_send_byte(ch) (EXTER_REG.uart_data1 = ch) + +/****************************************************************************/ + +#define uart2_set_baudrate(baudrate) (EXTER_REG.uart_scaler2 = (((BOARD_PERIPH_CLOCK*10)/(baudrate*8))-5)/10) + +#define uart2_parity_config(uart_parity) ( uart_parity == ODD \ + ? (EXTER_REG.uart_ctrl2 = ((EXTER_REG.uart_ctrl2 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (EXTER_REG.uart_ctrl2 = ((EXTER_REG.uart_ctrl2 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (EXTER_REG.uart_ctrl2 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define uart2_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (EXTER_REG.uart_ctrl2 |= MSK_UART_ENABLE_FLOW) \ + : (EXTER_REG.uart_ctrl2 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart2_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (EXTER_REG.uart_ctrl2 |= MSK_UART_LOOPBACK) \ + : (EXTER_REG.uart_ctrl2 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart2_enable() (EXTER_REG.uart_ctrl2 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart2_disable() (EXTER_REG.uart_ctrl2 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart2_tx_ready() ((EXTER_REG.uart_status2 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart2_rx_ready() ((EXTER_REG.uart_status2 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart2_send_byte(ch) (EXTER_REG.uart_data2 = ch) + +/****************************************************************************/ + +#define uart3_set_baudrate(baudrate) (BM3823_REG.uart_scaler3 = (((BOARD_PERIPH_CLOCK*10)/(baudrate*8))-5)/10) + +#define uart3_parity_config(uart_parity) ( uart_parity == ODD \ + ? (BM3823_REG.uart_ctrl3 = ((BM3823_REG.uart_ctrl3 | MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : ( uart_parity == EVEN \ + ? (BM3823_REG.uart_ctrl3 = ((BM3823_REG.uart_ctrl3 & ~MSK_UART_PAR) | MSK_UART_ENABLE_PAR)) \ + : (BM3823_REG.uart_ctrl3 &= ~MSK_UART_ENABLE_PAR ) \ + ) \ + ) + +#define uart3_flow_ctrl_config(uart_flow) ( uart_flow == ON \ + ? (BM3823_REG.uart_ctrl3 |= MSK_UART_ENABLE_FLOW) \ + : (BM3823_REG.uart_ctrl3 &= ~MSK_UART_ENABLE_FLOW) \ + ) + +#define uart3_loopback_config(uart_loopb) ( uart_loopb == ON \ + ? (BM3823_REG.uart_ctrl3 |= MSK_UART_LOOPBACK) \ + : (BM3823_REG.uart_ctrl3 &= ~MSK_UART_LOOPBACK) \ + ) + +#define uart3_enable() (BM3823_REG.uart_ctrl3 |= (MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) +#define uart3_disable() (BM3823_REG.uart_ctrl3 &= ~(MSK_UART_ENABLE_RX | MSK_UART_ENABLE_TX)) + +#define uart3_tx_ready() ((BM3823_REG.uart_status3 & MSK_UART_TXH_READY) == MSK_UART_TXH_READY ) +#define uart3_rx_ready() ((BM3823_REG.uart_status3 & MSK_UART_DATA_READY) == MSK_UART_DATA_READY) + +#define uart3_send_byte(ch) (BM3823_REG.uart_data3 = ch) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3823_BM3823_UART_H */ diff --git a/arch/sparc/src/bm3823/bm3823.h b/arch/sparc/src/bm3823/bm3823.h new file mode 100644 index 00000000000..afdab330624 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823.h @@ -0,0 +1,665 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823.h + * + * 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_SPARC_SRC_BM3823_BM3823_H +#define __ARCH_SARRC_SRC_BM3823_BM3823_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "bm3823-config.h" + +#ifdef CONFIG_SPARC_GPIOIRQ +# include +#endif + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The following defines the bits in Memory Configuration Register 1. */ + +#define BM3823_MEMORY_CONFIGURATION_PROM_SIZE_MASK 0x0003C000 + +/* The following defines the bits in Memory Configuration Register 1. */ + +#define BM3823_MEMORY_CONFIGURATION_RAM_SIZE_MASK 0x00001E00 + +/* The following defines the bits in the Timer Control Register. */ + +/* 1 = enable counting + * 0 = hold scalar and counter + */ + +#define BM3823_REG_TIMER_CONTROL_EN 0x00000001 + +/* 1 = reload at 0 + * 0 = stop at 0 + */ + +#define BM3823_REG_TIMER_CONTROL_RL 0x00000002 + +/* 1 = load counter + * 0 = no function + */ + +#define BM3823_REG_TIMER_CONTROL_LD 0x00000004 + +/* The following defines the bits in the UART Control Registers. */ + +#define BM3823_REG_UartCtrlRTD 0x000000FF /* RX/TX data */ + +/* The following defines the bits in the BM3823 UART Status Registers. */ + +#define BM3823_REG_UART_STATUS_CLR 0x00000000 /* Clear all status bits */ +#define BM3823_REG_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define BM3823_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define BM3823_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define BM3823_REG_UART_STATUS_BR 0x00000008 /* Break Error */ +#define BM3823_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */ +#define BM3823_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define BM3823_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */ +#define BM3823_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */ + +/* The following defines the bits in the BM3823 UART Status Registers. */ + +#define BM3823_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */ +#define BM3823_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */ +#define BM3823_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */ +#define BM3823_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */ +#define BM3823_REG_UART_CTRL_PS 0x00000010 /* Parity select */ +#define BM3823_REG_UART_CTRL_PE 0x00000020 /* Parity enable */ +#define BM3823_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */ +#define BM3823_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The following constants are intended to be used ONLY in assembly + * language files. + * + * NOTE: The intended style of usage is to load the address of BM3823 REGS + * into a register and then use these as displacements from + * that register. + */ + +#ifdef __ASSEMBLY__ + +#define BM3823_REG_MEMCFG1_OFFSET 0x00 +#define BM3823_REG_MEMCFG2_OFFSET 0x04 +#define BM3823_REG_EDACCTRL_OFFSET 0x08 +#define BM3823_REG_FAILADDR_OFFSET 0x0C +#define BM3823_REG_MEMSTATUS_OFFSET 0x10 +#define BM3823_REG_CACHECTRL_OFFSET 0x14 +#define BM3823_REG_POWERDOWN_OFFSET 0x18 +#define BM3823_REG_WRITEPROT1_OFFSET 0x1C +#define BM3823_REG_WRITEPROT2_OFFSET 0x20 +#define BM3823_REG_BM3823CONF_OFFSET 0x24 +#define BM3823_REG_UNIMPLEMENTED_2_OFFSET 0x28 +#define BM3823_REG_UNIMPLEMENTED_3_OFFSET 0x2C +#define BM3823_REG_UNIMPLEMENTED_4_OFFSET 0x30 +#define BM3823_REG_UNIMPLEMENTED_5_OFFSET 0x34 +#define BM3823_REG_UNIMPLEMENTED_6_OFFSET 0x38 +#define BM3823_REG_UNIMPLEMENTED_7_OFFSET 0x3C +#define BM3823_REG_TIMERCNT1_OFFSET 0x40 +#define BM3823_REG_TIMERLOAD1_OFFSET 0x44 +#define BM3823_REG_TIMERCTRL1_OFFSET 0x48 +#define BM3823_REG_WDOG_OFFSET 0x4C +#define BM3823_REG_TIMERCNT2_OFFSET 0x50 +#define BM3823_REG_TIMERLOAD2_OFFSET 0x54 +#define BM3823_REG_TIMERCTRL2_OFFSET 0x58 +#define BM3823_REG_UNIMPLEMENTED_8_OFFSET 0x5C +#define BM3823_REG_SCALERCNT_OFFSET 0x60 +#define BM3823_REG_SCALER_LOAD_OFFSET 0x64 +#define BM3823_REG_UNIMPLEMENTED_9_OFFSET 0x68 +#define BM3823_REG_UNIMPLEMENTED_10_OFFSET 0x6C +#define BM3823_REG_UARTDATA1_OFFSET 0x70 +#define BM3823_REG_UARTSTATUS1_OFFSET 0x74 +#define BM3823_REG_UARTCTRL1_OFFSET 0x78 +#define BM3823_REG_UARTSCALER1_OFFSET 0x7C +#define BM3823_REG_UARTDATA2_OFFSET 0x80 +#define BM3823_REG_UARTSTATUS2_OFFSET 0x84 +#define BM3823_REG_UARTCTRL2_OFFSET 0x88 +#define BM3823_REG_UARTSCALER2_OFFSET 0x8C +#define BM3823_REG_IRQMASK_OFFSET 0x90 +#define BM3823_REG_IRQPEND_OFFSET 0x94 +#define BM3823_REG_IRQFORCE_OFFSET 0x98 +#define BM3823_REG_IRQCLEAR_OFFSET 0x9C +#define BM3823_REG_PIODATA_OFFSET 0xA0 +#define BM3823_REG_PIODIR_OFFSET 0xA4 +#define BM3823_REG_PIOIRQ_OFFSET 0xA8 +#define BM3823_REG_SIM_RAM_SIZE_OFFSET 0xF4 +#define BM3823_REG_SIM_ROM_SIZE_OFFSET 0xF8 + +#else + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Trap Types for on-chip peripherals + * + * Source: Table 8 - Interrupt Trap Type and Default Priority Assignments + * + * NOTE: The priority level for each source corresponds to the least + * significant nibble of the trap type. + */ + +#define BM3823_TRAP_TYPE( _source ) SPARC_ASYNCHRONOUS_TRAP((_source) + 0x10) + +#define BM3823_TRAP_SOURCE( _trap ) ((_trap) - 0x10) + +#define BM3823_INT_TRAP( _trap ) \ + ( (_trap) >= BM3823_TRAP_TYPE( BM3823_IRQ_CORRECTABLE_MEMORY_ERROR ) && \ + (_trap) <= BM3823_TRAP_TYPE( BM3823_IRQ_EMPTY6 ) ) + +/* Structure for BM3823 memory mapped registers. + * + * Source: Section 6.1 - On-chip registers + * + * NOTE: There is only one of these structures per CPU, its base address + * is 0x80000000, and the variable BM3823_REG is placed there by the + * linkcmds file. + */ + +typedef struct +{ + volatile unsigned int mem_cfg1; /* Memory Configuration Register 1 */ + volatile unsigned int mem_cfg2; /* Memory Configuration Register 2 */ + volatile unsigned int mem_cfg3; /* Memory Configuration Register 3 */ + volatile unsigned int fail_addr; + + volatile unsigned int mem_status; /* 0x10 */ + volatile unsigned int dummy1; /* bm3823 */ + volatile unsigned int dummy2; /* bm3823 */ + volatile unsigned int write_prot1; /* Write protection 1 */ + + volatile unsigned int write_prot2; /* Write protection 2 0x20 */ + volatile unsigned int dummy3; /* bm3823 */ + volatile unsigned int dummy4; + volatile unsigned int dummy5; + + volatile unsigned int dummy6; /* 0x30 */ + volatile unsigned int dummy7; + volatile unsigned int dummy8; + volatile unsigned int dummy9; + + volatile unsigned int timer_cnt1; /* 0x40 */ + volatile unsigned int timer_load1; + volatile unsigned int timer_ctrl1; + volatile unsigned int wdog; + + volatile unsigned int timer_cnt2; /* 0x50 */ + volatile unsigned int timer_load2; + volatile unsigned int timer_ctrl2; + volatile unsigned int dummy10; + + volatile unsigned int scaler_cnt; /* 0x60 */ + volatile unsigned int scaler_load; + volatile unsigned int dummy11; + volatile unsigned int dummy12; + + volatile unsigned int uart_data1; /* UA1 data */ + volatile unsigned int uart_status1; /* UA1 status register */ + volatile unsigned int uart_ctrl1; /* UA1 control register */ + volatile unsigned int uart_scaler1; /* UA1 scaler register */ + + volatile unsigned int uart_data2; /* UA2 data */ + volatile unsigned int uart_status2; /* UA2 status register */ + volatile unsigned int uart_ctrl2; /* UA2 control register */ + volatile unsigned int uart_scaler2; /* UA2 scaler register */ + + volatile unsigned int dummy13; /* 0x90 */ + volatile unsigned int dummy14; + volatile unsigned int dummy15; + volatile unsigned int dummy16; + + volatile unsigned int dummy17; /* 0xA0 */ + volatile unsigned int dummy18; + volatile unsigned int dummy19; + volatile unsigned int dummy20; + + volatile unsigned int dummy21; /* 0xB0 */ + volatile unsigned int dummy22; + volatile unsigned int dummy23; + volatile unsigned int dummy24; + + volatile unsigned int dummy25; /* 0xC0 */ + volatile unsigned int dummy26; + volatile unsigned int dummy27; + volatile unsigned int dummy28; + + volatile unsigned int dummy29; /* 0xD0 */ + volatile unsigned int dummy30; + volatile unsigned int dummy31; + volatile unsigned int dummy32; + + volatile unsigned int dummy33; /* 0xE0 */ + volatile unsigned int dummy34; + volatile unsigned int dummy35; + volatile unsigned int dummy36; + + volatile unsigned int reserved1; /* 0xF0 */ + volatile unsigned int reserved2; + volatile unsigned int reserved3; + volatile unsigned int reserved4; + + volatile unsigned int mecfg1; /* 0x100 */ + volatile unsigned int mecfg2; +} BM3823_REGISTER_EXTER; + +typedef struct +{ + volatile unsigned int dummy1; /* bm3823 */ + volatile unsigned int dummy2; /* bm3823 */ + volatile unsigned int dummy3; /* /bm3823 */ + volatile unsigned int fail_addr; + + volatile unsigned int mem_status; /* 0x10 */ + volatile unsigned int cache_ctrl; /* Cache control register */ + volatile unsigned int dummy4; /* bm3823 */ + volatile unsigned int dummy5; /* bm3823 */ + + volatile unsigned int dummy6; /* bm3823 */ + volatile unsigned int pcr; + volatile unsigned int dummy7; + volatile unsigned int dummy8; + + volatile unsigned int mem_cfg1; /* Interior Memory Configuration + * Register 1 + */ + volatile unsigned int dummy9; + volatile unsigned int dummy10; + volatile unsigned int dummy11; + + volatile unsigned int dummy12; /* 0x40 */ + volatile unsigned int dummy13; + volatile unsigned int dummy14; + volatile unsigned int dummy15; + + volatile unsigned int dummy16; /* 0x50 */ + volatile unsigned int dummy17; + volatile unsigned int dummy18; + volatile unsigned int dummy19; + + volatile unsigned int dummy20; /* 0x60 */ + volatile unsigned int dummy21; + volatile unsigned int dummy22; + volatile unsigned int dummy23; + + volatile unsigned int dummy24; /* 0x70 */ + volatile unsigned int dummy25; + volatile unsigned int dummy26; + volatile unsigned int dummy27; + + volatile unsigned int dummy28; /* 0x80 */ + volatile unsigned int dummy29; + volatile unsigned int dummy30; + volatile unsigned int dummy31; + + volatile unsigned int int_mask; /* Interrupt Mask and Priority + * Register register + */ + + volatile unsigned int int_pend_force; /* Interrupt Pending and int_force + * Register register + */ + + volatile unsigned int int_sub_prio; /* Interrupt Clear Register + * register + */ + volatile unsigned int int_clear; + + volatile unsigned int dummy32; /* 0xA0 */ + volatile unsigned int dummy33; + volatile unsigned int dummy34; + volatile unsigned int dummy35; + + volatile unsigned int int_mask2; /* Interrupt Mask and Priority + * Register register + */ + + volatile unsigned int int_pend2; /* Interrupt Pending Register + * register + */ + + volatile unsigned int int_clear2; /* Interrupt Clear Register + * register + */ + + volatile unsigned int dummy36; +} BM3823_REGISTER_INTER; + +/* This is used to manipulate the on-chip registers. + * + * The following symbol must be defined in the linkcmds file and point + * to the correct location. + */ + +extern BM3823_REGISTER_EXTER EXTER_REG; +extern BM3823_REGISTER_INTER INTER_REG; +#define GPIO_DIR (*(volatile unsigned int *)0x81000408) +static __inline__ int bsp_irq_fixup(int irq) +{ + return irq; +} + +/* Macros to manipulate the Interrupt Clear,Interrupt Force, Interrupt Mask, + * and the Interrupt Pending Registers. + * + * NOTE:For operations which are not atomic, this code disables interrupts + * to guarantee there are no intervening accesses to the same register. + * The operations which read the register, modify the value and then + * store the result back are vulnerable. + */ + +#define BM3823_Clear_interrupt( _source ) \ + do { \ + INTER_REG.Interrupt_Clear = (1 << (_source)); \ + } while (0) + +#define BM3823_Force_interrupt( _source ) \ + do { \ + INTER_REG.Interrupt_Force = (1 << (_source)); \ + } while (0) + +#define BM3823_Is_int errupt_pending( _source ) \ + (INTER_REG.Interrupt_Pending & (1 << (_source))) + +#define BM3823_Is_interrupt_masked( _source ) \ + (!(INTER_REG.Interrupt_Mask & (1 << (_source)))) + +#define BM3823_Mask_interrupt( _source ) \ + do { \ + uint32_t _level; \ + \ + _level = sparc_disable_interrupts(); \ + INTER_REG.Interrupt_Mask &= ~(1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define BM3823_Unmask_interrupt( _source ) \ + do { \ + uint32_t _level; \ + \ + _level = sparc_disable_interrupts(); \ + INTER_REG.Interrupt_Mask |= (1 << (_source)); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +#define BM3823_Disable_interrupt( _source, _previous ) \ + do { \ + uint32_t _level; \ + uint32_t _mask = 1 << (_source); \ + \ + _level = sparc_disable_interrupts(); \ + (_previous) = INTER_REG.Interrupt_Mask; \ + INTER_REG.InIntSubPrioterrupt_Mask = _previous & ~_mask; \ + sparc_enable_interrupts( _level ); \ + (_previous) &= _mask; \ + } while (0) + +#define BM3823_Restore_interrupt( _source, _previous ) \ + do { \ + uint32_t _level; \ + uint32_t _mask = 1 << (_source); \ + \ + _level = sparc_disable_interrupts(); \ + INTER_REG.Interrupt_Mask = \ + (INTER_REG.Interrupt_Mask & ~_mask) | (_previous); \ + sparc_enable_interrupts( _level ); \ + } while (0) + +/* Make all SPARC BSPs have common macros for interrupt handling */ +#define BSP_Clear_interrupt(_source) BM3823_Clear_interrupt(_source) +#define BSP_Force_interrupt(_source) BM3823_Force_interrupt(_source) +#define BSP_Is_interrupt_pending(_source) BM3823_Is_interrupt_pending(_source) +#define BSP_Is_interrupt_masked(_source) BM3823_Is_interrupt_masked(_source) +#define BSP_Unmask_interrupt(_source) BM3823_Unmask_interrupt(_source) +#define BSP_Mask_interrupt(_source) BM3823_Mask_interrupt(_source) +#define BSP_Disable_interrupt(_source, _previous) \ + BM3823_Disable_interrupt(_source, _prev) +#define BSP_Restore_interrupt(_source, _previous) \ + BM3823_Restore_interrupt(_source, _previous) + +/* Make all SPARC BSPs have common macros for interrupt handling on any CPU */ +#define BSP_Cpu_Is_interrupt_masked(_source, _cpu) \ + BSP_Is_interrupt_masked(_source) +#define BSP_Cpu_Unmask_interrupt(_source, _cpu) \ + BSP_Unmask_interrupt(_source) +#define BSP_Cpu_Mask_interrupt(_source, _cpu) \ + BSP_Mask_interrupt(_source) +#define BSP_Cpu_Disable_interrupt(_source, _previous, _cpu) \ + BSP_Disable_interrupt(_source, _prev) +#define BSP_Cpu_Restore_interrupt(_source, _previous, _cpu) \ + BSP_Cpu_Restore_interrupt(_source, _previous) + +/* Each timer control register is organized as follows: + * + * D0 - Enable + * 1 = enable counting + * 0 = hold scaler and counter + * + * D1 - Counter Reload + * 1 = reload counter at zero and restart + * 0 = stop counter at zero + * + * D2 - Counter Load + * 1 = load counter with preset value + * 0 = no function + * + */ + +#define BM3823_REG_TIMER_COUNTER_RELOAD_AT_ZERO 0x00000002 +#define BM3823_REG_TIMER_COUNTER_STOP_AT_ZERO 0x00000000 + +#define BM3823_REG_TIMER_COUNTER_LOAD_COUNTER 0x00000004 + +#define BM3823_REG_TIMER_COUNTER_ENABLE_COUNTING 0x00000001 +#define BM3823_REG_TIMER_COUNTER_DISABLE_COUNTING 0x00000000 + +#define BM3823_REG_TIMER_COUNTER_RELOAD_MASK 0x00000002 +#define BM3823_REG_TIMER_COUNTER_ENABLE_MASK 0x00000001 + +#define BM3823_REG_TIMER_COUNTER_DEFINED_MASK 0x00000003 +#define BM3823_REG_TIMER_COUNTER_CURRENT_MODE_MASK 0x00000003 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Load 32-bit word by forcing a cache-miss */ + +static inline unsigned int bm3823_r32_no_cache(uintptr_t addr) +{ + unsigned int tmp; + __asm__ volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr)); + return tmp; +} + +/**************************************************************************** + * Name: up_clkinit + * + * Description: + * Initialiaze clock/PLL settings per the definitions in the board.h file. + * + ****************************************************************************/ + +void up_clkinitialize(void); + +/**************************************************************************** + * Name: usart0_reset and usart1_reset + * + * Description: + * Reset USART0 or USART1. + * + ****************************************************************************/ + +void usart1_reset(void); +void usart2_reset(void); +void usart3_reset(void); + +/**************************************************************************** + * Name: usart0_configure and usart1_configure + * + * Description: + * Configure USART0 or USART1. + * + ****************************************************************************/ + +void uart1_configure(void); +void uart2_configure(void); +void uart3_configure(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). + * + ****************************************************************************/ + +#ifdef HAVE_SERIAL_CONSOLE +void up_consoleinit(void); +#else +# define up_consoleinit() +#endif + +/**************************************************************************** + * Name: bm3823_uartconfigure + * + * Description: + * Configure a UART as a RS-232 UART. + * + ****************************************************************************/ + +#ifdef HAVE_UART_DEVICE +void bm3823_uartconfigure(uintptr_t uart_base, uint32_t baudrate, + unsigned int parity, unsigned int nbits, bool stop2); +#endif + +/**************************************************************************** + * Name: bm3823_boardinitialize + * + * Description: + * This function must be provided by the board-specific logic in the + * directory boards/sparc/bm3823//src. + * + ****************************************************************************/ + +void bm3823_boardinitialize(void); + +/**************************************************************************** + * Name: gpio_irqinitialize + * + * Description: + * Initialize all vectors to the unexpected interrupt handler + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + * Assumptions: + * Called during the early boot sequence before global interrupts have + * been enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void weak_function gpio_irqinitialize(void); +#endif + +/**************************************************************************** + * Name: gpio_irqattach + * + * Description: + * Attach in GPIO interrupt to the provide 'isr' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +int gpio_irqattach(int irq, xcpt_t newisr, xcpt_t *oldisr); +#endif + +/**************************************************************************** + * Name: gpio_irqenable + * + * Description: + * Enable the GPIO IRQ specified by 'irq' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void gpio_irqenable(int irq); +#endif + +/**************************************************************************** + * Name: gpio_irqdisable + * + * Description: + * Disable the GPIO IRQ specified by 'irq' + * + * Configuration Notes: + * Configuration CONFIG_AVR_GPIOIRQ must be selected to enable the + * overall GPIO IRQ feature. + * + ****************************************************************************/ + +#ifdef CONFIG_SPARC_GPIOIRQ +void gpio_irqdisable(int irq); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_BM3823_BM3823_H */ + diff --git a/arch/sparc/src/bm3823/bm3823_exceptions.S b/arch/sparc/src/bm3823/bm3823_exceptions.S new file mode 100644 index 00000000000..2e0f5353408 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823_exceptions.S @@ -0,0 +1,251 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823_exceptions.S + * + * 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 + +/**************************************************************************** + * External Symbols + ****************************************************************************/ + + .global _ISR_Handler + .global up_doirq /* Dispatch an IRQ */ + +/* + * void _ISR_Handler() + * + * This routine provides the RTEMS interrupt management. + * + * We enter this handler from the 4 instructions in the trap table with + * the following registers assumed to be set as shown: + * + * l0 = PSR + * l1 = PC + * l2 = nPC + * l3 = trap type + * + * NOTE: By an executive defined convention, trap type is between 0 and 255 if + * it is an asynchonous trap and 256 and 511 if it is synchronous. + */ + + .align 4 + +_ISR_Handler: + + /* + * Fix the return address for synchronous traps. + */ + + and %l3, 0xF0, %l6 + cmp %l6, 0x10 ! Is this a synchronous trap? + be,a dont_do_the_window ! No, then skip the adjustment + nop ! DELAY + mov %l2, %l1 ! do not return to the instruction + add %l2, 4, %l2 ! indicated + +dont_do_the_window: + /* + * Global registers %g4 and %g5 are saved directly from %l4 and + * %l5 directly into the ISF below. + */ + mov %g4, %l4 ! save the globals this block uses + mov %g5, %l5 + + restore + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + save +save_isf: + + /* + * Save the state of the interrupted task -- especially the global + * registers -- in the Interrupt Stack Frame. Note that the ISF + * includes a regular minimum stack frame which will be used if + * needed by register window overflow and underflow handlers. + * + * REGISTERS SAME AS AT _ISR_Handler + */ + + sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp + ! make space for ISF + + std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC + st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC + st %g1, [%sp + ISF_G1_OFFSET] ! save g1 + std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3 + std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above + std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7 + + std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1 + std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3 + std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5 + std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7 + + rd %y, %g1 + st %g1, [%sp + ISF_Y_OFFSET] ! save y + + mov %sp, %o1 ! 2nd arg to ISR Handler + !add %o1, 0x60,%o1 + + st %fsr, [%sp + ISF_FSR_OFFSET] + std %f0, [%sp + ISF_F0_OFFSET] + std %f2, [%sp + ISF_F2_OFFSET] + std %f4, [%sp + ISF_F4_OFFSET] + std %f6, [%sp + ISF_F6_OFFSET] + std %f8, [%sp + ISF_F8_OFFSET] + std %f10, [%sp + ISF_F10_OFFSET] + std %f12, [%sp + ISF_F12_OFFSET] + std %f14, [%sp + ISF_F14_OFFSET] + std %f16, [%sp + ISF_F16_OFFSET] + std %f18, [%sp + ISF_F18_OFFSET] + std %f20, [%sp + ISF_F20_OFFSET] + std %f22, [%sp + ISF_F22_OFFSET] + std %f24, [%sp + ISF_F24_OFFSET] + std %f26, [%sp + ISF_F26_OFFSET] + std %f28, [%sp + ISF_F28_OFFSET] + std %f30, [%sp + ISF_F30_OFFSET] ! total 32 word + +fix_pil: + mov %l0,%g5 + or %g5, SPARC_PSR_PIL_MASK, %g5 /* 0x00000F00 */ + wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS **** /* 0x00000020 */ + nop + nop + nop +/*==========================================================================*/ + ! o1 = 2nd arg = address of the ISF + ! WAS LOADED WHEN ISF WAS SAVED!!! + mov %l3, %o0 ! o0 = 1st arg = vector number + call up_doirq /* call ISR dispatcher */ + nop +/*==========================================================================*/ + mov %l0, %psr ! **** DISABLE TRAPS **** + nop; + nop; + nop; + + +simple_return: + ldd [%o0 + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7 + sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp + + ld [%o0 + ISF_Y_OFFSET], %l5 ! restore y + wr %l5, 0, %y + + ldd [%o0 + ISF_PSR_OFFSET], %l0 ! restore psr, PC + ld [%o0 + ISF_NPC_OFFSET], %l2 ! restore nPC + rd %psr, %l3 + and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP + andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task + or %l3, %l0, %l0 ! install it later... + andn %l0, SPARC_PSR_ET_MASK, %l0 + + /* + * Restore tasks global and out registers + */ + ld [%o0 + ISF_G1_OFFSET], %g1 ! restore g1 ! g1 is restored later + ldd [%o0 + ISF_G2_OFFSET], %g2 ! restore g2, g3 + ldd [%o0 + ISF_G4_OFFSET], %g4 ! restore g4, g5 + ldd [%o0 + ISF_G6_OFFSET], %g6 ! restore g6, g7 + + ldd [%o0 + ISF_I0_OFFSET], %i0 ! restore i0, i1 + ldd [%o0 + ISF_I2_OFFSET], %i2 ! restore i2, i3 + ldd [%o0 + ISF_I4_OFFSET], %i4 ! restore i4, i5 + !ldd [%o0 + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7 + + ldd [%o0 + PRE_STACK_FRAME_L0_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_L0_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_L2_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_L2_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_L4_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_L4_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_L6_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_L6_OFFSET] + + ldd [%o0 + PRE_STACK_FRAME_I0_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_I0_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_I2_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_I2_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_I4_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_I4_OFFSET] + ldd [%o0 + PRE_STACK_FRAME_I6_FP_OFFSET], %l4 + std %l4, [%fp + CPU_STACK_FRAME_I6_FP_OFFSET] + + + ldd [%o0 + ISF_F0_OFFSET] ,%f0 + ldd [%o0 + ISF_F2_OFFSET] ,%f2 + ldd [%o0 + ISF_F4_OFFSET] ,%f4 + ldd [%o0 + ISF_F6_OFFSET] ,%f6 + ldd [%o0 + ISF_F8_OFFSET] ,%f8 + ldd [%o0 + ISF_F10_OFFSET],%f10 + ldd [%o0 + ISF_F12_OFFSET],%f12 + ldd [%o0 + ISF_F14_OFFSET],%f14 + ldd [%o0 + ISF_F16_OFFSET],%f16 + ldd [%o0 + ISF_F18_OFFSET],%f18 + ldd [%o0 + ISF_F20_OFFSET],%f20 + ldd [%o0 + ISF_F22_OFFSET],%f22 + ldd [%o0 + ISF_F24_OFFSET],%f24 + ldd [%o0 + ISF_F26_OFFSET],%f26 + ldd [%o0 + ISF_F28_OFFSET],%f28 + ldd [%o0 + ISF_F30_OFFSET],%f30 + ld [%o0 + ISF_FSR_OFFSET],%fsr + nop + nop + nop + +good_task_window: + + restore ! Interruptee~s window + ldd [%sp + 0 * 4], %l0 ! restore L & I registers + ldd [%sp + 2 * 4], %l2 + ldd [%sp + 4 * 4], %l4 + ldd [%sp + 6 * 4], %l6 + + ldd [%sp + 8 * 4], %i0 + ldd [%sp + 10 * 4], %i2 + ldd [%sp + 12 * 4], %i4 + ldd [%sp + 14 * 4], %i6 + save + + mov %l0, %psr ! **** DISABLE TRAPS **** + nop; + nop; + nop + ! and restore condition codes. + + jmp %l1 ! transfer control and + rett %l2 ! go back to tasks window + nop + /* isr end */ + + /* trap handler end*/ + diff --git a/arch/sparc/src/bm3823/bm3823_head.S b/arch/sparc/src/bm3823/bm3823_head.S new file mode 100644 index 00000000000..fd844164b93 --- /dev/null +++ b/arch/sparc/src/bm3823/bm3823_head.S @@ -0,0 +1,624 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/bm3823_head.S + * + * 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 + + +#define RTRAP(_vector, _handler) mov %g0, %l0 ; sethi %hi(_handler), %l4 ; jmp %l4+%lo(_handler); mov _vector, %l3 +#define TRAP(_vector, _handler) mov %psr, %l0; sethi %hi(_handler), %l4 ; jmp %l4+%lo(_handler); mov _vector, %l3 + +/* Unexcpected trap will halt the processor by forcing it to error state */ +#define BAD_TRAP ta 0; nop; nop; nop; +#define SOFT_TRAP BAD_TRAP /* Software trap. Treat as BAD_TRAP */ + +/* + * System call optimized trap table entry + */ +#define IRQDIS_TRAP(_handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + or %l0, 0x0f00, %l3; ! Set PIL=0xf to disable IRQ + +/* + * System call optimized trap table entry + */ +#define IRQEN_TRAP(_handler) \ + mov %psr, %l0 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + andn %l0, 0xf00, %l3; ! Set PIL=0 to Enable IRQ + +/* + * Window Overflow optimized trap table entry + */ +#define WOTRAP(_vector, _handler) \ + sethi %hi(_handler), %l4; \ + jmp %l4+%lo(_handler); \ + save; \ + nop + +/* + * Window Underflow optimized trap table entry + */ +#define WUTRAP(_vector, _handler) \ + mov %wim, %l3 ; \ + sethi %hi(_handler), %l4 ; \ + jmp %l4+%lo(_handler); \ + sll %l3, 1, %l4 ! l4 = WIM << 1 + + .text + .global _trap_table, _hardreset + .global __start + .global up_lowinit /* Perform low level initialization */ + .global nx_start /* NuttX entry point */ + .global _userinit, _end + .global _window_overflow, _window_underflow, _flush_windows, _fpdis_enable + .global syscall_irqdis, syscall_irqen + .global _ISR_Handler + + /* Hardware traps */ +_trap_table: +_hardreset: + RTRAP(0,__start); ! 00 reset trap + BAD_TRAP; ! 01 instruction_access_exception + BAD_TRAP; ! 02 illegal_instruction + BAD_TRAP; ! 03 priveleged_instruction + TRAP(4,_fpdis_enable); ! 04 fp_disabled + WOTRAP(5,_window_overflow); ! 05 window_overflow + WUTRAP(6,_window_underflow); ! 06 window_underflow + BAD_TRAP; ! 07 memory_add0ress_not_aligned + BAD_TRAP; ! 08 fp_exception + BAD_TRAP; ! 09 data_access_exception + BAD_TRAP; ! 0A tag_overflow + BAD_TRAP; ! 0B undefined + BAD_TRAP; ! 0C undefined + BAD_TRAP; ! 0D undefined + BAD_TRAP; ! 0E undefined + BAD_TRAP; ! 0F undefined + BAD_TRAP; ! 10 undefined + + /* Interrupt entries */ + TRAP(0x11,_ISR_Handler) ! 11 interrupt level 1 + TRAP(0x12,_ISR_Handler) ! 12 interrupt level 2 + TRAP(0x13,_ISR_Handler) ! 13 interrupt level 3 + TRAP(0x14,_ISR_Handler) ! 14 interrupt level 4 + TRAP(0x15,_ISR_Handler) ! 15 interrupt level 5 + TRAP(0x16,_ISR_Handler) ! 16 interrupt level 6 + TRAP(0x17,_ISR_Handler) ! 17 interrupt level 7 + TRAP(0x18,_ISR_Handler) ! 18 interrupt level 8 + TRAP(0x19,_ISR_Handler) ! 19 interrupt level 9 + TRAP(0x1A,_ISR_Handler) ! 1A interrupt level 1 + TRAP(0x1B,_ISR_Handler) ! 1B interrupt level 11 + TRAP(0x1C,_ISR_Handler) ! 1C interrupt level 12 + TRAP(0x1D,_ISR_Handler) ! 1D interrupt level 13 + TRAP(0x1E,_ISR_Handler) ! 1E interrupt level 14 + TRAP(0x1F,_ISR_Handler) ! 1F interrupt level 15 + + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 undefined + BAD_TRAP; ! 24 cp_disabled + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 25 - 27 undefined + BAD_TRAP; ! 28 cp_exception + BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 29 - 2B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 33 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 43 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 63 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 73 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B undefined + BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F undefined + + /* + * Software traps + * + * NOTE: At the risk of being redundant... this is not a full + * table. The setjmp on the SPARC requires a window flush trap + * handler and RTEMS will preserve the entries that were + * installed before. + */ + + TRAP( 0x80, _ISR_Handler ); ! 80 halt syscall SW trap + SOFT_TRAP; SOFT_TRAP; ! 81 - 82 + TRAP( 0x83, _flush_windows); ! 83 flush windows SW trap + + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 84 - 87 + TRAP( 0x88, _ISR_Handler ); ! 88 + + /* + * SW Trap 9-15 Reserved for Operating System + * + * SPARC_SWTRAP_IRQDIS + * SPARC_SWTRAP_IRQEN + */ + IRQDIS_TRAP(syscall_irqdis); ! 89 IRQ Disable syscall trap + IRQEN_TRAP(syscall_irqen); ! 8A IRQ Enable syscall trap + + SOFT_TRAP; ! 8B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 8C - 8F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 90 - 93 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 94 - 97 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 98 - 9B + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! 9C - 9F + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A0 - A3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A4 - A7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! A8 - AB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! AC - AF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B0 - B3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B4 - B7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! B8 - BB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! BC - BF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C0 - C3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C4 - C7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! C8 - CB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! CC - CF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D0 - D3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D4 - D7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! D8 - DB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! DC - DF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E0 - E3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E4 - E7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! E8 - EB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! EC - EF + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F0 - F3 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F4 - F7 + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! F8 - FB + SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! FC - FF + +/* trap table end*/ + +/* + * Init for SPARC-CPU + */ +#define PSR_INIT 0x10c0 /* Disable traps, set s and ps */ + +__start: + mov %g0, %asr16 + mov %g0, %asr17 + nop + nop + + ! initial the IU register !disable trap + set 0x10c0, %g1 + mov %g1,%psr + nop + nop + nop + + mov %g0,%wim + nop + nop + nop + + mov %g0,%g1 + mov %g0,%g2 + mov %g0,%g3 + mov %g0,%g4 + mov %g0,%g5 + mov %g0,%g6 + mov %g0,%g7 + + /*Fill local and in/out register*/ + mov 0x8,%g1 +1: mov %g0,%l0 + mov %g0,%l1 + mov %g0,%l2 + mov %g0,%l3 + mov %g0,%l4 + mov %g0,%l5 + mov %g0,%l6 + mov %g0,%l7 + mov %g0,%i0 + mov %g0,%i1 + mov %g0,%i2 + mov %g0,%i3 + mov %g0,%i4 + mov %g0,%i5 + mov %g0,%i6 + mov %g0,%i7 + subcc %g1,1,%g1 + save + bne 1b + flush + nop + + ! initial the WIM register = 2 + set 2, %g1 + mov %g1, %wim + nop + nop + nop + + ! initial the TBR table + sethi %hi(_trap_table), %g1 + mov %g1, %tbr + nop + nop + nop + + ! enable traps,fpu in psr + set 0x10e0, %g1 + mov %g1,%psr + nop + nop + nop + set EXTER_REG,%g1 + ld [%g1+4], %g2 + or %g2, 0x4f, %g2 + st %g2, [%g1+4] + nop + nop + + ! initial the FSR register + set _fsrinit,%g1 + ld [%g1] , %fsr + nop + nop + nop + + ! initial the FPU %f register + set _fpdata,%g1 + ldd [%g1], %f0 + ldd [%g1], %f2 + ldd [%g1], %f4 + ldd [%g1], %f6 + ldd [%g1], %f8 + ldd [%g1], %f10 + ldd [%g1], %f12 + ldd [%g1], %f14 + ldd [%g1], %f16 + ldd [%g1], %f18 + ldd [%g1], %f20 + ldd [%g1], %f22 + ldd [%g1], %f24 + ldd [%g1], %f26 + ldd [%g1], %f28 + ldd [%g1], %f30 + nop + + ! initial cache controler + set EXTER_REG, %g1 + set 0x81000f,%g2 !open dcache,icache, dcache snoop,icache burst + ! set 0x80000f,%g2 !open dcache,icache, dcache snoop + ! set 0x01000f,%g2 !open dcache,icache, icache burst + ! set 0x00000f,%g2 !open dcache,icache + ! set 0x000000,%g2 !close dcache,icache + st %g2, [%g1 + 0x14] + nop + + set EXTER_REG,%g1 + ld [%g1+4], %g2 + or %g2, 0x4f, %g2 /*将存储器配置为读改写(区别于写选通),等待后期设置为最大*/ + st %g2, [%g1+4] + nop + + ! initial the stack point + sethi %hi(__stack), %g1 + or %g1, %lo(__stack), %g1 + subcc %g1, 16, %g1 + mov %g1, %sp + nop + + !call _userinit + nop + + call up_lowinit ! bm3803_lowinit.c + nop + + call nx_start ! sched/init/nx_start.c + nop + +_exit: + ta 0 + nop + nop + +_userinit: /* clear the bss */ + save %sp, -64, %sp + sethi %hi(__bss_start),%g2 + or %g2,%lo(__bss_start),%g2 ! g2 = start of bss + sethi %hi(_end),%g3 + or %g3,%lo(_end),%g3 ! g3 = end of bss + mov %g0,%g1 ! so std has two zeros + sub %g3, %g2, %g3 +zerobss: + subcc %g3, 8, %g3 + bge,a zerobss + std %g0,[%g2+%g3] + set _end, %o0 + st %g0,[%o0] + nop + + ret + restore + + +/* + * Init END + */ + +/* Number of register windows */ +#define NWINDOWS 8 + + /* + * Window overflow trap handler. + * + * On entry: + * + * prev regwin l1 = pc + * prev regwin l2 = npc + */ + .global _window_overflow +_window_overflow: + + /* + * Calculate new WIM by "rotating" the valid bits in the WIM right + * by one position. The following shows how the bits move for a SPARC + * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. + * + * OLD WIM = 76543210 + * NEW WIM = 07654321 + * + * NOTE: New WIM must be stored in a global register since the + * "save" instruction just prior to the load of the wim + * register will result in the local register set changing. + */ + + std %l0, [%sp + 0x00] ! save local register set + std %l2, [%sp + 0x08] + mov %wim, %l3 + sll %l3, NWINDOWS-1 , %l2 + ! l2 = WIM << (Number Windows - 1) + std %l4, [%sp + 0x10] + std %l6, [%sp + 0x18] + srl %l3, 1, %l3 ! l3 = WIM >> 1 + wr %l3, %l2, %wim ! WIM = (WIM >> 1) ^ + ! (WIM << (Number Windows - 1)) + ! 3 instruction delay not needed here + std %i0, [%sp + 0x20] ! save input register set + std %i2, [%sp + 0x28] + std %i4, [%sp + 0x30] + std %i6, [%sp + 0x38] + restore ! Go back to trap window. + jmp %l1 ! Re-execute save. + rett %l2 + + + /* + * Window underflow trap handler. + * + * On entry: + * + * l1 = pc + * l2 = npc + * l3 = wim (from trap vector) + * l4 = wim << 1 (from trap vector) + */ + .global _window_underflow +_window_underflow: + + /* + * Calculate new WIM by "rotating" the valid bits in the WIM left + * by one position. The following shows how the bits move for a SPARC + * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is 8. + * + * OLD WIM = 76543210 + * NEW WIM = 07654321 + * + * NOTE: New WIM must be stored in a global register since the + * "save" instruction just prior to the load of the wim + * register will result in the local register set changing. + */ + + srl %l3, NWINDOWS-1, %l5 + or %l5, %l4, %l5 ! l5 = (WIM << 1) | + ! (WIM >> (Number Windows-1)) + mov %l5, %wim ! load the new WIM + nop; nop; nop ! 3 slot delay + restore ! Two restores to get into the + restore ! window to restore + ldd [%sp + 0x00], %l0 ! First the local register set + ldd [%sp + 0x08], %l2 + ldd [%sp + 0x10], %l4 + ldd [%sp + 0x18], %l6 + ldd [%sp + 0x20], %i0 ! Then the input registers + ldd [%sp + 0x28], %i2 + ldd [%sp + 0x30], %i4 + ldd [%sp + 0x38], %i6 + save ! Get back to the trap window. + save + jmp %l1 ! Re-execute restore. + rett %l2 + + + /* + * Flush All Windows trap handler. + * + * Flush all windows with valid contents except the current one + * and the one we will be returning to. + * + * In examining the set register windows, one may logically divide + * the windows into sets (some of which may be empty) based on their + * current status: + * + * + current (i.e. in use), + * + used (i.e. a restore would not trap) + * + invalid (i.e. 1 in corresponding bit in WIM) + * + unused + * + * Either the used or unused set of windows may be empty. + * + * NOTE: We assume only one bit is set in the WIM at a time. + * + * Given a CWP of 5 and a WIM of 0x1, the registers are divided + * into sets as follows: + * + * + 0 - invalid + * + 1-4 - unused + * + 5 - current + * + 6-7 - used + * + * In this case, we only would save the used windows which we + * will not be returning to -- 6. + * + * Register Usage while saving the windows: + * g1 = current PSR + * g2 = current wim + * g3 = CWP + * g4 = wim scratch + * g5 = scratch + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + */ + .global _flush_windows +_flush_windows: + /* + * Save the global registers we will be using + */ + + mov %g1, %l3 + mov %g2, %l4 + mov %g3, %l5 + mov %g4, %l6 + mov %g5, %l7 + + mov %l0, %g1 ! g1 = psr + mov %wim, %g2 ! g2 = wim + and %l0, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP + + add %g3, 1, %g5 ! g5 = CWP + 1 + and %g5, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g5 + + mov 1, %g4 + sll %g4, %g5, %g4 ! g4 = WIM mask for CWP+1 invalid + + restore ! go back one register window + +save_frame_loop: + sll %g4, 1, %g5 ! rotate the "wim" left 1 + srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4 + or %g4, %g5, %g4 ! g4 = wim if we do one restore + + /* + * If a restore would not underflow, then continue. + */ + + andcc %g4, %g2, %g0 ! Any windows to flush? + bnz done_flushing ! No, then continue + nop + + restore ! back one window + + /* + * Now save the window just as if we overflowed to it. + */ + + std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET] + std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET] + std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET] + std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET] + + std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET] + std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET] + std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET] + std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET] + + ba save_frame_loop + nop + +done_flushing: + + add %g3, 2, %g3 ! calculate desired WIM + and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3 + mov 1, %g4 + sll %g4, %g3, %g4 ! g4 = new WIM + mov %g4, %wim + + mov %g1, %psr ! restore PSR + nop + nop + nop + + /* + * Restore the global registers we used + */ + + mov %l3, %g1 + mov %l4, %g2 + mov %l5, %g3 + mov %l6, %g4 + mov %l7, %g5 + + jmpl %l2, %g0 + rett %l2 + 4 + + +/* fpdis_enable */ + .global _fpdis_enable +_fpdis_enable: + + jmpl %l2, %g0 + rett %l2 + 4 + nop + nop +/*************************************************/ + + +/*************************************************/ + .data + .global _fsrinit, _fpdata, g_idle_topstack + .type g_idle_topstack, object +.align 8 +_fsrinit: + .word 0x0,0 + +.align 8 +_fpdata: + .word 0,0 + +.align 8 +g_idle_topstack: + .long _end + CONFIG_IDLETHREAD_STACKSIZE + .size g_idle_topstack, .-g_idle_topstack + .end + diff --git a/arch/sparc/src/bm3823/chip.h b/arch/sparc/src/bm3823/chip.h new file mode 100644 index 00000000000..1f42ab6b7e7 --- /dev/null +++ b/arch/sparc/src/bm3823/chip.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * arch/sparc/src/bm3823/chip.h + * + * 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_SPARC_SRC_BM3823_CHIP_H +#define __ARCH_SPARC_SRC_BM3823_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include only the memory map. Other chip hardware files should then + * include this file for the proper setup + */ + +#include "bm3823-memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Define features for supported chip in the SPARC family */ + +#if 1 +#else +# error "Unsupported SPARC chip" +#endif + +#endif /* __ARCH_SPARC_SRC_BM3823_CHIP_H */ + diff --git a/arch/sparc/src/common/Kconfig b/arch/sparc/src/common/Kconfig new file mode 100644 index 00000000000..88f885762fb --- /dev/null +++ b/arch/sparc/src/common/Kconfig @@ -0,0 +1,7 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_SPARC +endif diff --git a/arch/sparc/src/common/up_allocateheap.c b/arch/sparc/src/common/up_allocateheap.c new file mode 100644 index 00000000000..2eecca505a2 --- /dev/null +++ b/arch/sparc/src/common/up_allocateheap.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/sparc/src/common/up_allocateheap.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the + * size of the unprotected, user-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated (and protected) by an analogous up_allocate_kheap(). + * + ****************************************************************************/ + +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +{ + *heap_start = (FAR void *)g_idle_topstack; + *heap_size = CONFIG_RAM_END - g_idle_topstack; +} diff --git a/arch/sparc/src/common/up_arch.h b/arch/sparc/src/common/up_arch.h new file mode 100644 index 00000000000..af7e3e64b55 --- /dev/null +++ b/arch/sparc/src/common/up_arch.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/sparc/src/common/up_arch.h + * + * 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_SPARC_SRC_COMMON_UP_ARCH_H +#define __ARCH_SPARC_SRC_COMMON_UP_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +# 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)) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Atomic modification of registers */ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits); +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits); +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_COMMON_UP_ARCH_H */ + diff --git a/arch/sparc/src/common/up_assert.c b/arch/sparc/src/common/up_assert.c new file mode 100644 index 00000000000..395bbc85d64 --- /dev/null +++ b/arch/sparc/src/common/up_assert.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * arch/sparc/src/common/up_assert.c + * + * 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 +#include +#include + +#include + +#include "up_arch.h" +#include "sched/sched.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* USB trace dumping */ + +#ifndef CONFIG_USBDEV_TRACE +# undef CONFIG_ARCH_USBDUMP +#endif + +#ifndef CONFIG_BOARD_RESET_ON_ASSERT +# define CONFIG_BOARD_RESET_ON_ASSERT 0 +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) noreturn_function; +static void _up_assert(int errorcode) +{ + /* Flush any buffered SYSLOG data */ + + (void)syslog_flush(); + + /* Are we in an interrupt handler or the idle task? */ + + if (g_current_regs || running_task()->flink == NULL) + { + (void)up_irq_save(); + for (; ; ) + { +#if CONFIG_BOARD_RESET_ON_ASSERT >= 1 + board_reset(CONFIG_BOARD_ASSERT_RESET_VALUE); +#endif +#ifdef CONFIG_ARCH_LEDS + board_autoled_on(LED_PANIC); + up_mdelay(250); + board_autoled_off(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { +#if CONFIG_BOARD_RESET_ON_ASSERT >= 2 + board_reset(CONFIG_BOARD_ASSERT_RESET_VALUE); +#endif + exit(errorcode); + } +} + +/**************************************************************************** + * Name: assert_tracecallback + ****************************************************************************/ + +#ifdef CONFIG_ARCH_USBDUMP +static int usbtrace_syslog(FAR const char *fmt, ...) +{ + va_list ap; + int ret; + + /* Let nx_vsyslog do the real work */ + + va_start(ap, fmt); + ret = nx_vsyslog(LOG_EMERG, fmt, &ap); + va_end(ap); + return ret; +} + +static int assert_tracecallback(FAR struct usbtrace_s *trace, FAR void *arg) +{ + usbtrace_trprintf(usbtrace_syslog, trace->event, trace->value); + return 0; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const char *filename, int lineno) +{ +#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT) + struct tcb_s *rtcb = running_task(); +#endif + + /* Flush any buffered SYSLOG data (prior to the assertion) */ + + (void)syslog_flush(); + +#if CONFIG_TASK_NAME_SIZE > 0 + _alert("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + _alert("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + + up_dumpstate(); + + /* Flush any buffered SYSLOG data (from the above) */ + + (void)syslog_flush(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), running_task(), filename, lineno); +#endif + +#ifdef CONFIG_ARCH_USBDUMP + /* Dump USB trace data */ + + (void)usbtrace_enumerate(assert_tracecallback, NULL); +#endif + + _up_assert(EXIT_FAILURE); +} diff --git a/arch/sparc/src/common/up_checkstack.c b/arch/sparc/src/common/up_checkstack.c new file mode 100644 index 00000000000..d65e2a81198 --- /dev/null +++ b/arch/sparc/src/common/up_checkstack.c @@ -0,0 +1,211 @@ +/**************************************************************************** + * arch/sparc/src/common/up_checkstack.c + * + * 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 +#include + +#include "sched/sched.h" +#include "up_internal.h" + +#ifdef CONFIG_STACK_COLORATION + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static size_t do_stackcheck(uintptr_t alloc, size_t size, bool int_stack); + +/**************************************************************************** + * Name: do_stackcheck + * + * Description: + * Determine (approximately) how much stack has been used be searching the + * stack memory for a high water mark. That is, the deepest level of the + * stack that clobbered some recognizable marker in the stack memory. + * + * Input Parameters: + * alloc - Allocation base address of the stack + * size - The size of the stack in bytes + * + * Returned Value: + * The estimated amount of stack space used. + * + ****************************************************************************/ + +static size_t do_stackcheck(uintptr_t alloc, size_t size, bool int_stack) +{ + FAR uintptr_t start; + FAR uintptr_t end; + FAR uint32_t *ptr; + size_t mark; + + if (size == 0) + { + return 0; + } + + /* Get aligned addresses of the top and bottom of the stack */ + +#ifdef CONFIG_TLS + if (!int_stack) + { + /* Skip over the TLS data structure at the bottom of the stack */ + + DEBUGASSERT((alloc & TLS_STACK_MASK) == 0); + start = alloc + sizeof(struct tls_info_s); + } + else + { + start = alloc & ~3; + } +#else + UNUSED(int_stack); + start = alloc & ~3; +#endif + + end = (alloc + size + 3) & ~3; + + /* Get the adjusted size based on the top and bottom of the stack */ + + size = end - start; + + /* The ARM uses a push-down stack: the stack grows toward lower addresses + * in memory. We need to start at the lowest address in the stack memory + * allocation and search to higher addresses. The first word we encounter + * that does not have the magic value is the high water mark. + */ + + for (ptr = (FAR uint32_t *)start, mark = (size >> 2); + *ptr == STACK_COLOR && mark > 0; + ptr++, mark--); + + /* If the stack is completely used, then this might mean that the stack + * overflowed from above (meaning that the stack is too small), or may + * have been overwritten from below meaning that some other stack or data + * structure overflowed. + * + * If you see returned values saying that the entire stack is being used + * then enable the following logic to see it there are unused areas in the + * middle of the stack. + */ + +#if 0 + if (mark + 16 > nwords) + { + int i; + int j; + + ptr = (FAR uint32_t *)start; + for (i = 0; i < size; i += 4 * 64) + { + for (j = 0; j < 64; j++) + { + int ch; + if (*ptr++ == STACK_COLOR) + { + ch = '.'; + } + else + { + ch = 'X'; + } + + up_putc(ch); + } + + up_putc('\n'); + } + } +#endif + + /* Return our guess about how much stack space was used */ + + return mark << 2; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_check_stack and friends + * + * Description: + * Determine (approximately) how much stack has been used be searching the + * stack memory for a high water mark. That is, the deepest level of the + * stack that clobbered some recognizable marker in the stack memory. + * + * Input Parameters: + * None + * + * Returned Value: + * The estimated amount of stack space used. + * + ****************************************************************************/ + +size_t up_check_tcbstack(FAR struct tcb_s *tcb) +{ + return do_stackcheck((uintptr_t)tcb->stack_alloc_ptr, tcb->adj_stack_size, + false); +} + +ssize_t up_check_tcbstack_remain(FAR struct tcb_s *tcb) +{ + return (ssize_t)tcb->adj_stack_size - (ssize_t)up_check_tcbstack(tcb); +} + +size_t up_check_stack(void) +{ + return up_check_tcbstack(this_task()); +} + +ssize_t up_check_stack_remain(void) +{ + return up_check_tcbstack_remain(this_task()); +} + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +size_t up_check_intstack(void) +{ + return do_stackcheck((uintptr_t)&g_intstackalloc, + (CONFIG_ARCH_INTERRUPTSTACK & ~3), + true); +} + +size_t up_check_intstack_remain(void) +{ + return (CONFIG_ARCH_INTERRUPTSTACK & ~3) - up_check_intstack(); +} +#endif + +#endif /* CONFIG_STACK_COLORATION */ diff --git a/arch/sparc/src/common/up_createstack.c b/arch/sparc/src/common/up_createstack.c new file mode 100644 index 00000000000..21b605ed896 --- /dev/null +++ b/arch/sparc/src/common/up_createstack.c @@ -0,0 +1,203 @@ +/**************************************************************************** + * arch/sparc/src/common/up_createstack.c + * + * 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 +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* sparc requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#define STACK_ALIGNMENT 8 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_create_stack + * + * Description: + * Allocate a stack for a new thread and setup up stack-related information + * in the TCB. + * + * The following TCB fields must be initialized by this function: + * + * - adj_stack_size: Stack size after adjustment for hardware, processor, + * etc. This value is retained only for debug purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of + * the stack pointer. + * + * Input Parameters: + * - tcb: The TCB of new task + * - stack_size: The requested stack size. At least this much + * must be allocated. + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain contexts where the TCB may not be fully + * initialized when up_create_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is allocated. For example, kernel thread stacks should + * be allocated from protected kernel memory. Stacks for user tasks and + * threads must come from memory that is accessible to user code. + * + ****************************************************************************/ + +int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) +{ + /* Is there already a stack allocated of a different size? Because of + * alignment issues, stack_size might erroneously appear to be of a + * different size. Fortunately, this is not a critical operation. + */ + + if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) + { + /* Yes.. Release the old stack */ + + up_release_stack(tcb, ttype); + } + + /* Do we need to allocate a new stack? */ + + if (!tcb->stack_alloc_ptr) + { + /* Allocate the stack. If DEBUG is enabled (but not stack debug), + * then create a zeroed stack to make stack dumps easier to trace. + */ + +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); + } + +#ifdef CONFIG_DEBUG_FEATURES + /* Was the allocation successful? */ + + if (!tcb->stack_alloc_ptr) + { + serr("ERROR: Failed to allocate stack, size %d\n", stack_size); + } +#endif + } + + /* Did we successfully allocate a stack? */ + + if (tcb->stack_alloc_ptr) + { + size_t top_of_stack; + size_t size_of_stack; + + /* Yes.. If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ + +#ifdef CONFIG_STACK_COLORATION + memset(tcb->stack_alloc_ptr, 0xaa, stack_size); +#endif + + /* sparc uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register points to the + * lowest, valid working address (the "top" of the stack). Items on + * the stack are referenced as positive word offsets from sp. + */ + + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size - 4; + + /* The sparc stack must be aligned at word (8 byte) boundaries; for + * floating point use, the stack must be aligned to 8-byte addresses. + * If necessary top_of_stack must be rounded down to the next + * boundary to meet these alignment requirements. + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + + /* The size of the stack in bytes is then the difference between + * the top and the bottom of the stack (+4 because if the top + * is the same as the bottom, then the size is one 32-bit element). + * The size need not be aligned. + */ + + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr + 4; + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->stack_base_ptr = tcb->stack_alloc_ptr; + tcb->adj_stack_size = size_of_stack; + tcb->flags |= TCB_FLAG_FREE_STACK; + + board_autoled_on(LED_STACKCREATED); + return OK; + } + + return ERROR; +} diff --git a/arch/sparc/src/common/up_exit.c b/arch/sparc/src/common/up_exit.c new file mode 100644 index 00000000000..c21f4da397d --- /dev/null +++ b/arch/sparc/src/common/up_exit.c @@ -0,0 +1,184 @@ +/**************************************************************************** + * arch/sparc/src/common/up_exit.c + * + * 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 +#ifdef CONFIG_DUMP_ON_EXIT +# include +#endif + +#include "task/task.h" +#include "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_DEBUG_SCHED_INFO +# undef CONFIG_DUMP_ON_EXIT +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _up_dumponexit + * + * Description: + * Dump the state of all tasks whenever on task exits. This is debug + * instrumentation that was added to check file-related reference counting + * but could be useful again sometime in the future. + * + ****************************************************************************/ + +#ifdef CONFIG_DUMP_ON_EXIT +static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) +{ + FAR struct filelist *filelist; +#if CONFIG_NFILE_STREAMS > 0 + FAR struct streamlist *streamlist; +#endif + int i; + + sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); + sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); + + filelist = tcb->group->tg_filelist; + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + struct inode *inode = filelist->fl_files[i].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i, inode->i_crefs); + } + } + +#if CONFIG_NFILE_STREAMS > 0 + streamlist = tcb->group->tg_streamlist; + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + struct file_struct *filep = &streamlist->sl_streams[i]; + if (filep->fs_fd >= 0) + { +#ifndef CONFIG_STDIO_DISABLE_BUFFERING + if (filep->fs_bufstart != NULL) + { + sinfo(" fd=%d nbytes=%d\n", + filep->fs_fd, + filep->fs_bufpos - filep->fs_bufstart); + } + else +#endif + { + sinfo(" fd=%d\n", filep->fs_fd); + } + } + } +#endif +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_exit + * + * Description: + * This function causes the currently executing task to cease + * to exist. This is a special case of task_delete() where the task to + * be deleted is the currently executing task. It is more complex because + * a context switch must be perform to the next ready to run task. + * + ****************************************************************************/ + +void up_exit(int status) +{ + struct tcb_s *tcb = this_task(); + + /* Make sure that we are in a critical section with local interrupts. + * The IRQ state will be restored when the next task is started. + */ + + (void)enter_critical_section(); + + sinfo("TCB=%p exiting\n", tcb); + +#ifdef CONFIG_DUMP_ON_EXIT + sinfo("Other tasks:\n"); + sched_foreach(_up_dumponexit, NULL); +#endif + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(tcb); + + /* Destroy the task at the head of the ready to run list. */ + + (void)nxtask_exit(); + + /* Now, perform the context switch to the new ready-to-run task at the + * head of the list. + */ + + tcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously running + * task is closed down gracefully (data caches dump, MMU flushed) and + * set up the address environment for the new thread at the head of + * the ready-to-run list. + */ + + (void)group_addrenv(tcb); +#endif + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(tcb); + + /* Then switch contexts */ + + up_fullcontextrestore(tcb->xcp.regs); + + /* up_fullcontextrestore() should not return but could if software + * interrupts are disabled. NOTE: Can't use DEBUGPANIC here because + * that results in a GCC compilation warning: "No return function does + * return" + */ + + PANIC(); +} diff --git a/arch/sparc/src/common/up_idle.c b/arch/sparc/src/common/up_idle.c new file mode 100644 index 00000000000..3ca4df75c4a --- /dev/null +++ b/arch/sparc/src/common/up_idle.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/sparc/src/common/up_idle.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their + * is no other ready-to-run task. This is processor idle + * time and will continue until some interrupt occurs to + * cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., + * this is where power management operations might be + * performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, + * then process "fake" timer interrupts. Hopefully, something + * will wake up. + */ + + nxsched_process_timer(); +#endif +} + diff --git a/arch/sparc/src/common/up_initialize.c b/arch/sparc/src/common/up_initialize.c new file mode 100644 index 00000000000..1b0644b2321 --- /dev/null +++ b/arch/sparc/src/common/up_initialize.c @@ -0,0 +1,289 @@ +/**************************************************************************** + * arch/sparc/src/common/up_initialize.c + * + * 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determine which (if any) console driver to use. This will probably cause + * up_serialinit to be incorrectly called if there is no USART configured to + * be an RS-232 device (see as an example arch/sparc/src/at32uc23/at32uc3 + * config.h) This will probably have to be revisited someday. + * + * If a console is enabled and no other console device is specified, then a + * serial console is + * assumed. + */ + +#ifndef CONFIG_DEV_CONSOLE +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# undef CONFIG_RAMLOG_CONSOLE +#else +# if defined(CONFIG_RAMLOG_CONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# elif defined(CONFIG_DEV_LOWCONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# else +# define USE_SERIALDRIVER 1 +# define USE_EARLYSERIALINIT 1 +# endif +#endif + +/* If some other device is used as the console, then the serial driver may + * still be needed. Let's assume that if the upper half serial driver is + * built, then the lower half will also be needed. There is no need for + * the early serial initialization in this case. + */ + +#if !defined(USE_SERIALDRIVER) && defined(CONFIG_STANDARD_SERIAL) +# define USE_SERIALDRIVER 1 +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_color_intstack + * + * Description: + * Set the interrupt stack to a value so that later we can determine how + * much stack space was used by interrupt handling logic + * + ****************************************************************************/ + +#if defined(CONFIG_STACK_COLORATION) && CONFIG_ARCH_INTERRUPTSTACK > 3 +static inline void up_color_intstack(void) +{ + uint8_t *ptr = (uint8_t *)&g_intstackalloc; + ssize_t size; + + for (size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); + size > 0; + size -= sizeof(uint8_t)) + { + *ptr++ = INTSTACK_COLOR; + } +} +#else +# define up_color_intstack() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initialize + * + * Description: + * up_initialize will be called once during OS initialization after the + * basic OS services have been initialized. The architecture specific + * details of initializing the OS will be handled here. Such things as + * setting up interrupt service routines, starting the clock, and + * registering device drivers are some of the things that are different + * for each processor and hardware platform. + * + * up_initialize is called after the OS initialized but before the user + * initialization logic has been started and before the libraries have + * been initialized. OS services and driver services are available. + * + ****************************************************************************/ + +void up_initialize(void) +{ + /* Initialize global variables */ + + g_current_regs = NULL; + + /* Colorize the interrupt stack */ + + up_color_intstack(); + + /* Add any extra memory fragments to the memory manager */ + + up_addregion(); + + /* Initialize the interrupt subsystem */ + + up_irqinitialize(); + + /* Initialize the system timer interrupt */ + +#if !defined(CONFIG_SUPPRESS_INTERRUPTS) && \ + !defined(CONFIG_SUPPRESS_TIMER_INTS) + up_timer_initialize(); +#endif + +#ifdef CONFIG_ARCH_DMA + /* Initialize the DMA subsystem if the weak function up_dma_initialize has + * been brought into the build + */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (up_dma_initialize) +#endif + { + up_dma_initialize(); + } +#endif + +#ifdef CONFIG_MM_IOB + /* Initialize IO buffering */ + + iob_initialize(); +#endif + + /* Register devices */ + +#if defined(CONFIG_DEV_NULL) + devnull_register(); /* Standard /dev/null */ +#endif + +#if defined(CONFIG_DEV_RANDOM) + devrandom_register(); /* Standard /dev/random */ +#endif + +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + +#if defined(CONFIG_DEV_ZERO) + devzero_register(); /* Standard /dev/zero */ +#endif + +#if defined(CONFIG_DEV_LOOP) + loop_register(); /* Standard /dev/loop */ +#endif + +#if defined(CONFIG_SCHED_INSTRUMENTATION_BUFFER) && \ + defined(CONFIG_DRIVER_NOTE) + note_register(); /* Non-standard /dev/note */ +#endif + + /* Initialize the serial device driver */ + +#ifdef USE_SERIALDRIVER + up_serialinit(); +#endif + +#ifdef CONFIG_RPMSG_UART + rpmsg_serialinit(); +#endif + + /* Initialize the console device driver (if it is other than the standard + * serial driver). + */ + +#if defined(CONFIG_DEV_LOWCONSOLE) + lowconsole_init(); +#elif defined(CONFIG_CONSOLE_SYSLOG) + syslog_console_init(); +#elif defined(CONFIG_RAMLOG_CONSOLE) + ramlog_consoleinit(); +#endif + +#ifdef CONFIG_PSEUDOTERM_SUSV1 + /* Register the master pseudo-terminal multiplexor device */ + + (void)ptmx_register(); +#endif + + /* Initialize the console device driver (if it is other than the standard + * serial driver). + */ + +#if defined(CONFIG_CONSOLE_SYSLOG) + syslog_console_init(); +#endif + +#if defined(CONFIG_CRYPTO) + /* Initialize the HW crypto and /dev/crypto */ + + up_cryptoinitialize(); +#endif + +#ifdef CONFIG_CRYPTO_CRYPTODEV + devcrypto_register(); +#endif + +#ifndef CONFIG_NETDEV_LATEINIT + /* Initialize the network */ + + up_netinitialize(); +#endif + +#ifdef CONFIG_NETDEV_LOOPBACK + /* Initialize the local loopback device */ + + (void)localhost_initialize(); +#endif + +#ifdef CONFIG_NET_TUN + /* Initialize the TUN device */ + + (void)tun_initialize(); +#endif + +#ifdef CONFIG_NETDEV_TELNET + /* Initialize the Telnet session factory */ + + (void)telnet_initialize(); +#endif + + /* Initialize USB */ + + up_usbinitialize(); + +#if defined(ARCH_HAVE_LEDS) + board_autoled_on(LED_IRQSENABLED); +#endif +} diff --git a/arch/sparc/src/common/up_internal.h b/arch/sparc/src/common/up_internal.h new file mode 100644 index 00000000000..2414c0e4249 --- /dev/null +++ b/arch/sparc/src/common/up_internal.h @@ -0,0 +1,252 @@ +/**************************************************************************** + * arch/sparc/src/common/up_internal.h + * + * 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_SPARC_SRC_COMMON_UP_INTERNAL_H +#define __ARCH_SPARC_SRC_COMMON_UP_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +# include "sparc_v8.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Determine which (if any) console driver to use. If a console is enabled + * and no other console device is specified, then a serial console is + * assumed. + */ + +#ifndef CONFIG_DEV_CONSOLE +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# undef CONFIG_RAMLOG_CONSOLE +#else +# if defined(CONFIG_RAMLOG_CONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# elif defined(CONFIG_DEV_LOWCONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# else +# define USE_SERIALDRIVER 1 +# define USE_EARLYSERIALINIT 1 +# endif +#endif + +/* If some other device is used as the console, then the serial driver may + * still be needed. Let's assume that if the upper half serial driver is + * built, then the lower half will also be needed. There is no need for + * the early serial initialization in this case. + */ + +#if !defined(USE_SERIALDRIVER) && defined(CONFIG_STANDARD_SERIAL) +# define USE_SERIALDRIVER 1 +#endif + +/* Check if an interrupt stack size is configured */ + +#ifndef CONFIG_ARCH_INTERRUPTSTACK +# define CONFIG_ARCH_INTERRUPTSTACK 0 +#endif + +/* This is the value used to mark the stack for subsequent stack monitoring + * logic. + */ + +#define STACK_COLOR 0xdeadbeef +#define INTSTACK_COLOR 0xdeadbeef +#define HEAP_COLOR 'h' + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +typedef void (*up_vector_t)(void); +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +/* This holds a references to the current interrupt level register storage + * structure. If is non-NULL only during interrupt processing. + */ + +extern volatile uint32_t *g_current_regs; + +/* This is the beginning of heap as provided from up_head.S. This is the + * first address in DRAM after the loaded program+bss+idle stack. The end + * of the heap is CONFIG_RAM_END + */ + +extern uint32_t g_idle_topstack; + +/* Address of the saved user stack pointer */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +extern void g_intstackbase; +#endif + +/* These 'addresses' of these values are setup by the linker script.They are + * not actual uint32_t storage locations! They are only used meaningfully in + * the following way: + * + * - The linker script defines, for example, the symbol_sdata. + * - The declaration extern uint32_t _sdata; makes C happy. C will believe + * that the value _sdata is the address of a uint32_t variable _data + * (it is not!). + * - We can recoved the linker value then by simply taking the address of + * of _data. like: uint32_t *pdata = &_sdata; + */ + +extern uint32_t _text_start; /* Start of .text */ +extern uint32_t _etext; /* End+1 of .text + .rodata */ +extern const uint32_t _rodata_start; /* Start of .data in FLASH */ +extern uint32_t _sdata; /* Start of .data */ +extern uint32_t _edata; /* End+1 of .data */ +extern uint32_t _bss_start; /* Start of .bss */ +extern uint32_t _end; /* End+1 of .bss */ +#ifdef CONFIG_ARCH_RAMFUNCS +extern uint32_t _sramfunc; /* Start of ramfuncs */ +extern uint32_t _eramfunc; /* End+1 of ramfuncs */ +extern uint32_t _ramfunc_loadaddr; /* Start of ramfuncs in FLASH */ +extern uint32_t _ramfunc_sizeof; /* Size of ramfuncs */ +extern uint32_t _bmxdkpba_address; /* BMX register setting */ +extern uint32_t _bmxdudba_address; /* BMX register setting */ +extern uint32_t _bmxdupba_address; /* BMX register setting */ +#endif /* CONFIG_ARCH_RAMFUNCS */ +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Common Functions *********************************************************/ + +/* Common functions define in arch/sparc/src/common. These may be replaced + * with chip-specific functions of the same name if needed. See also + * functions prototyped in include/nuttx/arch.h. + */ + +/* Context switching */ + +void up_copystate(uint32_t *dest, uint32_t *src); + +/* Serial output */ + +void up_puts(const char *str); +void up_lowputs(const char *str); + +/* Defined in drivers/lowconsole.c */ + +#ifdef CONFIG_DEV_LOWCONSOLE +void lowconsole_init(void); +#else +# define lowconsole_init() +#endif + +/* Debug */ + +#ifdef CONFIG_ARCH_STACKDUMP +void up_dumpstate(void); +#else +# define up_dumpstate() +#endif + +/* Software interrupt 0 handler */ + +int up_swint0(int irq, FAR void *context, FAR void *arg); + +/* Software interrupt 1 handler */ + +int up_swint1(int irq, FAR void *context, FAR void *arg); + +/* Signals */ + +void up_sigdeliver(void); + +/* Chip-specific functions **************************************************/ + +/* Chip specific functions defined in arch/sparc/src/ */ + +/* IRQs */ + +void up_irqinitialize(void); +bool up_pending_irq(int irq); +void up_clrpend_irq(int irq); + +/* DMA */ + +#ifdef CONFIG_ARCH_DMA +void weak_function up_dma_initialize(void); +#endif + +/* Memory management */ + +#if CONFIG_MM_REGIONS > 1 +void up_addregion(void); +#else +# define up_addregion() +#endif + +/* Serial output */ + +void up_lowputc(char ch); +void up_earlyserialinit(void); +void up_serialinit(void); + +void rpmsg_serialinit(void); + +/* Network */ + +#if defined(CONFIG_NET) && !defined(CONFIG_NETDEV_LATEINIT) +void up_netinitialize(void); +#else +# define up_netinitialize() +#endif + +/* USB */ + +#ifdef CONFIG_USBDEV +void up_usbinitialize(void); +void up_usbuninitialize(void); +#else +# define up_usbinitialize() +# define up_usbuninitialize() +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_COMMON_UP_INTERNAL_H */ diff --git a/arch/sparc/src/common/up_interruptcontext.c b/arch/sparc/src/common/up_interruptcontext.c new file mode 100644 index 00000000000..53415ed5927 --- /dev/null +++ b/arch/sparc/src/common/up_interruptcontext.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * arch/sparc/src/common/up_interruptcontext.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_interrupt_context + * + * Description: Return true is we are currently executing in + * the interrupt handler context. + ****************************************************************************/ + +bool up_interrupt_context(void) +{ + return g_current_regs != NULL; +} diff --git a/arch/sparc/src/common/up_lowputs.c b/arch/sparc/src/common/up_lowputs.c new file mode 100644 index 00000000000..cde7b7039bf --- /dev/null +++ b/arch/sparc/src/common/up_lowputs.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/sparc/src/common/up_lowputs.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowputs + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_lowputs(const char *str) +{ + while (*str) + { + up_lowputc(*str++); + } +} + diff --git a/arch/sparc/src/common/up_mdelay.c b/arch/sparc/src/common/up_mdelay.c new file mode 100644 index 00000000000..d58a04c599a --- /dev/null +++ b/arch/sparc/src/common/up_mdelay.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/sparc/src/common/up_mdelay.c + * + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_mdelay + * + * Description: + * Delay inline for the requested number of milliseconds. + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_mdelay(unsigned int milliseconds) +{ + volatile int i; + volatile int j; + + for (i = 0; i < milliseconds; i++) + { + for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++) + { + } + } +} + diff --git a/arch/sparc/src/common/up_modifyreg16.c b/arch/sparc/src/common/up_modifyreg16.c new file mode 100644 index 00000000000..5b3cdfc0e36 --- /dev/null +++ b/arch/sparc/src/common/up_modifyreg16.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/sparc/src/common/up_modifyreg16.c + * + * 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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg16 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits) +{ + irqstate_t flags; + uint16_t regval; + + flags = enter_critical_section(); + regval = getreg16(addr); + regval &= ~clearbits; + regval |= setbits; + putreg16(regval, addr); + leave_critical_section(flags); +} + diff --git a/arch/sparc/src/common/up_modifyreg32.c b/arch/sparc/src/common/up_modifyreg32.c new file mode 100644 index 00000000000..da372f3e2df --- /dev/null +++ b/arch/sparc/src/common/up_modifyreg32.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/sparc/src/common/up_modifyreg32.c + * + * 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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg32 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits) +{ + irqstate_t flags; + uint32_t regval; + + flags = enter_critical_section(); + regval = getreg32(addr); + regval &= ~clearbits; + regval |= setbits; + putreg32(regval, addr); + leave_critical_section(flags); +} + diff --git a/arch/sparc/src/common/up_modifyreg8.c b/arch/sparc/src/common/up_modifyreg8.c new file mode 100644 index 00000000000..f809a5c08c2 --- /dev/null +++ b/arch/sparc/src/common/up_modifyreg8.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/sparc/src/common/up_modifyreg8.c + * + * 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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg8 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits) +{ + irqstate_t flags; + uint8_t regval; + + flags = enter_critical_section(); + regval = getreg8(addr); + regval &= ~clearbits; + regval |= setbits; + putreg8(regval, addr); + leave_critical_section(flags); +} + diff --git a/arch/sparc/src/common/up_puts.c b/arch/sparc/src/common/up_puts.c new file mode 100644 index 00000000000..7ab7bd07fff --- /dev/null +++ b/arch/sparc/src/common/up_puts.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * arch/sparc/src/common/up_puts.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_puts + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_puts(const char *str) +{ + while (*str) + { + up_putc(*str++); + } +} + diff --git a/arch/sparc/src/common/up_releasestack.c b/arch/sparc/src/common/up_releasestack.c new file mode 100644 index 00000000000..e5e7e4328dd --- /dev/null +++ b/arch/sparc/src/common/up_releasestack.c @@ -0,0 +1,114 @@ +/**************************************************************************** + * arch/sparc/src/common/up_releasestack.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_stack + * + * Description: + * A task has been stopped. Free all stack related resources retained in + * the defunct TCB. + * + * Input Parameters: + * - dtcb: The TCB containing information about the stack to be released + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain error recovery contexts where the TCB may + * not be fully initialized when up_release_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is freed. For example, kernel thread stacks may have + * been allocated from protected kernel memory. Stacks for user tasks + * and threads must have come from memory that is accessible to user + * code. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) +{ + /* Is there a stack allocated? */ + + if (dtcb->stack_alloc_ptr) + { +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + if (kmm_heapmember(dtcb->stack_alloc_ptr)) + { + kmm_free(dtcb->stack_alloc_ptr); + } + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + if (umm_heapmember(dtcb->stack_alloc_ptr)) + { + kmm_free(dtcb->stack_alloc_ptr); + } + } + + /* Mark the stack freed */ + + dtcb->stack_alloc_ptr = NULL; + } + + /* The size of the allocated stack is now zero */ + + dtcb->adj_stack_size = 0; +} + diff --git a/arch/sparc/src/common/up_stackframe.c b/arch/sparc/src/common/up_stackframe.c new file mode 100644 index 00000000000..cea0e5ae33b --- /dev/null +++ b/arch/sparc/src/common/up_stackframe.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/sparc/src/common/up_stackframe.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* sparc requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#define STACK_ALIGNMENT 8 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directly. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Input Parameters: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + FAR void *ret; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + ret = tcb->stack_base_ptr; + memset(ret, 0, frame_size); + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->stack_base_ptr = (FAR uint8_t *)tcb->stack_base_ptr + frame_size; + tcb->adj_stack_size -= frame_size; + + /* And return the pointer to the allocated region */ + + return ret; +} + diff --git a/arch/sparc/src/common/up_udelay.c b/arch/sparc/src/common/up_udelay.c new file mode 100644 index 00000000000..8fb3cb8a345 --- /dev/null +++ b/arch/sparc/src/common/up_udelay.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/sparc/src/common/up_udelay.c + * + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CONFIG_BOARD_LOOPSPER100USEC ((CONFIG_BOARD_LOOPSPERMSEC+5)/10) +#define CONFIG_BOARD_LOOPSPER10USEC ((CONFIG_BOARD_LOOPSPERMSEC+50)/100) +#define CONFIG_BOARD_LOOPSPERUSEC ((CONFIG_BOARD_LOOPSPERMSEC+500)/1000) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_udelay + * + * Description: + * Delay inline for the requested number of microseconds. NOTE: Because + * of all of the setup, several microseconds will be lost before the actual + * timing loop begins. Thus, the delay will always be a few microseconds + * longer than requested. + * + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_udelay(useconds_t microseconds) +{ + volatile int i; + + /* We'll do this a little at a time because we expect that the + * CONFIG_BOARD_LOOPSPERUSEC is very inaccurate during to truncation in + * the divisions of its calculation. We'll use the largest values that + * we can in order to prevent significant error buildup in the loops. + */ + + while (microseconds > 1000) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERMSEC; i++) + { + } + + microseconds -= 1000; + } + + while (microseconds > 100) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER100USEC; i++) + { + } + + microseconds -= 100; + } + + while (microseconds > 10) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER10USEC; i++) + { + } + + microseconds -= 10; + } + + while (microseconds > 0) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERUSEC; i++) + { + } + + microseconds--; + } +} + diff --git a/arch/sparc/src/common/up_usestack.c b/arch/sparc/src/common/up_usestack.c new file mode 100644 index 00000000000..25e4aeae046 --- /dev/null +++ b/arch/sparc/src/common/up_usestack.c @@ -0,0 +1,141 @@ +/**************************************************************************** + * arch/sparc/src/common/up_usestack.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* sparc requires at least a 4-byte stack alignment. For floating point use, + * however, the stack must be aligned to 8-byte addresses. + */ + +#define STACK_ALIGNMENT 8 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_use_stack + * + * Description: + * Setup up stack-related information in the TCB using pre-allocated stack + * memory. This function is called only from task_init() when a task or + * kernel thread is started (never for pthreads). + * + * The following TCB fields must be initialized: + * + * - adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Input Parameters: + * - tcb: The TCB of new task + * - stack_size: The allocated stack size. + * + * NOTE: Unlike up_stack_create() and up_stack_release, this function + * does not require the task type (ttype) parameter. The TCB flags will + * always be set to provide the task type to up_use_stack() if it needs + * that information. + * + ****************************************************************************/ + +int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) +{ + size_t top_of_stack; + size_t size_of_stack; + + /* Is there already a stack allocated? */ + + if (tcb->stack_alloc_ptr) + { + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); + } + + /* Save the new stack allocation */ + + tcb->stack_alloc_ptr = stack; + + /* If stack debug is enabled, then fill the stack with a recognizable value + * that we can use later to test for high water marks. + */ + +#ifdef CONFIG_STACK_COLORATION + memset(tcb->stack_alloc_ptr, 0xaa, stack_size); +#endif + + /* sparc uses a push-down stack: the stack grows toward loweraddresses in + * memory. The stack pointer register, points to the lowest, valid work + * address (the "top" of the stack). Items on the stack are referenced + * as positive word offsets from sp. + */ + + top_of_stack = (uint32_t)tcb->stack_alloc_ptr + stack_size; + + /* The sparc stack must be aligned at word (4 byte) or double word (8 byte) + * boundaries. If necessary top_of_stack must be rounded down to the + * next boundary + */ + + top_of_stack = STACK_ALIGN_DOWN(top_of_stack); + size_of_stack = top_of_stack - (uint32_t)tcb->stack_alloc_ptr; + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->stack_base_ptr = tcb->stack_alloc_ptr; + tcb->adj_stack_size = size_of_stack; + + return OK; +} diff --git a/arch/sparc/src/sparc_v8/Kconfig b/arch/sparc/src/sparc_v8/Kconfig new file mode 100644 index 00000000000..5f982727560 --- /dev/null +++ b/arch/sparc/src/sparc_v8/Kconfig @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_SPARC_V8 +comment "SPARC Configuration Options" + +choice + prompt "Toolchain" + default SPARC_TOOLCHAIN_CODEREDW if TOOLCHAIN_WINDOWS + default SPARC_TOOLCHAIN_BUILDROOT if !TOOLCHAIN_WINDOWS + +config SPARC_TOOLCHAIN_BUILDROOT + bool "Buildroot (Cygwin or Linux)" + depends on !WINDOWS_NATIVE + select ARCH_TOOLCHAIN_GNU + ---help--- + There is a buildroot version for the SPARC boards here: + https://www.gaisler.com/anonftp/bcc/bin/linux/. See + the following section for details on building this toolchain. + +config SPARC_TOOLCHAIN_CODEREDW + bool "CodeRed for Windows" + depends on TOOLCHAIN_WINDOWS + select ARCH_TOOLCHAIN_GNU + ---help--- + none. +endchoice # Toolchain + +endif # ARCH_FAMILY_SPARC diff --git a/arch/sparc/src/sparc_v8/Toolchain.defs b/arch/sparc/src/sparc_v8/Toolchain.defs new file mode 100644 index 00000000000..2a8328f1ca8 --- /dev/null +++ b/arch/sparc/src/sparc_v8/Toolchain.defs @@ -0,0 +1,80 @@ +############################################################################ +# arch/sparc/src/sparc/Toolchain.defs +# +# 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. +# +############################################################################ + +# Setup for the selected toolchain + +# +# Handle old-style chip-specific toolchain names in the absence of +# a new-style toolchain specification, force the selection of a single +# toolchain and allow the selected toolchain to be overridden by a +# command-line selection. +# + +ifeq ($(filter y, \ + $(CONFIG_SPARC_TOOLCHAIN_BUILDROOT) \ + ),y) + CONFIG_SPARC_TOOLCHAIN ?= BUILDROOT +endif + +ifeq ($(filter y, \ + $(CONFIG_SPARC_TOOLCHAIN_CODEREDW) \ + ),y) + CONFIG_SPARC_TOOLCHAIN ?= CODEREDW +endif + +ifeq ($(filter y, \ + $(CONFIG_SPARC_LINUXGCC_TOOLCHAIN) \ + ),y) + CONFIG_SPARC_TOOLCHAIN ?= LINUXGCC +endif + + +# Chip-specific CPU flags + +ifeq ($(CONFIG_ARCH_CHIP_BM3803),y) +# ARCHCPUFLAGS += -mcpu=leon -mflat + ARCHCPUFLAGS += -mcpu=leon +else ifeq ($(CONFIG_ARCH_CHIP_BM3823),y) + ARCHCPUFLAGS += -mcpu=leon -mflat +else + $(error "No valid CONFIG_ARCH_CHIP_ set in the configuration") +endif + +ifeq ($(CONFIG_DEBUG_CUSTOMOPT),y) + MAXOPTIMIZATION := $(CONFIG_DEBUG_OPTLEVEL) +endif + +# NuttX buildroot GCC toolchain under Linux or Cygwin + +ifeq ($(CONFIG_SPARC_TOOLCHAIN),BUILDROOT) + CROSSDEV ?= sparc-gaisler-elf- + MAXOPTIMIZATION ?= -O2 + LDFLAGS += -nostartfiles -nodefaultlibs + LDSCRIPT = sparc-gaisler-elf-debug.ld +endif + +# NuttX Windows Native toolchain + +ifeq ($(CONFIG_SPARC_TOOLCHAIN),CODEREDW) + CROSSDEV ?= sparc-elf- + MAXOPTIMIZATION ?= -O2 + LDFLAGS += -nostartfiles -nodefaultlibs + LDSCRIPT = sparc-elf-debug.ld +endif diff --git a/arch/sparc/src/sparc_v8/sparc_v8.h b/arch/sparc/src/sparc_v8/sparc_v8.h new file mode 100644 index 00000000000..b4a9c33ab6d --- /dev/null +++ b/arch/sparc/src/sparc_v8/sparc_v8.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/sparc_v8.h + * + * 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_SPARC_SRC_SPARC_V8_SPARC_V8_H +#define __ARCH_SPARC_SRC_SPARC_V8_SPARC_V8_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Macros to handle saving and restore interrupt state. The state is copied + * from the stack to the TCB, but only a referenced is passed to get the + * state from the TCB. + */ + +#define up_restorestate(regs) (g_current_regs = regs) + +#define up_savestate(regs) trap_flush_task(regs, (uint32_t*)g_current_regs) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +/* This holds a references to the current interrupt level register storage + * structure. If is non-NULL only during interrupt processing. + */ + +extern volatile uint32_t *g_current_regs; + +/* This is the beginning of heap as provided from up_head.S.This is the first + * address in DRAM after the loaded program+bss+idle stack. The end of the + * heap is CONFIG_RAM_END + */ + +extern uint32_t g_idle_topstack; + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: up_copystate + * + * Description: + * Copy the contents of a register state save structure from one location to + * another. + * + ****************************************************************************/ + +void up_copystate(uint32_t *dest, uint32_t *src); + +void task_flush_trap(uint32_t *trap, uint32_t *task); +void trap_flush_task(uint32_t *task, uint32_t *trap); + +/**************************************************************************** + * Name: up_doirq + * + * Description: + * Dispatch an interrupt. + * + ****************************************************************************/ + +uint32_t *up_doirq(int irq, uint32_t *regs); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_SPARC_SRC_SPARC_V8_SPARC_V8_H */ + diff --git a/arch/sparc/src/sparc_v8/up_blocktask.c b/arch/sparc/src/sparc_v8/up_blocktask.c new file mode 100644 index 00000000000..af9dcb4aa77 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_blocktask.c @@ -0,0 +1,165 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_blocktask.c + * + * 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 + +#include "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of + * the ready to run list must be stopped. Save its context + * and move it to the inactive list specified by task_state. + * + * Input Parameters: + * tcb: Refers to a task in the ready-to-run list (normally + * the task at the head of the list). It most be + * stopped, its context saved and moved into one of the + * waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new + * ready to run task must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(struct tcb_s *tcb, tstate_t task_state) +{ + struct tcb_s *rtcb = this_task(); + bool switch_needed; + + /* Verify that the context switch can be performed */ + + DEBUGASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && + (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = nxsched_remove_readytorun(tcb); + + /* Add the task to the specified blocked task list */ + + nxsched_add_blocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the ready-to-run + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= nxsched_merge_pending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Get the context of the task at the head of the ready to + * run list. + */ + + struct tcb_s *nexttcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(nexttcb); +#endif + /* Reset scheduler parameters */ + + nxsched_resume_scheduler(nexttcb); + + /* Then switch contexts */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/arch/sparc/src/sparc_v8/up_copystate.c b/arch/sparc/src/sparc_v8/up_copystate.c new file mode 100644 index 00000000000..e49a09d02a0 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_copystate.c @@ -0,0 +1,98 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_copystate.c + * + * 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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_copystate + ****************************************************************************/ + +/* Really just a memcpy */ + +void up_copystate(uint32_t *dest, uint32_t *src) +{ + int i; + + /* The state is copied from the stack to the TCB, but only a reference is + * passed to get the state from the TCB. So the following check avoids + * copying the TCB save area onto itself: + */ + + if (src != dest) + { + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } + } +} + +void task_flush_trap(uint32_t *trap, uint32_t *task) +{ + g_current_regs = task; +} + +void trap_flush_task(uint32_t *task, uint32_t *trap) +{ + uint32_t psr; + int i; + + if (task != trap) + { + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + task[i] = trap[i]; + } + } + + psr = trap[REG_PSR]; + +#ifdef CONFIG_SUPPRESS_INTERRUPTS + task[REG_PSR] = psr & ~SPARC_PSR_ET_MASK; +#else + task[REG_PSR] = psr | SPARC_PSR_ET_MASK; +#endif +} + diff --git a/arch/sparc/src/sparc_v8/up_doirq.c b/arch/sparc/src/sparc_v8/up_doirq.c new file mode 100644 index 00000000000..2c20feae8db --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_doirq.c @@ -0,0 +1,125 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_doirq.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +#include "group/group.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint32_t *up_doirq(int irq, uint32_t *regs) +{ + board_autoled_on(LED_INIRQ); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + PANIC(); +#else + regs = (uint32_t *)((uint32_t)regs + CPU_MINIMUM_STACK_FRAME_SIZE); + /* Current regs non-zero indicates that we are processing an interrupt; + * g_current_regs is also used to manage interrupt level context switches. + * + * Nested interrupts are not supported. + */ + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + +#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV) + /* Check for a context switch. If a context switch occurred, then + * g_current_regs will have a different value than it did on entry. + * If an interrupt level context switch has occurred, then restore + * the floating point state and the establish the correct address + * environment before returning from the interrupt. + */ + + if (regs != g_current_regs) + { +#ifdef CONFIG_ARCH_FPU + /* Restore floating point registers */ + + up_restorefpu((uint32_t *)g_current_regs); +#endif + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(NULL); +#endif + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint32_t *)((uint32_t)g_current_regs - + CPU_MINIMUM_STACK_FRAME_SIZE); + + /* Set g_current_regs to NULL to indicate that we are no longer in + * an interrupt handler. + */ + + g_current_regs = NULL; +#endif + board_autoled_off(LED_INIRQ); + return regs; +} diff --git a/arch/sparc/src/sparc_v8/up_dumpstate.c b/arch/sparc/src/sparc_v8/up_dumpstate.c new file mode 100644 index 00000000000..978ad9df0dc --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_dumpstate.c @@ -0,0 +1,229 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_dumpstate.c + * + * 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 + +#include "up_arch.h" +#include "sched/sched.h" +#include "up_internal.h" + +#ifdef CONFIG_ARCH_STACKDUMP + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_getsp + ****************************************************************************/ + +/* I don't know if the builtin to get SP is enabled */ + +static inline uint32_t up_getsp(void) +{ + uint32_t retval; + + do + { + retval = 0; + __asm__ volatile("mov %%sp, %0" : "=r" (retval) : "0" (retval)); + } + while (0); + + return retval; +} + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +static void up_stackdump(uint32_t sp, uint32_t stack_base) +{ + uint32_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t *)stack; + _alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +} + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +static inline void up_registerdump(void) +{ + /* Are user registers available from interrupt processing? */ + + if (g_current_regs) + { + _alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", + 0, + g_current_regs[REG_R16], g_current_regs[REG_R17], + g_current_regs[REG_R18], g_current_regs[REG_R19], + g_current_regs[REG_R20], g_current_regs[REG_R21], + g_current_regs[REG_R22], g_current_regs[REG_R23]); + + _alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", + 8, + g_current_regs[REG_R24], g_current_regs[REG_R25], + g_current_regs[REG_R26], g_current_regs[REG_R27], + g_current_regs[REG_R28], g_current_regs[REG_R29], + g_current_regs[REG_R30], g_current_regs[REG_R31]); + + _alert("SR: %08x\n", g_current_regs[REG_R14]); + } +} + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +void up_dumpstate(void) +{ + struct tcb_s *rtcb = running_task(); + uint32_t sp = up_getsp(); + uint32_t ustackbase; + uint32_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint32_t istackbase; + uint32_t istacksize; +#endif + + /* Dump the registers (if available) */ + + up_registerdump(); + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) /* Check for CPU0 IDLE thread */ + { + ustackbase = g_idle_topstack - 4; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint32_t)rtcb->stack_base_ptr; + ustacksize = (uint32_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint32_t)&g_intstackbase; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4; + + /* Show interrupt stack info */ + + _alert("sp: %08x\n", sp); + _alert("IRQ stack:\n"); + _alert(" base: %08x\n", istackbase); + _alert(" size: %08x\n", istacksize); +#ifdef CONFIG_STACK_COLORATION + _alert(" used: %08x\n", up_check_intstack()); +#endif + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + } + else if (g_current_regs) + { + _alert("ERROR: Stack pointer is not within the interrupt stack\n"); + up_stackdump(istackbase - istacksize, istackbase); + } + + /* Extract the user stack pointer if we are in an interrupt handler. + * If we are not in an interrupt handler. Then sp is the user stack + * pointer (and the above range check should have failed). + */ + + if (g_current_regs) + { + sp = g_current_regs[REG_I6]; + _alert("sp: %08x\n", sp); + } + + _alert("User stack:\n"); + _alert(" base: %08x\n", ustackbase); + _alert(" size: %08x\n", ustacksize); +#ifdef CONFIG_STACK_COLORATION + _alert(" used: %08x\n", up_check_tcbstack(rtcb)); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp <= ustackbase && sp > ustackbase - ustacksize) + { + up_stackdump(sp, ustackbase); + } + else + { + _alert("ERROR: Stack pointer is not within allocated stack\n"); + up_stackdump(ustackbase - ustacksize, ustackbase); + } +#else + _alert("sp: %08x\n", sp); + _alert("stack base: %08x\n", ustackbase); + _alert("stack size: %08x\n", ustacksize); +#ifdef CONFIG_STACK_COLORATION + _alert("stack used: %08x\n", up_check_tcbstack(rtcb)); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { + _alert("ERROR: Stack pointer is not within allocated stack\n"); + up_stackdump(ustackbase - ustacksize, ustackbase); + } + else + { + up_stackdump(sp, ustackbase); + } +#endif +} +#endif diff --git a/arch/sparc/src/sparc_v8/up_initialstate.c b/arch/sparc/src/sparc_v8/up_initialstate.c new file mode 100644 index 00000000000..7d4112d8741 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_initialstate.c @@ -0,0 +1,104 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_initialstate.c + * + * 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 "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB has been created. This + * function is called to initialize the processor specific portions of the + * new TCB. + * + * This function must setup the initial architecture registers and/or stack + * so that execution will begin at tcb->start on the next context switch. + * + ****************************************************************************/ + +void up_initial_state(struct tcb_s *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + uint32_t regval; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* Set the initial stack pointer to the "base" of the allocated stack */ + + xcp->regs[REG_I6] = (uint32_t)tcb->stack_base_ptr + + tcb->adj_stack_size; + + /* Save the task entry point */ + + xcp->regs[REG_PC] = (uint32_t)(tcb->start); + xcp->regs[REG_NPC] = (uint32_t)(tcb->start + 4); + + /* Set supervisor- or user-mode, depending on how NuttX is configured and + * what kind of thread is being started. Disable FIQs in any event + * + * If the kernel build is not selected, then all threads run in + * supervisor-mode. + */ + +#ifdef CONFIG_BUILD_KERNEL +# error "Missing logic for the CONFIG_BUILD_KERNEL build" +#endif + + /* Enable or disable interrupts, based on user configuration */ + + sparc_get_psr(regval); +#ifdef CONFIG_SUPPRESS_INTERRUPTS + xcp->regs[REG_PSR] = regval & ~SPARC_PSR_ET_MASK; +#else + xcp->regs[REG_PSR] = regval | SPARC_PSR_ET_MASK; +#endif +} + diff --git a/arch/sparc/src/sparc_v8/up_irq.c b/arch/sparc/src/sparc_v8/up_irq.c new file mode 100644 index 00000000000..8294ad9e75a --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_irq.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_irq.c + * + * 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 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irq_save + * + * Description: + * Save the current interrupt state and disable interrupts. + * + * Input Parameters: + * None + * + * Returned Value: + * Interrupt state prior to disabling interrupts. + * + ****************************************************************************/ + +irqstate_t up_irq_save(void) +{ + /* register irqstate_t status; */ + + register irqstate_t ret; + + /* Get psr status */ + + /* sparc_get_psr( status ); */ + + /* Save the status */ + + ret = sparc_disable_interrupts(); + + /* BM3803_REG.int_mask = 0; */ + + return ret; /* Return status before interrupts disabled */ +} + +/**************************************************************************** + * Name: up_irq_restore + * + * Description: + * Restore the previous up_irq_enable state (i.e., the one previously + * returned by up_irq_save()) + * + * Input Parameters: + * state - The interrupt state to be restored. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_irq_restore(irqstate_t irqstate) +{ + sparc_enable_interrupts(irqstate); +} + +/**************************************************************************** + * Name: up_irq_enable + * + * Description: + * Enable interrupts + * + * Input Parameters: + * None. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_irq_enable(void) +{ + uint32_t psr; + + psr = sparc_disable_interrupts(); + sparc_enable_interrupts(psr); +} + +/**************************************************************************** + * Name: up_irq_disable + * + * Description: + * Disable interrupts + * + * Input Parameters: + * None. + * + * Returned Value: + * the entire PSR contents + * + ****************************************************************************/ + +uint32_t up_irq_disable(void) +{ + uint32_t psr; + + psr = sparc_disable_interrupts(); + + return psr; +} diff --git a/arch/sparc/src/sparc_v8/up_releasepending.c b/arch/sparc/src/sparc_v8/up_releasepending.c new file mode 100644 index 00000000000..bac279138e4 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_releasepending.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_releasepending.c + * + * 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 "sched/sched.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + struct tcb_s *rtcb = this_task(); + + sinfo("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the ready-to-run task list */ + + /* sched_lock(); */ + + if (nxsched_merge_pending()) + { + /* The currently active task has changed! We will need to switch + * contexts. + */ + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(rtcb); + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + struct tcb_s *nexttcb = this_task(); + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(nexttcb); + + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} + diff --git a/arch/sparc/src/sparc_v8/up_reprioritizertr.c b/arch/sparc/src/sparc_v8/up_reprioritizertr.c new file mode 100644 index 00000000000..da8501475b8 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_reprioritizertr.c @@ -0,0 +1,175 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_reprioritizertr.c + * + * 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 +#include + +#include "sched/sched.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Input Parameters: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE +#if SCHED_PRIORITY_MIN > 0 + || priority < SCHED_PRIORITY_MIN +#endif +#if SCHED_PRIORITY_MAX < UINT8_MAX + || priority > SCHED_PRIORITY_MAX +#endif + ) + { + DEBUGASSERT(0); + } + else + { + struct tcb_s *rtcb = this_task(); + bool switch_needed; + + sinfo("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * nxsched_remove_readytorun will return true if we just + * remove the head of the ready to run list. + */ + + switch_needed = nxsched_remove_readytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * nxsched_add_readytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + + switch_needed ^= nxsched_add_readytorun(tcb); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + nxsched_merge_pending(); + } + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + struct tcb_s *nexttcb = this_task(); + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(nexttcb); + + /* Switch context to the context of the task at the head of the + * ready to run list. + */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return,it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } + } +} + diff --git a/arch/sparc/src/sparc_v8/up_romgetc.c b/arch/sparc/src/sparc_v8/up_romgetc.c new file mode 100644 index 00000000000..572c379d2c9 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_romgetc.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_romgetc.c + * + * 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 + +#ifdef CONFIG_ARCH_ROMGETC + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_romgetc + * + * Description: + * In Harvard architectures, data accesses and instruction accesses occur + * on different busses, perhaps concurrently. All data accesses are + * performed on the data bus unless special machine instructions are + * used to read data from the instruction address space. Also, in the + * typical MCU, the available SRAM data memory is much smaller that the + * non-volatile FLASH instruction memory. So if the application requires + * many constant strings, the only practical solution may be to store + * those constant strings in FLASH memory where they can only be accessed + * using architecture-specific machine instructions. + * + * A similar case is where strings are retained in "external" memory such + * as EEPROM or serial FLASH. This case is similar only in that again + * special operations are required to obtain the string data; it cannot + * be accessed directly from a string pointer. + * + * If CONFIG_ARCH_ROMGETC is defined, then the architecture logic must + * export the function up_romgetc(). up_romgetc() will simply read one + * byte of data from the instruction space. + * + * If CONFIG_ARCH_ROMGETC, certain C stdio functions are effected: (1) + * All format strings in printf, fprintf, sprintf, etc. are assumed to + * lie in FLASH (string arguments for %s are still assumed to reside in + * SRAM). And (2), the string argument to puts and fputs is assumed to + * reside in FLASH. Clearly, these assumptions may have to modified for + * the particular needs of your environment.There is no "one-size-fits-all" + * solution for this problem. + * + * Additional AVR Assumptions: + * + * - This version of up_romgetc obtains string data from FLASH memory. + * - Since the passed pointer is 16-bits, the strings must lie in the first + * 64Kb of FLASH. + * + ****************************************************************************/ + +char up_romgetc(FAR const char *ptr) +{ + return pgm_read_byte_near(ptr); +} +#endif diff --git a/arch/sparc/src/sparc_v8/up_schedulesigaction.c b/arch/sparc/src/sparc_v8/up_schedulesigaction.c new file mode 100644 index 00000000000..563c9324639 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_schedulesigaction.c @@ -0,0 +1,178 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_schedulesigaction.c + * + * 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 "sched/sched.h" +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more + * signal handling actions have been queued for execution. + * The architecture specific code must configure things so + * that the 'igdeliver' callback is executed on the thread + * specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked + * nor should it cause any immediate execution of sigdeliver. + * Typically, a few cases need to be considered: + * + * (1) This function may be called from an interrupt handler + * During interrupt processing, all xcptcontext structures + * should be valid for all tasks. That structure should + * be modified to invoke sigdeliver() either on return + * from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT + * the currently executing task, then again just modify + * the saved xcptcontext structure for the recipient + * task so it will invoke sigdeliver when that task is + * later resumed. + * (3) If not in an interrupt handler and the tcb IS the + * currently executing task -- just call the signal + * handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +{ + irqstate_t flags; + + sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + + /* Make sure that interrupts are disabled */ + + flags = enter_critical_section(); + + /* Refuse to handle nested signal actions */ + + if (!tcb->xcp.sigdeliver) + { + /* First, handle some special cases when the signal is + * being delivered to the currently executing task. + */ + + sinfo("rtcb=0x%p g_current_regs=0x%p\n", + this_task(), g_current_regs); + + if (tcb == this_task()) + { + /* CASE 1: We are not in an interrupt handler and + * a task is signalling itself for some reason. + */ + + if (!g_current_regs) + { + /* In this case just deliver the signal now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the + * interrupted task is the same as the one that + * must receive the signal, then we will have to modify + * the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following + * logic would fail in the strange case where we are in an + * interrupt handler, the thread is signalling itself, but + * a context switch to another task has occurred so that + * g_current_regs does not refer to the thread of this_task()! + */ + + else + { + /* Save registers that must be protected while the signal + * handler runs. These will be restored by the signal + * trampoline after the signal(s) have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = g_current_regs[REG_PC]; + tcb->xcp.saved_npc = g_current_regs[REG_NPC]; + tcb->xcp.saved_status = g_current_regs[REG_PSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + g_current_regs[REG_PC] = (uint32_t)up_sigdeliver; + g_current_regs[REG_NPC] = (uint32_t)up_sigdeliver + 4; + g_current_regs[REG_PSR] |= SPARC_PSR_ET_MASK; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save registers that must be protected while the signal handler + * runs. These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_pc = tcb->xcp.regs[REG_PC]; + tcb->xcp.saved_npc = tcb->xcp.regs[REG_NPC]; + tcb->xcp.saved_status = tcb->xcp.regs[REG_PSR]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_PC] = (uint32_t)up_sigdeliver; + tcb->xcp.regs[REG_NPC] = (uint32_t)up_sigdeliver + 4; + tcb->xcp.regs[REG_PSR] |= SPARC_PSR_ET_MASK; + } + } + + leave_critical_section(flags); +} diff --git a/arch/sparc/src/sparc_v8/up_sigdeliver.c b/arch/sparc/src/sparc_v8/up_sigdeliver.c new file mode 100644 index 00000000000..863c8081a75 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_sigdeliver.c @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_sigdeliver.c + * + * 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 +#include +#include + +#include "sched/sched.h" +#include "up_internal.h" +#include "up_arch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + struct tcb_s *rtcb = this_task(); + + uint32_t regs[XCPTCONTEXT_REGS]; + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably + * EINTR). + */ + + board_autoled_on(LED_SIGNAL); + + sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + DEBUGASSERT(rtcb->xcp.sigdeliver != NULL); + + /* Save the return state on the stack. */ + + up_copystate(regs, rtcb->xcp.regs); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* Then make sure that interrupts are enabled. Signal handlers must always + * run with interrupts enabled. + */ + + up_irq_enable(); +#endif + + /* Deliver the signal */ + + ((sig_deliver_t)rtcb->xcp.sigdeliver)(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sinfo("Resuming\n"); + (void)up_irq_save(); + + /* Modify the saved return state with the actual saved values in the + * TCB. This depends on the fact that nested signal handling is + * not supported. Therefore, these values will persist throughout the + * signal handling action. + * + * Keeping this data in the TCB resolves a security problem in protected + * and kernel mode: The regs[] array is visible on the user stack and + * could be modified by a hostile program. + */ + + regs[REG_PC] = rtcb->xcp.saved_pc; + regs[REG_NPC] = rtcb->xcp.saved_npc; + regs[REG_PSR] = rtcb->xcp.saved_status; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + + /* Then restore the correct state for this thread of execution. This is an + * unusual case that must be handled by up_fullcontextresore. This case is + * unusal in two ways: + * + * 1. It is not a context switch between threads. Rather, + * up_fullcontextrestore must behave more it more like a longjmp + * within the same task, using + * he same stack. + * 2. In this case, up_fullcontextrestore is called with r12 pointing to + * a register save area on the stack to be destroyed. This is + * dangerous because there is the very real possibility that the new + * stack pointer might overlap with the register save area and hat + * stack usage in up_fullcontextrestore might corrupt the register + * save data before the state is restored. At present, there does + * not appear to be any stack overlap problems. If there were, then + * adding 3 words to the size of register save structure size will + * protect its contents. + */ + + board_autoled_off(LED_SIGNAL); + up_fullcontextrestore(regs); +} diff --git a/arch/sparc/src/sparc_v8/up_swint1.c b/arch/sparc/src/sparc_v8/up_swint1.c new file mode 100644 index 00000000000..57397099fd1 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_swint1.c @@ -0,0 +1,239 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_swint1.c + * + * 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 + +#include "up_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO +static void up_registerdump(const uint32_t *regs) +{ +} +#else +# define up_registerdump(regs) +#endif + +/**************************************************************************** + * Name: dispatch_syscall + * + * Description: + * Call the stub function corresponding to the system call. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_KERNEL +static void dispatch_syscall(void) naked_function; +static void dispatch_syscall(void) +{ +# error "Missing logic" +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_swint1 + * + * Description: + * This is software interrupt 8 exception handler that performs context + * switching and manages system calls + * + ****************************************************************************/ + +int up_swint1(int irq, FAR void *context, FAR void *arg) +{ + uint32_t *regs = (uint32_t *)context; + + DEBUGASSERT(regs && regs == g_current_regs); + + /* Software interrupt 0 is invoked with REG_A0 (REG_R4) = system call + * command and REG_A1-3 and REG_T0-2 (REG_R5-10) = variable number of + * arguments depending on the system call. + */ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO + svcinfo("Entry: regs: %p cmd: %d\n", regs, regs[REG_I0]); + up_registerdump(regs); +#endif + + /* Handle the SWInt according to the command in $4 */ + + switch (regs[REG_I0]) + { + /* A0=SYS_restore_context: This a restore context command: + * + * void up_fullcontextrestore(uint32_t *restoreregs) noreturn_function; + * + * At this point, the following values are saved in context: + * + * A0 = SYS_restore_context + * A1 = restoreregs + * + * In this case, we simply need to set g_current_regs to restore + * register area referenced in the saved R1. context == g_current + * regs is the normal exception return. By setting g_current + * regs = context[R1], we force the return to the saved context + * referenced in $a1. + */ + + case SYS_restore_context: + { + DEBUGASSERT(regs[REG_I1] != 0); + g_current_regs = (uint32_t *)regs[REG_I1]; + } + break; + + /* A0=SYS_switch_context: This a switch context command: + * + * void up_switchcontext(uint32_t *saveregs, uint32_t *restoreregs); + * + * At this point, the following values are saved in context: + * + * A0 = SYS_switch_context + * A1 = saveregs + * A2 = restoreregs + * + * In this case, we save the context registers to the save register + * area referenced by the saved contents of R5 and then set + * g_current_regs to the save register area referenced by the saved + * contents of R6. + */ + + case SYS_switch_context: + { + DEBUGASSERT(regs[REG_I1] != 0 && regs[REG_I2] != 0); + trap_flush_task((uint32_t *)regs[REG_I1], regs); + + /* task_flush_trap(regs,(uint32_t *)regs[REG_I2]); */ + + g_current_regs = (uint32_t *)regs[REG_I2]; + } + break; + + /* R0=SYS_syscall_return: This a switch context command: + * + * void up_sycall_return(void); + * + * At this point, the following values are saved in context: + * + * R0 = SYS_syscall_return + * + * We need to restore the saved return address and return in + * unprivileged thread mode. + */ + +#ifdef CONFIG_BUILD_KERNEL + case SYS_syscall_return: + { + struct tcb_s *rtcb = sched_self(); + int index = (int)rtcb->xcp.nsyscalls - 1; + + /* Make sure that there is a saved syscall return address. */ + + DEBUGASSERT(index >= 0); + + /* Setup to return to the saved syscall return address in + * the original mode. + */ + + g_current_regs[REG_I7] = rtcb->xcp.syscall[index].sysreturn; +#error "Missing logic -- need to restore the original mode" + rtcb->xcp.nsyscalls = index; + } + break; +#endif + + default: + { +#ifdef CONFIG_BUILD_KERNEL + FAR struct tcb_s *rtcb = sched_self(); + int index = rtcb->xcp.nsyscalls; + + /* Verify that the SYS call number is within range */ + + DEBUGASSERT(g_current_regs[REG_I1] < SYS_maxsyscall); + + /* Make sure that we got here that there is a no saved syscall + * return address. We cannot yet handle nested system calls. + */ + + DEBUGASSERT(index < CONFIG_SYS_NNEST); + + /* Setup to return to dispatch_syscall in privileged mode. */ + + rtcb->xcpsyscall[index].sysreturn = regs[REG_I7]; +#error "Missing logic -- Need to save mode" + rtcb->xcp.nsyscalls = index + 1; + + regs[REG_I7] = (uint32_t)dispatch_syscall; +#error "Missing logic -- Need to set privileged mode" + + /* Offset R0 to account for the reserved values */ + + /* g_current_regs[REG_R0] -= CONFIG_SYS_RESERVED; *//*zouboan*/ +#else + svcerr("ERROR: Bad SYS call: %d\n", regs[REG_I1]); +#endif + } + break; + } + + /* Report what happened. That might difficult in the case of a context + * switch + */ + +#ifdef CONFIG_DEBUG_SYSCALL_INFO + if (regs != g_current_regs) + { + svcinfo("SWInt Return: Context switch!\n"); + up_registerdump((const uint32_t *)g_current_regs); + } + else + { + svcinfo("SWInt Return: %d\n", regs[REG_I0]); + } +#endif + + return OK; +} diff --git a/arch/sparc/src/sparc_v8/up_syscall.S b/arch/sparc/src/sparc_v8/up_syscall.S new file mode 100644 index 00000000000..b226dfd9dcd --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_syscall.S @@ -0,0 +1,173 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/upsyscall_irq.S + * + * 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 "up_internal.h" + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .file "up_syscall.S" + .global sys_call0 + .global sys_call1 + .global sys_call2 + .global sys_call3 + .global sys_call4 + .global sys_call5 + + .global up_swint0 + .global sparcsyscall_exit + .global syscall_irqdis + .global syscall_irqen + +/**************************************************************************** + * Private Data + ****************************************************************************/ +#define SYS_exit 1 +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_swint0 + * + * Description: + * This file contains emulated system calls using software trap 0. + * The following calls are supported: + * + * + SYS_exit (halt) + * + SYS_irqdis (disable interrupts) + * + SYS_irqset (set interrupt level) + * + ****************************************************************************/ + + .seg "text" + /* + * system call - halt + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + * g1 = system call id (1) + * + * System Call 1 (exit): + * g2 = additional exit code 1 + * g3 = additional exit code 2 + */ + +up_swint0: + ta 0 ! syscall 0, halt with %g1,%g2,%g3 info + +sparcsyscall_exit: + + mov SYS_exit, %g1 + mov %o0, %g2 ! Additional exit code 1 + mov %o1, %g3 ! Additional exit code 2 + ta SPARC_SWTRAP_SYSCALL + + /* + * system call - Interrupt Disable + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + * l3 = psr | SPARC_PSR_PIL_MASK + * + * On exit: + * g1 = old psr (to user) + */ + + .align 32 ! Align to 32-byte cache-line + +syscall_irqdis: + mov %l3, %psr ! Set PSR. Write delay 3 instr + or %l0, SPARC_PSR_ET_MASK, %g1 ! return old PSR with ET=1 + nop; nop ! PSR write delay; + jmp %l2 ! Return to after TA 9. + rett %l2 + 4 + + /* + * system call - Interrupt Enable + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + * l3 = psr & ~0x0f00 + * g1 = new PIL to write (from user) + */ + + .align 32 ! Align to 32-byte cache-line + +syscall_irqen: + and %g1, SPARC_PSR_PIL_MASK, %l4 ! %l4 = (%g1 & 0xf00) + wr %l3, %l4, %psr ! PSR = (PSR & ~0xf00) ^ %l4 + nop; nop ! PSR write delay; + jmp %l2 ! Return to after TA 10. + rett %l2 + 4 + +/************************************************************************************ + * Name: up_syscall0, up_syscall1, up_syscall2, up_syscall3, up_syscall4, up_syscall5 + * + * Description: + * up_syscall0 - System call SYS_ argument and no additional parameters. + * up_syscall1 - System call SYS_ argument and one additional parameter. + * up_syscall2 - System call SYS_ argument and two additional parameters. + * up_syscall3 - System call SYS_ argument and three additional parameters. + * up_syscall4 - System call SYS_ argument and four additional parameters. + * up_syscall5 - System call SYS_ argument and five additional parameters. + * + * Assumption: + * All interrupts are disabled except for the software interrupts. + * + ************************************************************************************/ +sys_call0: /* %o0 holds the syscall number */ +sys_call1: /* %o0 holds the syscall number, argument in %o1 */ +sys_call2: /* %o0 holds the syscall number, arguments in %o1 and %o2 */ +sys_call3: /* %o0 holds the syscall number, arguments in %o1, %o2, and %o3 */ +sys_call4: /* %o0 holds the syscall number, arguments in %o1, %o2, a3 and %o4 */ +sys_call5: /* %o0 holds the syscall number, arguments in %o1, %o2, %o3, %o4 and %o5 */ + + /* Issue the ECALL opcode to perform a SW interrupt to the OS */ + ta 8; ! syscall 8 + nop; + nop; + nop; + + jmp %o7 + 8 + nop + diff --git a/arch/sparc/src/sparc_v8/up_systemreset.c b/arch/sparc/src/sparc_v8/up_systemreset.c new file mode 100644 index 00000000000..e703b989023 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_systemreset.c @@ -0,0 +1,65 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_systemreset.c + * + * 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 "up_arch.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_systemreset + * + * Description: + * Internal, sparc reset logic. + * + ****************************************************************************/ + +void up_systemreset(void) +{ + asm("st %g0,[%g1+0x90]"); /* ÐŽÈëÖжό¶±ðºÍÓÅÏÈ¿ØÖƌĎæÆ÷£¬ÆÁ±ÎËùÓÐÖÐ¶Ï */ + asm("st %g0,[%g1+0x94]"); /* ÐŽÈëÖжÏÇëÇóŒÄŽæÆ÷,Çå³ýËùÓеÄÖÐ¶Ï */ + asm("st %g0,[%g1+0x98]"); /* ÐŽÈëÇ¿ÖÆÖжόĎæÆ÷£¬Çå³ýËùÓÐÖÐ¶Ï */ + + /* Çå³ýËùÓб»×èÈûµÄÖÐ¶Ï */ + + asm("set 0xfffe,%g2"); /* ÉèÖÃÖжÏÇå³ýŒÄŽæÆ÷µÄÖµ */ + asm("st %g2,[%g1+0x9c]"); /* ÐŽÈëÖжÏÇå³ýŒÄŽæÆ÷£¬Çå³ýËùÓеÄÖÐ¶Ï */ + + asm("set 0x1024, %l4"); + asm("jmp %l4"); + asm("nop"); + asm("nop"); +} diff --git a/arch/sparc/src/sparc_v8/up_unblocktask.c b/arch/sparc/src/sparc_v8/up_unblocktask.c new file mode 100644 index 00000000000..6785d4c65d2 --- /dev/null +++ b/arch/sparc/src/sparc_v8/up_unblocktask.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * arch/sparc/src/sparc_v8/up_unblocktask.c + * + * 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 "sched/sched.h" +#include "group/group.h" +#include "clock/clock.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list + * but has been prepped to execute. Move the TCB to the + * ready-to-run list, restore its context, and start execution. + * + * Input Parameters: + * tcb: Refers to the tcb to be unblocked. This tcb is + * in one of the waiting tasks lists. It must be moved to + * the ready-to-run list and, if it is the highest priority + * ready to run task, executed. + * + ****************************************************************************/ + +void up_unblock_task(struct tcb_s *tcb) +{ + struct tcb_s *rtcb = this_task(); + + /* Verify that the context switch can be performed */ + + DEBUGASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && + (tcb->task_state <= LAST_BLOCKED_STATE)); + + /* Remove the task from the blocked task list */ + + nxsched_remove_blocked(tcb); + + /* Add the task in the correct location in the prioritized + * ready-to-run task list + */ + + if (nxsched_add_readytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + */ + + /* Update scheduler parameters */ + + nxsched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + + /* Update scheduler parameters */ + + nxsched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* No, then we will need to perform the user context switch */ + + else + { + /* Restore the exception context of the new task that is ready to + * run (probably tcb). This is the new rtcb at the head of the + * ready-to-run task list. + */ + + struct tcb_s *nexttcb = this_task(); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(nexttcb); +#endif + /* Update scheduler parameters */ + + nxsched_resume_scheduler(nexttcb); + + /* Then switch contexts */ + + up_switchcontext(rtcb->xcp.regs, nexttcb->xcp.regs); + + /* up_switchcontext forces a context switch to the task at the + * head of the ready-to-run list. It does not 'return' in the + * normal sense. When it does return, it is because the blocked + * task is again ready to run and has execution priority. + */ + } + } +} diff --git a/boards/Kconfig b/boards/Kconfig index 6e3716afb38..28faf21f3fb 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -2280,6 +2280,20 @@ config ARCH_BOARD_PHY6222 ---help--- none +config ARCH_BOARD_XX3803 + bool "Sparc Bm3803 XX3803 Board" + depends on ARCH_CHIP_BM3803 + select ARCH_HAVE_LEDS + ---help--- + none + +config ARCH_BOARD_XX3823 + bool "Sparc Bm3823 XX3823 Board" + depends on ARCH_CHIP_BM3823 + select ARCH_HAVE_LEDS + ---help--- + none + config ARCH_BOARD_SIM bool "User mode simulation" select ARCH_HAVE_BUTTONS @@ -2591,6 +2605,8 @@ config ARCH_BOARD default "sim" if ARCH_BOARD_SIM default "moxa" if ARCH_BOARD_MOXA default "spresense" if ARCH_BOARD_SPRESENSE + default "xx3803" if ARCH_BOARD_XX3803 + default "xx3823" if ARCH_BOARD_XX3823 comment "Common Board Options" @@ -3335,6 +3351,12 @@ endif if ARCH_BOARD_PHY6222 source "boards/arm/phy62xx/phy6222/Kconfig" endif +if ARCH_BOARD_XX3803 +source "boards/sparc/bm3803/xx3803/Kconfig" +endif +if ARCH_BOARD_XX3823 +source "boards/sparc/bm3823/xx3823/Kconfig" +endif comment "Board-Common Options" diff --git a/boards/sparc/bm3803/xx3803/Kconfig b/boards/sparc/bm3803/xx3803/Kconfig new file mode 100644 index 00000000000..543c35277e4 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/Kconfig @@ -0,0 +1,106 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_XX3803 + +config XX3803_WDG + bool "xx3803 wdg kicker support" + depends on BM3803_WDG + depends on WATCHDOG + +config XX3803_WDG_TIMEOUT + int "xx3803 wdg Timeout (ms)" + default 1000 + depends on XX3803_WDG + ---help--- + Watchdog timeout value in milliseconds. + +if XX3803_WDG +config XX3803_WDG_THREAD + bool "Watchdog Deamon Thread" + +if XX3803_WDG_THREAD +config XX3803_WDG_THREAD_NAME + string "Watchdog Thread Name" + default "wdog" + +config XX3803_WDG_THREAD_INTERVAL + int "Watchdog Thread Interval (ms)" + default 500 + +config XX3803_WDG_THREAD_PRIORITY + int "Watchdog Thread Priority" + default 200 + +config XX3803_WDG_THREAD_STACKSIZE + int "Watchdog Thread Stacksize" + default 2048 + +endif # XX3803_WDG_THREAD +endif # XX3803_WDG + +config XX3803_FLASH + bool "MTD driver for AM29LV FLASH" + default n + select MTD + select MTD_AM29LV + ---help--- + Configures an MTD device for use with the onboard flash + +config XX3803_FLASH_PARA + bool "Create application para data on partition or sector of FLASH" + default n + depends on XX3803_FLASH + ---help--- + Enables creation of a /dev/para on the FLASH + +config XX3803_FLASH_MINOR + int "Minor number for the FLASH /dev/smart entry" + default 0 + depends on XX3803_FLASH + depends on FS_SMARTFS + ---help--- + Sets the minor number for the FLASH MTD /dev entry + +config XX3803_FLASH_PART + bool "Enable partition support on FLASH" + default y + depends on XX3803_FLASH + select MTD_PARTITION + ---help--- + Enables creation of partitions on the FLASH + +config XX3803_FLASH_CONFIG_PART + bool "Create application config data partition on FLASH" + default n + depends on XX3803_FLASH_PART + depends on PLATFORM_CONFIGDATA + ---help--- + Enables creation of a /dev/config partition on the FLASH + +config XX3803_FLASH_CONFIG_PART_NUMBER + int "Index number of config partition (in list below)" + default 0 + depends on XX3803_FLASH_CONFIG_PART + ---help--- + Specifies the index number of the config data partition + from the partition list. + +config XX3803_FLASH_PART_LIST + string "Flash partition size list" + default "1024,1024,1024,1024" + depends on XX3803_FLASH_PART + ---help--- + Comma separated list of partition sizes in KB. + +config XX3803_FLASH_PART_NAMES + string "Flash partition name list" + default "first,second,third,forth" + depends on XX3803_FLASH_PART + depends on MTD_PARTITION_NAMES + ---help--- + Comma separated list of partition names. + +endif diff --git a/boards/sparc/bm3803/xx3803/configs/nsh/defconfig b/boards/sparc/bm3803/xx3803/configs/nsh/defconfig new file mode 100644 index 00000000000..48e8d84ff24 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/configs/nsh/defconfig @@ -0,0 +1,99 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_ARCH_RAMFUNCS is not set +# CONFIG_DISABLE_ENVIRON is not set +# CONFIG_DISABLE_PSEUDOFS_OPERATIONS is not set +# CONFIG_NSH_DISABLE_DATE is not set +# CONFIG_NSH_DISABLE_DD is not set +# CONFIG_NSH_DISABLE_EXEC is not set +# CONFIG_NSH_DISABLE_EXIT is not set +# CONFIG_NSH_DISABLE_GET is not set +# CONFIG_NSH_DISABLE_HEXDUMP is not set +# CONFIG_NSH_DISABLE_MKRD is not set +# CONFIG_NSH_DISABLE_PRINTF is not set +# CONFIG_NSH_DISABLE_PS is not set +# CONFIG_NSH_DISABLE_TIME is not set +CONFIG_ARCH="sparc" +CONFIG_ARCH_BOARD="xx3803" +CONFIG_ARCH_BOARD_XX3803=y +CONFIG_ARCH_CHIP="bm3803" +CONFIG_ARCH_CHIP_BM3803=y +CONFIG_ARCH_SPARC=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BM3803_GPIOIRQ=y +CONFIG_BM3803_GPIOIRQ_PORT4=y +CONFIG_BM3803_GPIOIRQ_PORT5=y +CONFIG_BM3803_GPIOIRQ_PORT6=y +CONFIG_BM3803_GPIOIRQ_PORT7=y +CONFIG_BM3803_TIM1=y +CONFIG_BM3803_TIM2=y +CONFIG_BM3803_UART3=y +CONFIG_BM3803_WDG=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARDCTL_ROMDISK=y +CONFIG_BOARD_LOOPSPERMSEC=800 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEFAULT_SMALL=y +CONFIG_ELF=y +CONFIG_ELF_ALIGN_LOG2=3 +CONFIG_ELF_BUFFERINCR=64 +CONFIG_ELF_BUFFERSIZE=64 +CONFIG_ELF_STACKSIZE=8192 +CONFIG_ENDIAN_BIG=y +CONFIG_EXAMPLES_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_HELLO_STACKSIZE=4096 +CONFIG_EXAMPLES_NULL=y +CONFIG_EXECFUNCS_HAVE_SYMTAB=y +CONFIG_EXECFUNCS_SYSTEM_SYMTAB=y +CONFIG_FS_ROMFS=y +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=4096 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBM=y +CONFIG_MEMSET_64BIT=y +CONFIG_MEMSET_OPTSPEED=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILE_APPS=y +CONFIG_NUNGET_CHARS=0 +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=32768 +CONFIG_PREALLOC_TIMERS=0 +CONFIG_PTHREAD_STACK_DEFAULT=4096 +CONFIG_RAM_SIZE=1048576 +CONFIG_RAM_START=0x40000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=10 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKSTACKSIZE=4096 +CONFIG_SCHED_LPWORK=y +CONFIG_SCHED_LPWORKPRIORITY=120 +CONFIG_SCHED_LPWORKSTACKSIZE=4096 +CONFIG_SCHED_TICKLESS=y +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SPECIFIC_DRIVERS=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=16 +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_SYSTEM_NSH_STACKSIZE=4096 +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=32768 +CONFIG_UART3_SERIAL_CONSOLE=y +CONFIG_USEC_PER_TICK=1 +CONFIG_XX3803_WDG=y +CONFIG_XX3803_WDG_THREAD=y diff --git a/boards/sparc/bm3803/xx3803/include/board.h b/boards/sparc/bm3803/xx3803/include/board.h new file mode 100644 index 00000000000..bf0394032be --- /dev/null +++ b/boards/sparc/bm3803/xx3803/include/board.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/include/board.h + * + * 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 __BOARDS_SPARC_BM3803_XX3803_INCLUDE_BOARD_H +#define __BOARDS_SPARC_BM3803_XX3803_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Clocking *****************************************************************/ + +/* Assume default CLKDIV8 fuse setting is overridden to CLKDIV1 */ + +#define BOARD_XTAL_FREQ 60000000 /* 60MHz crystal */ +#define BOARD_CPU_CLOCK BOARD_XTAL_FREQ /* F_CPU = 60MHz */ +#define CHIP_NUARTS 3 + +#define BOARD_TIM1_FREQUENCY BOARD_CPU_CLOCK +#define BOARD_TIM2_FREQUENCY BOARD_CPU_CLOCK + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_SPARC_BM3803_XX3803_INCLUDE_BOARD_H */ diff --git a/boards/sparc/bm3803/xx3803/scripts/Make.defs b/boards/sparc/bm3803/xx3803/scripts/Make.defs new file mode 100644 index 00000000000..a28ff1d23e2 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/scripts/Make.defs @@ -0,0 +1,116 @@ +############################################################################ +# boards/sparc/bm3803/xx3803/scripts/Make.defs +# +# 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/sparc/src/sparc_v8/Toolchain.defs + +LDSCRIPT = linksparc.ld + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = $(ARCHINCLUDES) "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem "$(TOPDIR)/include" + ARCHXXINCLUDES = $(ARCHINCLUDES) -isystem "$(TOPDIR)/include/cxx" + ARCHSCRIPT = -T$(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT) +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +STRIP = $(CROSSDEV)strip --strip-unneeded +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +# ARCHOPTIMIZATION += -fno-zero-initialized-in-bss + +# 20210818 zouboan +ARCHOPTIMIZATION += -fno-delete-null-pointer-checks + +ARCHCFLAGS = -fno-builtin +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +# ELF module definitions + +CELFFLAGS = $(CFLAGS) +CXXELFFLAGS = $(CXXFLAGS) + +LDELFFLAGS = -r -e main +ifeq ($(WINTOOL),y) + LDELFFLAGS += -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld}" +else + LDELFFLAGS += -T $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/gnu-elf.ld +endif + +# File extensions + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = .elf + +# Linker flags + +ifneq ($(CROSSDEV),sparc-nuttx-elf-) + LDFLAGS += -nostartfiles -nodefaultlibs +endif +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + +# Host tools + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = + diff --git a/boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld b/boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld new file mode 100644 index 00000000000..71f7620e89e --- /dev/null +++ b/boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld @@ -0,0 +1,84 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/scripts/gnu-elf.ld + * + * 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. + * + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.jcr) + _etext = . ; + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + . = ALIGN(4); + _edata = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + +} diff --git a/boards/sparc/bm3803/xx3803/scripts/linksparc.ld b/boards/sparc/bm3803/xx3803/scripts/linksparc.ld new file mode 100644 index 00000000000..2eaf6343780 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/scripts/linksparc.ld @@ -0,0 +1,208 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/scripts/linksparc.ld + * + * 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 memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _endtext | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + + +/* + * User modifiable values: + * + * _CLOCK_SPEED in Mhz (used to program the counter/timers) + * + * _PROM_SIZE size of PROM (permissible values are 128K, 256K, + * 512K, 1M, 2M, 4M, 8M and 16M) + * _RAM_SIZE size of RAM (permissible values are 256K, 512K, + * 1M, 2M, 4M, 8M, 16M, and 32M) + * + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = 4M; +/*_RAM_SIZE = 512K;*/ +_RAM_SIZE = 1M; + +_RAM_START = 0x40000000; +_RAM_END = _RAM_START + _RAM_SIZE; + +_PROM_START = 0x00000000; +_PROM_END = _PROM_START + _PROM_SIZE; + +/* + * Alternate names without leading _. + */ + +PROM_START = _PROM_START; +PROM_SIZE = _PROM_SIZE; +PROM_END = _PROM_END; + +RAM_START = _RAM_START; +RAM_SIZE = _RAM_SIZE; +RAM_END = _RAM_END; + +/* + PROVIDE (__stack = _RAM_END); //move to the file of stack.ld +*/ +__stack = _RAM_END; +/* + * Base address of the on-CPU peripherals + */ + +_BM3803_REG = 0x80000000; +BM3803_REG = 0x80000000; + +/* these are the maximum values */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 4M + ram (rw!x) : ORIGIN = 0x40000000, LENGTH = 1M +} + +OUTPUT_FORMAT("elf32-sparc") +OUTPUT_ARCH(sparc) +__DYNAMIC = 0; +ENTRY(__start) +/* + * stick everything in ram (of course) + */ +SECTIONS +{ + .text : + { + CREATE_OBJECT_SYMBOLS + text_start = .; + _text_start = .; + *(.text) + . = ALIGN (16); + + *(.eh_frame) + . = ALIGN (16); + + /* *(.gnu.linkonce.t*) */ + + /* + * C++ constructors + */ + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + + _rodata_start = . ; + *(.rodata*) + /* *(.gnu.linkonce.r*) */ + _erodata = ALIGN( 0x10 ) ; + + etext = ALIGN(0x10); + _etext = .; + *(.init) + *(.fini) + *(.lit) + *(.shdata) + . = ALIGN (16); + _endtext = .; + } >ram + + /* + .dynamic : { *(.dynamic) } >ram + .got : { *(.got) } >ram + .plt : { *(.plt) } >ram + .hash : { *(.hash) } >ram + .dynrel : { *(.dynrel) } >ram + .dynsym : { *(.dynsym) } >ram + .dynstr : { *(.dynstr) } >ram + .hash : { *(.hash) } >ram + */ + + .data : + { + data_start = .; + _data_start = .; + _sdata = . ; + *(.data) + /* + *(.gnu.linkonce.d*) + *(.gcc_except_table) + */ + . = ALIGN(0x10); + edata = .; + _edata = .; + } > ram + .shbss : + { + *(.shbss) + } + .bss : + { + __bss_start = ALIGN(0x10); + _bss_start = .; + bss_start = .; + *(.bss) + *(COMMON) + end = .; + _end = ALIGN(0x10); + __end = ALIGN(0x10); + } > ram + + + .jcr . (NOLOAD) : { *(.jcr) } + + .stab . (NOLOAD) : + { + [ .stab ] + } + .stabstr . (NOLOAD) : + { + [ .stabstr ] + } + + +} diff --git a/boards/sparc/bm3803/xx3803/src/Makefile b/boards/sparc/bm3803/xx3803/src/Makefile new file mode 100644 index 00000000000..29d67eb8d39 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/Makefile @@ -0,0 +1,41 @@ +############################################################################ +# boards/sparc/bm3803/xx3803/src/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = bm3803_boot.c + +ifeq ($(CONFIG_BOARDCTL),y) +CSRCS += bm3803_appinit.c +ifeq ($(CONFIG_BOARDCTL_RESET),y) +CSRCS += bm3803_reset.c +endif +endif + +ifeq ($(CONFIG_MTD_AM29LV),y) +CSRCS += bm3803_am29lv.c +endif + +ifeq ($(CONFIG_XX3803_WDG),y) +CSRCS += bm3803_wdt.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/sparc/bm3803/xx3803/src/bm3803_am29lv.c b/boards/sparc/bm3803/xx3803/src/bm3803_am29lv.c new file mode 100644 index 00000000000..93a8375832f --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/bm3803_am29lv.c @@ -0,0 +1,155 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/bm3803_am29lv.c + * + * 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 +#ifdef CONFIG_MTD_AM29LV +# include +# include +# include +#endif + +#include "xx3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Can't support the W25 device if it SPI1 or W25 support is not enabled */ + +#define HAVE_AM29LV 1 +#if !defined(CONFIG_MTD_AM29LV) +# undef HAVE_AM29LV +#endif + +/* Can't support W25 features if mountpoints are disabled */ + +#if defined(CONFIG_DISABLE_MOUNTPOINT) +# undef HAVE_AM29LV +#endif + +/* Can't support both FAT and SMARTFS */ + +#if defined(CONFIG_FS_FAT) && defined(CONFIG_FS_SMARTFS) +# warning "Can't support both FAT and SMARTFS -- using FAT" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_w25initialize + * + * Description: + * Initialize and register the W25 FLASH file system. + * + ****************************************************************************/ + +int bm3803_am29lv_initialize(int minor) +{ + int ret; +#ifdef HAVE_AM29LV + FAR struct mtd_dev_s *mtd; +#if defined(CONFIG_MTD_PARTITION_NAMES) + FAR const char *partname = CONFIG_XX3803_FLASH_PART_NAMES; +#endif + + /* Now bind the SPI interface to the W25 SPI FLASH driver */ + + mtd = am29lv_initialize(); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to initialize AM29LV FLASH driver\n"); + return -ENODEV; + } +#if defined(CONFIG_XX3803_FLASH_PARA) + + /* Register the MTD as the System Parameter device */ + + ret = mtdpara_register(mtd); + if (ret < 0) + { + _err("ERROR: Failed to register the /dev/para: %d\n", errno); + return ret; + } +#endif + +#ifdef CONFIG_MTD_PARTITION + + mtd = mtd_partition(mtd, 48, 79); + if (!mtd) + { + _err("ERROR: mtd_partition failed\n"); + return ret; + } +#endif + +#ifdef CONFIG_FS_LITTLEFS + + /* Register the MTD driver so that it can be accessed from the + * VFS. + */ + + ret = register_mtddriver("/dev/flash", mtd, 0755, NULL); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to register MTD driver: %d\n", ret); + } + + /* mtd_dev->ioctl(mtd_dev, MTDIOC_BULKERASE, 0); */ + + /* Mount the LittleFS file system */ + + ret = mount("/dev/flash", "/mnt/lfs", "littlefs", 0, + "autoformat"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to mount LittleFS at /mnt/lfs: %d\n", + ret); + } +#endif + +#endif /* HAVE_AM29LV */ + + /* Create a RAM MTD device if configured */ + +#if defined(CONFIG_RAMMTD) && defined(CONFIG_XX3803_RAMMTD) + uint8_t *start = (uint8_t *)kmm_malloc(CONFIG_XX3803_RAMMTD_SIZE * 1024); + mtd = rammtd_initialize(start, CONFIG_XX3803_RAMMTD_SIZE * 1024); + mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); +#endif /* CONFIG_RAMMTD && CONFIG_XX3803_RAMMTD */ + + return OK; +} diff --git a/boards/sparc/bm3803/xx3803/src/bm3803_appinit.c b/boards/sparc/bm3803/xx3803/src/bm3803_appinit.c new file mode 100644 index 00000000000..778a4bc2ba7 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/bm3803_appinit.c @@ -0,0 +1,146 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/bm3803_appinit.c + * + * 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 "bm3803_wdg.h" +#include "bm3803.h" +#include "xx3803.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Assume that we support everything until convinced otherwise */ + +#define HAVE_AM29LV 1 + +/* Can't support the AM29LV device if it AM29LV support is not enabled */ + +#if !defined(CONFIG_MTD_AM29LV) +# undef HAVE_AM29LV +#endif + +/* Can't support AM29LV features if mountpoints are disabled */ + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# undef HAVE_AM29LV +#endif + +/* Default AM29LV minor number */ + +#if defined(HAVE_AM29LV) && !defined(CONFIG_NSH_AM29LVMINOR) +# define CONFIG_NSH_AM29LVMINOR 0 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ +#ifdef CONFIG_ONESHOT + struct oneshot_lowerhalf_s *os = NULL; +#endif + int ret; + + /* Initialize and register the AM29LV FLASH file system. */ + +#ifdef HAVE_AM29LV + ret = bm3803_am29lv_initialize(CONFIG_NSH_AM29LVMINOR); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize AM29LV minor %d: %d\n", + CONFIG_NSH_AM29LVMINOR, ret); + return ret; + } +#endif + +#ifdef CONFIG_ONESHOT + os = oneshot_initialize(1, 10); + if (os) + { + ret = oneshot_register("/dev/oneshot", os); + } +#endif + +#ifdef CONFIG_BM3803_WDG + /* Initialize the watchdog timer */ + + bm3803_wdginitialize("/dev/watchdog0"); +#endif + +#ifdef CONFIG_XX3803_WDG + /* Start WDG kicker thread */ + + ret = xx3803_watchdog_initialize(); + if (ret != OK) + { + syslog(LOG_ERR, "Failed to start watchdog thread: %d\n", ret); + return ret; + } +#endif + + return ret; +} diff --git a/boards/sparc/bm3803/xx3803/src/bm3803_boot.c b/boards/sparc/bm3803/xx3803/src/bm3803_boot.c new file mode 100644 index 00000000000..38989c26058 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/bm3803_boot.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/bm3803_boot.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +#include "bm3803.h" +#include "xx3803.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_boardinitialize + * + * Description: + * All bm3803 architectures must provide the following entry point. + * This entry point is called early in the intitialization -- after all + * memory has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void bm3803_boardinitialize(void) +{ + BM3803_REG.mecfg2 = 0x0; + BM3803_REG.mecfg3 = 0x0; + BM3803_REG.mecfg1 = 0xf0038000; + + BM3803_REG.mem_cfg1 = 0x14f9f91f; + BM3803_REG.mem_cfg2 = 0x00078c67; + BM3803_REG.mem_cfg3 = 0x0; + + /* BM3803_REG.CacheCtrl = 0x0; */ + + BM3803_REG.timer_ctrl1 = 0; + BM3803_REG.timer_cnt1 = 0; + BM3803_REG.timer_load1 = 0; +} diff --git a/boards/sparc/bm3803/xx3803/src/bm3803_reset.c b/boards/sparc/bm3803/xx3803/src/bm3803_reset.c new file mode 100644 index 00000000000..b3859816739 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/bm3803_reset.c @@ -0,0 +1,66 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/bm3803_reset.c + * + * 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 + +#ifdef CONFIG_BOARDCTL_RESET + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_reset + * + * Description: + * Reset board. Support for this function is required by board-level + * logic if CONFIG_BOARDCTL_RESET is selected. + * + * Input Parameters: + * status - Status information provided with the reset event. This + * meaning of this status information is board-specific. If not + * used by a board, the value zero may be provided in calls to + * board_reset(). + * + * Returned Value: + * If this function returns, then it was not possible to power-off the + * board due to some constraints. The return value int this case is a + * board-specific reason for the failure to shutdown. + * + ****************************************************************************/ + +int board_reset(int status) +{ + up_systemreset(); + return 0; +} + +#endif /* CONFIG_BOARDCTL_RESET */ diff --git a/boards/sparc/bm3803/xx3803/src/bm3803_wdt.c b/boards/sparc/bm3803/xx3803/src/bm3803_wdt.c new file mode 100644 index 00000000000..352e2502663 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/bm3803_wdt.c @@ -0,0 +1,162 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/bm3803_wdt.c + * + * 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 +#include + +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* Watchdog daemon thread */ + +#if defined(CONFIG_XX3803_WDG_THREAD) + +static int wdog_daemon(int argc, char *argv[]) +{ + FAR struct file filestruct; + int ret; + + /* Open watchdog device */ + + ret = file_open(&filestruct, CONFIG_WATCHDOG_DEVPATH, O_RDONLY); + if (ret < 0) + { + wderr("ERROR: open %s failed: %d\n", CONFIG_WATCHDOG_DEVPATH, ret); + return ret; + } + + /* Start watchdog timer */ + + ret = file_ioctl(&filestruct, WDIOC_START, 0); + if (ret < 0) + { + wderr("ERROR: ioctl(WDIOC_START) failed: %d\n", errno); + goto exit_close_dev; + } + + while (1) + { + nxsig_usleep((CONFIG_XX3803_WDG_THREAD_INTERVAL)*1000); + + /* Send keep alive ioctl */ + + ret = file_ioctl(&filestruct, WDIOC_KEEPALIVE, 0); + if (ret < 0) + { + wderr("ERROR: ioctl(WDIOC_KEEPALIVE) failed: %d\n", errno); + break; + } + } + +exit_close_dev: + + /* Close watchdog device and exit. */ + + file_close(&filestruct); + return ret; +} + +#endif /* CONFIG_XX3803_WDG_THREAD */ + +/**************************************************************************** + * Name: xx3803_watchdog_initialize() + * + * Description: + * Perform architecture-specific initialization of the Watchdog hardware. + * This interface must be provided by all configurations using + * apps/examples/watchdog + * + ****************************************************************************/ + +int xx3803_watchdog_initialize(void) +{ + FAR struct file filestruct; + int ret = 0; + + /* Open the watchdog device */ + + ret = file_open(&filestruct, CONFIG_WATCHDOG_DEVPATH, O_RDONLY); + if (ret < 0) + { + wderr("ERROR: open %s failed: %d\n", CONFIG_WATCHDOG_DEVPATH, ret); + return ret; + } + + /* Set the watchdog timeout */ + +#ifdef CONFIG_XX3803_WDG + wdinfo("Timeout = %d.\n", CONFIG_XX3803_WDG_TIMEOUT); + ret = file_ioctl(&filestruct, WDIOC_SETTIMEOUT, + (unsigned long)CONFIG_XX3803_WDG_TIMEOUT); +#else +# error "No watchdog configured" +#endif + + /* Close watchdog as it is not needed here anymore */ + + (void)file_close(&filestruct); + + if (ret < 0) + { + wderr("ERROR: watchdog configuration failed: %d\n", errno); + return ret; + } + +#if defined(CONFIG_XX3803_WDG_THREAD) + + sched_lock(); + + /* Spawn wdog daemon thread */ + + int taskid = kthread_create(CONFIG_XX3803_WDG_THREAD_NAME, + CONFIG_XX3803_WDG_THREAD_PRIORITY, + CONFIG_XX3803_WDG_THREAD_STACKSIZE, + (main_t)wdog_daemon, (FAR char * const *)NULL); + + DEBUGASSERT(taskid > 0); + UNUSED(taskid); + + sched_unlock(); + +#endif /* CONFIG_XX3803_WDG_THREAD */ + + return OK; +} diff --git a/boards/sparc/bm3803/xx3803/src/xx3803.h b/boards/sparc/bm3803/xx3803/src/xx3803.h new file mode 100644 index 00000000000..6989ac00ca2 --- /dev/null +++ b/boards/sparc/bm3803/xx3803/src/xx3803.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3803/src/xx3803.h + * + * 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 __BOARDS_SPARC_BM3803_XX3803_SRC_XX3803_H +#define __BOARDS_SPARC_BM3803_XX3803_SRC_XX3803_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ +#define GPIO_PULSE_IRQ 0 /* GPIO 4*/ +#define GPIO_1553B_IRQ 1 /* GPIO 5*/ +#define GPIO_RS422_IRQ 2 /* GPIO 6*/ +#define GPIO_SPACEWIRE_IRQ 3 /* GPIO 7*/ + +/* procfs File System */ + +#ifdef CONFIG_FS_PROCFS +# ifdef CONFIG_NSH_PROC_MOUNTPOINT +# define BM3803_PROCFS_MOUNTPOINT CONFIG_NSH_PROC_MOUNTPOINT +# else +# define BM3803_PROCFS_MOUNTPOINT "/proc" +# endif +#endif + +/* Configuration ************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3803_ledinit + * + * Description: + * Configure on-board LEDs if LED support has been selected. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void bm3803_led_initialize(void); +#endif + +/**************************************************************************** + * Name: bm3803_am29lv_initialize + * + * Description: + * Initialize and register the AM29LV FLASH file system. + * + ****************************************************************************/ + +#ifdef CONFIG_MTD_AM29LV +int bm3803_am29lv_initialize(int minor); +#endif + +#ifdef CONFIG_DRIVERS_1553B +int bm3803_1553b_initialize(void); +#endif + +#ifdef CONFIG_DRIVERS_SPACEWIRE +int bm3803_spacewire_initialize(void); +#endif + +#ifdef CONFIG_XX3803_WDG +int xx3803_watchdog_initialize(void); +#endif + +#ifdef CONFIG_FPGA_UART +int bm3803_fpga_uart_initialize(void); +#endif + +#ifdef CONFIG_SECOND_PULSE +int bm3803_secpulse_initialize(void); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_SPARC_BM3803_XX3803_SRC_XX3803_H */ diff --git a/boards/sparc/bm3823/xx3823/Kconfig b/boards/sparc/bm3823/xx3823/Kconfig new file mode 100644 index 00000000000..86dcf431d9b --- /dev/null +++ b/boards/sparc/bm3823/xx3823/Kconfig @@ -0,0 +1,65 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_BOARD_XX3823 + +config XX3823_FLASH + bool "MTD driver for AM29LV FLASH" + default n + select MTD + select MTD_AM29LV + select MTD_SMART + select FS_SMARTFS + select MTD_BYTE_WRITE + ---help--- + Configures an MTD device for use with the onboard flash + +config XX3823_FLASH_MINOR + int "Minor number for the FLASH /dev/smart entry" + default 0 + depends on XX3823_FLASH + ---help--- + Sets the minor number for the FLASH MTD /dev entry + +config XX3823_FLASH_PART + bool "Enable partition support on FLASH" + default y + depends on XX3823_FLASH + select MTD_PARTITION + ---help--- + Enables creation of partitions on the FLASH + +config XX3823_FLASH_CONFIG_PART + bool "Create application config data partition on FLASH" + default n + depends on XX3823_FLASH_PART + depends on PLATFORM_CONFIGDATA + ---help--- + Enables creation of a /dev/config partition on the FLASH + +config XX3823_FLASH_CONFIG_PART_NUMBER + int "Index number of config partition (in list below)" + default 0 + depends on XX3823_FLASH_CONFIG_PART + ---help--- + Specifies the index number of the config data partition + from the partition list. + +config XX3823_FLASH_PART_LIST + string "Flash partition size list" + default "1024,1024,1024,1024" + depends on XX3823_FLASH_PART + ---help--- + Comma separated list of partition sizes in KB. + +config XX3823_FLASH_PART_NAMES + string "Flash partition name list" + default "first,second,third,forth" + depends on XX3823_FLASH_PART + depends on MTD_PARTITION_NAMES + ---help--- + Comma separated list of partition names. + +endif diff --git a/boards/sparc/bm3823/xx3823/configs/nsh/defconfig b/boards/sparc/bm3823/xx3823/configs/nsh/defconfig new file mode 100644 index 00000000000..992cc023e1f --- /dev/null +++ b/boards/sparc/bm3823/xx3823/configs/nsh/defconfig @@ -0,0 +1,67 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_RAMFUNCS is not set +CONFIG_ARCH="sparc" +CONFIG_ARCH_BOARD="xx3823" +CONFIG_ARCH_BOARD_XX3823=y +CONFIG_ARCH_CHIP="bm3823" +CONFIG_ARCH_CHIP_BM3823=y +CONFIG_ARCH_SPARC=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BM3823_UART1=y +CONFIG_BM3823_UART2=y +CONFIG_BOARD_LOOPSPERMSEC=800 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_DEBUG_ERROR=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEBUG_WARN=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DISABLE_MOUNTPOINT=y +CONFIG_DISABLE_MQUEUE=y +CONFIG_DISABLE_PTHREAD=y +CONFIG_ELF=y +CONFIG_ENDIAN_BIG=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_HELLO_STACKSIZE=4096 +CONFIG_EXAMPLES_NULL=y +CONFIG_FS_WRITABLE=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_MAX_TASKS=16 +CONFIG_MAX_WDOGPARMS=2 +CONFIG_NFILE_DESCRIPTORS=8 +CONFIG_NFILE_STREAMS=8 +CONFIG_NPTHREAD_KEYS=4 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILE_APPS=y +CONFIG_NUNGET_CHARS=0 +CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=512 +CONFIG_PREALLOC_TIMERS=0 +CONFIG_PREALLOC_WDOGS=4 +CONFIG_RAM_SIZE=524288 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=16 +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=768 +CONFIG_UART1_BAUD=9600 +CONFIG_UART1_SERIAL_CONSOLE=y +CONFIG_UART2_BAUD=9600 +CONFIG_USERMAIN_STACKSIZE=4096 +CONFIG_USER_ENTRYPOINT="nsh_main" +CONFIG_WDOG_INTRESERVE=0 diff --git a/boards/sparc/bm3823/xx3823/include/board.h b/boards/sparc/bm3823/xx3823/include/board.h new file mode 100644 index 00000000000..d45f0313412 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/include/board.h @@ -0,0 +1,132 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/include/board.h + * + * 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 __BOARDS_SPARC_BM3823_XX3823_INCLUDE_BOARD_H +#define __BOARDS_SPARC_BM3823_XX3823_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Clocking *****************************************************************/ + +/* Assume default CLKDIV8 fuse setting is overridden to CLKDIV1 */ + +#define BOARD_XTAL_FREQ 25000000L /* 25MHz crystal */ + +/* F_CPU = 300MHz */ + +#define BOARD_CPU_CLOCK ((uint32_t)((BOARD_XTAL_FREQ*8*3)/2)) + +/* F_peripheral = 100MHz */ + +#define BOARD_PERIPH_CLOCK ((uint32_t)(BOARD_CPU_CLOCK/3)) +#define CHIP_NUARTS 2 + +/* LED definitions **********************************************************/ + +/* ----- ----- ------------------------------------------------------------- + * LABEL COLOR CONTROL + * ----- ----- ------------------------------------------------------------- + * USB Green RF3. This could be used by software if USB is not used. + * Otherwise, RF3 is used as the USBID signal. + * LED1 While RE2, Pulled up. Low value illuminates + * LED2 Red RE1, Pulled up. Low value illuminates + * LED3 Yellow RE0, Pulled up. Low value illuminates + * PWR Blue Illuminated when 5V is present, not controlled by software + */ + +/* LED index values for use with board_userled() */ + +#define BM3823_XX3823_LED1 0 +#define BM3823_XX3823_LED2 1 +#define BM3823_XX3823_LED3 2 +#define BM3823_XX3823_NLEDS 3 + +/* LED bits for use with board_userled_all() */ + +#define BM3823_XX3823_LED1_BIT (1 << BM3823_XX3823_LED1) +#define BM3823_XX3823_LED2_BIT (1 << BM3823_XX3823_LED2) +#define BM3823_XX3823_LED3_BIT (1 << BM3823_XX3823_LED3) + +/* If CONFIG_ARCH_LEDS is defined, + * then NuttX will control these LEDs as follows: + * + * ON OFF + * ------------------------- ---- ---- ---- ---- ---- ---- + * LED1 LED2 LED3 LED1 LED2 LED3 + * ------------------------- ---- ---- ---- ---- ---- ---- + * LED_STARTED 0 OFF OFF OFF --- --- --- + * LED_HEAPALLOCATE 1 ON OFF N/C --- --- --- + * LED_IRQSENABLED 2 OFF ON N/C --- --- --- + * LED_STACKCREATED 3 ON ON N/C --- --- --- + * LED_INIRQ 4 N/C N/C ON N/C N/C OFF + * LED_SIGNAL 4 N/C N/C ON N/C N/C OFF + * LED_ASSERTION 4 N/C N/C ON N/C N/C OFF + * LED_PANIC 5 ON N/C N/C OFF N/C N/C + */ + +#define LED_STARTED 0 +#define LED_HEAPALLOCATE 1 +#define LED_IRQSENABLED 2 +#define LED_STACKCREATED 3 +#define LED_INIRQ 4 +#define LED_SIGNAL 4 +#define LED_ASSERTION 4 +#define LED_PANIC 5 + +#define LED_NVALUES 6 +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_SPARC_BM3823_XX3823_INCLUDE_BOARD_H */ diff --git a/boards/sparc/bm3823/xx3823/scripts/Make.defs b/boards/sparc/bm3823/xx3823/scripts/Make.defs new file mode 100644 index 00000000000..2a8d51cecd6 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/scripts/Make.defs @@ -0,0 +1,89 @@ +############################################################################ +# boards/sparc/bm3823/xx3823/scripts/Make.defs +# +# 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk +include ${TOPDIR}/arch/sparc/src/sparc_v8/Toolchain.defs + +LDSCRIPT = linksparc.ld + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = $(ARCHINCLUDES) "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)}" +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem "$(TOPDIR)/include" + ARCHXXINCLUDES = $(ARCHINCLUDES) -isystem "$(TOPDIR)/include/cxx" + ARCHSCRIPT = -T$(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT) +endif + +CC = $(CROSSDEV)gcc +CXX = $(CROSSDEV)g++ +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +STRIP = $(CROSSDEV)strip --strip-unneeded +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer +endif + +# ARCHOPTIMIZATION += -fno-zero-initialized-in-bss + +ARCHCFLAGS = -fno-builtin +ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHWARNINGSXX = -Wall -Wshadow -Wundef +ARCHDEFINES = + +CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS) +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +NXFLATLDFLAGS1 = -r -d -warn-common +NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-gotoff.ld -no-check-sections +LDNXFLATFLAGS = -e main -s 2048 + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = .elf + + +HOSTCC = gcc +HOSTINCLUDES = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = + diff --git a/boards/sparc/bm3823/xx3823/scripts/linksparc.ld b/boards/sparc/bm3823/xx3823/scripts/linksparc.ld new file mode 100644 index 00000000000..4f7ae7d095b --- /dev/null +++ b/boards/sparc/bm3823/xx3823/scripts/linksparc.ld @@ -0,0 +1,210 @@ +/**************************************************************************** + * boards/sparc/bm3803/xx3823/scripts/linksparc.ld + * + * 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 memory map looks like this: + * +--------------------+ <- low memory + * | .text | + * | etext | + * | ctor list | the ctor and dtor lists are for + * | dtor list | C++ support + * | _endtext | + * +--------------------+ + * | .data | initialized data goes here + * | _sdata | + * | _edata | + * +--------------------+ + * | .bss | + * | __bss_start | start of bss, cleared by crt0 + * | _end | start of heap, used by sbrk() + * +--------------------+ + * | heap space | + * | _ENDHEAP | + * | stack space | + * | __stack | top of stack + * +--------------------+ <- high memory + */ + + +/* + * User modifiable values: + * + * _CLOCK_SPEED in Mhz (used to program the counter/timers) + * + * _PROM_SIZE size of PROM (permissible values are 128K, 256K, + * 512K, 1M, 2M, 4M, 8M and 16M) + * _RAM_SIZE size of RAM (permissible values are 256K, 512K, + * 1M, 2M, 4M, 8M, 16M, and 32M) + * + */ + +/* Default values, can be overridden */ + +_PROM_SIZE = 4M; +_RAM_SIZE = 512K; + +_RAM_START = 0x20000000; +_RAM_END = _RAM_START + _RAM_SIZE; + +_PROM_START = 0x00000000; +_PROM_END = _PROM_START + _PROM_SIZE; + +/* + * Alternate names without leading _. + */ + +PROM_START = _PROM_START; +PROM_SIZE = _PROM_SIZE; +PROM_END = _PROM_END; + +RAM_START = _RAM_START; +RAM_SIZE = _RAM_SIZE; +RAM_END = _RAM_END; + +/* + PROVIDE (__stack = _RAM_END); //move to the file of stack.ld +*/ +__stack = _RAM_END; +/* + * Base address of the on-CPU peripherals + */ + +_INTER_REG = 0x80000000; +INTER_REG = 0x80000000; +_EXTER_REG = 0x81000000; +EXTER_REG = 0x81000000; + +/* these are the maximum values */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 4M + ram (rw!x) : ORIGIN = 0x20000000, LENGTH = 512K +} + +OUTPUT_FORMAT("elf32-sparc") +OUTPUT_ARCH(sparc) +__DYNAMIC = 0; +ENTRY(__start) +/* + * stick everything in ram (of course) + */ +SECTIONS +{ + .text : + { + CREATE_OBJECT_SYMBOLS + text_start = .; + _text_start = .; + *(.text) + . = ALIGN (16); + + *(.eh_frame) + . = ALIGN (16); + + /* *(.gnu.linkonce.t*) */ + + /* + * C++ constructors + */ + __CTOR_LIST__ = .; + LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + __CTOR_END__ = .; + __DTOR_LIST__ = .; + LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + __DTOR_END__ = .; + + _rodata_start = . ; + *(.rodata*) + /* *(.gnu.linkonce.r*) */ + _erodata = ALIGN( 0x10 ) ; + + etext = ALIGN(0x10); + _etext = .; + *(.init) + *(.fini) + *(.lit) + *(.shdata) + . = ALIGN (16); + _endtext = .; + } >ram + + /* + .dynamic : { *(.dynamic) } >ram + .got : { *(.got) } >ram + .plt : { *(.plt) } >ram + .hash : { *(.hash) } >ram + .dynrel : { *(.dynrel) } >ram + .dynsym : { *(.dynsym) } >ram + .dynstr : { *(.dynstr) } >ram + .hash : { *(.hash) } >ram + */ + + .data : + { + data_start = .; + _data_start = .; + _sdata = . ; + *(.data) + /* + *(.gnu.linkonce.d*) + *(.gcc_except_table) + */ + . = ALIGN(0x10); + edata = .; + _edata = .; + } > ram + .shbss : + { + *(.shbss) + } + .bss : + { + __bss_start = ALIGN(0x10); + _bss_start = .; + bss_start = .; + *(.bss) + *(COMMON) + end = .; + _end = ALIGN(0x10); + __end = ALIGN(0x10); + } > ram + + + .jcr . (NOLOAD) : { *(.jcr) } + + .stab . (NOLOAD) : + { + [ .stab ] + } + .stabstr . (NOLOAD) : + { + [ .stabstr ] + } + + +} diff --git a/boards/sparc/bm3823/xx3823/src/Makefile b/boards/sparc/bm3823/xx3823/src/Makefile new file mode 100644 index 00000000000..a3b1f9d53a6 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# boards/sparc/bm3823/xx3823/src/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = bm3823_boot.c bm3823_leds.c + +ifeq ($(CONFIG_LIB_BOARDCTL),y) +CSRCS += bm3823_appinit.c +endif + +ifeq ($(CONFIG_MTD_AM29LV),y) +CSRCS += bm3823_am29lv.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/sparc/bm3823/xx3823/src/bm3823_am29lv.c b/boards/sparc/bm3823/xx3823/src/bm3823_am29lv.c new file mode 100644 index 00000000000..ea658604511 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/bm3823_am29lv.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/src/bm3823_am29lv.c + * + * 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 + +#ifdef CONFIG_MTD_AM29LV +# include +# include +# include +#endif + +#include "xx3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Can't support the W25 device if it SPI1 or W25 support is not enabled */ + +#define HAVE_AM29LV 1 +#if !defined(CONFIG_MTD_AM29LV) +# undef HAVE_AM29LV +#endif + +/* Can't support W25 features if mountpoints are disabled */ + +#if defined(CONFIG_DISABLE_MOUNTPOINT) +# undef HAVE_AM29LV +#endif + +/* Can't support both FAT and SMARTFS */ + +#if defined(CONFIG_FS_FAT) && defined(CONFIG_FS_SMARTFS) +# warning "Can't support both FAT and SMARTFS -- using FAT" +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3823_w25initialize + * + * Description: + * Initialize and register the W25 FLASH file system. + * + ****************************************************************************/ + +int bm3823_am29lv_initialize(int minor) +{ + int ret; +#ifdef HAVE_AM29LV + FAR struct mtd_dev_s *mtd; + FAR struct mtd_geometry_s geo; +#if defined(CONFIG_MTD_PARTITION_NAMES) + FAR const char *partname = CONFIG_XX3823_FLASH_PART_NAMES; +#endif + + /* Now bind the SPI interface to the W25 SPI FLASH driver */ + + mtd = am29lv_initialize(); + if (!mtd) + { + syslog(LOG_ERR, "ERROR: Failed to initialize AM29LV FLASH driver\n"); + return -ENODEV; + } + +#endif /* HAVE_AM29LV */ + + /* Create a RAM MTD device if configured */ + +#if defined(CONFIG_RAMMTD) && defined(CONFIG_XX3823_RAMMTD) + + uint8_t *start = (uint8_t *)kmm_malloc(CONFIG_XX3823_RAMMTD_SIZE * 1024); + mtd = rammtd_initialize(start, CONFIG_XX3823_RAMMTD_SIZE * 1024); + mtd->ioctl(mtd, MTDIOC_BULKERASE, 0); + +#endif /* CONFIG_RAMMTD && CONFIG_XX3823_RAMMTD */ + + return OK; +} diff --git a/boards/sparc/bm3823/xx3823/src/bm3823_appinit.c b/boards/sparc/bm3823/xx3823/src/bm3823_appinit.c new file mode 100644 index 00000000000..4c2248942ab --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/bm3823_appinit.c @@ -0,0 +1,117 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/src/bm3823_appinit.c + * + * 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 "bm3823.h" +#include "xx3823.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Assume that we support everything until convinced otherwise */ + +#define HAVE_AM29LV 1 + +/* Can't support the AM29LV device if it AM29LV support is not enabled */ + +#if !defined(CONFIG_MTD_AM29LV) +# undef HAVE_AM29LV +#endif + +/* Can't support AM29LV features if mountpoints are disabled */ + +#ifdef CONFIG_DISABLE_MOUNTPOINT +# undef HAVE_AM29LV +#endif + +/* Default AM29LV minor number */ + +#if defined(HAVE_AM29LV) && !defined(CONFIG_NSH_AM29LVMINOR) +# define CONFIG_NSH_AM29LVMINOR 0 +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +int board_app_initialize(uintptr_t arg) +{ + int ret; + + /* Initialize and register the AM29LV FLASH file system. */ + +#ifdef HAVE_AM29LV + ret = bm3823_am29lv_initialize(CONFIG_NSH_AM29LVMINOR); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize AM29LV minor %d: %d\n", + CONFIG_NSH_AM29LVMINOR, ret); + return ret; + } +#endif + + return ret; +} diff --git a/boards/sparc/bm3823/xx3823/src/bm3823_boot.c b/boards/sparc/bm3823/xx3823/src/bm3823_boot.c new file mode 100644 index 00000000000..5d6f742d268 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/bm3823_boot.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/src/bm3823_boot.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +#include "bm3823.h" +#include "xx3823.h" + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_boardinitialize + * + * Description: + * All bm3823 architectures must provide the following entry point. + * This entry point is called early in the intitialization -- after all + * memory has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void bm3823_boardinitialize(void) +{ + EXTER_REG.mem_cfg1 = 0x14f9f91f; + EXTER_REG.mem_cfg2 = 0x7c47906f; + INTER_REG.cache_ctrl = 0x0; + + /* Configure on-board LEDs if LED support has been selected. */ + +#ifdef CONFIG_ARCH_LEDS + bm3823_led_initialize(); +#endif +} diff --git a/boards/sparc/bm3823/xx3823/src/bm3823_leds.c b/boards/sparc/bm3823/xx3823/src/bm3823_leds.c new file mode 100644 index 00000000000..d9c810f0c19 --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/bm3823_leds.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/src/bm3823_leds.c + * + * 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 "up_arch.h" +#include "up_internal.h" + +#include "bm3823.h" +#include "xx3823.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3823_led_initialize + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void bm3823_led_initialize(void) +{ + /* Configure output pins */ +} + +/**************************************************************************** + * Name: board_autoled_on + ****************************************************************************/ + +void board_autoled_on(int led) +{ +} + +/**************************************************************************** + * Name: board_autoled_off + ****************************************************************************/ + +void board_autoled_off(int led) +{ +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/sparc/bm3823/xx3823/src/xx3823.h b/boards/sparc/bm3823/xx3823/src/xx3823.h new file mode 100644 index 00000000000..b503bbfbb0b --- /dev/null +++ b/boards/sparc/bm3823/xx3823/src/xx3823.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/sparc/bm3823/xx3823/src/xx3823.h + * + * 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 __BOARDS_SPARC_BM3823_XX3823_SRC_XX3823_H +#define __BOARDS_SPARC_BM3823_XX3823_SRC_XX3823_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bm3823_ledinit + * + * Description: + * Configure on-board LEDs if LED support has been selected. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void bm3823_led_initialize(void); +#endif + +/**************************************************************************** + * Name: bm3823_am29lv_initialize + * + * Description: + * Initialize and register the AM29LV FLASH file system. + * + ****************************************************************************/ + +#ifdef CONFIG_MTD_AM29LV +int bm3823_am29lv_initialize(int minor); +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_SPARC_BM3823_XX3823_SRC_XX3823_H */ diff --git a/libs/libc/machine/Kconfig b/libs/libc/machine/Kconfig index 2ca6f79dcae..5be155064d1 100644 --- a/libs/libc/machine/Kconfig +++ b/libs/libc/machine/Kconfig @@ -190,4 +190,8 @@ if ARCH_RENESAS source "libs/libc/machine/renesas/Kconfig" endif +if ARCH_SPARC +source libs/libc/machine/sparc/Kconfig +endif + endmenu # Architecture-Specific Support diff --git a/libs/libc/machine/Make.defs b/libs/libc/machine/Make.defs index 6f654a359a9..b792ba588c3 100644 --- a/libs/libc/machine/Make.defs +++ b/libs/libc/machine/Make.defs @@ -40,7 +40,9 @@ endif ifeq ($(CONFIG_ARCH_RENESAS),y) include $(TOPDIR)/libs/libc/machine/renesas/Make.defs endif - +ifeq ($(CONFIG_ARCH_SPARC),y) +include $(TOPDIR)/libs/libc/machine/sparc/Make.defs +endif DEPPATH += --dep-path machine VPATH += :machine diff --git a/libs/libc/machine/sparc/Kconfig b/libs/libc/machine/sparc/Kconfig new file mode 100644 index 00000000000..f72f3c094ce --- /dev/null +++ b/libs/libc/machine/sparc/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# diff --git a/libs/libc/machine/sparc/Make.defs b/libs/libc/machine/sparc/Make.defs new file mode 100644 index 00000000000..183c2dce77d --- /dev/null +++ b/libs/libc/machine/sparc/Make.defs @@ -0,0 +1,28 @@ +############################################################################ +# libs/libc/machine/sparc/Make.defs +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_LIBC_ARCH_ELF),y) + +CSRCS += arch_elf.c + +DEPPATH += --dep-path machine/sparc +VPATH += :machine/sparc + +endif diff --git a/libs/libc/machine/sparc/arch_elf.c b/libs/libc/machine/sparc/arch_elf.c new file mode 100644 index 00000000000..7777c723a21 --- /dev/null +++ b/libs/libc/machine/sparc/arch_elf.c @@ -0,0 +1,252 @@ +/**************************************************************************** + * libs/libc/machine/sparc/arch_elf.c + * + * 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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkarch + * + * Description: + * Given the ELF header in 'hdr', verify that the ELF file is appropriate + * for the current, configured architecture. Every architecture that uses + * the ELF loader must provide this function. + * + * Input Parameters: + * hdr - The ELF header read from the ELF file. + * + * Returned Value: + * True if the architecture supports this ELF file. + * + ****************************************************************************/ + +bool up_checkarch(FAR const Elf32_Ehdr *ehdr) +{ + /* Make sure it's an Sparc executable */ + + if (ehdr->e_machine != EM_SPARC) + { + berr("ERROR: Not for Sparc: e_machine=%04x\n", ehdr->e_machine); + return false; + } + + /* Make sure that 32-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + { + berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", + ehdr->e_ident[EI_CLASS]); + return false; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) +#else + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) +#endif + { + berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n", + ehdr->e_ident[EI_DATA]); + return false; + } + + return true; +} + +/**************************************************************************** + * Name: up_relocate and up_relocateadd + * + * Description: + * Perform on architecture-specific ELF relocation. Every architecture + * that uses the ELF loader must provide this function. + * + * Input Parameters: + * rel - The relocation type + * sym - The ELF symbol structure containing the fully resolved value. + * There are a few relocation types for a few architectures that do + * not require symbol information. For those, this value will be + * NULL. Implementations of these functions must be able to handle + * that case. + * addr - The address that requires the relocation. + * + * Returned Value: + * Zero (OK) if the relocation was successful. Otherwise, a negated errno + * value indicating the cause of the relocation failure. + * + ****************************************************************************/ + +int up_relocate(FAR const Elf32_Rel *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + unsigned int relotype; + + /* All relocations except NONE depend upon having valid symbol + * information. + */ + + relotype = ELF32_R_TYPE(rel->r_info); + if (sym == NULL && relotype != R_SPARC_NONE) + { + return -EINVAL; + } + + berr("ERROR: Unsupported relocation: %u\n", relotype); + + return OK; +} + +int up_relocateadd(FAR const Elf32_Rela *rel, FAR const Elf32_Sym *sym, + uintptr_t addr) +{ + unsigned int relotype; + uint32_t value; + + /* All relocations except NONE depend upon having valid symbol + * information. + */ + + relotype = ELF32_R_TYPE(rel->r_info); + if (sym == NULL) + { + if (relotype != R_SPARC_NONE) + { + return -EINVAL; + } + } + else + { + value = sym->st_value + rel->r_addend; + } + + /* Handle the relocation by relocation type */ + + switch (relotype) + { + case R_SPARC_NONE: + break; + case R_SPARC_8: + (*(FAR uint8_t *)addr) = (uint8_t)value; + break; + + case R_SPARC_16: + (*(FAR uint16_t *)addr) = (uint16_t)value; + break; + + case R_SPARC_32: + (*(FAR uint32_t *)addr) = value; + break; + + case R_SPARC_DISP8: + case R_SPARC_DISP16: + case R_SPARC_DISP32: + (*(FAR uint32_t *)addr) = value - addr; + break; + + case R_SPARC_WDISP30: + value -= addr; + (*(FAR uint32_t *)addr) &= (~0x3fffffff); + (*(FAR uint32_t *)addr) |= (value >> 2) & 0x3fffffff; + break; + + case R_SPARC_WDISP22: + value -= addr; + (*(FAR uint32_t *)addr) &= (~0x3fffff); + (*(FAR uint32_t *)addr) |= (value >> 2) & 0x3fffff; + break; + + case R_SPARC_HI22: + (*(FAR uint32_t *)addr) &= (~0x3fffff); + (*(FAR uint32_t *)addr) |= (value >> 10) & 0x3fffff; + break; + + case R_SPARC_22: + (*(FAR uint32_t *)addr) &= (~0x3fffff); + (*(FAR uint32_t *)addr) |= value & 0x3fffff; + break; + + case R_SPARC_13: + (*(FAR uint32_t *)addr) &= (~0x1ffff); + (*(FAR uint32_t *)addr) |= value & 0x1ffff; + break; + + case R_SPARC_LO10: + (*(FAR uint32_t *)addr) &= (~0x3ff); + (*(FAR uint32_t *)addr) |= value & 0x3ff; + break; + + case R_SPARC_PC10: + value -= addr; + (*(FAR uint32_t *)addr) &= (~0x3ff); + (*(FAR uint32_t *)addr) |= value & 0x3ff; + break; + + case R_SPARC_PC22: + value -= addr; + (*(FAR uint32_t *)addr) &= (~0x3fffff); + (*(FAR uint32_t *)addr) |= (value >> 10) & 0x3fffff; + break; + + case R_SPARC_UA32: + case R_SPARC_GLOB_DAT: + (*(FAR uint32_t *)addr) = value; + break; + + case R_SPARC_JMP_SLOT: + (*(FAR uint32_t *)(addr + 1)) = OPCODE_SETHI_G1 | ((value >> 10) & + 0x3fffff); + (*(FAR uint32_t *)(addr + 2)) = OPCODE_JMP_G1 | (value & 0x3ff); + break; + + default: + berr("ERROR: RELA relocation %u not supported\n", relotype); + return -EINVAL; + } + + return OK; +}