diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 71cbcfc25c9..fab5dd53ffb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -686,6 +686,13 @@ config ARCH_CHIP_AT32 ---help--- Artery AT32 architectures (ARM Cortex-M4) +config ARCH_CHIP_CXD32XX + bool "Sony CXD32xx" + select ARCH_CORTEXM4 + select ARCH_HAVE_FPU + ---help--- + Sony CXD32XX (ARM Cortex-M4) architectures + config ARCH_CHIP_ARM_CUSTOM bool "Custom ARM chip" select ARCH_CHIP_CUSTOM @@ -1104,6 +1111,7 @@ config ARCH_CHIP default "mps" if ARCH_CHIP_MPS default "goldfish" if ARCH_CHIP_GOLDFISH_ARM default "at32" if ARCH_CHIP_AT32 + default "cxd32xx" if ARCH_CHIP_CXD32XX config ARM_THUMB bool "Thumb Mode" @@ -1588,4 +1596,7 @@ endif if ARCH_CHIP_AT32 source "arch/arm/src/at32/Kconfig" endif +if ARCH_CHIP_CXD32XX +source "arch/arm/src/cxd32xx/Kconfig" +endif endif # ARCH_ARM diff --git a/arch/arm/include/cxd32xx/chip.h b/arch/arm/include/cxd32xx/chip.h new file mode 100644 index 00000000000..57d65ae1d94 --- /dev/null +++ b/arch/arm/include/cxd32xx/chip.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * arch/arm/include/cxd32xx/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_ARM_INCLUDE_CXD32XX_CHIP_H +#define __ARCH_ARM_INCLUDE_CXD32XX_CHIP_H + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +#define CXD32M4_SYSH_PRIORITY_MIN 0xe0 /* All bits[7:5] set is minimum priority */ +#define CXD32M4_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define CXD32M4_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define CXD32M4_SYSH_PRIORITY_STEP 0x20 /* Steps between priorities */ + +#define NVIC_SYSH_PRIORITY_MIN CXD32M4_SYSH_PRIORITY_MIN +#define NVIC_SYSH_PRIORITY_DEFAULT CXD32M4_SYSH_PRIORITY_DEFAULT +#define NVIC_SYSH_PRIORITY_MAX CXD32M4_SYSH_PRIORITY_MAX +#define NVIC_SYSH_PRIORITY_STEP CXD32M4_SYSH_PRIORITY_STEP + +#endif /* __ARCH_ARM_INCLUDE_CXD32XX_CHIP_H */ diff --git a/arch/arm/include/cxd32xx/irq.h b/arch/arm/include/cxd32xx/irq.h new file mode 100644 index 00000000000..2da12a346a9 --- /dev/null +++ b/arch/arm/include/cxd32xx/irq.h @@ -0,0 +1,126 @@ +/**************************************************************************** + * arch/arm/include/cxd32xx/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 directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_CXD32XX_IRQ_H +#define __ARCH_ARM_INCLUDE_CXD32XX_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map + * directly to bits in the NVIC. This does, however, waste several words of + * memory in the IRQ to handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define CXD32_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define CXD32_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define CXD32_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define CXD32_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define CXD32_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define CXD32_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ +#define CXD32_IRQ_SIGNVALUE (7) /* Vector 7: Sign value */ +#define CXD32_IRQ_SVCALL (11)/* Vector 11: SVC call */ +#define CXD32_IRQ_DBGMONITOR (12)/* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define CXD32_IRQ_PENDSV (14)/* Vector 14: Pendable system service request */ +#define CXD32_IRQ_SYSTICK (15)/* Vector 15: System tick */ +#define CXD32_IRQ_EXTINT (16)/* Vector 16: Vector number of the first external interrupt */ + +/* Cortex-M4 External interrupts (vectors >= 16) */ + +#define CXD32_IRQ_XXX (CXD32_IRQ_EXTINT+0) /* XXX IRQ number */ + +/* XXX The details of interrupt number will be described later. */ +#define CXD32_IRQ_UART0 (CXD32_IRQ_EXTINT+73) /* 16+73: UART0 interrupt */ + +#define CXD32_IRQ_TIM01 (CXD32_IRQ_EXTINT+77) /* 16+77: TIMER0_1 interrupt */ +#define CXD32_IRQ_TIM02 (CXD32_IRQ_EXTINT+78) /* 16+78: TIMER0_2 interrupt */ +#define CXD32_IRQ_TIM11 (CXD32_IRQ_EXTINT+79) /* 16+79: TIMER1_1 interrupt */ +#define CXD32_IRQ_TIM12 (CXD32_IRQ_EXTINT+80) /* 16+80: TIMER1_2 interrupt */ +#define CXD32_IRQ_TIM21 (CXD32_IRQ_EXTINT+81) /* 16+81: TIMER2_1 interrupt */ +#define CXD32_IRQ_TIM22 (CXD32_IRQ_EXTINT+82) /* 16+82: TIMER2_2 interrupt */ +#define CXD32_IRQ_TIM31 (CXD32_IRQ_EXTINT+83) /* 16+83: TIMER3_1 interrupt */ +#define CXD32_IRQ_TIM32 (CXD32_IRQ_EXTINT+84) /* 16+84: TIMER3_2 interrupt */ +#define CXD32_IRQ_TIM41 (CXD32_IRQ_EXTINT+85) /* 16+85: TIMER4_1 interrupt */ +#define CXD32_IRQ_TIM42 (CXD32_IRQ_EXTINT+86) /* 16+86: TIMER4_2 interrupt */ + +#define CXD32_IRQ_NEXTINT (128) +#define CXD32_IRQ_NIRQS (CXD32_IRQ_EXTINT+CXD32_IRQ_NEXTINT) + +/* Total number of IRQ numbers (This will need to be revisited if/when the + * Cortex-M0 is supported) + */ + +#define NR_VECTORS CXD32_IRQ_NIRQS +#define NR_IRQS CXD32_IRQ_NIRQS + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +typedef void (*vic_vector_t)(uint32_t *regs); +#endif + +/**************************************************************************** + * 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_ARM_INCLUDE_CXD32XX_IRQ_H */ diff --git a/arch/arm/src/cxd32xx/Kconfig b/arch/arm/src/cxd32xx/Kconfig new file mode 100644 index 00000000000..09ece5f9303 --- /dev/null +++ b/arch/arm/src/cxd32xx/Kconfig @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menu "Peripheral Support" + +config CXD32_UART0 + bool "UART0" + default y + select UART0_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS + ---help--- + UART0 must be used as console device at CXD32xx. + +endmenu # "Peripheral Support" diff --git a/arch/arm/src/cxd32xx/Make.defs b/arch/arm/src/cxd32xx/Make.defs new file mode 100644 index 00000000000..94aac1dd8bd --- /dev/null +++ b/arch/arm/src/cxd32xx/Make.defs @@ -0,0 +1,32 @@ +############################################################################ +# arch/arm/src/cxd32xx/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 armv7-m/Make.defs + +CHIP_ASRCS += + +CHIP_CSRCS += cxd32_start.c cxd32_uart.c cxd32_irq.c cxd32_timerisr.c + +ifeq ($(CONFIG_UART_PL011),y) +CHIP_CSRCS += cxd32_serial_pl011.c +else +CHIP_CSRCS += cxd32_serial.c +endif + diff --git a/arch/arm/src/cxd32xx/chip.h b/arch/arm/src/cxd32xx/chip.h new file mode 100644 index 00000000000..556cc7d9b33 --- /dev/null +++ b/arch/arm/src/cxd32xx/chip.h @@ -0,0 +1,47 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/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_ARM_SRC_CXD32XX_CHIP_H +#define __ARCH_ARM_SRC_CXD32XX_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +#endif + +/* Include the chip capabilities file */ + +#include + +#define ARMV7M_PERIPHERAL_INTERRUPTS 128 + +#include "hardware/cxd3277_clockfreq.h" +#include "hardware/cxd3277_memorymap.h" + +/**************************************************************************** + * Macro Definitions + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_CXD32XX_CHIP_H */ diff --git a/arch/arm/src/cxd32xx/cxd32_config.h b/arch/arm/src/cxd32xx/cxd32_config.h new file mode 100644 index 00000000000..5fa073f94fc --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_config.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_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_ARM_SRC_CXD32XX_CXD32_CONFIG_H +#define __ARCH_ARM_SRC_CXD32XX_CXD32_CONFIG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Required configuration settings */ + +/* Are any UARTs enabled? */ + +#undef HAVE_UART +#if defined(CONFIG_CXD32_UART0) +# define HAVE_UART 1 +#endif + +/* Is there a serial console? There should be at most one defined. It could + * be on any UARTn, n=0,1,2,3 - OR - there might not be any serial console at + * all. + */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define HAVE_CONSOLE 1 +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_CXD32XX_CXD32_CONFIG_H */ diff --git a/arch/arm/src/cxd32xx/cxd32_irq.c b/arch/arm/src/cxd32xx/cxd32_irq.c new file mode 100644 index 00000000000..ba23f7ba86f --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_irq.c @@ -0,0 +1,483 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_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 + +#include "chip.h" +#include "nvic.h" +#include "ram_vectors.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (CXD32M4_SYSH_PRIORITY_DEFAULT << 24 | CXD32M4_SYSH_PRIORITY_DEFAULT << 16 | \ + CXD32M4_SYSH_PRIORITY_DEFAULT << 8 | CXD32M4_SYSH_PRIORITY_DEFAULT) + +#define INTC_EN(n) (CXD32_INTC_BASE + 0x10 + (((n) >> 5) << 2)) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: cxd32_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_IRQ_INFO) +static void cxd32_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = enter_critical_section(); + irqinfo("NVIC (%s, irq=%d):\n", msg, irq); + irqinfo(" INTCTRL: %08x VECTAB: %08x\n", getreg32(NVIC_INTCTRL), + getreg32(NVIC_VECTAB)); + irqinfo(" IRQ ENABLE: %08x %08x\n", getreg32(NVIC_IRQ0_31_ENABLE), + getreg32(NVIC_IRQ32_63_ENABLE)); + irqinfo(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), + getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + irqinfo(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), + getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), + getreg32(NVIC_IRQ12_15_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), + getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), + getreg32(NVIC_IRQ28_31_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), + getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), + getreg32(NVIC_IRQ44_47_PRIORITY)); + irqinfo(" %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), + getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY)); + leave_critical_section(flags); +} +#else +# define cxd32_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: cxd32_nmi, cxd32_pendsv, cxd32_pendsv, cxd32_reserved + * + * Description: + * Handlers for various exceptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int cxd32_nmi(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int cxd32_pendsv(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); + return 0; +} + +static int cxd32_reserved(int irq, void *context, void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: cxd32_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_USEBASEPRI +static inline void cxd32_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} +#endif + +static int excinfo(int irq, uintptr_t *regaddr, uint32_t *bit) +{ + *regaddr = NVIC_SYSHCON; + switch (irq) + { + case CXD32_IRQ_MEMFAULT: + *bit = NVIC_SYSHCON_MEMFAULTENA; + break; + + case CXD32_IRQ_BUSFAULT: + *bit = NVIC_SYSHCON_BUSFAULTENA; + break; + + case CXD32_IRQ_USAGEFAULT: + *bit = NVIC_SYSHCON_USGFAULTENA; + break; + + case CXD32_IRQ_SYSTICK: + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + break; + + default: + return ERROR; /* Invalid or unsupported exception */ + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + * + * Description: + * Complete initialization of the interrupt system and enable normal, + * interrupt processing. + * + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + + /* Disable all interrupts */ + + putreg32(0, NVIC_IRQ0_31_ENABLE); + putreg32(0, NVIC_IRQ32_63_ENABLE); + putreg32(0, NVIC_IRQ64_95_ENABLE); + putreg32(0, NVIC_IRQ96_127_ENABLE); + + /* Make sure that we are using the correct vector table. The default + * vector address is 0x0000:0000 but if we are executing code that is + * positioned in SRAM or in external FLASH, then we may need to reset + * the interrupt vector so that it refers to the table in SRAM or in + * external FLASH. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + arm_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(CXD32_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(CXD32_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO + /* up_prioritize_irq(CXD32_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); + */ + +#endif + +#ifdef CONFIG_ARMV7M_USEBASEPRI + cxd32_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); +#endif + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARM_MPU + irq_attach(CXD32_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(CXD32_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(CXD32_IRQ_NMI, cxd32_nmi, NULL); +# ifndef CONFIG_ARM_MPU + irq_attach(CXD32_IRQ_MEMFAULT, arm_memfault, NULL); +# endif + irq_attach(CXD32_IRQ_BUSFAULT, arm_busfault, NULL); + irq_attach(CXD32_IRQ_USAGEFAULT, arm_usagefault, NULL); + irq_attach(CXD32_IRQ_PENDSV, cxd32_pendsv, NULL); + arm_enable_dbgmonitor(); + irq_attach(CXD32_IRQ_DBGMONITOR, arm_dbgmonitor, NULL); + irq_attach(CXD32_IRQ_RESERVED, cxd32_reserved, NULL); +#endif + + cxd32_dumpnvic("initial", CXD32_IRQ_NIRQS); + + /* If a debugger is connected, try to prevent it from catching hardfaults. + * If CONFIG_ARMV7M_USEBASEPRI, no hardfaults are expected in normal + * operation. + */ + +#if defined(CONFIG_DEBUG_FEATURES) && !defined(CONFIG_ARMV7M_USEBASEPRI) + { + uint32_t regval; + + regval = getreg32(NVIC_DEMCR); + regval &= ~NVIC_DEMCR_VCHARDERR; + putreg32(regval, NVIC_DEMCR); + } +#endif + + /* And finally, enable interrupts */ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (irq >= CXD32_IRQ_EXTINT) + { + irqstate_t flags = spin_lock_irqsave(NULL); + irq -= CXD32_IRQ_EXTINT; + bit = 1 << (irq & 0x1f); + + regval = getreg32(INTC_EN(irq)); + regval &= ~bit; + putreg32(regval, INTC_EN(irq)); + spin_unlock_irqrestore(NULL, flags); + putreg32(bit, NVIC_IRQ_CLEAR(irq)); + } + else + { + if (excinfo(irq, ®addr, &bit) == OK) + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } + + cxd32_dumpnvic("disable", irq); +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (irq >= CXD32_IRQ_EXTINT) + { + irqstate_t flags = spin_lock_irqsave(NULL); + irq -= CXD32_IRQ_EXTINT; + bit = 1 << (irq & 0x1f); + + regval = getreg32(INTC_EN(irq)); + regval |= bit; + putreg32(regval, INTC_EN(irq)); + spin_unlock_irqrestore(NULL, flags); + putreg32(bit, NVIC_IRQ_ENABLE(irq)); + } + else + { + if (excinfo(irq, ®addr, &bit) == OK) + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } + + cxd32_dumpnvic("enable", irq); +} + +/**************************************************************************** + * Name: arm_ack_irq + * + * Description: + * Acknowledge the IRQ + * + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ +#ifdef CONFIG_ARCH_LEDS_CPU_ACTIVITY + board_autoled_on(LED_CPU); +#endif + + /* Check for external interrupt */ + + if (irq >= CXD32_IRQ_EXTINT) + { + irq -= CXD32_IRQ_EXTINT; + putreg32(1 << (irq & 0x1f), NVIC_IRQ_CLRPEND(irq)); + } +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= CXD32_IRQ_MEMFAULT && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < CXD32_IRQ_EXTINT) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= CXD32_IRQ_EXTINT; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + cxd32_dumpnvic("prioritize", irq); + return OK; +} +#endif diff --git a/arch/arm/src/cxd32xx/cxd32_serial.c b/arch/arm/src/cxd32xx/cxd32_serial.c new file mode 100644 index 00000000000..b36ccce9b27 --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_serial.c @@ -0,0 +1,998 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_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 + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "arm_internal.h" +#include "hardware/cxd32_uart.h" +#include "cxd32_config.h" +#include "cxd32_serial.h" +#include "cxd32_uart.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. + */ + +#if defined(USE_SERIALDRIVER) && defined(HAVE_UART) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct up_dev_s +{ + uintptr_t uartbase; /* Base address of UART registers */ + uint32_t basefreq; /* Base frequency of input clock */ + uint32_t baud; /* Configured baud */ + uint32_t ier; /* Saved IER value */ + uint8_t id; /* ID=0,1,2,3 */ + uint8_t irq; /* IRQ associated with this UART */ + 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 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* input flow control (RTS) enabled */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* output flow control (CTS) enabled */ +#endif +#ifdef HAVE_RS485 + bool dtrdir; /* DTR pin is the direction bit */ +#endif + void *pmhandle; + spinlock_t lock; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void up_set_format(struct uart_dev_s *dev); +#endif +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, unsigned int *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_CXD32_UART0 +static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE]; +static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE]; +#endif + +/* This describes the state of the CXD32xx uart0 port. */ + +#ifdef CONFIG_CXD32_UART0 +static struct up_dev_s g_uart0priv = +{ + .uartbase = CXD32_UART0_BASE, + .basefreq = CXD32_UART_BASEFREQ, + .baud = CONFIG_UART0_BAUD, + .id = 1, + .irq = CXD32_IRQ_UART0, + .parity = CONFIG_UART0_PARITY, + .bits = CONFIG_UART0_BITS, + .stopbits2 = CONFIG_UART0_2STOP, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .iflow = false, /* flow control is not supported */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + .oflow = false, /* flow control is not supported */ +#endif +}; + +static uart_dev_t g_uart0port = +{ + .recv = + { + .size = CONFIG_UART0_RXBUFSIZE, + .buffer = g_uart0rxbuffer, + }, + .xmit = + { + .size = CONFIG_UART0_TXBUFSIZE, + .buffer = g_uart0txbuffer, + }, + .ops = &g_uart_ops, + .priv = &g_uart0priv, +}; +# define TTYS0_DEV g_uart0port /* UART0=ttyS0 */ +#endif + +/* Which UART with be tty0/console and which tty1? tty2? tty3? */ + +#ifdef HAVE_CONSOLE +# if defined(CONFIG_UART0_SERIAL_CONSOLE) +# define CONSOLE_DEV g_uart0port /* UART0=console */ +# endif +#endif /* HAVE_CONSOLE */ + +/**************************************************************************** + * Inline 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_disableuartint + ****************************************************************************/ + +static inline void up_disableuartint(struct up_dev_s *priv, + uint32_t *ier) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + if (ier) + { + *ier = priv->ier & UART_INTR_ALL; + } + + priv->ier &= ~UART_INTR_ALL; + up_serialout(priv, CXD32_UART_IMSC, priv->ier); + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Name: up_restoreuartint + ****************************************************************************/ + +static inline void up_restoreuartint(struct up_dev_s *priv, uint32_t ier) +{ + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + priv->ier |= ier & UART_INTR_ALL; + up_serialout(priv, CXD32_UART_IMSC, priv->ier); + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Name: up_enablebreaks + ****************************************************************************/ + +static inline void up_enablebreaks(struct up_dev_s *priv, bool enable) +{ + uint32_t lcr = up_serialin(priv, CXD32_UART_LCR_H); + if (enable) + { + lcr |= UART_LCR_BRK; + } + else + { + lcr &= ~UART_LCR_BRK; + } + + up_serialout(priv, CXD32_UART_LCR_H, lcr); +} + +/**************************************************************************** + * Name: up_set_format + * + * Description: + * Set the serial line format and speed. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void up_set_format(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t lcr; + uint32_t cr; + uint32_t cr_en; + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + + /* Get the original state of control register */ + + cr = up_serialin(priv, CXD32_UART_CR); + cr_en = cr & UART_CR_EN; + cr &= ~UART_CR_EN; + + /* Disable until the format bits and baud rate registers are updated */ + + up_serialout(priv, CXD32_UART_CR, cr); + + /* Set the BAUD divisor */ + + cxd32_setbaud(priv->uartbase, priv->basefreq, priv->baud); + + /* Set up the LCR */ + + lcr = up_serialin(priv, CXD32_UART_LCR_H); + + lcr &= ~(UART_LCR_WLEN(8) | UART_LCR_STP2 | UART_LCR_EPS | UART_LCR_PEN); + + if ((5 <= priv->bits) && (priv->bits < 8)) + { + lcr |= UART_LCR_WLEN(priv->bits); + } + else + { + lcr |= UART_LCR_WLEN(8); + } + + if (priv->stopbits2) + { + lcr |= UART_LCR_STP2; + } + + if (priv->parity == 1) + { + lcr |= (UART_LCR_PEN); + } + else if (priv->parity == 2) + { + lcr |= (UART_LCR_PEN | UART_LCR_EPS); + } + + up_serialout(priv, CXD32_UART_LCR_H, lcr); + + /* CXD32 does not have CTS/RTS pin, so these are disbled */ + + cr &= ~(UART_CR_RTSEN | UART_CR_CTSEN); + up_serialout(priv, CXD32_UART_CR, cr | cr_en); + + spin_unlock_irqrestore(&priv->lock, flags); +} +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + +/**************************************************************************** + * Name: up_setup + * + * Description: + * Configure the UART baud, bits, parity, fifos, 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; + uint32_t lcr; + uint32_t cr; + + cxd32_uart_setup(priv->id); + + /* Init HW */ + + up_serialout(priv, CXD32_UART_CR, 0); + up_serialout(priv, CXD32_UART_LCR_H, 0); + up_serialout(priv, CXD32_UART_DMACR, 0); + up_serialout(priv, CXD32_UART_RSR_ECR, 0xf); + + /* Set up the IER */ + + priv->ier = up_serialin(priv, CXD32_UART_IMSC); + + /* Configure the UART line format and speed. */ + + up_set_format(dev); + + /* Set interrupt FIFO level */ + + up_serialout(priv, CXD32_UART_IFLS, 0); + + /* Clear all interrupts */ + + up_serialout(priv, CXD32_UART_ICR, 0x7ff); + + /* Enable FIFO and UART in the last */ + + lcr = up_serialin(priv, CXD32_UART_LCR_H); + lcr |= UART_LCR_FEN; + up_serialout(priv, CXD32_UART_LCR_H, lcr); + + cr = up_serialin(priv, CXD32_UART_CR); + cr |= UART_CR_RXE | UART_CR_TXE | UART_CR_EN; + up_serialout(priv, CXD32_UART_CR, cr); +#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 further interrupts from the UART */ + + up_disableuartint(priv, NULL); + + /* Put the UART hardware back its reset state */ + + switch (priv->id) + { + case 0: + case 1: + case 2: + break; + + default: + break; + } +} + +/**************************************************************************** + * 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 when 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 UART + */ + + 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; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: up_rxflowcontrol + * + * Description: + * Called when Rx buffer is full (or exceeds configured watermark levels + * if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined). + * Return true if UART activated RX flow control to block more incoming + * data + * + * Input parameters: + * dev - UART device instance + * nbuffered - the number of characters currently buffered + * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is + * not defined the value will be 0 for an empty buffer or the + * defined buffer size for a full buffer) + * upper - true indicates the upper watermark was crossed where + * false indicates the lower watermark has been crossed + * + * Returned Value: + * true if RX flow control activated. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool up_rxflowcontrol(struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ + up_rxint(dev, !upper); + return true; +} +#endif /* CONFIG_SERIAL_IFLOWCONTROL */ + +/**************************************************************************** + * Name: up_interrupt + * + * Description: + * This is the UART interrupt handler. It will be invoked when an + * interrupt is received on the 'irq'. It should call uart_xmitchars or + * uart_recvchars to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'arg' to the + * appropriate 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 status; + int passes; + + 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. + */ + + for (passes = 0; passes < 256; passes++) + { + /* Get the current UART status and check for loop + * termination conditions + */ + + status = up_serialin(priv, CXD32_UART_MIS); + if (status == 0) + { + return OK; + } + + up_serialout(priv, CXD32_UART_ICR, status); + if (status & UART_INTR_RI) + { + } + + if (status & UART_INTR_CTS) + { + } + + if (status & UART_INTR_DCD) + { + } + + if (status & UART_INTR_DSR) + { + } + + if (status & (UART_INTR_RX | UART_INTR_RT)) + { + uart_recvchars(dev); + } + + if (status & UART_INTR_TX) + { + uart_xmitchars(dev); + } + + if (status & UART_INTR_FE) + { + } + + if (status & UART_INTR_PE) + { + } + + if (status & UART_INTR_BE) + { + } + + if (status & UART_INTR_OE) + { + } + } + + 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) +{ + struct inode *inode = filep->f_inode; + struct uart_dev_s *dev = inode->i_private; + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + struct up_dev_s *user = (struct up_dev_s *)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct up_dev_s)); + } + } + break; +#endif + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + irqstate_t flags; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + flags = spin_lock_irqsave(&priv->lock); + + termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0) | +#ifdef CONFIG_SERIAL_OFLOWCONTROL + ((priv->oflow) ? CCTS_OFLOW : 0) | +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + ((priv->iflow) ? CRTS_IFLOW : 0) | +#endif + ((priv->stopbits2) ? CSTOPB : 0); + + cfsetispeed(termiosp, priv->baud); + + switch (priv->bits) + { + case 5: + termiosp->c_cflag |= CS5; + break; + + case 6: + termiosp->c_cflag |= CS6; + break; + + case 7: + termiosp->c_cflag |= CS7; + break; + + case 8: + default: + termiosp->c_cflag |= CS8; + break; + } + + spin_unlock_irqrestore(&priv->lock, flags); + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + irqstate_t flags; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + flags = spin_lock_irqsave(&priv->lock); + + switch (termiosp->c_cflag & CSIZE) + { + case CS5: + priv->bits = 5; + break; + + case CS6: + priv->bits = 6; + break; + + case CS7: + priv->bits = 7; + break; + + case CS8: + default: + priv->bits = 8; + break; + } + + if ((termiosp->c_cflag & PARENB) != 0) + { + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + priv->parity = 0; + } + + priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; +#endif + priv->baud = cfgetispeed(termiosp); + + spin_unlock_irqrestore(&priv->lock, flags); + + /* Configure the UART line format and speed. */ + + up_set_format(dev); + } + break; +#endif + + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags = spin_lock_irqsave(&priv->lock); + up_enablebreaks(priv, true); + spin_unlock_irqrestore(&priv->lock, flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + flags = spin_lock_irqsave(&priv->lock); + up_enablebreaks(priv, false); + spin_unlock_irqrestore(&priv->lock, flags); + } + break; + + case TCFLSH: /* Flush TX fifo etc. */ + { + while (!up_txempty(dev)); + } + break; + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * 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, unsigned int *status) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t rbr; + + rbr = up_serialin(priv, CXD32_UART_DR); + *status = rbr & 0xf00; + return rbr & 0xff; +} + +/**************************************************************************** + * 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; + irqstate_t flags; + + flags = spin_lock_irqsave(&priv->lock); + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ier |= (UART_INTR_RX | UART_INTR_RT); +#endif + } + else + { + priv->ier &= ~(UART_INTR_RX | UART_INTR_RT); + } + + up_serialout(priv, CXD32_UART_IMSC, priv->ier); + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Name: up_rxavailable + * + * Description: + * Return true if the receive fifo is not empty + * + ****************************************************************************/ + +static bool up_rxavailable(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + return ((up_serialin(priv, CXD32_UART_FR) & UART_FLAG_RXFE) == 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, CXD32_UART_DR, (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 = spin_lock_irqsave(&priv->lock); + if (enable) + { +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + priv->ier |= UART_INTR_TX; + up_serialout(priv, CXD32_UART_IMSC, priv->ier); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + +# ifdef CONFIG_SMP + spin_unlock_irqrestore(&priv->lock, flags); +# endif + uart_xmitchars(dev); +# ifdef CONFIG_SMP + flags = spin_lock_irqsave(&priv->lock); +# endif +#endif + } + else + { + priv->ier &= ~UART_INTR_TX; + up_serialout(priv, CXD32_UART_IMSC, priv->ier); + } + + spin_unlock_irqrestore(&priv->lock, flags); +} + +/**************************************************************************** + * Name: up_txready + * + * Description: + * Return true if the tranmsit fifo is not full + * + ****************************************************************************/ + +static bool up_txready(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + return ((up_serialin(priv, CXD32_UART_FR) & UART_FLAG_TXFF) == 0); +} + +/**************************************************************************** + * Name: up_txempty + * + * Description: + * Return true if the transmit fifo is empty + * + ****************************************************************************/ + +static bool up_txempty(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s *)dev->priv; + uint32_t rbr = 0; + rbr = up_serialin(priv, CXD32_UART_FR); + return (((rbr & UART_FLAG_TXFE) != 0) && ((rbr & UART_FLAG_BUSY) == 0)); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_serialinit + * + * 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 arm_serialinit. + * + * NOTE: Configuration of the CONSOLE UART was performed by up_lowsetup() + * very early in the boot sequence. + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void arm_earlyserialinit(void) +{ + /* Configuration whichever one is the console */ + +# ifdef CONSOLE_DEV + CONSOLE_DEV.isconsole = true; + up_setup(&CONSOLE_DEV); +# endif +} +#endif + +/**************************************************************************** + * Name: arm_serialinit + * + * Description: + * Register serial console and serial ports. This assumes that + * arm_earlyserialinit was called previously. + * + ****************************************************************************/ + +void arm_serialinit(void) +{ +#ifdef CONSOLE_DEV + uart_register("/dev/console", &CONSOLE_DEV); +#endif +#ifdef TTYS0_DEV + uart_register("/dev/ttyS0", &TTYS0_DEV); +#endif +} + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#ifdef HAVE_CONSOLE + struct up_dev_s *priv = (struct up_dev_s *)CONSOLE_DEV.priv; + uint32_t ier; + up_disableuartint(priv, &ier); +#endif + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); +#ifdef HAVE_CONSOLE + up_restoreuartint(priv, ier); +#endif + + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm/src/cxd32xx/cxd32_serial.h b/arch/arm/src/cxd32xx/cxd32_serial.h new file mode 100644 index 00000000000..6d93f83b39b --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_serial.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_serial.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_ARM_SRC_CXD32XX_CXD32_SERIAL_H +#define __ARCH_ARM_SRC_CXD32XX_CXD32_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_CXD32XX_CXD32_SERIAL_H */ diff --git a/arch/arm/src/cxd32xx/cxd32_serial_pl011.c b/arch/arm/src/cxd32xx/cxd32_serial_pl011.c new file mode 100644 index 00000000000..5801f59624f --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_serial_pl011.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * arch/arm/src/cxd32xx/cxd32_serial_pl011.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 "arm_internal.h" + +#ifdef USE_SERIALDRIVER + +/*************************************************************************** + * Public Functions + ***************************************************************************/ + +/*************************************************************************** + * Name: arm_earlyserialinit + * + * Description: + * see arm_internal.h + * + ***************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void arm_earlyserialinit(void) +{ + /* Enable the console UART. The other UARTs will be initialized if and + * when they are first opened. + */ + + pl011_earlyserialinit(); +} +#endif + +/*************************************************************************** + * Name: arm_serialinit + * + * Description: + * see arm_internal.h + * + ***************************************************************************/ + +void arm_serialinit(void) +{ + pl011_serialinit(); +} + +#ifdef CONFIG_UART_PL011_PLATFORMIF +/*************************************************************************** + * Name: pl011_platform interface + * + * Description: + * see drivers/serial/serial_pl011.c + * pl011_setup + * pl011_shutdown + * + ***************************************************************************/ + +int pl011_platform_setup(uint32_t base) +{ + /* If needed, implement platform specific process such as enabling pl011 + * to reduce power consumption. + */ + + return 0; +} + +int pl011_platform_shutdown(uint32_t base) +{ + /* If needed, implement platform specific process such as disabling pl011 + * to reduce power consumption. + */ + + return 0; +} +#endif /* CONFIG_UART_PL011_PLATFORMIF */ +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm/src/cxd32xx/cxd32_start.c b/arch/arm/src/cxd32xx/cxd32_start.c new file mode 100644 index 00000000000..db6341e2615 --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_start.c @@ -0,0 +1,177 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_start.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 "chip.h" +#include "arm_internal.h" +#include "init/init.h" + +#include "cxd32_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) arm_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* _sbss is the start of the BSS region (see the linker script) _ebss is the + * end of the BSS region (see the linker script). The idle task stack starts + * at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE + * thread is the thread that the system boots on and, eventually, becomes the + * idle, do nothing task that runs only when there is nothing else to run. + * The heap continues from there until the configured end of memory. + * g_idle_topstack is the beginning of this heap region (not necessarily + * aligned). + */ + +const uintptr_t g_idle_topstack = (uintptr_t)_ebss + + CONFIG_IDLETHREAD_STACKSIZE; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: __start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +void __start(void) __attribute__((section(".entry"))); +void __start(void) +{ + const uint32_t *src; + uint32_t *dest; + + /* Set MSP/PSP to IDLE stack */ + + __asm__ __volatile__("\tmsr msp, %0\n" : + : "r" (_ebss + CONFIG_IDLETHREAD_STACKSIZE)); + __asm__ __volatile__("\tmsr psp, %0\n" : + : "r" (_ebss + CONFIG_IDLETHREAD_STACKSIZE)); + + up_irq_disable(); + + cxd32_lowsetup(); + 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 = (uint32_t *)_sbss; dest < (uint32_t *)_ebss; ) + { + *dest++ = 0; + } + + showprogress('B'); + + /* Move the initialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = (const uint32_t *)_eronly, + dest = (uint32_t *)_sdata; dest < (uint32_t *)_edata; + ) + { + *dest++ = *src++; + } + + showprogress('C'); + + /* Initialize the FPU (if configured) */ + + arm_fpuconfig(); + + showprogress('D'); + +#ifdef CONFIG_ARMV7M_ITMSYSLOG + /* Perform ARMv7-M ITM SYSLOG initialization */ + + itm_syslog_initialize(); +#endif + + /* Perform early serial initialization */ + +#ifdef USE_EARLYSERIALINIT + arm_earlyserialinit(); +#endif + showprogress('E'); + + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + +#ifdef CONFIG_BUILD_PROTECTED + showprogress('F'); +#endif + + /* Initialize onboard resources */ + + cxd32_boardinitialize(); + showprogress('G'); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + + nx_start(); + + /* Shouldn't get here */ + + for (; ; ); +} diff --git a/arch/arm/src/cxd32xx/cxd32_timerisr.c b/arch/arm/src/cxd32xx/cxd32_timerisr.c new file mode 100644 index 00000000000..799f25a9bdc --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_timerisr.c @@ -0,0 +1,171 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_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 "clock/clock.h" +#include "arm_internal.h" +#include "hardware/cxd32_timer.h" + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The desired timer interrupt frequency is provided by the definition + * CLK_TCK (see include/time.h). CLK_TCK defines the desired number of + * system clock ticks per second. That value is a user configurable setting + * that defaults to 100 (100 ticks per second = 10 MS interval). + * + * The Clock Source: Either the internal CCLK or external STCLK (P3.26) clock + * as the source in the STCTRL register. This file alwyays configures the + * timer to use CCLK as its source. + */ + +#define TICK_RELOAD ((CXD32_TIMER_BASEFREQ / CLK_TCK) - 1) + +/* The size of the reload field is 24 bits. Verify taht the reload value + * will fit in the reload register. + */ + +#if TICK_RELOAD > 0x00ffffff +# error TICK_RELOAD exceeds the range of the RELOAD register +#endif + +#define TIMER4_CH0 (CXD32_TIMER4_BASE+CXD32_TIMER_CH0_OFFSET) +#define TIMER4_CH1 (CXD32_TIMER4_BASE+CXD32_TIMER_CH1_OFFSET) +#define TIMER4_CH1_INITVALUE 0xFFFFFFFF + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: cxd32_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int cxd32_timerisr(int irq, uint32_t *regs, void *arg) +{ + /* Process timer interrupt */ + + putreg32(TIMER_INTERRUPT, TIMER4_CH0 + CXD32_TIMER_INTCLR); + + nxsched_process_timer(); + + return 0; +} + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +static void cxd32_timer0_initialize(void) +{ + uint32_t ctrl; + + /* Configure Tick to interrupt at the requested rate */ + + putreg32(TICK_RELOAD, TIMER4_CH0 + CXD32_TIMER_LOAD); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(CXD32_IRQ_TIM41, (xcpt_t)cxd32_timerisr, NULL); + + /* Enable Timer */ + + ctrl = (TIMERCTRL_ENABLE | TIMERCTRL_DIV_1 | + TIMERCTRL_SIZE_32BIT | TIMERCTRL_MODE_WRAP); + ctrl |= (TIMERCTRL_PERIODIC | TIMERCTRL_INTENABLE); + + putreg32(ctrl, TIMER4_CH0 + CXD32_TIMER_CONTROL); + + /* And enable the timer interrupt */ + + up_enable_irq(CXD32_IRQ_TIM41); +} + +static void cxd32_timer1_initialize(void) +{ + uint32_t ctrl; + + /* Configure the coutner */ + + putreg32(TIMER4_CH1_INITVALUE, TIMER4_CH1 + CXD32_TIMER_LOAD); + + /* Enable Timer */ + + ctrl = (TIMERCTRL_ENABLE | TIMERCTRL_DIV_1 | + TIMERCTRL_SIZE_32BIT | TIMERCTRL_MODE_WRAP); + ctrl |= (TIMERCTRL_PERIODIC); + + putreg32(ctrl, TIMER4_CH1 + CXD32_TIMER_CONTROL); +} + +void up_timer_initialize(void) +{ + cxd32_timer0_initialize(); + cxd32_timer1_initialize(); +} + +/**************************************************************************** + * Function: cxd32_timerget + * + * Description: + * This function returns the count of timer. + * + ****************************************************************************/ + +uint32_t cxd32_timerget(void) +{ + return getreg32(TIMER4_CH1 + CXD32_TIMER_VALUE); +} diff --git a/arch/arm/src/cxd32xx/cxd32_uart.c b/arch/arm/src/cxd32xx/cxd32_uart.c new file mode 100644 index 00000000000..2a185a21866 --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_uart.c @@ -0,0 +1,289 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_uart.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 "arm_internal.h" +#include "chip.h" +#include "cxd32_config.h" +#include "cxd32_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Select UART parameters for the selected console */ + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) + #define CONSOLE_BASE CXD32_UART0_BASE + #define CONSOLE_BASEFREQ CXD32_UART_BASEFREQ + #define CONSOLE_BAUD CONFIG_UART0_BAUD + #define CONSOLE_BITS CONFIG_UART0_BITS + #define CONSOLE_PARITY CONFIG_UART0_PARITY + #define CONSOLE_2STOP CONFIG_UART0_2STOP +#elif defined(HAVE_CONSOLE) + #error "No CONFIG_UARTn_SERIAL_CONSOLE Setting" +#endif + +/* Get word length setting for the console */ + +#if CONSOLE_BITS >= 5 && CONSOLE_BITS <= 8 + #define CONSOLE_LCR_WLS UART_LCR_WLEN(CONSOLE_BITS) +#elif defined(HAVE_CONSOLE) + #error "Invalid CONFIG_UARTn_BITS setting for console " +#endif + +/* Get parity setting for the console */ + +#if CONSOLE_PARITY == 0 + #define CONSOLE_LCR_PAR 0 +#elif CONSOLE_PARITY == 1 + #define CONSOLE_LCR_PAR (UART_LCR_PEN) +#elif CONSOLE_PARITY == 2 + #define CONSOLE_LCR_PAR (UART_LCR_PEN | UART_LCR_EPS) +#elif CONSOLE_PARITY == 3 + #define CONSOLE_LCR_PAR (UART_LCR_PEN | UART_LCR_SPS) +#elif CONSOLE_PARITY == 4 + #define CONSOLE_LCR_PAR (UART_LCR_PEN | UART_LCR_EPS | UART_LCR_SPS) +#elif defined(HAVE_CONSOLE) + #error "Invalid CONFIG_UARTn_PARITY setting for CONSOLE" +#endif + +/* Get stop-bit setting for the console and UART0/1/2 */ + +#if CONSOLE_2STOP != 0 + #define CONSOLE_LCR_STOP UART_LCR_STP2 +#else + #define CONSOLE_LCR_STOP 0 +#endif + +/* LCR and FCR values for the console */ + +#define CONSOLE_LCR_VALUE (CONSOLE_LCR_WLS | CONSOLE_LCR_PAR | CONSOLE_LCR_STOP) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct uartdev +{ + uintptr_t uartbase; /* Base address of UART registers */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct uartdev g_uartdevs[] = +{ + { + CXD32_UART0_BASE + }, + { + CXD32_UART1_BASE + }, + { + CXD32_UART2_BASE + } +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void arm_lowputc(char ch) +{ +#if defined HAVE_UART && defined HAVE_CONSOLE + /* Wait for the transmitter to be available */ + + while ((getreg32(CONSOLE_BASE + CXD32_UART_FR) & UART_FLAG_TXFF)); + + /* Send the character */ + + putreg32((uint32_t)ch, CONSOLE_BASE + CXD32_UART_DR); +#endif +} + +/**************************************************************************** + * Name: cxd32_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level + * initialization of the serial console. + * + ****************************************************************************/ + +void cxd32_lowsetup(void) +{ +#ifdef HAVE_UART + /* Enable clocking and for all console UART and disable power for + * other UARTs + */ + + /* Configure the console (only) */ + +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + { + uint32_t val; + val = getreg32(CONSOLE_BASE + CXD32_UART_CR); + if (val & UART_CR_EN) + { + return; + } + } + +#if defined(CONFIG_UART0_SERIAL_CONSOLE) + cxd32_uart_setup(0); + cxd32_uart_initialize(0); + + putreg32(CONSOLE_LCR_VALUE, CONSOLE_BASE + CXD32_UART_LCR_H); + cxd32_setbaud(CONSOLE_BASE, CONSOLE_BASEFREQ, CONSOLE_BAUD); + putreg32(0, CONSOLE_BASE + CXD32_UART_IFLS); + putreg32(UART_INTR_ALL, CONSOLE_BASE + CXD32_UART_ICR); +#endif + +#endif +#endif +} + +/**************************************************************************** + * Name: cxd32_uart_reset + * + * Description: + * Reset a UART. This function is used by the serial driver when a + * UART is closed. + * + ****************************************************************************/ + +void cxd32_uart_reset(int ch) +{ + /* XXX: disabling uart controller */ +} + +/**************************************************************************** + * Name: cxd32_uart_setup + * + ****************************************************************************/ + +void cxd32_uart_setup(int ch) +{ + /* XXX: enabling uart contrller */ +} + +/**************************************************************************** + * Name: cxd32_uart_initialize + * + * Description: + * Various initial registration + * + ****************************************************************************/ + +void cxd32_uart_initialize(int ch) +{ + uint32_t regval; + + regval = 0x00000000; + + /* disable Control register */ + + putreg32(regval, g_uartdevs[ch].uartbase + CXD32_UART_CR); + + /* init IrDA low-power counter register */ + + putreg32(regval, g_uartdevs[ch].uartbase + CXD32_UART_ILPR); + + /* init Integer baud rate register */ + + putreg32(regval, g_uartdevs[ch].uartbase + CXD32_UART_IBRD); + + /* init Fractional baud rate register */ + + putreg32(regval, g_uartdevs[ch].uartbase + CXD32_UART_FBRD); + + /* init DMA control register */ + + putreg32(regval, g_uartdevs[ch].uartbase + CXD32_UART_DMACR); +} + +/**************************************************************************** + * Name: cxd32_setbaud + * + ****************************************************************************/ + +#define DIV_MASK 0x000000FF +#define FBRD_MASK 0x3F + +void cxd32_setbaud(uintptr_t uartbase, uint32_t basefreq, uint32_t baud) +{ + uint64_t div; + uint32_t ibrd; + uint32_t fbrd; + uint32_t lcr_h; + + irqstate_t flags = spin_lock_irqsave(NULL); + + div = (uint64_t)(basefreq); + div *= (uint64_t)(256); + div /= (uint64_t)(16); + div /= (uint64_t)(baud); + ibrd = (uint32_t)(div >> 8); + fbrd = (uint32_t)(((div & DIV_MASK) * 64 + 0x80) / 256); + + putreg32(ibrd + (fbrd >> 6), uartbase + CXD32_UART_IBRD); + putreg32(fbrd & FBRD_MASK, uartbase + CXD32_UART_FBRD); + + /* Baud rate is updated by writing to LCR_H. */ + + lcr_h = getreg32(uartbase + CXD32_UART_LCR_H); + putreg32(lcr_h, uartbase + CXD32_UART_LCR_H); + + spin_unlock_irqrestore(NULL, flags); +} diff --git a/arch/arm/src/cxd32xx/cxd32_uart.h b/arch/arm/src/cxd32xx/cxd32_uart.h new file mode 100644 index 00000000000..70a6a57e7d8 --- /dev/null +++ b/arch/arm/src/cxd32xx/cxd32_uart.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/cxd32_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_ARM_SRC_CXD32XX_CXD32_UART_H +#define __ARCH_ARM_SRC_CXD32XX_CXD32_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" +#include "hardware/cxd32_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: cxd32_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level + * initialization of the serial console. + * + ****************************************************************************/ + +void cxd32_lowsetup(void); + +/**************************************************************************** + * Name: cxd32_uart_reset + * + * Description: + * Reset a UART. This function is used by the serial driver when a + * UART is closed. + * + ****************************************************************************/ + +void cxd32_uart_reset(int ch); + +/**************************************************************************** + * Name: cxd32_uart_setup + * + * Description: + * Configure the UART. This involves: + * + * 1. Connecting the input clock to the UART as specified in the + * board.h file, + * 2. Configuring the UART pins + * + ****************************************************************************/ + +void cxd32_uart_setup(int); + +/**************************************************************************** + * Name: cxd32_setbaud + * + * Description: + * Configure the UART divisors to accomplish the desired BAUD given the + * UART base frequency. + * + ****************************************************************************/ + +void cxd32_setbaud(uintptr_t uartbase, uint32_t basefreq, uint32_t baud); + +/**************************************************************************** + * Name: cxd32_uart_initialize + * + * Description: + * Various initial registration + * + ****************************************************************************/ + +void cxd32_uart_initialize(int ch); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_CXD32XX_CXD32_UART_H */ diff --git a/arch/arm/src/cxd32xx/hardware/cxd3277_clockfreq.h b/arch/arm/src/cxd32xx/hardware/cxd3277_clockfreq.h new file mode 100644 index 00000000000..1d87f09b5b2 --- /dev/null +++ b/arch/arm/src/cxd32xx/hardware/cxd3277_clockfreq.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/hardware/cxd3277_clockfreq.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_ARM_SRC_CXD32XX_HARDWARE_CXD3277_CLOCKFREQ_H +#define __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD3277_CLOCKFREQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CXD32_TIMER_BASEFREQ (8*1000*1000) +#define CXD32_UART_BASEFREQ (32*1000*1000) + +#endif /* __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD3277_CLOCKFREQ_H */ diff --git a/arch/arm/src/cxd32xx/hardware/cxd3277_memorymap.h b/arch/arm/src/cxd32xx/hardware/cxd3277_memorymap.h new file mode 100644 index 00000000000..3a1c498210e --- /dev/null +++ b/arch/arm/src/cxd32xx/hardware/cxd3277_memorymap.h @@ -0,0 +1,46 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/hardware/cxd3277_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_ARM_SRC_CXD32XX_HARDWARE_CXD3277_MEMORYMAP_H +#define __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD3277_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CXD32_UART0_BASE (0x42100000+0x4000) +#define CXD32_UART1_BASE (0x42100000+0x5000) +#define CXD32_UART2_BASE (0x42100000+0x6000) + +#define CXD32_TIMER0_BASE (0x42200000+0x2000) +#define CXD32_TIMER1_BASE (0x42200000+0x3000) +#define CXD32_TIMER2_BASE (0x42200000+0x4000) +#define CXD32_TIMER3_BASE (0x42200000+0x5000) +#define CXD32_TIMER4_BASE (0x42200000+0x6000) + +#define CXD32_INTC_BASE 0xe0045000 + +#endif /* __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD3277_MEMORYMAP_H */ diff --git a/arch/arm/src/cxd32xx/hardware/cxd32_timer.h b/arch/arm/src/cxd32xx/hardware/cxd32_timer.h new file mode 100644 index 00000000000..f747fedfe57 --- /dev/null +++ b/arch/arm/src/cxd32xx/hardware/cxd32_timer.h @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/hardware/cxd32_timer.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_ARM_SRC_CXD32XX_HARDWARE_CXD32_TIMER_H +#define __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD32_TIMER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register addresses */ + +#define CXD32_TIMER_LOAD (0x0000) /* Load register */ +#define CXD32_TIMER_VALUE (0x0004) /* Value register [RO] */ +#define CXD32_TIMER_CONTROL (0x0008) /* Control register */ +#define CXD32_TIMER_INTCLR (0x000C) /* Clear Interrupt register [WO] */ +#define CXD32_TIMER_RIS (0x0010) /* Raw Interrupt Status register [RO] */ +#define CXD32_TIMER_MIS (0x0014) /* Interrupt Status register [RO] */ +#define CXD32_TIMER_BGLOAD (0x0018) /* Backround Load register [RO] */ +#define CXD32_TIMER_ITCR (0x0F00) /* Integration Test Control register */ +#define CXD32_TIMER_ITOP (0x0F04) /* Integration Test Output register [WO] */ +#define CXD32_TIMER_PERIPHID0 (0x0FE0) /* Peripheral ID0 register [RO] */ +#define CXD32_TIMER_PERIPHID1 (0x0FE4) /* Peripheral ID1 register [RO] */ +#define CXD32_TIMER_PERIPHID2 (0x0FE8) /* Peripheral ID2 register [RO] */ +#define CXD32_TIMER_PERIPHID3 (0x0FFC) /* Peripheral ID3 register [RO] */ +#define CXD32_TIMER_PCELLID0 (0x0FF0) /* PrimeCell ID0 register [RO] */ +#define CXD32_TIMER_PCELLID1 (0x0FF4) /* PrimeCell ID1 register [RO] */ +#define CXD32_TIMER_PCELLID2 (0x0FF8) /* PrimeCell ID2 register [RO] */ +#define CXD32_TIMER_PCELLID3 (0x0FFC) /* PrimeCell ID3 register [RO] */ + +#define CXD32_TIMER_CH0_OFFSET (0x00000000)/* CHANNEL0 offset */ +#define CXD32_TIMER_CH1_OFFSET (0x00000020)/* CHANNEL1 offset */ + +/* Register bit definitions */ + +/* Control Register */ + +#define TIMERCTRL_ENABLE (0x1u << 7) +#define TIMERCTRL_DISABLE (0x0u << 7) +#define TIMERCTRL_PERIODIC (0x1u << 6) +#define TIMERCTRL_FREERUN (0x0u << 6) +#define TIMERCTRL_INTENABLE (0x1u << 5) +#define TIMERCTRL_INTDISABLE (0x0u << 5) +#define TIMERCTRL_DIV_256 (0x2u << 2) +#define TIMERCTRL_DIV_16 (0x1u << 2) +#define TIMERCTRL_DIV_1 (0x0u << 2) +#define TIMERCTRL_SIZE_32BIT (0x1u << 1) +#define TIMERCTRL_SIZE_16BIT (0x0u << 1) +#define TIMERCTRL_MODE_ONESHOT (0x1u << 0) +#define TIMERCTRL_MODE_WRAP (0x0u << 0) + +/* Interrupt Register */ + +#define TIMER_INTERRUPT (0x1u << 0) + +/* Integration Test Control register */ + +#define TIMERITCR_ENABLE (0x1u << 0) + +/* Integration Test Output register */ + +#define TIMERITOP_TIMINT1 (0x1u << 0) +#define TIMERITOP_TIMINT2 (0x1u << 1) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD32_TIMER_H */ diff --git a/arch/arm/src/cxd32xx/hardware/cxd32_uart.h b/arch/arm/src/cxd32xx/hardware/cxd32_uart.h new file mode 100644 index 00000000000..3f6e7e95e86 --- /dev/null +++ b/arch/arm/src/cxd32xx/hardware/cxd32_uart.h @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/arm/src/cxd32xx/hardware/cxd32_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_ARM_SRC_CXD32XX_HARDWARE_CXD32_UART_H +#define __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD32_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register offsets *********************************************************/ + +/* Common Register Offsets */ + +#define CXD32_UART_DR 0x000 /* Data register */ +#define CXD32_UART_RSR_ECR 0x004 /* Receive status/error clear register */ +#define CXD32_UART_FR 0x018 /* Flag register */ +#define CXD32_UART_ILPR 0x020 /* IrDA low-power counter register */ +#define CXD32_UART_IBRD 0x024 /* Integer baud rate register */ +#define CXD32_UART_FBRD 0x028 /* Fractional baud rate register */ +#define CXD32_UART_LCR_H 0x02c /* Line control register */ +#define CXD32_UART_CR 0x030 /* Control register */ +#define CXD32_UART_IFLS 0x034 /* Interrupt FIFO level select register */ +#define CXD32_UART_IMSC 0x038 /* Interrupt mask set/clear register */ +#define CXD32_UART_RIS 0x03c /* Raw Interrupt status register */ +#define CXD32_UART_MIS 0x040 /* Masked interrupt status register */ +#define CXD32_UART_ICR 0x044 /* Interrupt clear register */ +#define CXD32_UART_DMACR 0x048 /* DMA control register */ + +#define UART_FR_RI (0x1 << 8) +#define UART_FR_TXFE (0x1 << 7) +#define UART_FR_RXFF (0x1 << 6) +#define UART_FR_TXFF (0x1 << 5) +#define UART_FR_RXFE (0x1 << 4) +#define UART_FR_BUSY (0x1 << 3) +#define UART_FR_DCD (0x1 << 2) +#define UART_FR_DSR (0x1 << 1) +#define UART_FR_CTS (0x1 << 0) + +#define UART_LCR_SPS (1u << 7) +#define UART_LCR_WLEN(x) ((((x)-5)&3)<<5) +#define UART_LCR_FEN (1u << 4) +#define UART_LCR_STP2 (1u << 3) +#define UART_LCR_EPS (1u << 2) +#define UART_LCR_PEN (1u << 1) +#define UART_LCR_BRK (1u << 0) + +#define UART_CR_CTSEN (1u << 15) +#define UART_CR_RTSEN (1u << 14) +#define UART_CR_OUT2 (1u << 13) +#define UART_CR_OUT1 (1u << 12) +#define UART_CR_RTS (1u << 11) +#define UART_CR_DTR (1u << 10) +#define UART_CR_RXE (1u << 9) +#define UART_CR_TXE (1u << 8) +#define UART_CR_LBE (1u << 7) +#define UART_CR_SIRLP (1u << 2) +#define UART_CR_SIREN (1u << 1) +#define UART_CR_EN (1u << 0) + +#define UART_INTR_RI (1u << 0) /* nUARTRI modem interrupt */ +#define UART_INTR_CTS (1u << 1) /* nUARTCTS modem interrupt */ +#define UART_INTR_DCD (1u << 2) /* nUARTDCD modem interrupt */ +#define UART_INTR_DSR (1u << 3) /* nUARTDSR modem interrupt */ +#define UART_INTR_RX (1u << 4) /* Receive interrupt */ +#define UART_INTR_TX (1u << 5) /* Transmit interrupt */ +#define UART_INTR_RT (1u << 6) /* Receive timeout interrupt */ +#define UART_INTR_FE (1u << 7) /* Framing error interrupt */ +#define UART_INTR_PE (1u << 8) /* Parity error interrupt */ +#define UART_INTR_BE (1u << 9) /* Break error interrupt */ +#define UART_INTR_OE (1u << 10) /* Overrun error interrupt */ +#define UART_INTR_ALL (0x7ff) /* All of interrupts */ + +#define UART_FLAG_RI (1u << 8) /* Ring indicator */ +#define UART_FLAG_TXFE (1u << 7) /* Transmit FIFO empty */ +#define UART_FLAG_RXFF (1u << 6) /* Receive FIFO full */ +#define UART_FLAG_TXFF (1u << 5) /* Transmit FIFO full */ +#define UART_FLAG_RXFE (1u << 4) /* Receive FIFO empty */ +#define UART_FLAG_BUSY (1u << 3) /* UART busy */ +#define UART_FLAG_DCD (1u << 2) /* Data carrier detect */ +#define UART_FLAG_DSR (1u << 1) /* Data set ready */ +#define UART_FLAG_CTS (1u << 0) /* Cleart to send */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_CXD32XX_HARDWARE_CXD32_UART_H */