cpu: Split frame handling macros to the new header cpu/frame.h
authorbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 10 Aug 2008 19:41:26 +0000 (19:41 +0000)
committerbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 10 Aug 2008 19:41:26 +0000 (19:41 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1616 38d2e660-2303-0410-9eaa-f027e97ec537

bertos/cpu/attr.h
bertos/cpu/frame.h [new file with mode: 0644]
bertos/kern/monitor.c
bertos/kern/proc.c

index c5f0201e6dde1b949209e26a67e0f0e9f6642906..02c745e57fb2819f68db50f3e5025c8036b5979a 100644 (file)
@@ -26,7 +26,7 @@
  * invalidate any other reasons why the executable file might be covered by
  * the GNU General Public License.
  *
- * Copyright 2004, 2005, 2006, 2007 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2004, 2005, 2006, 2007, 2008 Develer S.r.l. (http://www.develer.com/)
  * Copyright 2004 Giovanni Bajo
  *
  * -->
@@ -44,8 +44,6 @@
 #include "detect.h"
 
 #include "cfg/cfg_attr.h"      /* CONFIG_FAST_MEM */
-#include "cfg/cfg_arch.h"      /* ARCH_EMUL */
-#include <cfg/compiler.h>      /* for uintXX_t */
 
 
 /**
 
        #define CPU_REG_BITS            16
        #define CPU_REGS_CNT            16
-       #define CPU_STACK_GROWS_UPWARD  0
-       #define CPU_SP_ON_EMPTY_SLOT    0
        #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
-       #define CPU_HARVARD             0
+       #define CPU_HARVARD             0
 
        /// Valid pointers should be >= than this value (used for debug)
        #define CPU_RAM_START           0x100
        #define NOP                     asm volatile ("nop")
 
        #define CPU_REGS_CNT            7
-       #define CPU_SAVED_REGS_CNT      7
-       #define CPU_STACK_GROWS_UPWARD  0
-       #define CPU_SP_ON_EMPTY_SLOT    0
        #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
-       #define CPU_HARVARD             0
+       #define CPU_HARVARD             0
 
        #if CPU_X86_64
                #define CPU_REG_BITS    64
 
 #elif CPU_ARM
 
-       /* Register counts include SREG too */
        #define CPU_REG_BITS           32
        #define CPU_REGS_CNT           16
-       #define CPU_SAVED_REGS_CNT     9
-       #define CPU_STACK_GROWS_UPWARD 0
-       #define CPU_SP_ON_EMPTY_SLOT   0
        #define CPU_HARVARD            0
 
        /// Valid pointers should be >= than this value (used for debug)
 
                #define NOP            asm volatile ("mov r0,r0" ::)
 
-               /**
-                * Initialization value for registers in stack frame.
-                * The register index is not directly corrispondent to CPU
-                * register numbers, but is related to how are pushed to
-                * stack (\see asm_switch_context).
-                * Index (CPU_SAVED_REGS_CNT - 1) is the CPSR register,
-                * the initial value is set to:
-                * - All flags (N, Z, C, V) set to 0.
-                * - IRQ and FIQ enabled.
-                * - ARM state.
-                * - CPU in Supervisor Mode (SVC).
-                */
-               #define CPU_REG_INIT_VALUE(reg) (reg == (CPU_SAVED_REGS_CNT - 1) ? 0x13 : 0)
-
                #if CONFIG_FAST_MEM
                        /**
                         * Function attribute for use with performance critical code.
        #endif /* !__IAR_SYSTEMS_ICC_ */
 
 #elif CPU_PPC
-       #define NOP                 asm volatile ("nop" ::)
 
-       /* Register counts include SREG too */
+       #define NOP                    asm volatile ("nop" ::)
+
        #define CPU_REG_BITS           (CPU_PPC32 ? 32 : 64)
        #define CPU_REGS_CNT           FIXME
-       #define CPU_SAVED_REGS_CNT     1  // FIXME
-       #define CPU_STACK_GROWS_UPWARD 0  //FIXME
-       #define CPU_SP_ON_EMPTY_SLOT   0  //FIXME
        #define CPU_BYTE_ORDER         (__BIG_ENDIAN__ ? CPU_BIG_ENDIAN : CPU_LITTLE_ENDIAN)
        #define CPU_HARVARD            0
 
 
        #define CPU_REG_BITS            16
        #define CPU_REGS_CNT            FIXME
-       #define CPU_SAVED_REGS_CNT      8
-       #define CPU_STACK_GROWS_UPWARD  1
-       #define CPU_SP_ON_EMPTY_SLOT    0
        #define CPU_BYTE_ORDER          CPU_BIG_ENDIAN
        #define CPU_HARVARD             1
 
 
 #elif CPU_AVR
 
-       #define NOP           asm volatile ("nop" ::)
+       #define NOP                     asm volatile ("nop" ::)
 
-       /* Register counts include SREG too */
        #define CPU_REG_BITS            8
-       #define CPU_REGS_CNT           33
-       #define CPU_SAVED_REGS_CNT     19
-       #define CPU_STACK_GROWS_UPWARD  0
-       #define CPU_SP_ON_EMPTY_SLOT    1
+       #define CPU_REGS_CNT           33 /* Includes SREG */
        #define CPU_BYTE_ORDER          CPU_LITTLE_ENDIAN
        #define CPU_HARVARD             1
 
-       /**
-        * Initialization value for registers in stack frame.
-        * The register index is not directly corrispondent to CPU
-        * register numbers. Index 0 is the SREG register: the initial
-        * value is all 0 but the interrupt bit (bit 7).
-        */
-       #define CPU_REG_INIT_VALUE(reg) (reg == 0 ? 0x80 : 0)
-
        /// Valid pointers should be >= than this value (used for debug)
        #define CPU_RAM_START           0x100
 
        #error No CPU_... defined.
 #endif
 
-/// Default for macro not defined in the right arch section
-#ifndef CPU_REG_INIT_VALUE
-       #define CPU_REG_INIT_VALUE(reg)     0
-#endif
-
-#ifndef CPU_STACK_GROWS_UPWARD
-       #error CPU_STACK_GROWS_UPWARD should have been defined to either 0 or 1
-#endif
-
-#ifndef CPU_SP_ON_EMPTY_SLOT
-       #error CPU_SP_ON_EMPTY_SLOT should have been defined to either 0 or 1
-#endif
-
 #ifndef FAST_FUNC
-       /**
-        * Function attribute for use with performance critical code.
-        */
+       /// Function attribute for use with performance critical code.
        #define FAST_FUNC /* */
 #endif
 
 #ifndef FAST_RODATA
-       /**
-        * Data attribute to move constant data to fast memory storage.
-        */
+       /// Data attribute to move constant data to fast memory storage.
        #define FAST_RODATA /* */
 #endif
 
-/*
- * Support stack handling peculiarities of a few CPUs.
- *
- * Most processors let their stack grow downward and
- * keep SP pointing at the last pushed value.
- */
-#if !CPU_STACK_GROWS_UPWARD
-       #if !CPU_SP_ON_EMPTY_SLOT
-               /* Most microprocessors (x86, m68k...) */
-               #define CPU_PUSH_WORD(sp, data) \
-                       do { *--(sp) = (data); } while (0)
-               #define CPU_POP_WORD(sp) \
-                       (*(sp)++)
-       #else
-               /* AVR insanity */
-               #define CPU_PUSH_WORD(sp, data) \
-                       do { *(sp)-- = (data); } while (0)
-               #define CPU_POP_WORD(sp) \
-                       (*++(sp))
-       #endif
-
-#else /* CPU_STACK_GROWS_UPWARD */
-
-       #if !CPU_SP_ON_EMPTY_SLOT
-               /* DSP56K and other weirdos */
-               #define CPU_PUSH_WORD(sp, data) \
-                       do { *++(sp) = (cpustack_t)(data); } while (0)
-               #define CPU_POP_WORD(sp) \
-                       (*(sp)--)
-       #else
-               #error I bet you cannot find a CPU like this
-       #endif
-#endif
-
-
-#if CPU_DSP56K
-       /*
-        * DSP56k pushes both PC and SR to the stack in the JSR instruction, but
-        * RTS discards SR while returning (it does not restore it). So we push
-        * 0 to fake the same context.
-        */
-       #define CPU_PUSH_CALL_FRMAE(sp, func) \
-               do { \
-                       CPU_PUSH_WORD((sp), (func)); \
-                       CPU_PUSH_WORD((sp), 0x100); \
-               } while (0);
-
-#elif CPU_AVR
-       /*
-        * On AVR, addresses are pushed into the stack as little-endian, while
-        * memory accesses are big-endian (actually, it's a 8-bit CPU, so there is
-        * no natural endianess).
-        */
-       #define CPU_PUSH_CALL_FRAME(sp, func) \
-               do { \
-                       uint16_t funcaddr = (uint16_t)(func); \
-                       CPU_PUSH_WORD((sp), funcaddr); \
-                       CPU_PUSH_WORD((sp), funcaddr>>8); \
-               } while (0)
-
-       /*
-        * If the kernel is in idle-spinning, the processor executes:
-        *
-        * IRQ_ENABLE;
-        * CPU_IDLE;
-        * IRQ_DISABLE;
-        *
-        * IRQ_ENABLE is translated in asm as "sei" and IRQ_DISABLE as "cli".
-        * We could define CPU_IDLE to expand to none, so the resulting
-        * asm code would be:
-        *
-        * sei;
-        * cli;
-        *
-        * But Atmel datasheet states:
-        * "When using the SEI instruction to enable interrupts,
-        * the instruction following SEI will be executed *before*
-        * any pending interrupts", so "cli" is executed before any
-        * pending interrupt with the result that IRQs will *NOT*
-        * be enabled!
-        * To ensure that IRQ will run a NOP is required.
-        */
-       #define CPU_IDLE NOP
-
-#elif CPU_PPC
-
-       #define CPU_PUSH_CALL_FRAME(sp, func) \
-               do { \
-                       CPU_PUSH_WORD((sp), (cpustack_t)(func)); /* LR -> 8(SP) */ \
-                       CPU_PUSH_WORD((sp), 0);                  /* CR -> 4(SP) */ \
-               } while (0)
-
-#else
-       #define CPU_PUSH_CALL_FRAME(sp, func) \
-               CPU_PUSH_WORD((sp), (cpustack_t)(func))
-#endif
-
-/**
- * \def CPU_IDLE
- *
- * \brief Invoked by the scheduler to stop the CPU when idle.
- *
- * This hook can be redefined to put the CPU in low-power mode, or to
- * profile system load with an external strobe, or to save CPU cycles
- * in hosted environments such as emulators.
- */
-#ifndef CPU_IDLE
-       #if defined(ARCH_EMUL) && (ARCH & ARCH_EMUL)
-               /* This emulator hook should yield the CPU to the host.  */
-               EXTERN_C_BEGIN
-               void emul_idle(void);
-               EXTERN_C_END
-               #define CPU_IDLE emul_idle()
-       #else /* !ARCH_EMUL */
-               #define CPU_IDLE do { /* nothing */ } while (0)
-       #endif /* !ARCH_EMUL */
-#endif /* !CPU_IDLE */
-
 #endif /* CPU_ATTR_H */
diff --git a/bertos/cpu/frame.h b/bertos/cpu/frame.h
new file mode 100644 (file)
index 0000000..a17c8ef
--- /dev/null
@@ -0,0 +1,240 @@
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2008 Bernie Innocenti <bernie@codewiz.org>
+ * Copyright 2004, 2005, 2006, 2007, 2008 Develer S.r.l. (http://www.develer.com/)
+ * Copyright 2004 Giovanni Bajo
+ *
+ * -->
+ *
+ * \brief CPU-specific stack frame handling macros.
+ *
+ * These are mainly used by the portable part of the scheduler
+ * to work with the process stack frames.
+ *
+ * \author Giovanni Bajo <rasky@develer.com>
+ * \author Bernie Innocenti <bernie@codewiz.org>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ * \author Francesco Sacchi <batt@develer.com>
+ */
+#ifndef CPU_FRAME_H
+#define CPU_FRAME_H
+
+#include <cpu/detect.h>
+
+#include "cfg/cfg_arch.h"      /* ARCH_EMUL */
+#include <cfg/compiler.h>      /* for uintXX_t */
+
+#if CPU_X86
+
+       #define CPU_SAVED_REGS_CNT      7
+       #define CPU_STACK_GROWS_UPWARD  0
+       #define CPU_SP_ON_EMPTY_SLOT    0
+
+#elif CPU_ARM
+
+       #define CPU_SAVED_REGS_CNT     9
+       #define CPU_STACK_GROWS_UPWARD 0
+       #define CPU_SP_ON_EMPTY_SLOT   0
+
+       /**
+        * Initialization value for registers in stack frame.
+        * The register index is not directly corrispondent to CPU
+        * register numbers, but is related to how are pushed to
+        * stack (\see asm_switch_context).
+        * Index (CPU_SAVED_REGS_CNT - 1) is the CPSR register,
+        * the initial value is set to:
+        * - All flags (N, Z, C, V) set to 0.
+        * - IRQ and FIQ enabled.
+        * - ARM state.
+        * - CPU in Supervisor Mode (SVC).
+        */
+       #define CPU_REG_INIT_VALUE(reg) (reg == (CPU_SAVED_REGS_CNT - 1) ? 0x13 : 0)
+
+#elif CPU_PPC
+
+       #define CPU_SAVED_REGS_CNT     1
+       #define CPU_STACK_GROWS_UPWARD 0
+       #define CPU_SP_ON_EMPTY_SLOT   0
+
+#elif CPU_DSP56K
+
+       #define CPU_SAVED_REGS_CNT      8
+       #define CPU_STACK_GROWS_UPWARD  1
+       #define CPU_SP_ON_EMPTY_SLOT    0
+
+#elif CPU_AVR
+
+       #define CPU_SAVED_REGS_CNT     19
+       #define CPU_STACK_GROWS_UPWARD  0
+       #define CPU_SP_ON_EMPTY_SLOT    1
+
+       /**
+        * Initialization value for registers in stack frame.
+        * The register index is not directly corrispondent to CPU
+        * register numbers. Index 0 is the SREG register: the initial
+        * value is all 0 but the interrupt bit (bit 7).
+        */
+       #define CPU_REG_INIT_VALUE(reg) (reg == 0 ? 0x80 : 0)
+
+#else
+       #error No CPU_... defined.
+#endif
+
+#ifndef CPU_STACK_GROWS_UPWARD
+       #error CPU_STACK_GROWS_UPWARD should have been defined to either 0 or 1
+#endif
+
+#ifndef CPU_SP_ON_EMPTY_SLOT
+       #error CPU_SP_ON_EMPTY_SLOT should have been defined to either 0 or 1
+#endif
+
+/// Default for macro not defined in the right arch section
+#ifndef CPU_REG_INIT_VALUE
+       #define CPU_REG_INIT_VALUE(reg)     0
+#endif
+
+/*
+ * Support stack handling peculiarities of a few CPUs.
+ *
+ * Most processors let their stack grow downward and
+ * keep SP pointing at the last pushed value.
+ */
+#if !CPU_STACK_GROWS_UPWARD
+       #if !CPU_SP_ON_EMPTY_SLOT
+               /* Most microprocessors (x86, m68k...) */
+               #define CPU_PUSH_WORD(sp, data) \
+                       do { *--(sp) = (data); } while (0)
+               #define CPU_POP_WORD(sp) \
+                       (*(sp)++)
+       #else
+               /* AVR insanity */
+               #define CPU_PUSH_WORD(sp, data) \
+                       do { *(sp)-- = (data); } while (0)
+               #define CPU_POP_WORD(sp) \
+                       (*++(sp))
+       #endif
+
+#else /* CPU_STACK_GROWS_UPWARD */
+
+       #if !CPU_SP_ON_EMPTY_SLOT
+               /* DSP56K and other weirdos */
+               #define CPU_PUSH_WORD(sp, data) \
+                       do { *++(sp) = (cpustack_t)(data); } while (0)
+               #define CPU_POP_WORD(sp) \
+                       (*(sp)--)
+       #else
+               #error I bet you cannot find a CPU like this
+       #endif
+#endif
+
+
+#if CPU_DSP56K
+       /*
+        * DSP56k pushes both PC and SR to the stack in the JSR instruction, but
+        * RTS discards SR while returning (it does not restore it). So we push
+        * 0 to fake the same context.
+        */
+       #define CPU_PUSH_CALL_FRMAE(sp, func) \
+               do { \
+                       CPU_PUSH_WORD((sp), (func)); \
+                       CPU_PUSH_WORD((sp), 0x100); \
+               } while (0);
+
+#elif CPU_AVR
+       /*
+        * On AVR, addresses are pushed into the stack as little-endian, while
+        * memory accesses are big-endian (actually, it's a 8-bit CPU, so there is
+        * no natural endianess).
+        */
+       #define CPU_PUSH_CALL_FRAME(sp, func) \
+               do { \
+                       uint16_t funcaddr = (uint16_t)(func); \
+                       CPU_PUSH_WORD((sp), funcaddr); \
+                       CPU_PUSH_WORD((sp), funcaddr>>8); \
+               } while (0)
+
+       /*
+        * If the kernel is in idle-spinning, the processor executes:
+        *
+        * IRQ_ENABLE;
+        * CPU_IDLE;
+        * IRQ_DISABLE;
+        *
+        * IRQ_ENABLE is translated in asm as "sei" and IRQ_DISABLE as "cli".
+        * We could define CPU_IDLE to expand to none, so the resulting
+        * asm code would be:
+        *
+        * sei;
+        * cli;
+        *
+        * But Atmel datasheet states:
+        * "When using the SEI instruction to enable interrupts,
+        * the instruction following SEI will be executed *before*
+        * any pending interrupts", so "cli" is executed before any
+        * pending interrupt with the result that IRQs will *NOT*
+        * be enabled!
+        * To ensure that IRQ will run a NOP is required.
+        */
+       #define CPU_IDLE NOP
+
+#elif CPU_PPC
+
+       #define CPU_PUSH_CALL_FRAME(sp, func) \
+               do { \
+                       CPU_PUSH_WORD((sp), (cpustack_t)(func)); /* LR -> 8(SP) */ \
+                       CPU_PUSH_WORD((sp), 0);                  /* CR -> 4(SP) */ \
+               } while (0)
+
+#else
+       #define CPU_PUSH_CALL_FRAME(sp, func) \
+               CPU_PUSH_WORD((sp), (cpustack_t)(func))
+#endif
+
+/**
+ * \def CPU_IDLE
+ *
+ * \brief Invoked by the scheduler to stop the CPU when idle.
+ *
+ * This hook can be redefined to put the CPU in low-power mode, or to
+ * profile system load with an external strobe, or to save CPU cycles
+ * in hosted environments such as emulators.
+ */
+#ifndef CPU_IDLE
+       #if defined(ARCH_EMUL) && (ARCH & ARCH_EMUL)
+               /* This emulator hook should yield the CPU to the host.  */
+               EXTERN_C_BEGIN
+               void emul_idle(void);
+               EXTERN_C_END
+               #define CPU_IDLE emul_idle()
+       #else /* !ARCH_EMUL */
+               #define CPU_IDLE do { /* nothing */ } while (0)
+       #endif /* !ARCH_EMUL */
+#endif /* !CPU_IDLE */
+
+#endif /* CPU_ATTR_H */
index f9eaf3b8de5a9b2b3d7f4e6abd366282e14e246c..1f9ee7919acd1032afda8724ad3b459f884b567b 100644 (file)
@@ -45,6 +45,7 @@
 #include <mware/list.h>
 #include <drv/timer.h>
 #include <kern/proc.h>
+#include <cpu/frame.h> /* CPU_STACK_GROWS_UPWARD */
 #include <cfg/macros.h>
 #include <cfg/debug.h>
 
index 84c5366370911c10e61c3a5f1b2c8dd5397dfd9c..51cf0c14b3f91c8043322ff9e292155a28d8b3fd 100644 (file)
@@ -54,6 +54,7 @@
 #include <cpu/irq.h>
 #include <cpu/types.h>
 #include <cpu/attr.h>
+#include <cpu/frame.h>
 
 #include <mware/event.h>