Backported improvement to the CM0 port from version 2.3.0.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/stable_2.2.x@2823 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2011-03-18 13:50:39 +00:00
parent ee227c0552
commit c413e450e1
5 changed files with 65 additions and 67 deletions

View File

@ -31,7 +31,7 @@ PROJECT_NAME = ChibiOS/RT
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 2.2.2
PROJECT_NUMBER = 2.2.3
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@ -46,7 +46,7 @@
/**
* @brief Kernel version string.
*/
#define CH_KERNEL_VERSION "2.2.2"
#define CH_KERNEL_VERSION "2.2.3"
/**
* @brief Kernel version major number.
@ -61,7 +61,7 @@
/**
* @brief Kernel version patch number.
*/
#define CH_KERNEL_PATCH 2
#define CH_KERNEL_PATCH 3
/*
* Common values.

View File

@ -34,11 +34,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.
@ -55,40 +50,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) { \
@ -140,6 +134,33 @@ void port_switch(Thread *ntp, Thread *otp) {
POP_CONTEXT(r13);
}
/**
* @brief IRQ epilogue code.
*
* @param[in] lr value of the @p LR register on ISR entry
*/
void _port_irq_epilogue(regarm_t lr) {
if (lr != (regarm_t)0xFFFFFFF1) {
port_lock_from_isr();
if (chSchIsRescRequiredExI()) {
register struct extctx *ctxp;
/* 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();
}
}
/**
* @brief Start a thread by invoking its work function.
* @details If the work function returns @p chThdExit() is automatically

View File

@ -39,10 +39,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;
@ -53,18 +51,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;
@ -134,20 +120,7 @@ struct intctx {
* @details This macro must be inserted at the end of all IRQ handlers
* enabled to invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
if (_saved_lr != (regarm_t)0xFFFFFFF1) { \
port_lock_from_isr(); \
if (chSchIsRescRequiredExI()) { \
register struct cmxctx *ctxp; \
\
asm volatile ("mrs %0, PSP" : "=r" (ctxp) : ); \
_port_saved_pc = ctxp->pc; \
ctxp->pc = _port_switch_from_isr; \
return; \
} \
port_unlock_from_isr(); \
} \
}
#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr)
/**
* @brief IRQ handler function declaration.
@ -233,15 +206,12 @@ struct intctx {
#define port_wait_for_interrupt()
#endif
#if !defined(__DOXYGEN__)
extern regarm_t _port_saved_pc;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void port_halt(void);
void port_switch(Thread *ntp, Thread *otp);
void _port_irq_epilogue(regarm_t lr);
void _port_switch_from_isr(void);
void _port_thread_start(void);
#ifdef __cplusplus

View File

@ -68,6 +68,13 @@
*** Releases ***
*****************************************************************************
*** 2.2.3 ***
- NEW: Improved 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. The GCC port code
now does not inline the epilogue code in each ISR saving significant ROM
space for each interrupt handler in the system.
*** 2.2.2 ***
- FIX: Fixed race condition in CM0 ports, the fix also improves the
ISR latency (bug 3193062).