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:
parent
ee227c0552
commit
c413e450e1
|
@ -31,7 +31,7 @@ PROJECT_NAME = ChibiOS/RT
|
||||||
# This could be handy for archiving the generated documentation or
|
# This could be handy for archiving the generated documentation or
|
||||||
# if some version control system is used.
|
# 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)
|
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||||
# base path where the generated documentation will be put.
|
# base path where the generated documentation will be put.
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Kernel version string.
|
* @brief Kernel version string.
|
||||||
*/
|
*/
|
||||||
#define CH_KERNEL_VERSION "2.2.2"
|
#define CH_KERNEL_VERSION "2.2.3"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Kernel version major number.
|
* @brief Kernel version major number.
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief Kernel version patch number.
|
* @brief Kernel version patch number.
|
||||||
*/
|
*/
|
||||||
#define CH_KERNEL_PATCH 2
|
#define CH_KERNEL_PATCH 3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common values.
|
* Common values.
|
||||||
|
|
|
@ -34,11 +34,6 @@
|
||||||
|
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief PC register temporary storage.
|
|
||||||
*/
|
|
||||||
regarm_t _port_saved_pc;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief System Timer vector.
|
* @brief System Timer vector.
|
||||||
* @details This interrupt is used as system tick.
|
* @details This interrupt is used as system tick.
|
||||||
|
@ -55,40 +50,39 @@ CH_IRQ_HANDLER(SysTickVector) {
|
||||||
CH_IRQ_EPILOGUE();
|
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.
|
* @brief Post-IRQ switch code.
|
||||||
* @details On entry the stack and the registers are restored by the exception
|
* @details The switch is performed in thread context then an NMI exception
|
||||||
* return, the PC value is stored in @p _port_saved_pc, the interrupts
|
* is enforced in order to return to the exact point before the
|
||||||
* are disabled.
|
* preemption.
|
||||||
*/
|
*/
|
||||||
#if !defined(__DOXYGEN__)
|
#if !defined(__DOXYGEN__)
|
||||||
__attribute__((naked))
|
__attribute__((naked))
|
||||||
#endif
|
#endif
|
||||||
void _port_switch_from_isr(void) {
|
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();
|
chSchDoRescheduleI();
|
||||||
|
SCB_ICSR = ICSR_NMIPENDSET;
|
||||||
/* Note, the last register is restored alone after re-enabling the
|
/* The following loop should never be executed, the NMI will kick in
|
||||||
interrupts in order to minimize the (very remote and unlikely)
|
immediately.*/
|
||||||
possibility that the stack is filled by continuous and saturating
|
while (TRUE)
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PUSH_CONTEXT(sp) { \
|
#define PUSH_CONTEXT(sp) { \
|
||||||
|
@ -140,6 +134,33 @@ void port_switch(Thread *ntp, Thread *otp) {
|
||||||
POP_CONTEXT(r13);
|
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.
|
* @brief Start a thread by invoking its work function.
|
||||||
* @details If the work function returns @p chThdExit() is automatically
|
* @details If the work function returns @p chThdExit() is automatically
|
||||||
|
|
|
@ -39,10 +39,8 @@
|
||||||
/* Port implementation part. */
|
/* Port implementation part. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
#if !defined(__DOXYGEN__)
|
||||||
* @brief Cortex-Mx exception context.
|
struct extctx {
|
||||||
*/
|
|
||||||
struct cmxctx {
|
|
||||||
regarm_t r0;
|
regarm_t r0;
|
||||||
regarm_t r1;
|
regarm_t r1;
|
||||||
regarm_t r2;
|
regarm_t r2;
|
||||||
|
@ -53,18 +51,6 @@ struct cmxctx {
|
||||||
regarm_t xpsr;
|
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 {
|
struct intctx {
|
||||||
regarm_t r8;
|
regarm_t r8;
|
||||||
regarm_t r9;
|
regarm_t r9;
|
||||||
|
@ -134,20 +120,7 @@ struct intctx {
|
||||||
* @details This macro must be inserted at the end of all IRQ handlers
|
* @details This macro must be inserted at the end of all IRQ handlers
|
||||||
* enabled to invoke system APIs.
|
* enabled to invoke system APIs.
|
||||||
*/
|
*/
|
||||||
#define PORT_IRQ_EPILOGUE() { \
|
#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr)
|
||||||
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(); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief IRQ handler function declaration.
|
* @brief IRQ handler function declaration.
|
||||||
|
@ -233,15 +206,12 @@ struct intctx {
|
||||||
#define port_wait_for_interrupt()
|
#define port_wait_for_interrupt()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(__DOXYGEN__)
|
|
||||||
extern regarm_t _port_saved_pc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
void port_halt(void);
|
void port_halt(void);
|
||||||
void port_switch(Thread *ntp, Thread *otp);
|
void port_switch(Thread *ntp, Thread *otp);
|
||||||
|
void _port_irq_epilogue(regarm_t lr);
|
||||||
void _port_switch_from_isr(void);
|
void _port_switch_from_isr(void);
|
||||||
void _port_thread_start(void);
|
void _port_thread_start(void);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -68,6 +68,13 @@
|
||||||
*** Releases ***
|
*** 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 ***
|
*** 2.2.2 ***
|
||||||
- FIX: Fixed race condition in CM0 ports, the fix also improves the
|
- FIX: Fixed race condition in CM0 ports, the fix also improves the
|
||||||
ISR latency (bug 3193062).
|
ISR latency (bug 3193062).
|
||||||
|
|
Loading…
Reference in New Issue