diff options
Diffstat (limited to 'demos')
-rw-r--r-- | demos/ARM7-LPC214x-GCC/chcore.c | 169 | ||||
-rw-r--r-- | demos/ARM7-LPC214x-GCC/chcore.h | 31 | ||||
-rw-r--r-- | demos/ARM7-LPC214x-GCC/chcore2.s | 139 | ||||
-rw-r--r-- | demos/ARM7-LPC214x-GCC/crt0.s | 21 | ||||
-rw-r--r-- | demos/Win32-MSVS/chcore.h | 2 | ||||
-rw-r--r-- | demos/Win32-MinGW/chcore.h | 2 |
6 files changed, 197 insertions, 167 deletions
diff --git a/demos/ARM7-LPC214x-GCC/chcore.c b/demos/ARM7-LPC214x-GCC/chcore.c index 5313ecdb4..8b9b4d464 100644 --- a/demos/ARM7-LPC214x-GCC/chcore.c +++ b/demos/ARM7-LPC214x-GCC/chcore.c @@ -162,19 +162,11 @@ void chSysPuts(char *msg) { __attribute__((naked, weak))
void IrqHandler(void) {
- asm(".code 32 \n\t" \
- "stmfd sp!, {r0-r3, r12, lr} \n\t");
-#ifdef THUMB
- asm("add r0, pc, #1 \n\t" \
- "bx r0 \n\t" \
- ".code 16 \n\t");
- VICVectAddr = 0;
- asm("ldr r0, =IrqCommon \n\t" \
- "bx r0 \n\t");
-#else
- VICVectAddr = 0;
- asm("b IrqCommon \n\t");
-#endif
+ chSysIRQEnterI();
+
+ /* nothing */
+
+ chSysIRQExitI();
}
/*
@@ -183,21 +175,148 @@ void IrqHandler(void) { __attribute__((naked, weak))
void T0IrqHandler(void) {
- asm(".code 32 \n\t" \
- "stmfd sp!, {r0-r3, r12, lr} \n\t");
-#ifdef THUMB
- asm("add r0, pc, #1 \n\t" \
- "bx r0 \n\t" \
- ".code 16 \n\t");
+ chSysIRQEnterI();
+
T0IR = 1; /* Clear interrupt on match MR0. */
chSysTimerHandlerI();
+
+ chSysIRQExitI();
+}
+
+/*
+ * Common IRQ exit code, \p chSysIRQExitI() just jumps here.
+ *
+ * System stack frame structure after a context switch in the
+ * interrupt handler:
+ *
+ * High +------------+
+ * | LR_USR | -+
+ * | R12 | |
+ * | R3 | |
+ * | R2 | | External context: IRQ handler frame
+ * | R1 | |
+ * | R0 | |
+ * | LR_IRQ | | (user code return address)
+ * | SPSR | -+ (user code status)
+ * | .... | <- chSchDoRescheduleI() stack frame, optimize it for space
+ * | LR | -+ (system code return address)
+ * | R11 | |
+ * | R10 | |
+ * | R9 | |
+ * | R8 | | Internal context: chSysSwitchI() frame
+ * | (R7) | | (optional, see CH_CURRP_REGISTER_CACHE)
+ * | R6 | |
+ * | R5 | |
+ * SP-> | R4 | -+
+ * Low +------------+
+ */
+__attribute__((naked, weak))
+void IrqCommon(void) {
+ register BOOL b asm("r0");
+
VICVectAddr = 0;
- asm("ldr r0, =IrqCommon \n\t" \
- "bx r0 \n\t");
+ b = chSchRescRequiredI();
+#ifdef THUMB
+ asm(".p2align 2,, \n\t" \
+ "mov lr, pc \n\t" \
+ "bx lr \n\t" \
+ ".code 32 \n\t");
+#endif
+ /*
+ * If a reschedulation is not required then just returns from the IRQ.
+ */
+ asm("cmp r0, #0 \n\t" \
+ "ldmeqfd sp!, {r0-r3, r12, lr} \n\t" \
+ "subeqs pc, lr, #4 \n\t");
+ /*
+ * Reschedulation required, saves the external context on the
+ * system/user stack and empties the IRQ stack.
+ */
+ asm(".set MODE_IRQ, 0x12 \n\t" \
+ ".set MODE_SYS, 0x1F \n\t" \
+ ".set I_BIT, 0x80 \n\t" \
+ "ldmfd sp!, {r0-r3, r12, lr} \n\t" \
+ "msr CPSR_c, #MODE_SYS | I_BIT \n\t" \
+ "stmfd sp!, {r0-r3, r12, lr} \n\t" \
+ "msr CPSR_c, #MODE_IRQ | I_BIT \n\t" \
+ "mrs r0, SPSR \n\t" \
+ "mov r1, lr \n\t" \
+ "msr CPSR_c, #MODE_SYS | I_BIT \n\t" \
+ "stmfd sp!, {r0, r1} \n\t");
+
+#ifdef THUMB_NO_INTERWORKING
+ asm("add r0, pc, #1 \n\t" \
+ "bx r0 \n\t" \
+ ".code 16 \n\t" \
+ "bl chSchDoRescheduleI \n\t" \
+ ".p2align 2,, \n\t" \
+ "mov lr, pc \n\t" \
+ "bx lr \n\t" \
+ ".code 32 \n\t");
#else
- T0IR = 1; /* Clear interrupt on match MR0. */
- chSysTimerHandlerI();
- VICVectAddr = 0;
- asm("b IrqCommon \n\t");
+ asm("bl chSchDoRescheduleI \n\t");
+#endif
+
+ /*
+ * Restores the external context.
+ */
+ asm("ldmfd sp!, {r0, r1} \n\t" \
+ "msr CPSR_c, #MODE_IRQ | I_BIT \n\t" \
+ "msr SPSR_fsxc, r0 \n\t" \
+ "mov lr, r1 \n\t" \
+ "msr CPSR_c, #MODE_SYS | I_BIT \n\t" \
+ "ldmfd sp!, {r0-r3, r12, lr} \n\t" \
+ "msr CPSR_c, #MODE_IRQ | I_BIT \n\t" \
+ "subs pc, lr, #4 \n\t");
+
+ /*
+ * Threads entry/exit code. It is declared weak so you can easily replace it.
+ * NOTE: It is always invoked in ARM mode, it does the mode switching.
+ * NOTE: It is included into IrqCommon to make sure the symbol refers to
+ * 32 bit code.
+ */
+ asm(".set F_BIT, 0x40 \n\t" \
+ ".weak threadstart \n\t" \
+ ".globl threadstart \n\t" \
+ "threadstart: \n\t" \
+ "msr CPSR_c, #MODE_SYS \n\t");
+#ifndef THUMB_NO_INTERWORKING
+ asm("mov r0, r5 \n\t" \
+ "mov lr, pc \n\t" \
+ "bx r4 \n\t" \
+ "bl chThdExit \n\t");
+#else
+ asm("add r0, pc, #1 \n\t" \
+ "bx r0 \n\t" \
+ ".code 16 \n\t" \
+ "mov r0, r5 \n\t" \
+ "bl jmpr4 \n\t" \
+ "bl chThdExit \n\t" \
+ "jmpr4: \n\t" \
+ "bx r4 \n\t");
+#endif
+}
+
+/*
+ * System halt.
+ */
+__attribute__((naked, weak))
+void chSysHalt(void) {
+
+ asm(".set F_BIT, 0x40 \n\t" \
+ ".set I_BIT, 0x80 \n\t");
+#ifdef THUMB
+ asm(".p2align 2,, \n\t" \
+ "mov r0, pc \n\t" \
+ "bx r0 \n\t");
#endif
+ asm(".code 32 \n\t" \
+ ".weak _halt32 \n\t" \
+ ".globl _halt32 \n\t" \
+ "_halt32: \n\t" \
+ "mrs r0, CPSR \n\t" \
+ "orr r0, #I_BIT | F_BIT \n\t" \
+ "msr CPSR_c, r0 \n\t" \
+ ".loop: \n\t" \
+ "b .loop \n\t");
}
diff --git a/demos/ARM7-LPC214x-GCC/chcore.h b/demos/ARM7-LPC214x-GCC/chcore.h index 941036830..cc1113c18 100644 --- a/demos/ARM7-LPC214x-GCC/chcore.h +++ b/demos/ARM7-LPC214x-GCC/chcore.h @@ -92,7 +92,7 @@ extern void chSysUnlock(void); #define INT_REQUIRED_STACK 0x10
#else /* !THUMB */
#define INT_REQUIRED_STACK 0
-#endif /* THUMB */
+#endif /* !THUMB */
#define StackAlign(n) ((((n) - 1) | 3) + 1)
#define UserStackSize(n) StackAlign(sizeof(Thread) + \
sizeof(struct intctx) + \
@@ -101,16 +101,37 @@ extern void chSysUnlock(void); INT_REQUIRED_STACK)
#define WorkingArea(s, n) ULONG32 s[UserStackSize(n) >> 2];
+#ifdef THUMB
+#define chSysIRQEnterI() { \
+ asm(".code 32 \n\t" \
+ "stmfd sp!, {r0-r3, r12, lr} \n\t" \
+ "add r0, pc, #1 \n\t" \
+ "bx r0 \n\t" \
+ ".code 16 \n\t"); \
+}
+
+#define chSysIRQExitI() { \
+ VICVectAddr = 0; \
+ asm("ldr r0, =IrqCommon \n\t" \
+ "bx r0 \n\t"); \
+}
+#else /* !THUMB */
+#define chSysIRQEnterI() { \
+ asm("stmfd sp!, {r0-r3, r12, lr} \n\t"); \
+}
+
+#define chSysIRQExitI() { \
+ asm("b IrqCommon \n\t"); \
+}
+#endif /* !THUMB */
+
/* It requires zero bytes, but better be safe.*/
#define IDLE_THREAD_STACK_SIZE 8
void _IdleThread(void *p) __attribute__((noreturn));
-void chSysHalt(void) __attribute__((noreturn));
+void chSysHalt(void);
void chSysSwitchI(Context *oldp, Context *newp);
void chSysPuts(char *msg);
void threadstart(void);
-void DefFiqHandler(void);
-void DefIrqHandler(void);
-void SpuriousHandler(void);
#endif /* _CHCORE_H_ */
diff --git a/demos/ARM7-LPC214x-GCC/chcore2.s b/demos/ARM7-LPC214x-GCC/chcore2.s index 7c9d1d0d7..35dd49597 100644 --- a/demos/ARM7-LPC214x-GCC/chcore2.s +++ b/demos/ARM7-LPC214x-GCC/chcore2.s @@ -34,73 +34,15 @@ .code 32
.balign 4
-.globl threadstart
-threadstart:
- msr CPSR_c, #MODE_SYS
-#ifndef THUMB_NO_INTERWORKING
- mov r0, r5
- mov lr, pc
- bx r4
- bl chThdExit
-#else
- add r0, pc, #1
- bx r0
-.code 16
- mov r0, r5
- bl jmpr4
- bl chThdExit
-jmpr4: bx r4
-.code 32
-#endif
-
-.weak UndHandler
-.globl UndHandler
-UndHandler:
-
-.weak SwiHandler
-.globl SwiHandler
-SwiHandler:
-
-.weak PrefetchHandler
-.globl PrefetchHandler
-PrefetchHandler:
-
-.weak AbortHandler
-.globl AbortHandler
-AbortHandler:
-
-.weak FiqHandler
-.globl FiqHandler
-FiqHandler:
- b halt32
-
-.weak chSysHalt
-#ifdef THUMB_NO_INTERWORKING
-.code 16
-.globl chSysHalt
-chSysHalt:
- mov r0, pc
- bx r0
-.code 32
-#else
-.globl chSysHalt
-chSysHalt:
-#endif
-halt32:
- mrs r0, CPSR
- orr r0, #I_BIT | F_BIT
- msr CPSR_c, r0
-.loop: b .loop
-
#ifdef THUMB
.globl chSysLock
chSysLock:
- msr CPSR_c, #0x9F
+ msr CPSR_c, #MODE_SYS | I_BIT
bx lr
.globl chSysUnlock
chSysUnlock:
- msr CPSR_c, #0x1F
+ msr CPSR_c, #MODE_SYS
bx lr
#endif
@@ -127,80 +69,3 @@ chSysSwitchI: ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
#endif
#endif /* CH_CURRP_REGISTER_CACHE */
-
-/*
- * Common exit point for all IRQ routines, it performs the rescheduling if
- * required.
- * System stack frame structure after a context switch in the
- * interrupt handler:
- *
- * High +------------+
- * | LR_USR | -+
- * | R12 | |
- * | R3 | |
- * | R2 | | External context: IRQ handler frame
- * | R1 | |
- * | R0 | |
- * | LR_IRQ | | (user code return address)
- * | SPSR | -+ (user code status)
- * | .... | <- mk_DoRescheduleI() stack frame, optimize it for space
- * | LR | -+ (system code return address)
- * | R11 | |
- * | R10 | |
- * | R9 | |
- * | R8 | | Internal context: mk_SwitchI() frame
- * | (R7) | | (optional, see CH_CURRP_REGISTER_CACHE)
- * | R6 | |
- * | R5 | |
- * SP-> | R4 | -+
- * Low +------------+
- */
-#ifdef THUMB_NO_INTERWORKING
-.code 16
-.globl IrqCommon
-IrqCommon:
- bl chSchRescRequiredI
- mov lr, pc
- bx lr
-.code 32
-#else
-.globl IrqCommon
-IrqCommon:
- bl chSchRescRequiredI
-#endif
- cmp r0, #0 // Simply returns if a
- ldmeqfd sp!, {r0-r3, r12, lr} // reschedule is not
- subeqs pc, lr, #4 // required.
-
- // Saves the IRQ mode registers in the system stack.
- ldmfd sp!, {r0-r3, r12, lr} // IRQ stack now empty.
- msr CPSR_c, #MODE_SYS | I_BIT
- stmfd sp!, {r0-r3, r12, lr} // Registers on System Stack.
- msr CPSR_c, #MODE_IRQ | I_BIT
- mrs r0, SPSR
- mov r1, lr
- msr CPSR_c, #MODE_SYS | I_BIT
- stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
-
- // Context switch.
-#ifdef THUMB_NO_INTERWORKING
- add r0, pc, #1
- bx r0
-.code 16
- bl chSchDoRescheduleI
- mov lr, pc
- bx lr
-.code 32
-#else
- bl chSchDoRescheduleI
-#endif
-
- // Re-establish the IRQ conditions again.
- ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ.
- msr CPSR_c, #MODE_IRQ | I_BIT
- msr SPSR_fsxc, r0
- mov lr, r1
- msr CPSR_c, #MODE_SYS | I_BIT
- ldmfd sp!, {r0-r3, r12, lr}
- msr CPSR_c, #MODE_IRQ | I_BIT
- subs pc, lr, #4
diff --git a/demos/ARM7-LPC214x-GCC/crt0.s b/demos/ARM7-LPC214x-GCC/crt0.s index a7845036d..9032b0742 100644 --- a/demos/ARM7-LPC214x-GCC/crt0.s +++ b/demos/ARM7-LPC214x-GCC/crt0.s @@ -147,3 +147,24 @@ bssloop: bl chSysHalt
.code 32
#endif
+
+.weak UndHandler
+.globl UndHandler
+UndHandler:
+
+.weak SwiHandler
+.globl SwiHandler
+SwiHandler:
+
+.weak PrefetchHandler
+.globl PrefetchHandler
+PrefetchHandler:
+
+.weak AbortHandler
+.globl AbortHandler
+AbortHandler:
+
+.weak FiqHandler
+.globl FiqHandler
+FiqHandler:
+ b _halt32
diff --git a/demos/Win32-MSVS/chcore.h b/demos/Win32-MSVS/chcore.h index 91fd7be9e..b9fbb0147 100644 --- a/demos/Win32-MSVS/chcore.h +++ b/demos/Win32-MSVS/chcore.h @@ -60,6 +60,8 @@ typedef struct { #define chSysLock()
#define chSysUnlock()
#define chSysPuts(msg) {}
+#define chSysIRQEnterI()
+#define chSysIRQExitI()
#define INT_REQUIRED_STACK 0
#define StackAlign(n) ((((n) - 1) | 3) + 1)
diff --git a/demos/Win32-MinGW/chcore.h b/demos/Win32-MinGW/chcore.h index 2b90dd470..43265326b 100644 --- a/demos/Win32-MinGW/chcore.h +++ b/demos/Win32-MinGW/chcore.h @@ -60,6 +60,8 @@ typedef struct { #define chSysLock()
#define chSysUnlock()
#define chSysPuts(msg) {}
+#define chSysIRQEnterI()
+#define chSysIRQExitI()
#define INT_REQUIRED_STACK 0
#define StackAlign(n) ((((n) - 1) | 3) + 1)
|