aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2007-12-17 14:57:44 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2007-12-17 14:57:44 +0000
commit0bb20d36f4f1c8457416167b399d976d26660611 (patch)
tree9c7419af17e2c81944eaeb7aa230681c0936c707
parent430010715e7a9af17185412273165674f3b58f20 (diff)
downloadChibiOS-0bb20d36f4f1c8457416167b399d976d26660611.tar.gz
ChibiOS-0bb20d36f4f1c8457416167b399d976d26660611.tar.bz2
ChibiOS-0bb20d36f4f1c8457416167b399d976d26660611.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@142 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--demos/ARM7-LPC214x-GCC/chcore.c169
-rw-r--r--demos/ARM7-LPC214x-GCC/chcore.h31
-rw-r--r--demos/ARM7-LPC214x-GCC/chcore2.s139
-rw-r--r--demos/ARM7-LPC214x-GCC/crt0.s21
-rw-r--r--demos/Win32-MSVS/chcore.h2
-rw-r--r--demos/Win32-MinGW/chcore.h2
-rw-r--r--ports/ARM7-LPC214x/GCC/lpc214x_serial.c33
-rw-r--r--readme.txt13
-rw-r--r--src/chmtx.c12
-rw-r--r--src/templates/chcore.h15
10 files changed, 236 insertions, 201 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)
diff --git a/ports/ARM7-LPC214x/GCC/lpc214x_serial.c b/ports/ARM7-LPC214x/GCC/lpc214x_serial.c
index cfd4f696e..43adab3b5 100644
--- a/ports/ARM7-LPC214x/GCC/lpc214x_serial.c
+++ b/ports/ARM7-LPC214x/GCC/lpc214x_serial.c
@@ -55,7 +55,6 @@ static void ServeInterrupt(UART *u, FullDuplexDriver *com) {
switch (u->UART_IIR & IIR_SRC_MASK) {
case IIR_SRC_NONE:
- VICVectAddr = 0;
return;
case IIR_SRC_ERROR:
SetError(u->UART_LSR, com);
@@ -98,37 +97,21 @@ static void ServeInterrupt(UART *u, FullDuplexDriver *com) {
__attribute__((naked, weak))
void UART0IrqHandler(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");
- ServeInterrupt(U0Base, &COM1);
- asm("ldr r0, =IrqCommon \n\t" \
- "bx r0 \n\t");
-#else
+ chSysIRQEnterI();
+
ServeInterrupt(U0Base, &COM1);
- asm("b IrqCommon \n\t");
-#endif
+
+ chSysIRQExitI();
}
__attribute__((naked, weak))
void UART1IrqHandler(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");
- ServeInterrupt(U1Base, &COM2);
- asm("ldr r0, =IrqCommon \n\t" \
- "bx r0 \n\t");
-#else
+ chSysIRQEnterI();
+
ServeInterrupt(U1Base, &COM2);
- asm("b IrqCommon \n\t");
-#endif
+
+ chSysIRQExitI();
}
#ifdef FIFO_PRELOAD
diff --git a/readme.txt b/readme.txt
index 18ba71eb5..f6692c623 100644
--- a/readme.txt
+++ b/readme.txt
@@ -43,13 +43,20 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not complete yet.
- NEW: Binary Mutexes, the new mechanism provides a complete implementation
of the "priority inheritance" algorithm as a tool for work around the
priority inversion problem.
- The Mutexes are not meant to replace the Semaphores that are still the best
- mechanism for synchronization between interrupt handlers and high level
- code, something Mutexes cannot do.
+ The Mutexes are not meant to replace the Semaphores that still are the best
+ synchronization mechanism between interrupt handlers and high level
+ code, something that Mutexes cannot do.
Soon an article will be added to the wiki describing pro and cons of the
various mechanisms and the correct use cases.
- RT Semaphores subsystem removed, the Mutexes implements a better solution
for the same problem.
+- Modified the test suite in order to have each test case to have the same
+ alignment enforced on functions. This is done to reduce MAM/Cache alignment
+ effects on the measurement.
+- IRQ entry/exit code is now encapsulated into two new macros, see chcore.h
+ for details.
+- Most of the asm code previously in chcore2.s is now inline asm code in
+ chcore.c (ARM port).
*** 0.4.5 ***
- Moved the serial IRQ handlers and VIC vectors initialization inside the
diff --git a/src/chmtx.c b/src/chmtx.c
index 1c0055acd..c097f2f33 100644
--- a/src/chmtx.c
+++ b/src/chmtx.c
@@ -56,15 +56,15 @@ static void prio_enq(Thread *tp, ThreadsQueue *tqp) {
}
/*
- * 0 +++BA++------------------2+++--8++++++++++BR0----------------------------
- * 1 .......++AA++--2+++++++++BA....8..........++++++++BR8++++AR1-------------
- * 2 .............++AA..............................................----++AR++
- * 8 .............................++AA........................++++++AR++......
+ * 0 +++BL++------------------2+++--8++++++++++BU0----------------------------
+ * 1 .......++AL++--2+++++++++BL....8..........++++++++BU8++++AU1-------------
+ * 2 .............++AL..............................................----++AU++
+ * 8 .............................++AL........................++++++AU++......
*
*
- * 5 ++++++++++++++++++AA+....9++++++++++++++AR5------------------------------
+ * 5 ++++++++++++++++++AL+....9++++++++++++++AU5------------------------------
* 7 .....................++--------------------------------------------------
- * 9 .......................++AA.............+++++++++AR++++++++++++++++++++++
+ * 9 .......................++AL.............+++++++++AU++++++++++++++++++++++
*/
/**
diff --git a/src/templates/chcore.h b/src/templates/chcore.h
index c88748f8b..3f796e8ab 100644
--- a/src/templates/chcore.h
+++ b/src/templates/chcore.h
@@ -100,6 +100,21 @@ typedef struct {
*/
#define chSysUnlock()
+/**
+ * IRQ handler enter code.
+ * @note Usually IRQ handlers function are also declared naked.
+ * @note On some architectures this macro can be empty.
+ */
+#define chSysIRQEnterI()
+
+/**
+ * IRQ handler exit code.
+ * @note Usually IRQ handlers function are also declared naked.
+ * @note This macro must perform the final reschedulation by using
+ * \p chSchRescRequiredI() and \p chSchDoRescheduleI().
+ */
+#define chSysIRQExitI()
+
void _IdleThread(void *p);
void chSysHalt(void);
void chSysSwitchI(Context *oldp, Context *newp);