From b78323deb2b3658d2e93c651cc2026c398289bfd Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 13 May 2009 14:29:22 +0000 Subject: lm3s6918 update git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1775 7fd9a85b-ad96-42d3-883c-3090e2eb8679 --- nuttx/arch/arm/include/irq.h | 194 +--------------------- nuttx/arch/arm/include/irq_arm.h | 229 ++++++++++++++++++++++++++ nuttx/arch/arm/include/irq_thumb2.h | 210 ++++++++++++++++++++++++ nuttx/arch/arm/src/common/arm.h | 12 +- nuttx/arch/arm/src/common/cortexm3_psr.h | 91 +++++++++++ nuttx/arch/arm/src/common/up_assert.c | 5 + nuttx/arch/arm/src/common/up_doirq.c | 12 +- nuttx/arch/arm/src/common/up_internal.h | 4 +- nuttx/arch/arm/src/lm3s/chip.h | 30 ---- nuttx/arch/arm/src/lm3s/lm3s_ethernet.c | 2 + nuttx/arch/arm/src/lm3s/lm3s_gpio.h | 143 ----------------- nuttx/arch/arm/src/lm3s/lm3s_internal.h | 257 ++++++++++++++++++++++++++++++ nuttx/arch/arm/src/lm3s/lm3s_irq.c | 3 +- nuttx/arch/arm/src/lm3s/lm3s_lowputc.c | 1 + nuttx/arch/arm/src/lm3s/lm3s_start.c | 1 + nuttx/arch/arm/src/lm3s/lm3s_syscontrol.c | 1 + nuttx/arch/arm/src/lm3s/lm3s_syscontrol.h | 39 ----- nuttx/arch/arm/src/lm3s/lm3s_timerisr.c | 1 + nuttx/arch/arm/src/lm3s/lm3s_vectors.S | 98 +++++++++++- 19 files changed, 919 insertions(+), 414 deletions(-) create mode 100644 nuttx/arch/arm/include/irq_arm.h create mode 100644 nuttx/arch/arm/include/irq_thumb2.h create mode 100644 nuttx/arch/arm/src/common/cortexm3_psr.h create mode 100644 nuttx/arch/arm/src/lm3s/lm3s_internal.h (limited to 'nuttx/arch') diff --git a/nuttx/arch/arm/include/irq.h b/nuttx/arch/arm/include/irq.h index b2cd3d9c05..1d2c3e1225 100644 --- a/nuttx/arch/arm/include/irq.h +++ b/nuttx/arch/arm/include/irq.h @@ -47,206 +47,24 @@ #include #include +#ifdef __thumb2__ +# include +#else +# include +#endif + /**************************************************************************** * Definitions ****************************************************************************/ -/* IRQ Stack Frame Format: - * - * Context is always saved/restored in the same way: - * - * (1) stmia rx, {r0-r14} - * (2) then the PC and CPSR - * - * This results in the following set of indices that - * can be used to access individual registers in the - * xcp.regs array: - */ - -#define REG_R0 (0) -#define REG_R1 (1) -#define REG_R2 (2) -#define REG_R3 (3) -#define REG_R4 (4) -#define REG_R5 (5) -#define REG_R6 (6) -#define REG_R7 (7) -#define REG_R8 (8) -#define REG_R9 (9) -#define REG_R10 (10) -#define REG_R11 (11) -#define REG_R12 (12) -#define REG_R13 (13) -#define REG_R14 (14) -#define REG_R15 (15) -#define REG_CPSR (16) - -#define XCPTCONTEXT_REGS (17) -#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) - -#define REG_A1 REG_R0 -#define REG_A2 REG_R1 -#define REG_A3 REG_R2 -#define REG_A4 REG_R3 -#define REG_V1 REG_R4 -#define REG_V2 REG_R5 -#define REG_V3 REG_R6 -#define REG_V4 REG_R7 -#define REG_V5 REG_R8 -#define REG_V6 REG_R9 -#define REG_V7 REG_R10 -#define REG_SB REG_R9 -#define REG_SL REG_R10 -#define REG_FP REG_R11 -#define REG_IP REG_R12 -#define REG_SP REG_R13 -#define REG_LR REG_R14 -#define REG_PC REG_R15 - /**************************************************************************** * Public Types ****************************************************************************/ -/* This struct defines the way the registers are stored. We - * need to save: - * - * 1 CPSR - * 7 Static registers, v1-v7 (aka r4-r10) - * 1 Frame pointer, fp (aka r11) - * 1 Stack pointer, sp (aka r13) - * 1 Return address, lr (aka r14) - * --- - * 11 (XCPTCONTEXT_USER_REG) - * - * On interrupts, we also need to save: - * 4 Volatile registers, a1-a4 (aka r0-r3) - * 1 Scratch Register, ip (aka r12) - *--- - * 5 (XCPTCONTEXT_IRQ_REGS) - * - * For a total of 17 (XCPTCONTEXT_REGS) - */ - -#ifndef __ASSEMBLY__ -struct xcptcontext -{ - /* The following function pointer is non-zero if there - * are pending signals to be processed. - */ - -#ifndef CONFIG_DISABLE_SIGNALS - void *sigdeliver; /* Actual type is sig_deliver_t */ - - /* These are saved copies of LR and CPSR used during - * signal processing. - */ - - uint32 saved_pc; - uint32 saved_cpsr; -#endif - - /* Register save area */ - - uint32 regs[XCPTCONTEXT_REGS]; -}; -#endif - /**************************************************************************** * Inline functions ****************************************************************************/ -#ifndef __ASSEMBLY__ - -#ifdef __thumb2__ - -/* Save the current interrupt enable state & disable IRQs */ - -static inline irqstate_t irqsave(void) -{ - unsigned short primask; - - /* Return the the current value of primask register and set - * bit 0 of the primask register to disable interrupts - */ - - __asm__ __volatile__ - ( - "\tmrs %0, primask\n" - "\tcpsid i\n" - : "=r" (primask) - : - : "memory"); - return primask; -} - -/* Restore saved IRQ & FIQ state */ - -static inline void irqrestore(irqstate_t primask) -{ - /* If bit 0 of the primask is 0, then we need to restore - * interupts. - */ - - __asm__ __volatile__ - ( - "\ttst %0, #1\n" - "\tbne 1f\n" - "\tcpsie i\n" - "1:\n" - : - : "r" (primask) - : "memory"); -} - -#else /* __thumb2__ */ - -/* Save the current interrupt enable state & disable IRQs */ - -static inline irqstate_t irqsave(void) -{ - unsigned int flags; - unsigned int temp; - __asm__ __volatile__ - ( - "\tmrs %0, cpsr\n" - "\torr %1, %0, #128\n" - "\tmsr cpsr_c, %1" - : "=r" (flags), "=r" (temp) - : - : "memory"); - return flags; -} - -/* Restore saved IRQ & FIQ state */ - -static inline void irqrestore(irqstate_t flags) -{ - __asm__ __volatile__ - ( - "msr cpsr_c, %0" - : - : "r" (flags) - : "memory"); -} - -static inline void system_call(swint_t func, int parm1, - int parm2, int parm3) -{ - __asm__ __volatile__ - ( - "mov\tr0,%0\n\t" - "mov\tr1,%1\n\t" - "mov\tr2,%2\n\t" - "mov\tr3,%3\n\t" - "swi\t0x900001\n\t" - : - : "r" ((long)(func)), "r" ((long)(parm1)), - "r" ((long)(parm2)), "r" ((long)(parm3)) - : "r0", "r1", "r2", "r3", "lr"); -} -#endif /* __thumb2__ */ -#endif /* __ASSEMBLY__ */ - /**************************************************************************** * Public Variables ****************************************************************************/ diff --git a/nuttx/arch/arm/include/irq_arm.h b/nuttx/arch/arm/include/irq_arm.h new file mode 100644 index 0000000000..efaa5f8167 --- /dev/null +++ b/nuttx/arch/arm/include/irq_arm.h @@ -0,0 +1,229 @@ +/**************************************************************************** + * arch/arm/include/irq_arm.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_IRQ_ARM_H +#define __ARCH_ARM_INCLUDE_IRQ_ARM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* IRQ Stack Frame Format: + * + * Context is always saved/restored in the same way: + * + * (1) stmia rx, {r0-r14} + * (2) then the PC and CPSR + * + * This results in the following set of indices that + * can be used to access individual registers in the + * xcp.regs array: + */ + +#define REG_R0 (0) +#define REG_R1 (1) +#define REG_R2 (2) +#define REG_R3 (3) +#define REG_R4 (4) +#define REG_R5 (5) +#define REG_R6 (6) +#define REG_R7 (7) +#define REG_R8 (8) +#define REG_R9 (9) +#define REG_R10 (10) +#define REG_R11 (11) +#define REG_R12 (12) +#define REG_R13 (13) +#define REG_R14 (14) +#define REG_R15 (15) +#define REG_CPSR (16) + +#define XCPTCONTEXT_REGS (17) +#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) + +#define REG_A1 REG_R0 +#define REG_A2 REG_R1 +#define REG_A3 REG_R2 +#define REG_A4 REG_R3 +#define REG_V1 REG_R4 +#define REG_V2 REG_R5 +#define REG_V3 REG_R6 +#define REG_V4 REG_R7 +#define REG_V5 REG_R8 +#define REG_V6 REG_R9 +#define REG_V7 REG_R10 +#define REG_SB REG_R9 +#define REG_SL REG_R10 +#define REG_FP REG_R11 +#define REG_IP REG_R12 +#define REG_SP REG_R13 +#define REG_LR REG_R14 +#define REG_PC REG_R15 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This struct defines the way the registers are stored. We + * need to save: + * + * 1 CPSR + * 7 Static registers, v1-v7 (aka r4-r10) + * 1 Frame pointer, fp (aka r11) + * 1 Stack pointer, sp (aka r13) + * 1 Return address, lr (aka r14) + * --- + * 11 (XCPTCONTEXT_USER_REG) + * + * On interrupts, we also need to save: + * 4 Volatile registers, a1-a4 (aka r0-r3) + * 1 Scratch Register, ip (aka r12) + *--- + * 5 (XCPTCONTEXT_IRQ_REGS) + * + * For a total of 17 (XCPTCONTEXT_REGS) + */ + +#ifndef __ASSEMBLY__ +struct xcptcontext +{ + /* The following function pointer is non-zero if there + * are pending signals to be processed. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved copies of LR and CPSR used during + * signal processing. + */ + + uint32 saved_pc; + uint32 saved_cpsr; +#endif + + /* Register save area */ + + uint32 regs[XCPTCONTEXT_REGS]; +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Save the current interrupt enable state & disable IRQs */ + +static inline irqstate_t irqsave(void) +{ + unsigned int flags; + unsigned int temp; + __asm__ __volatile__ + ( + "\tmrs %0, cpsr\n" + "\torr %1, %0, #128\n" + "\tmsr cpsr_c, %1" + : "=r" (flags), "=r" (temp) + : + : "memory"); + return flags; +} + +/* Restore saved IRQ & FIQ state */ + +static inline void irqrestore(irqstate_t flags) +{ + __asm__ __volatile__ + ( + "msr cpsr_c, %0" + : + : "r" (flags) + : "memory"); +} + +static inline void system_call(swint_t func, int parm1, + int parm2, int parm3) +{ + __asm__ __volatile__ + ( + "mov\tr0,%0\n\t" + "mov\tr1,%1\n\t" + "mov\tr2,%2\n\t" + "mov\tr3,%3\n\t" + "swi\t0x900001\n\t" + : + : "r" ((long)(func)), "r" ((long)(parm1)), + "r" ((long)(parm2)), "r" ((long)(parm3)) + : "r0", "r1", "r2", "r3", "lr"); +} +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * 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_IRQ_ARM_H */ + diff --git a/nuttx/arch/arm/include/irq_thumb2.h b/nuttx/arch/arm/include/irq_thumb2.h new file mode 100644 index 0000000000..e138c157a0 --- /dev/null +++ b/nuttx/arch/arm/include/irq_thumb2.h @@ -0,0 +1,210 @@ +/**************************************************************************** + * arch/arm/include/irq_thumb2.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_IRQ_THUMB2_H +#define __ARCH_ARM_INCLUDE_IRQ_THUMB2_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* IRQ Stack Frame Format: */ + +/* On entry into an IRQ, the hardware automatically saves the following + * registers on the stack in this (address) order: + */ + +#define REG_XPSR (16) /* xPSR */ +#define REG_R15 (15) /* R15 = PC */ +#define REG_R14 (14) /* R14 = LR */ +#define REG_R12 (13) /* R12 */ +#define REG_R3 (12) /* R3 */ +#define REG_R2 (11) /* R2 */ +#define REG_R1 (10) /* R1 */ +#define REG_R0 (9) /* R0 */ + +#define HW_XCPT_REGS (8) +#define HW_XCPT_SIZE (4 * HW_XCPT_REGS) + +/* The following additional registers are stored by the interrupt handling + * logic. + */ + +#define REG_R13 (8) /* R13 = SP at time of interrupt */ +#define REG_R11 (7) /* R11 */ +#define REG_R10 (6) /* R10 */ +#define REG_R9 (5) /* R9 */ +#define REG_R8 (4) /* R8 */ +#define REG_R7 (3) /* R7 */ +#define REG_R6 (2) /* R6 */ +#define REG_R5 (1) /* R5 */ +#define REG_R4 (0) /* R4 */ + +#define XCPTCONTEXT_REGS (17) +#define XCPTCONTEXT_SIZE (4 * XCPTCONTEXT_REGS) + +#define REG_A1 REG_R0 +#define REG_A2 REG_R1 +#define REG_A3 REG_R2 +#define REG_A4 REG_R3 +#define REG_V1 REG_R4 +#define REG_V2 REG_R5 +#define REG_V3 REG_R6 +#define REG_V4 REG_R7 +#define REG_V5 REG_R8 +#define REG_V6 REG_R9 +#define REG_V7 REG_R10 +#define REG_SB REG_R9 +#define REG_SL REG_R10 +#define REG_FP REG_R11 +#define REG_IP REG_R12 +#define REG_SP REG_R13 +#define REG_LR REG_R14 +#define REG_PC REG_R15 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* The following structure is included in the TCB and defines the complete + * state of the thread. + */ + +#ifndef __ASSEMBLY__ +struct xcptcontext +{ + /* The following function pointer is non-zero if there + * are pending signals to be processed. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved copies of LR and CPSR used during + * signal processing. + */ + + uint32 saved_pc; + uint32 saved_xpsr; +#endif + + /* Register save area */ + + uint32 regs[XCPTCONTEXT_REGS]; +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Save the current interrupt enable state & disable IRQs */ + +static inline irqstate_t irqsave(void) +{ + unsigned short primask; + + /* Return the the current value of primask register and set + * bit 0 of the primask register to disable interrupts + */ + + __asm__ __volatile__ + ( + "\tmrs %0, primask\n" + "\tcpsid i\n" + : "=r" (primask) + : + : "memory"); + return primask; +} + +/* Restore saved IRQ & FIQ state */ + +static inline void irqrestore(irqstate_t primask) +{ + /* If bit 0 of the primask is 0, then we need to restore + * interupts. + */ + + __asm__ __volatile__ + ( + "\ttst %0, #1\n" + "\tbne 1f\n" + "\tcpsie i\n" + "1:\n" + : + : "r" (primask) + : "memory"); +} + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * 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_IRQ_THUMB2_H */ + diff --git a/nuttx/arch/arm/src/common/arm.h b/nuttx/arch/arm/src/common/arm.h index e3e97f9ad4..07b21de643 100644 --- a/nuttx/arch/arm/src/common/arm.h +++ b/nuttx/arch/arm/src/common/arm.h @@ -1,7 +1,7 @@ /************************************************************************************ * arch/arm/src/common/arm.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -44,9 +44,9 @@ # include #endif -/************************************************************************** - * Conditional Compilation - **************************************************************************/ +/************************************************************************************ + * Definitions + ************************************************************************************/ #undef CONFIG_ALIGNMENT_TRAP #undef CONFIG_DCACHE_WRITETHROUGH @@ -54,10 +54,6 @@ #undef CONFIG_DCACHE_DISABLE #undef CONFIG_ICACHE_DISABLE -/************************************************************************************ - * Definitions - ************************************************************************************/ - /* ARM9EJS **************************************************************************/ /* PSR bits */ diff --git a/nuttx/arch/arm/src/common/cortexm3_psr.h b/nuttx/arch/arm/src/common/cortexm3_psr.h new file mode 100644 index 0000000000..1ea3c85e64 --- /dev/null +++ b/nuttx/arch/arm/src/common/cortexm3_psr.h @@ -0,0 +1,91 @@ +/************************************************************************************ + * arch/arm/src/common/cortexm3_psr.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_COMMON_CORTEXM_PSR_H +#define __ARCH_ARM_SRC_COMMON_CORTEXM_PSR_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +#endif + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* Application Program Status Register (APSR) */ + +#define CORTEXM3_APSR_Q (1 << 27) /* Bit 27: Sticky saturation flag */ +#define CORTEXM3_APSR_V (1 << 28) /* Bit 28: Overflow flag */ +#define CORTEXM3_APSR_C (1 << 29) /* Bit 29: Carry/borrow flag */ +#define CORTEXM3_APSR_Z (1 << 30) /* Bit 30: Zero flag */ +#define CORTEXM3_APSR_N (1 << 31) /* Bit 31: Negative, less than flag */ + +/* Interrupt Program Status Register (IPSR) */ + +#define CORTEMX_IPSR_ISR_SHIFT 0 /* Bits 8-0: ISR number */ +#define CORTEMX_IPSR_ISR_MASK (0x1ff << CORTEMX_IPSR_ISR_SHIFT) + +/* Execution PSR Register (EPSR) */ + +#define CORTEMX_EPSR_ICIIT1_SHIFT 10 /* Bits 15-10: Interrupt-Continuable-Instruction/If-Then bits */ +#define CORTEMX_EPSR_ICIIT1_MASK (3 << CORTEMX_EPSR_ICIIT1_SHIFT) +#define CORTEMX_EPSR_T (1 << 24) /* Bit 24: T-bit */ +#define CORTEMX_EPSR_ICIIT2_SHIFT 25 /* Bits 26-25: Interrupt-Continuable-Instruction/If-Then bits */ +#define CORTEMX_EPSR_ICIIT2_MASK (3 << CORTEMX_EPSR_ICIIT2_SHIFT) + +/* Save xPSR bits */ + +#define CORTEMX_IPSR_ISR_SHIFT 0 /* Bits 8-0: ISR number */ +#define CORTEMX_IPSR_ISR_MASK (0x1ff << CORTEMX_IPSR_ISR_SHIFT) +#define CORTEMX_EPSR_ICIIT1_SHIFT 25 /* Bits 15-10: Interrupt-Continuable-Instruction/If-Then bits */ +#define CORTEMX_EPSR_ICIIT1_MASK (3 << CORTEMX_EPSR_ICIIT_SHIFT) +#define CORTEMX_EPSR_T (1 << 24) /* Bit 24: T-bit */ +#define CORTEMX_EPSR_ICIIT2_SHIFT 25 /* Bits 26-25: Interrupt-Continuable-Instruction/If-Then bits */ +#define CORTEMX_EPSR_ICIIT2_MASK (3 << CORTEMX_EPSR_ICIIT_SHIFT) +#define CORTEXM3_APSR_Q (1 << 27) /* Bit 27: Sticky saturation flag */ +#define CORTEXM3_APSR_V (1 << 28) /* Bit 28: Overflow flag */ +#define CORTEXM3_APSR_C (1 << 29) /* Bit 29: Carry/borrow flag */ +#define CORTEXM3_APSR_Z (1 << 30) /* Bit 30: Zero flag */ +#define CORTEXM3_APSR_N (1 << 31) /* Bit 31: Negative, less than flag */ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#endif /* __ARCH_ARM_SRC_COMMON_CORTEXM_PSR_H */ diff --git a/nuttx/arch/arm/src/common/up_assert.c b/nuttx/arch/arm/src/common/up_assert.c index 294fce44c5..8460c6b713 100644 --- a/nuttx/arch/arm/src/common/up_assert.c +++ b/nuttx/arch/arm/src/common/up_assert.c @@ -132,7 +132,12 @@ static inline void up_registerdump(void) regs, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]); } + +#ifdef __thumb2__ + lldbg("xPSR: %08x\n", current_regs[REG_XPSR]); +#else lldbg("CPSR: %08x\n", current_regs[REG_CPSR]); +#endif } } #else diff --git a/nuttx/arch/arm/src/common/up_doirq.c b/nuttx/arch/arm/src/common/up_doirq.c index 293b9fdc4f..b863ec0c5b 100644 --- a/nuttx/arch/arm/src/common/up_doirq.c +++ b/nuttx/arch/arm/src/common/up_doirq.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/common/up_doirq.c * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ * Public Functions ****************************************************************************/ -void up_doirq(int irq, uint32* regs) +uint32 *up_doirq(int irq, uint32* regs) { up_ledon(LED_INIRQ); #ifdef CONFIG_SUPPRESS_INTERRUPTS @@ -89,6 +89,13 @@ void up_doirq(int irq, uint32* regs) irq_dispatch(irq, regs); + /* If a context switch occurred while processing the interrupt + * then current_regs may have value (depending upon the implementaton + * of context switching for te particular chip. + */ + + regs = current_regs; + /* Indicate that we are no long in an interrupt handler */ current_regs = NULL; @@ -101,4 +108,5 @@ void up_doirq(int irq, uint32* regs) } up_ledoff(LED_INIRQ); #endif + return regs; } diff --git a/nuttx/arch/arm/src/common/up_internal.h b/nuttx/arch/arm/src/common/up_internal.h index f1f5e252b9..4306318539 100644 --- a/nuttx/arch/arm/src/common/up_internal.h +++ b/nuttx/arch/arm/src/common/up_internal.h @@ -1,7 +1,7 @@ /**************************************************************************** * common/up_internal.h * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -122,7 +122,7 @@ extern void up_boot(void); extern void up_copystate(uint32 *dest, uint32 *src); extern void up_dataabort(uint32 *regs); extern void up_decodeirq(uint32 *regs); -extern void up_doirq(int irq, uint32 *regs); +extern uint32 *up_doirq(int irq, uint32 *regs); extern void up_fullcontextrestore(uint32 *regs) __attribute__ ((noreturn)); extern void up_irqinitialize(void); extern void up_prefetchabort(uint32 *regs); diff --git a/nuttx/arch/arm/src/lm3s/chip.h b/nuttx/arch/arm/src/lm3s/chip.h index f6ff0c16a1..129cd9f374 100644 --- a/nuttx/arch/arm/src/lm3s/chip.h +++ b/nuttx/arch/arm/src/lm3s/chip.h @@ -53,16 +53,6 @@ * Definitions ************************************************************************************/ -/* The LM3S6918 only supports 8 priority levels. The hardware priority mechanism - * will only look at the upper N bits of the 8-bit priority level (where N is 3 for - * the Stellaris family), so any prioritization must be performed in those bits. - * The default priority level is set to the middle value - */ - -#define NVIC_SYSH_PRIORITY_MIN 0x00 -#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 -#define NVIC_SYSH_PRIORITY_MAX 0xe0 - /************************************************************************************ * Public Types ************************************************************************************/ @@ -71,28 +61,8 @@ * Public Data ************************************************************************************/ -#ifndef __ASSEMBLY__ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" { -#else -#define EXTERN extern -#endif - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -/* Defined in lm3s_lowputc.c */ - -EXTERN void up_lowsetup(void); - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - -#endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_LM3S_CHIP_H */ diff --git a/nuttx/arch/arm/src/lm3s/lm3s_ethernet.c b/nuttx/arch/arm/src/lm3s/lm3s_ethernet.c index eccf6b83e2..6e0081d158 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_ethernet.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_ethernet.c @@ -53,6 +53,8 @@ #include #include +#include "lm3s_internal.h" + /**************************************************************************** * Definitions ****************************************************************************/ diff --git a/nuttx/arch/arm/src/lm3s/lm3s_gpio.h b/nuttx/arch/arm/src/lm3s/lm3s_gpio.h index 16d3545ebb..7424d74e33 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_gpio.h +++ b/nuttx/arch/arm/src/lm3s/lm3s_gpio.h @@ -352,159 +352,16 @@ #define LM3S_GPIOH_PCELLID2 (LM3S_GPIOH_BASE + LM3S_GPIO_PCELLID2_OFFSET) #define LM3S_GPIOH_PCELLID3 (LM3S_GPIOH_BASE + LM3S_GPIO_PCELLID3_OFFSET) -/* Bit-encoded input to lm3s_configgpio() *******************************************/ - -#define GPIO_FUNC_SHIFT 29 /* Bit 31-29: GPIO function */ -#define GPIO_FUNC_MASK (7 << GPIO_FUNC_SHIFT) /* (See table 9-1 in data sheet) */ -#define GPIO_FUNC_INPUT (0 << GPIO_FUNC_SHIFT) /* Digital GPIO input */ -#define GPIO_FUNC_OUTPUT (1 << GPIO_FUNC_SHIFT) /* Digital GPIO output */ -#define GPIO_FUNC_ODINPUT (2 << GPIO_FUNC_SHIFT) /* Open-drain GPIO input */ -#define GPIO_FUNC_ODOUTPUT (3 << GPIO_FUNC_SHIFT) /* Open-drain GPIO output */ -#define GPIO_FUNC_PFODIO (4 << GPIO_FUNC_SHIFT) /* Open-drain input/output (I2C) */ -#define GPIO_FUNC_PFINPUT (5 << GPIO_FUNC_SHIFT) /* Digital input (Timer, CCP) */ -#define GPIO_FUNC_PFOUTPUT (5 << GPIO_FUNC_SHIFT) /* Digital output (Timer, PWM, Comparator) */ -#define GPIO_FUNC_PFIO (5 << GPIO_FUNC_SHIFT) /* Digital input/output (SSI, UART) */ -#define GPIO_FUNC_ANINPUT (6 << GPIO_FUNC_SHIFT) /* Analog input (Comparator) */ -#define GPIO_FUNC_INTERRUPT (7 << GPIO_FUNC_SHIFT) /* Interrupt function */ - -#define GPIO_INT_SHIFT 26 /* Bits 28-26: Interrupt type */ -#define GPIO_INT_MASK (7 << GPIO_INT_SHIFT) -#define GPIO_INT_FALLINGEDGE (0 << GPIO_INT_SHIFT) /* Interrupt on falling edge */ -#define GPIO_INT_RISINGEDGE (1 << GPIO_INT_SHIFT) /* Interrupt on rising edge */ -#define GPIO_INT_BOTHEDGES (2 << GPIO_INT_SHIFT) /* Interrupt on both edges */ -#define GPIO_INT_LOWLEVEL (3 << GPIO_INT_SHIFT) /* Interrupt on low level */ -#define GPIO_INT_HIGHLEVEL (4 << GPIO_INT_SHIFT) /* Interrupt on high level */ - -#define GPIO_STRENGTH_SHIFT 24 /* Bits 25-24: Pad drive strength */ -#define GPIO_STRENGTH_MASK (3 << GPIO_STRENGTH_SHIFT) -#define GPIO_STRENGTH_2MA (0 << GPIO_STRENGTH_SHIFT) /* 2mA pad drive strength */ -#define GPIO_STRENGTH_4MA (1 << GPIO_STRENGTH_SHIFT) /* 4mA pad drive strength */ -#define GPIO_STRENGTH_8MA (2 << GPIO_STRENGTH_SHIFT) /* 8mA pad drive strength */ -#define GPIO_STRENGTH_8MASC (3 << GPIO_STRENGTH_SHIFT) /* 8mA Pad drive with slew rate control */ - -#define GPIO_PADTYPE_SHIFT 21 /* Bits 21-23: Pad type */ -#define GPIO_PADTYPE_MASK (7 << GPIO_PADTYPE_SHIFT) -#define GPIO_PADTYPE_STD (0 << GPIO_PADTYPE_SHIFT) /* Push-pull */ -#define GPIO_PADTYPE_STDWPU (1 << GPIO_PADTYPE_SHIFT) /* Push-pull with weak pull-up */ -#define GPIO_PADTYPE_STDWPD (2 << GPIO_PADTYPE_SHIFT) /* Push-pull with weak pull-down */ -#define GPIO_PADTYPE_OD (3 << GPIO_PADTYPE_SHIFT) /* Open-drain */ -#define GPIO_PADTYPE_ODWPU (4 << GPIO_PADTYPE_SHIFT) /* Open-drain with weak pull-up */ -#define GPIO_PADTYPE_ODWPD (5 << GPIO_PADTYPE_SHIFT) /* Open-drain with weak pull-down */ -#define GPIO_PADTYPE_ANALOG (6 << GPIO_PADTYPE_SHIFT) /* Analog comparator */ - -#define GPIO_VALUE_SHIFT 6 /* Bit 6: If output, inital value of output */ -#define GPIO_VALUE_MASK (1 << GPIO_VALUE_SHIFT) -#define GPIO_VALUE_ZERO (0 << GPIO_VALUE_SHIFT) /* Initial value is zero */ -#define GPIO_VALUE_ONE (1 << GPIO_VALUE_SHIFT) /* Initial value is one */ - -#define GPIO_PORT_SHIFT 3 /* Bit 3-5: Port number */ -#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT) -#define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */ -#define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */ -#define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */ -#define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */ -#define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */ -#define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */ -#define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */ -#define GPIO_PORTH (7 << GPIO_PORT_SHIFT) /* GPIOH */ - -#define GPIO_NUMBER_SHIFT 0 /* Bits 0-2: GPIO number: 0-7 */ -#define GPIO_NUMBER_MASK (7 << GPIO_NUMBER_SHIFT) - -/* The following lists the input value to lm3s_configgpio to setup the alternate, - * hardware function for each pin. - */ - -#define GPIO_UART0_RX (GPIO_FUNC_PFINPUT | GPIO_PORTA | 0) /* PA0: UART 0 receive (U0Rx) */ -#define GPIO_UART0_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTA | 1) /* PA1: UART 0 transmit (U0Tx) */ -#define GPIO_SSI0_CLK (GPIO_FUNC_PFIO | GPIO_PORTA | 2) /* PA2: SSI0 clock (SSI0Clk) */ -#define GPIO_SSI0_FSS (GPIO_FUNC_PFIO | GPIO_PORTA | 3) /* PA3: SSI0 frame (SSI0Fss) */ -#define GPIO_SSI0_RX (GPIO_FUNC_PFINPUT | GPIO_PORTA | 4) /* PA4: SSI0 receive (SSI0Rx) */ -#define GPIO_SSI0_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTA | 5) /* PA5: SSI0 transmit (SSI0Tx) */ -#define GPIO_PWM1_CCP (GPIO_FUNC_PFIO | GPIO_PORTA | 6) /* PA6: Capture/Compare/PWM1 (CCP1) */ -#define GPIO_I2C1_SDA (GPIO_FUNC_PFODIO | GPIO_PORTA | 7) /* PA7: I2C1 data (I2C1SDA) */ -#define GPIO_PWM0_CCP (GPIO_FUNC_PFIO | GPIO_PORTB | 0) /* PB0: Capture/Compare/PWM0 (CCP0) */ -#define GPIO_PWM2_CCP (GPIO_FUNC_PFIO | GPIO_PORTB | 1) /* PB1: Capture/Compare/PWM2 (CCP2) */ -#define GPIO_I2C0_SCL (GPIO_FUNC_PFOUTPUT | GPIO_PORTB | 2) /* PB2: I2C0 clock (I2C0SCL) */ -#define GPIO_I2C0_SDA (GPIO_FUNC_PFODIO | GPIO_PORTB | 3) /* PB3: I2C0 data (I2C0SDA) */ -#define GPIO_CMP0_NIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 4) /* PB4: Analog comparator 0 negative input (C0-) */ -#define GPIO_CMP1_NIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 5) /* PB5: Analog comparator 1 negative input (C1-) */ -#define GPIO_CMP0_PIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 6) /* PB6: Analog comparator 0 positive input (C0+) */ -#define GPIO_JTAG_TRST (GPIO_FUNC_PFINPUT | GPIO_PORTB | 7) /* PB7: JTAG ~TRST */ -#define GPIO_JTAG_TCK (GPIO_FUNC_PFINPUT | GPIO_PORTC | 0) /* PC0: JTAG/SWD CLK */ -#define GPIO_JTAG_SWCLK (GPIO_FUNC_PFINPUT | GPIO_PORTC | 0) /* PC0: JTAG/SWD CLK */ -#define GPIO_JTAG_TMS (GPIO_FUNC_PFIO | GPIO_PORTC | 1) /* PC1: JTAG TMS */ -#define GPIO_JTAG_SWDIO (GPIO_FUNC_PFIO | GPIO_PORTC | 1) /* PC1: JTAG SWDIO */ -#define GPIO_JTAG_TDI (GPIO_FUNC_PFINPUT | GPIO_PORTC | 2) /* PC2: JTAG TDI */ -#define GPIO_JTAG_TDO (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 3) /* PC3: JTAG TDO */ -#define GPIO_JTAG_SWO (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 3) /* PC3: JTAG SWO */ -#define GPIO_PWM5_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 4) /* PC4: Capture/Compare/PWM5 (CCP5) */ -#define GPIO_CMP1_PIN (GPIO_FUNC_PFINPUT | GPIO_PORTC | 5) /* PC5: Analog comparator 1 positive input (C1+) */ -#define GPIO_CMP0_OUT (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 5) /* PC5: Analog comparator 0 output (C0o) */ -#define GPIO_PWM3_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 6) /* PC6: Capture/Compare/PWM3 (CCP3) */ -#define GPIO_PWM4_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 7) /* PC7: Capture/Compare/PWM4 (CCP4) */ -#define GPIO_UART1_RX (GPIO_FUNC_PFINPUT | GPIO_PORTD | 2) /* PD2: UART 1 receive (U1Rx) */ -#define GPIO_UART1_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTD | 3) /* PD3: UART 1 transmit (U1Tx) */ -#define GPIO_SSI1_CLK (GPIO_FUNC_PFIO1 | GPIO_PORTE | 0) /* PE0: SSI1 clock (SSI1Clk) */ -#define GPIO_SSI1_FSS (GPIO_FUNC_PFIO | GPIO_PORTE | 1) /* PE1: SSI1 frame (SSI1Fss) */ -#define GPIO_SSI1_RX (GPIO_FUNC_PFINPUT | GPIO_PORTE | 2) /* PE2: SSI1 receive (SSI1Rx) */ -#define GPIO_SSI1_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTE | 3) /* PE3: SSI1 transmit (SSI1Tx) */ -#define GPIO_ETHPHY_LED1 (GPIO_FUNC_PFOUTPUT | GPIO_PORTF | 2) /* PF2: LED1 */ -#define GPIO_ETHPHY_LED0 (GPIO_FUNC_PFOUTPUT | GPIO_PORTF | 3) /* PF3: LED0 */ -#define GPIO_I2C1_SCL (GPIO_FUNC_PFOUTPUT | GPIO_PORTG | 0) /* PG0: I2C1 clock (I2C1SCL) */ - /************************************************************************************ * Public Types ************************************************************************************/ -#ifndef __ASSEMBLY__ - -/************************************************************************************ - * Inline Functions - ************************************************************************************/ - -static inline uint32 lm3s_gpiobaseaddress(unsigned int port) -{ -#ifdef CONFIG_ARCH_CHIP_LM3S6918 - unsigned int portno = (port >> GPIO_PORT_SHIFT) & 7; - if (portno < 4) - { - return LM3S_GPIOA_BASE + 0x1000 * portno; - } - else - { - return LM3S_GPIOE_BASE + 0x1000 * portno; - } -#else -# error "GPIO register base addresses not known for this LM3S chip" - return 0; -#endif -} - /************************************************************************************ * Public Data ************************************************************************************/ -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" { -#else -#define EXTERN extern -#endif - /************************************************************************************ * Public Function Prototypes ************************************************************************************/ -/* Configure a GPIO pin */ - -EXTERN int lm3s_configgpio(uint32 bitset); - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - -#endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_LM3S_LM3S_GPIO_H */ diff --git a/nuttx/arch/arm/src/lm3s/lm3s_internal.h b/nuttx/arch/arm/src/lm3s/lm3s_internal.h new file mode 100644 index 0000000000..349a3461ea --- /dev/null +++ b/nuttx/arch/arm/src/lm3s/lm3s_internal.h @@ -0,0 +1,257 @@ +/************************************************************************************ + * arch/arm/src/lm3s/lm3s_internal.h + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************************/ + +#ifndef __ARCH_ARM_SRC_LM3S_LM3S_INTERNAL_H +#define __ARCH_ARM_SRC_LM3S_LM3S_INTERNAL_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +/************************************************************************************ + * Definitions + ************************************************************************************/ + +/* The LM3S6918 only supports 8 priority levels. The hardware priority mechanism + * will only look at the upper N bits of the 8-bit priority level (where N is 3 for + * the Stellaris family), so any prioritization must be performed in those bits. + * The default priority level is set to the middle value + */ + +#define NVIC_SYSH_PRIORITY_MIN 0x00 +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 +#define NVIC_SYSH_PRIORITY_MAX 0xe0 + +/* Bit-encoded input to lm3s_configgpio() *******************************************/ + +#define GPIO_FUNC_SHIFT 29 /* Bit 31-29: GPIO function */ +#define GPIO_FUNC_MASK (7 << GPIO_FUNC_SHIFT) /* (See table 9-1 in data sheet) */ +#define GPIO_FUNC_INPUT (0 << GPIO_FUNC_SHIFT) /* Digital GPIO input */ +#define GPIO_FUNC_OUTPUT (1 << GPIO_FUNC_SHIFT) /* Digital GPIO output */ +#define GPIO_FUNC_ODINPUT (2 << GPIO_FUNC_SHIFT) /* Open-drain GPIO input */ +#define GPIO_FUNC_ODOUTPUT (3 << GPIO_FUNC_SHIFT) /* Open-drain GPIO output */ +#define GPIO_FUNC_PFODIO (4 << GPIO_FUNC_SHIFT) /* Open-drain input/output (I2C) */ +#define GPIO_FUNC_PFINPUT (5 << GPIO_FUNC_SHIFT) /* Digital input (Timer, CCP) */ +#define GPIO_FUNC_PFOUTPUT (5 << GPIO_FUNC_SHIFT) /* Digital output (Timer, PWM, Comparator) */ +#define GPIO_FUNC_PFIO (5 << GPIO_FUNC_SHIFT) /* Digital input/output (SSI, UART) */ +#define GPIO_FUNC_ANINPUT (6 << GPIO_FUNC_SHIFT) /* Analog input (Comparator) */ +#define GPIO_FUNC_INTERRUPT (7 << GPIO_FUNC_SHIFT) /* Interrupt function */ + +#define GPIO_INT_SHIFT 26 /* Bits 28-26: Interrupt type */ +#define GPIO_INT_MASK (7 << GPIO_INT_SHIFT) +#define GPIO_INT_FALLINGEDGE (0 << GPIO_INT_SHIFT) /* Interrupt on falling edge */ +#define GPIO_INT_RISINGEDGE (1 << GPIO_INT_SHIFT) /* Interrupt on rising edge */ +#define GPIO_INT_BOTHEDGES (2 << GPIO_INT_SHIFT) /* Interrupt on both edges */ +#define GPIO_INT_LOWLEVEL (3 << GPIO_INT_SHIFT) /* Interrupt on low level */ +#define GPIO_INT_HIGHLEVEL (4 << GPIO_INT_SHIFT) /* Interrupt on high level */ + +#define GPIO_STRENGTH_SHIFT 24 /* Bits 25-24: Pad drive strength */ +#define GPIO_STRENGTH_MASK (3 << GPIO_STRENGTH_SHIFT) +#define GPIO_STRENGTH_2MA (0 << GPIO_STRENGTH_SHIFT) /* 2mA pad drive strength */ +#define GPIO_STRENGTH_4MA (1 << GPIO_STRENGTH_SHIFT) /* 4mA pad drive strength */ +#define GPIO_STRENGTH_8MA (2 << GPIO_STRENGTH_SHIFT) /* 8mA pad drive strength */ +#define GPIO_STRENGTH_8MASC (3 << GPIO_STRENGTH_SHIFT) /* 8mA Pad drive with slew rate control */ + +#define GPIO_PADTYPE_SHIFT 21 /* Bits 21-23: Pad type */ +#define GPIO_PADTYPE_MASK (7 << GPIO_PADTYPE_SHIFT) +#define GPIO_PADTYPE_STD (0 << GPIO_PADTYPE_SHIFT) /* Push-pull */ +#define GPIO_PADTYPE_STDWPU (1 << GPIO_PADTYPE_SHIFT) /* Push-pull with weak pull-up */ +#define GPIO_PADTYPE_STDWPD (2 << GPIO_PADTYPE_SHIFT) /* Push-pull with weak pull-down */ +#define GPIO_PADTYPE_OD (3 << GPIO_PADTYPE_SHIFT) /* Open-drain */ +#define GPIO_PADTYPE_ODWPU (4 << GPIO_PADTYPE_SHIFT) /* Open-drain with weak pull-up */ +#define GPIO_PADTYPE_ODWPD (5 << GPIO_PADTYPE_SHIFT) /* Open-drain with weak pull-down */ +#define GPIO_PADTYPE_ANALOG (6 << GPIO_PADTYPE_SHIFT) /* Analog comparator */ + +#define GPIO_VALUE_SHIFT 6 /* Bit 6: If output, inital value of output */ +#define GPIO_VALUE_MASK (1 << GPIO_VALUE_SHIFT) +#define GPIO_VALUE_ZERO (0 << GPIO_VALUE_SHIFT) /* Initial value is zero */ +#define GPIO_VALUE_ONE (1 << GPIO_VALUE_SHIFT) /* Initial value is one */ + +#define GPIO_PORT_SHIFT 3 /* Bit 3-5: Port number */ +#define GPIO_PORT_MASK (7 << GPIO_PORT_SHIFT) +#define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */ +#define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */ +#define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */ +#define GPIO_PORTD (3 << GPIO_PORT_SHIFT) /* GPIOD */ +#define GPIO_PORTE (4 << GPIO_PORT_SHIFT) /* GPIOE */ +#define GPIO_PORTF (5 << GPIO_PORT_SHIFT) /* GPIOF */ +#define GPIO_PORTG (6 << GPIO_PORT_SHIFT) /* GPIOG */ +#define GPIO_PORTH (7 << GPIO_PORT_SHIFT) /* GPIOH */ + +#define GPIO_NUMBER_SHIFT 0 /* Bits 0-2: GPIO number: 0-7 */ +#define GPIO_NUMBER_MASK (7 << GPIO_NUMBER_SHIFT) + +/* The following lists the input value to lm3s_configgpio to setup the alternate, + * hardware function for each pin. + */ + +#define GPIO_UART0_RX (GPIO_FUNC_PFINPUT | GPIO_PORTA | 0) /* PA0: UART 0 receive (U0Rx) */ +#define GPIO_UART0_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTA | 1) /* PA1: UART 0 transmit (U0Tx) */ +#define GPIO_SSI0_CLK (GPIO_FUNC_PFIO | GPIO_PORTA | 2) /* PA2: SSI0 clock (SSI0Clk) */ +#define GPIO_SSI0_FSS (GPIO_FUNC_PFIO | GPIO_PORTA | 3) /* PA3: SSI0 frame (SSI0Fss) */ +#define GPIO_SSI0_RX (GPIO_FUNC_PFINPUT | GPIO_PORTA | 4) /* PA4: SSI0 receive (SSI0Rx) */ +#define GPIO_SSI0_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTA | 5) /* PA5: SSI0 transmit (SSI0Tx) */ +#define GPIO_PWM1_CCP (GPIO_FUNC_PFIO | GPIO_PORTA | 6) /* PA6: Capture/Compare/PWM1 (CCP1) */ +#define GPIO_I2C1_SDA (GPIO_FUNC_PFODIO | GPIO_PORTA | 7) /* PA7: I2C1 data (I2C1SDA) */ +#define GPIO_PWM0_CCP (GPIO_FUNC_PFIO | GPIO_PORTB | 0) /* PB0: Capture/Compare/PWM0 (CCP0) */ +#define GPIO_PWM2_CCP (GPIO_FUNC_PFIO | GPIO_PORTB | 1) /* PB1: Capture/Compare/PWM2 (CCP2) */ +#define GPIO_I2C0_SCL (GPIO_FUNC_PFOUTPUT | GPIO_PORTB | 2) /* PB2: I2C0 clock (I2C0SCL) */ +#define GPIO_I2C0_SDA (GPIO_FUNC_PFODIO | GPIO_PORTB | 3) /* PB3: I2C0 data (I2C0SDA) */ +#define GPIO_CMP0_NIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 4) /* PB4: Analog comparator 0 negative input (C0-) */ +#define GPIO_CMP1_NIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 5) /* PB5: Analog comparator 1 negative input (C1-) */ +#define GPIO_CMP0_PIN (GPIO_FUNC_PFINPUT | GPIO_PORTB | 6) /* PB6: Analog comparator 0 positive input (C0+) */ +#define GPIO_JTAG_TRST (GPIO_FUNC_PFINPUT | GPIO_PORTB | 7) /* PB7: JTAG ~TRST */ +#define GPIO_JTAG_TCK (GPIO_FUNC_PFINPUT | GPIO_PORTC | 0) /* PC0: JTAG/SWD CLK */ +#define GPIO_JTAG_SWCLK (GPIO_FUNC_PFINPUT | GPIO_PORTC | 0) /* PC0: JTAG/SWD CLK */ +#define GPIO_JTAG_TMS (GPIO_FUNC_PFIO | GPIO_PORTC | 1) /* PC1: JTAG TMS */ +#define GPIO_JTAG_SWDIO (GPIO_FUNC_PFIO | GPIO_PORTC | 1) /* PC1: JTAG SWDIO */ +#define GPIO_JTAG_TDI (GPIO_FUNC_PFINPUT | GPIO_PORTC | 2) /* PC2: JTAG TDI */ +#define GPIO_JTAG_TDO (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 3) /* PC3: JTAG TDO */ +#define GPIO_JTAG_SWO (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 3) /* PC3: JTAG SWO */ +#define GPIO_PWM5_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 4) /* PC4: Capture/Compare/PWM5 (CCP5) */ +#define GPIO_CMP1_PIN (GPIO_FUNC_PFINPUT | GPIO_PORTC | 5) /* PC5: Analog comparator 1 positive input (C1+) */ +#define GPIO_CMP0_OUT (GPIO_FUNC_PFOUTPUT | GPIO_PORTC | 5) /* PC5: Analog comparator 0 output (C0o) */ +#define GPIO_PWM3_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 6) /* PC6: Capture/Compare/PWM3 (CCP3) */ +#define GPIO_PWM4_CCP (GPIO_FUNC_PFIO | GPIO_PORTC | 7) /* PC7: Capture/Compare/PWM4 (CCP4) */ +#define GPIO_UART1_RX (GPIO_FUNC_PFINPUT | GPIO_PORTD | 2) /* PD2: UART 1 receive (U1Rx) */ +#define GPIO_UART1_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTD | 3) /* PD3: UART 1 transmit (U1Tx) */ +#define GPIO_SSI1_CLK (GPIO_FUNC_PFIO1 | GPIO_PORTE | 0) /* PE0: SSI1 clock (SSI1Clk) */ +#define GPIO_SSI1_FSS (GPIO_FUNC_PFIO | GPIO_PORTE | 1) /* PE1: SSI1 frame (SSI1Fss) */ +#define GPIO_SSI1_RX (GPIO_FUNC_PFINPUT | GPIO_PORTE | 2) /* PE2: SSI1 receive (SSI1Rx) */ +#define GPIO_SSI1_TX (GPIO_FUNC_PFOUTPUT | GPIO_PORTE | 3) /* PE3: SSI1 transmit (SSI1Tx) */ +#define GPIO_ETHPHY_LED1 (GPIO_FUNC_PFOUTPUT | GPIO_PORTF | 2) /* PF2: LED1 */ +#define GPIO_ETHPHY_LED0 (GPIO_FUNC_PFOUTPUT | GPIO_PORTF | 3) /* PF3: LED0 */ +#define GPIO_I2C1_SCL (GPIO_FUNC_PFOUTPUT | GPIO_PORTG | 0) /* PG0: I2C1 clock (I2C1SCL) */ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +static inline uint32 lm3s_gpiobaseaddress(unsigned int port) +{ +#ifdef CONFIG_ARCH_CHIP_LM3S6918 + unsigned int portno = (port >> GPIO_PORT_SHIFT) & 7; + if (portno < 4) + { + return LM3S_GPIOA_BASE + 0x1000 * portno; + } + else + { + return LM3S_GPIOE_BASE + 0x1000 * portno; + } +#else +# error "GPIO register base addresses not known for this LM3S chip" + return 0; +#endif +} + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level initialization. + * + ****************************************************************************/ + +EXTERN void up_lowsetup(void); + +/**************************************************************************** + * Name: lm3s_clockconfig + * + * Description: + * Called to check to new clock based on desired rcc and rcc2 settings. + * This is use to set up the initial clocking but can be used later to + * support slow clocked, low power consumption modes. + * + ****************************************************************************/ + +EXTERN void lm3s_clockconfig(uint32 newrcc, uint32 newrcc2); + +/**************************************************************************** + * Name: up_clockconfig + * + * Description: + * Called early in the bootsequence (before .data and .bss are available) + * in order to configure initial clocking. + * + ****************************************************************************/ + +EXTERN void up_clockconfig(void); + +/* Configure a GPIO pin */ + +/**************************************************************************** + * Name: lm3s_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * + ****************************************************************************/ + +EXTERN int lm3s_configgpio(uint32 bitset); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_LM3S_LM3S_INTERNAL_H */ diff --git a/nuttx/arch/arm/src/lm3s/lm3s_irq.c b/nuttx/arch/arm/src/lm3s/lm3s_irq.c index b85800cb81..04110e3cfe 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_irq.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_irq.c @@ -45,6 +45,7 @@ #include "up_arch.h" #include "os_internal.h" #include "up_internal.h" +#include "lm3s_internal.h" /**************************************************************************** * Definitions @@ -382,4 +383,4 @@ int lm3s_reserved(int irq, FAR void *context) PANIC(OSERR_UNEXPECTEDISR); return 0; } -#endif \ No newline at end of file +#endif diff --git a/nuttx/arch/arm/src/lm3s/lm3s_lowputc.c b/nuttx/arch/arm/src/lm3s/lm3s_lowputc.c index 684f988462..bec33ac5e0 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_lowputc.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_lowputc.c @@ -44,6 +44,7 @@ #include "up_arch.h" #include "chip.h" +#include "lm3s_internal.h" /************************************************************************** * Private Definitions diff --git a/nuttx/arch/arm/src/lm3s/lm3s_start.c b/nuttx/arch/arm/src/lm3s/lm3s_start.c index fba5e93253..1eeed3af6c 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_start.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_start.c @@ -48,6 +48,7 @@ #include "up_arch.h" #include "up_internal.h" +#include "lm3s_internal.h" /**************************************************************************** * Private Definitions diff --git a/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.c b/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.c index 248588b098..f44511259d 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.c @@ -49,6 +49,7 @@ #include "up_arch.h" #include "up_internal.h" +#include "lm3s_internal.h" /**************************************************************************** * Private Definitions diff --git a/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.h b/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.h index 0b6f811cb6..5fe7ffd371 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.h +++ b/nuttx/arch/arm/src/lm3s/lm3s_syscontrol.h @@ -480,47 +480,8 @@ * Public Data ************************************************************************************/ -#ifndef __ASSEMBLY__ - -#undef EXTERN -#if defined(__cplusplus) -#define EXTERN extern "C" -extern "C" { -#else -#define EXTERN extern -#endif - /************************************************************************************ * Public Functions ************************************************************************************/ -/**************************************************************************** - * Name: lm3s_clockconfig - * - * Description: - * Called to check to new clock based on desired rcc and rcc2 settings. - * This is use to set up the initial clocking but can be used later to - * support slow clocked, low power consumption modes. - * - ****************************************************************************/ - -EXTERN void lm3s_clockconfig(uint32 newrcc, uint32 newrcc2); - -/**************************************************************************** - * Name: up_clockconfig - * - * Description: - * Called early in the bootsequence (before .data and .bss are available) - * in order to configure initial clocking. - * - ****************************************************************************/ - -EXTERN void up_clockconfig(void); - -#undef EXTERN -#if defined(__cplusplus) -} -#endif - -#endif /* __ASSEMBLY__ */ #endif /* __ARCH_ARM_SRC_LM3S_LM3S_SYSCONTROL_H */ diff --git a/nuttx/arch/arm/src/lm3s/lm3s_timerisr.c b/nuttx/arch/arm/src/lm3s/lm3s_timerisr.c index e4950d0424..f063ee9c50 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_timerisr.c +++ b/nuttx/arch/arm/src/lm3s/lm3s_timerisr.c @@ -49,6 +49,7 @@ #include "up_arch.h" #include "chip.h" +#include "lm3s_internal.h" /**************************************************************************** * Definitions diff --git a/nuttx/arch/arm/src/lm3s/lm3s_vectors.S b/nuttx/arch/arm/src/lm3s/lm3s_vectors.S index 1d10e9021c..3f196ae921 100644 --- a/nuttx/arch/arm/src/lm3s/lm3s_vectors.S +++ b/nuttx/arch/arm/src/lm3s/lm3s_vectors.S @@ -68,9 +68,16 @@ * Macros ************************************************************************************/ +/* On entry into an IRQ, the hardware automatically saves the xPSR, PC, LR, R12, R0-R3 + * registers on the stack, then branches to an instantantiation of the following + * macro. This macro simply loads the IRQ number into R0, then jumps to the common + * IRQ handling logic. + */ + .macro HANDLER, label, irqno \label: -#warning "Missing logic" + mov r0, \irqno + br lm3s_irqcommon .endm /************************************************************************************ @@ -171,6 +178,8 @@ lm3s_vectors: .text .thumb_func + .type handlers, function +handlers: HANDLER lm3s_reserved, LMSB_IRQ_RESERVED /* Unexpected/reserved vector */ HANDLER lm3s_nmi, LMSB_IRQ_NMI /* Vector 2: Non-Maskable Interrupt (NMI) */ HANDLER lm3s_hardfault, LMSB_IRQ_HARDFAULT /* Vector 3: Hard fault */ @@ -220,6 +229,93 @@ lm3s_vectors: # error "Vectors not specified for this LM3S chip" #endif + +/* Common IRQ handling logic. On entry here, the stack is like the following: + * + * REG_XPSR + * REG_R15 + * REG_R14 + * REG_R12 + * REG_R3 + * REG_R2 + * REG_R1 + * PSP->REG_R0 + * + * and R0 contains the IRQ number + */ + +lm3s_irqcommon: + /* Complete the context save */ + + mrs r1, psp /* R1=The process stack pointer */ + mov r3, r1 /* R3=Copy of the process stack pointer */ + add r3, #HW_XCPT_SIZE /* R3=PSP before the interrupt was taken */ + stmdb r1!, {r3-r11} /* Save the remaining registers plus the SP value */ + + /* Disable interrupts, select the stack to use for interrupt handling + * and call up_doirq to handle the interrupt + */ + + cpsid i /* Disable further interrupts */ + + /* If CONFIG_ARCH_INTERRUPTSTACK is defined, we will use a special interrupt + * stack pointer. The way that this is done here prohibits nested interrupts! + * Otherwise, we will re-use the process stack for interrupt level processing. + */ + +#ifdef CONFIG_ARCH_INTERRUPTSTACK + ld sp, #up_interruptstack_base +#else + mov sp, r1 /* Use the process stack pointer */ +#endif + stmdb sp!, {r1, r14} /* Save the process SP and the return LR */ + bl up_doirq /* R0=IRQ, R1=register save */ + ldmia sp!, {r1, r14} /* Recover the process SP and the return LR */ + + /* On return from up_doirq, R0 will hold a pointer to register context + * array to use for the interrupt return. If that return value is the same + * as current stack pointer, then things are relatively easy. + */ + + cmp r0, r1 + beq 1f /* Branch if no context switch */ + + /* We are returning from a context switch. This is different because in this + * case, the register save structure does not lie on the stack but, rather, + * is within a TCB structure. We'll have to copy some values to the stack. + */ + + add r1, r0, #(XCPTCONTEXT_SIZE-4) /* r2=offset HW save area */ + ldmia r1, {r4, r11} /* Eight registers in HW save area */ + ldr r1, [r0, #(4*REG_SP)] /* R1=Value of SP before interrupt */ + stmdb r1!, {r4, r11} /* Eight registers in HW save area */ + mov psp, r1 /* New PSP */ + + /* We simply need to "unwind" the same stack frame that we created */ +1: + cpsie i /* Restore interrupts */ + stmdb r0!, {r3-r11} /* Recover R4-R11 (R3 does not have the correct value yet) * the remaining registers plus the SP value */ + bx r14 /* And return */ + .size handler, .-handlers + +/************************************************************************************ + * Name: up_interruptstack/g_userstack + * + * Description: + * Shouldn't happen + * + ************************************************************************************/ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + .bss + .align 4 +up_interruptstack: + .skip ((CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4) +up_interruptstack_base: + .skip 4 + .size up_interruptstack, .-up_interruptstack +#endif + /************************************************************************************ * .rodata ************************************************************************************/ -- cgit v1.2.3