Improved preemption for Cortex-M0 port.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2797 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
645fce5f28
commit
3cc5ac6d9a
|
@ -126,7 +126,7 @@ Settings: CLK=48, (2 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.8 (Benchmark, round robin context switching)
|
||||
--- Score : 253328 ctxswc/S
|
||||
--- Score : 253332 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.9 (Benchmark, I/O Queues throughput)
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
|
||||
#include "ch.h"
|
||||
|
||||
/**
|
||||
* @brief PC register temporary storage.
|
||||
*/
|
||||
regarm_t _port_saved_pc;
|
||||
|
||||
/**
|
||||
* @brief System Timer vector.
|
||||
* @details This interrupt is used as system tick.
|
||||
|
@ -48,40 +43,39 @@ CH_IRQ_HANDLER(SysTickVector) {
|
|||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NMI vector.
|
||||
* @details The NMI vector is used for exception mode re-entering after a
|
||||
* context switch.
|
||||
*/
|
||||
void NMIVector(void) {
|
||||
register struct extctx *ctxp;
|
||||
|
||||
/* Discarding the current exception context and positioning the stack to
|
||||
point to the real one.*/
|
||||
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory");
|
||||
ctxp++;
|
||||
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory");
|
||||
port_unlock_from_isr();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Post-IRQ switch code.
|
||||
* @details On entry the stack and the registers are restored by the exception
|
||||
* return, the PC value is stored in @p _port_saved_pc, the interrupts
|
||||
* are disabled.
|
||||
* @details The switch is performed in thread context then an NMI exception
|
||||
* is enforced in order to return to the exact point before the
|
||||
* preemption.
|
||||
*/
|
||||
#if !defined(__DOXYGEN__)
|
||||
__attribute__((naked))
|
||||
#endif
|
||||
void _port_switch_from_isr(void) {
|
||||
/* Note, saves r4 to make space for the PC.*/
|
||||
asm volatile ("push {r0, r1, r2, r3, r4} \n\t"
|
||||
"mrs r0, APSR \n\t"
|
||||
"mov r1, r12 \n\t"
|
||||
"push {r0, r1, lr} \n\t"
|
||||
"ldr r0, =_port_saved_pc \n\t"
|
||||
"ldr r0, [r0] \n\t"
|
||||
"add r0, r0, #1 \n\t"
|
||||
"str r0, [sp, #28]" : : : "memory");
|
||||
|
||||
chSchDoRescheduleI();
|
||||
|
||||
/* Note, the last register is restored alone after re-enabling the
|
||||
interrupts in order to minimize the (very remote and unlikely)
|
||||
possibility that the stack is filled by continuous and saturating
|
||||
interrupts that would not allow that last words to be pulled out of
|
||||
the stack.*/
|
||||
asm volatile ("pop {r0, r1, r2} \n\t"
|
||||
"mov r12, r1 \n\t"
|
||||
"msr APSR, r0 \n\t"
|
||||
"mov lr, r2 \n\t"
|
||||
"pop {r0, r1, r2, r3} \n\t"
|
||||
"cpsie i \n\t"
|
||||
"pop {pc}" : : : "memory");
|
||||
SCB_ICSR = ICSR_NMIPENDSET;
|
||||
/* The following loop should never be executed, the NMI will kick in
|
||||
immediately.*/
|
||||
while (TRUE)
|
||||
;
|
||||
}
|
||||
|
||||
#define PUSH_CONTEXT(sp) { \
|
||||
|
|
|
@ -32,10 +32,8 @@
|
|||
/* Port implementation part. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Cortex-Mx exception context.
|
||||
*/
|
||||
struct cmxctx {
|
||||
#if !defined(__DOXYGEN__)
|
||||
struct extctx {
|
||||
regarm_t r0;
|
||||
regarm_t r1;
|
||||
regarm_t r2;
|
||||
|
@ -46,18 +44,6 @@ struct cmxctx {
|
|||
regarm_t xpsr;
|
||||
};
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
struct extctx {
|
||||
regarm_t xpsr;
|
||||
regarm_t r12;
|
||||
regarm_t lr;
|
||||
regarm_t r0;
|
||||
regarm_t r1;
|
||||
regarm_t r2;
|
||||
regarm_t r3;
|
||||
regarm_t pc;
|
||||
};
|
||||
|
||||
struct intctx {
|
||||
regarm_t r8;
|
||||
regarm_t r9;
|
||||
|
@ -131,11 +117,17 @@ struct intctx {
|
|||
if (_saved_lr != (regarm_t)0xFFFFFFF1) { \
|
||||
port_lock_from_isr(); \
|
||||
if (chSchIsRescRequiredExI()) { \
|
||||
register struct cmxctx *ctxp; \
|
||||
register struct extctx *ctxp; \
|
||||
\
|
||||
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : ); \
|
||||
_port_saved_pc = ctxp->pc; \
|
||||
/* Adding an artificial exception return context, there is no need to \
|
||||
populate it fully.*/ \
|
||||
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : : "memory"); \
|
||||
ctxp--; \
|
||||
asm volatile ("msr PSP, %0" : : "r" (ctxp) : "memory"); \
|
||||
ctxp->pc = _port_switch_from_isr; \
|
||||
ctxp->xpsr = (regarm_t)0x01000000; \
|
||||
/* Note, returning without unlocking is intentional, this is done in \
|
||||
order to keep the rest of the context switching atomic.*/ \
|
||||
return; \
|
||||
} \
|
||||
port_unlock_from_isr(); \
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
2.2.1).
|
||||
- FIX: Error in MAC driver (bug 3179783)(backported to 2.2.1).
|
||||
- FIX: Fixed wrong serial driver macros (bug 3173336)(backported to 2.2.1).
|
||||
- NEW: Inproved preemption implementation for the Cortex-M0, now it uses
|
||||
the NMI vector in order to restore the original context. The change makes
|
||||
IRQ handling faster and also saves some RAM/ROM space (backported to 2.2.3).
|
||||
- NEW: Added "IRQ STORM" long duration tests for the STM32 and LPC11xx. The
|
||||
test demonstrates the system stability in a thread-intensive, progressively
|
||||
CPU-saturating, IRQ-intensive long duration test.
|
||||
|
|
Loading…
Reference in New Issue