summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2007-11-06 22:53:06 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2007-11-06 22:53:06 +0000
commit7afd0b130baa3d361b4536a9210818a2feb61cdc (patch)
tree7cc5bf8f48bc9cc8711ea14dde74c1f4c87d4c73 /cpukit
parent2007-11-03 Ray Xu <rayx.cn@gmail.com> (diff)
downloadrtems-7afd0b130baa3d361b4536a9210818a2feb61cdc.tar.bz2
2007-11-06 Joel Sherrill <joel.sherrill@OARcorp.com>
* .cvsignore, ChangeLog, Makefile.am, thumb_isr.c: New files.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/score/cpu/arm/thumb/.cvsignore1
-rw-r--r--cpukit/score/cpu/arm/thumb/ChangeLog8
-rw-r--r--cpukit/score/cpu/arm/thumb/Makefile.am14
-rw-r--r--cpukit/score/cpu/arm/thumb/thumb_isr.c182
4 files changed, 205 insertions, 0 deletions
diff --git a/cpukit/score/cpu/arm/thumb/.cvsignore b/cpukit/score/cpu/arm/thumb/.cvsignore
new file mode 100644
index 0000000000..70845e08eb
--- /dev/null
+++ b/cpukit/score/cpu/arm/thumb/.cvsignore
@@ -0,0 +1 @@
+Makefile.in
diff --git a/cpukit/score/cpu/arm/thumb/ChangeLog b/cpukit/score/cpu/arm/thumb/ChangeLog
new file mode 100644
index 0000000000..6a35e22e9c
--- /dev/null
+++ b/cpukit/score/cpu/arm/thumb/ChangeLog
@@ -0,0 +1,8 @@
+2007-11-06 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * .cvsignore, ChangeLog, Makefile.am, thumb_isr.c: New files.
+
+2007-11-03 Ray Xu <rayx.cn@gmail.com>
+
+ * Makefile.am, thumb_isr.c : add support for ARM<->THUMB veneer
+ thumb_isr.c control CPSR/SPRS in thumb mode
diff --git a/cpukit/score/cpu/arm/thumb/Makefile.am b/cpukit/score/cpu/arm/thumb/Makefile.am
new file mode 100644
index 0000000000..b263afae29
--- /dev/null
+++ b/cpukit/score/cpu/arm/thumb/Makefile.am
@@ -0,0 +1,14 @@
+##
+## $Id$
+##
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+
+noinst_LIBRARIES = libthumbisr.a
+libthumbisr_a_SOURCES = thumb_isr.c
+libthumbisr_a_CPPFLAGS = $(AM_CPPFLAGS)
+#CFLAGS += -marm -mthumb-interwork
+
+include $(top_srcdir)/automake/subdirs.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/arm/thumb/thumb_isr.c b/cpukit/score/cpu/arm/thumb/thumb_isr.c
new file mode 100644
index 0000000000..34a38a06de
--- /dev/null
+++ b/cpukit/score/cpu/arm/thumb/thumb_isr.c
@@ -0,0 +1,182 @@
+/*
+* The thumb mode do not support multi-level ISR, only disable and enable
+*/
+#include <rtems/system.h>
+
+#if (defined(__THUMB_INTERWORK__) || defined(__thumb__))
+
+/*
+ *
+ * _CPU_ISR_Get_level_Thumb - returns the current interrupt level
+ */
+uint32_t _CPU_ISR_Get_level_Thumb(void) __attribute__ ((naked));
+unsigned int _CPU_ISR_Disable_Thumb(void ) __attribute__ ((naked));
+void __inline__ _CPU_ISR_Enable_Thumb(int _level ) __attribute__ ((naked));
+void __inline__ _CPU_ISR_Flash_Thumb(int _level ) __attribute__ ((naked));
+void __inline__ _CPU_ISR_Set_level_Thumb(int new_level ) __attribute__ ((naked));
+
+/*
+ * prevent multipule enable/disable ISR
+ * 0: ISR enabled, >1 ISR disabled
+ */
+
+/*
+ * Set the CPSR bit 6,7 to 1 disables FIQ and IRQ
+ * Set the CPSR bit 6,7 to 0 enables FIQ and IRQ
+ */
+
+
+
+/*
+ * Fix me: use mutex to visit isr_flag
+ */
+
+#define str(x) #x
+#define xstr(x) str(x)
+#define L(x) #x "_" xstr(__LINE__)
+
+#define U0THR (*((volatile unsigned char *) 0xE000C000))
+#define U0LSR (*((volatile unsigned char *) 0xE000C014))
+
+void __inline__ UART0_Send_Byte(char data)
+{
+ U0THR = data;
+
+ while( (U0LSR&0x40)==0 );
+}
+
+/*
+ * Switch to ARM mode Veneer,ugly but safe
+ */
+#define TO_ARM_MODE(x) \
+ asm volatile ( \
+ ".code 16 \n" \
+ L(x) "_thumb: \n" \
+ ".align 2 \n" \
+ "push {lr} \n" \
+ "adr %0, "L(x) "_arm \n" \
+ "bl " L(x)" \n" \
+ "pop {pc} \n" \
+ ".balign 4 \n" \
+ L(x) ": \n" \
+ "bx %0 \n" \
+ "nop \n" \
+ ".pool \n" \
+ ".code 32 \n" \
+ L(x) "_arm: \n" \
+ : "=&r" (reg))
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+unsigned int __inline__ _CPU_ISR_Disable_Thumb(void )
+ {
+ int reg=0;
+ TO_ARM_MODE(disable);
+ asm volatile ( \
+ ".code 32 \n" \
+ "STMDB sp!, {r1} \n" \
+ "MRS r0, CPSR \n" \
+ "DISABLE_ARM: \n" \
+ "ORR r1, r0, #0xc0 \n" \
+ "MSR CPSR, r1 \n" \
+ "pop {r1} \n" \
+ "BX LR \n" \
+ ".code 16 \n" );
+ }
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable_Thumb).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified. I do not think _level is useful in this
+ */
+
+void __inline__ _CPU_ISR_Enable_Thumb(int _level )
+ {
+ int reg=0;
+ TO_ARM_MODE(enable);
+ asm volatile ( \
+ ".code 32 \n" \
+ "ENABLE_ARM: \n" \
+ "MSR CPSR, %0 \n" \
+ /* Return back to thumb.*/ \
+ "BX R14 \n" \
+ ".code 16 \n" \
+ : : "r"(_level));
+ }
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+void __inline__ _CPU_ISR_Flash_Thumb(int _level )
+ {
+ int reg=0;
+ UART0_Send_Byte(70);
+ //asm volatile("NOP");
+ //(*((volatile unsigned char *) 0xE000C000))='\r';
+ TO_ARM_MODE(flash);
+ asm volatile ( \
+ ".code 32 \n" \
+ "FLASH_ARM: \n" \
+ "MRS %0, CPSR \n" \
+ "BIC %0, %0, #0xC0 \n" \
+ /* enable the irq*/ \
+ "MSR CPSR_c, %0 \n" \
+ "ORR %0, %0, #0xc0 \n" \
+ "MSR CPSR_c, %0 \n" \
+ "BX R14 \n" \
+ ".code 16 \n" \
+ :"=&r"(reg) : "r" (_level));
+ }
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * The get routine usually must be implemented as a subroutine.
+ * ARM/Thumb dont distinguishd the interrupt levels
+ */
+
+void __inline__ _CPU_ISR_Set_level_Thumb(int new_level )
+ {
+ int reg = 0; /* to avoid warning */ \
+ TO_ARM_MODE(SetISR); \
+ asm volatile (\
+ ".code 32 \n" \
+ "SET_LEVEL_ARM: \n" \
+ "MRS %0, CPSR \n" \
+ "BIC %0, %0, #0xC0 \n" \
+ "MSR CPSR_c, %0 \n" \
+ "BX lr \n" \
+ ".code 16 \n" \
+ : "=r" (reg) \
+ : "0" (reg));
+ }
+
+uint32_t __inline__ _CPU_ISR_Get_level_Thumb( void )
+{
+ uint32_t reg = 0; /* to avoid warning */
+ TO_ARM_MODE(GetISR); \
+ asm volatile (\
+ ".code 32 \n" \
+ "GET_ISR_ARM: \n" \
+ "MRS r0, cpsr \n" \
+ "AND r0, r0, #0xC0 \n" \
+ "EOR r0, r0, #0xC0 \n" \
+ "BX LR \n" \
+ ".code 16 \n" \
+ ".thumb_func \n" );
+}
+
+#endif