diff options
author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2010-03-14 09:13:21 +0000 |
---|---|---|
committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2010-03-14 09:13:21 +0000 |
commit | 075b89133ec371480bdcf670d3f412b1cf131b0e (patch) | |
tree | 886089b9e7d4c6715a0cb2e14ea0de271b83cce4 /os | |
parent | f1bb1a01ca40b8c999346c701450fcf0ca74827a (diff) | |
download | ChibiOS-075b89133ec371480bdcf670d3f412b1cf131b0e.tar.gz ChibiOS-075b89133ec371480bdcf670d3f412b1cf131b0e.tar.bz2 ChibiOS-075b89133ec371480bdcf670d3f412b1cf131b0e.zip |
Performance optimization (not complete yet).
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1739 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os')
-rw-r--r-- | os/kernel/include/chdebug.h | 2 | ||||
-rw-r--r-- | os/kernel/include/chsys.h | 4 | ||||
-rw-r--r-- | os/kernel/src/chdebug.c | 4 | ||||
-rw-r--r-- | os/kernel/src/chschd.c | 16 | ||||
-rw-r--r-- | os/kernel/templates/chcore.c | 12 | ||||
-rw-r--r-- | os/kernel/templates/chcore.h | 2 | ||||
-rw-r--r-- | os/ports/GCC/ARM7/chcore.h | 186 | ||||
-rw-r--r-- | os/ports/GCC/ARM7/chcoreasm.s | 8 | ||||
-rw-r--r-- | os/ports/GCC/ARMCM3/chcore.c | 39 | ||||
-rw-r--r-- | os/ports/GCC/ARMCM3/chcore.h | 195 | ||||
-rw-r--r-- | os/ports/GCC/PPC/chcore.c | 8 | ||||
-rw-r--r-- | os/ports/GCC/PPC/chcore.h | 2 | ||||
-rw-r--r-- | os/ports/RC/STM8/chcore.h | 4 |
13 files changed, 289 insertions, 193 deletions
diff --git a/os/kernel/include/chdebug.h b/os/kernel/include/chdebug.h index 316d9e633..c79be7a3b 100644 --- a/os/kernel/include/chdebug.h +++ b/os/kernel/include/chdebug.h @@ -147,7 +147,7 @@ extern "C" { #if CH_DBG_ENABLE_TRACE
extern TraceBuffer trace_buffer;
void trace_init(void);
- void chDbgTrace(Thread *otp, Thread *ntp);
+ void chDbgTrace(Thread *ntp, Thread *otp);
#endif
#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
extern char *panic_msg;
diff --git a/os/kernel/include/chsys.h b/os/kernel/include/chsys.h index 52fa7331b..0a2fa67ad 100644 --- a/os/kernel/include/chsys.h +++ b/os/kernel/include/chsys.h @@ -40,10 +40,10 @@ /**
* @brief Performs a context switch.
*
- * @param[in] otp the thread to be switched out
* @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
*/
-#define chSysSwitchI(otp, ntp) port_switch(otp, ntp)
+#define chSysSwitchI(ntp, otp) port_switch(ntp, otp)
/**
* @brief Raises the system interrupt priority mask to the maximum level.
diff --git a/os/kernel/src/chdebug.c b/os/kernel/src/chdebug.c index ebe93e8a5..969718082 100644 --- a/os/kernel/src/chdebug.c +++ b/os/kernel/src/chdebug.c @@ -45,10 +45,10 @@ void trace_init(void) { /**
* @brief Inserts in the circular debug trace buffer a context switch record.
*
- * @param[in] otp the thread being switched out
* @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread being switched out
*/
-void chDbgTrace(Thread *otp, Thread *ntp) {
+void chDbgTrace(Thread *ntp, Thread *otp) {
trace_buffer.tb_ptr->cse_wtobjp = otp->p_u.wtobjp;
trace_buffer.tb_ptr->cse_time = chTimeNow();
diff --git a/os/kernel/src/chschd.c b/os/kernel/src/chschd.c index 8cfd5cd81..441559c36 100644 --- a/os/kernel/src/chschd.c +++ b/os/kernel/src/chschd.c @@ -90,8 +90,8 @@ void chSchGoSleepS(tstate_t newstate) { #if CH_TIME_QUANTUM > 0
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
- chDbgTrace(otp, currp);
- chSysSwitchI(otp, currp);
+ chDbgTrace(currp, otp);
+ chSysSwitchI(currp, otp);
}
/*
@@ -185,8 +185,8 @@ void chSchWakeupS(Thread *ntp, msg_t msg) { rlist.r_preempt = CH_TIME_QUANTUM;
#endif
(currp = ntp)->p_state = THD_STATE_CURRENT;
- chDbgTrace(otp, ntp);
- chSysSwitchI(otp, ntp);
+ chDbgTrace(ntp, otp);
+ chSysSwitchI(ntp, otp);
}
}
@@ -204,8 +204,8 @@ void chSchDoRescheduleI(void) { #if CH_TIME_QUANTUM > 0
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
- chDbgTrace(otp, currp);
- chSysSwitchI(otp, currp);
+ chDbgTrace(currp, otp);
+ chSysSwitchI(currp, otp);
}
/**
@@ -272,8 +272,8 @@ void chSchDoYieldS(void) { #if CH_TIME_QUANTUM > 0
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
- chDbgTrace(otp, currp);
- chSysSwitchI(otp, currp);
+ chDbgTrace(currp, otp);
+ chSysSwitchI(currp, otp);
}
}
diff --git a/os/kernel/templates/chcore.c b/os/kernel/templates/chcore.c index 2bca5eb6c..0d4f8c3a1 100644 --- a/os/kernel/templates/chcore.c +++ b/os/kernel/templates/chcore.c @@ -80,8 +80,8 @@ void port_disable(void) { }
/**
- * @brief Disables the interrupt sources that are not supposed to preempt
- * the kernel.
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
*/
void port_suspend(void) {
}
@@ -93,7 +93,7 @@ void port_enable(void) { }
/**
- * @brief Enters an architecture-dependent halt mode.
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
* @details The function is meant to return when an interrupt becomes pending.
* The simplest implementation is an empty function or macro but this
* would not take advantage of architecture-specific power saving
@@ -123,10 +123,10 @@ void port_halt(void) { * @note The implementation of this code affects <b>directly</b> the context
* switch performance so optimize here as much as you can.
*
- * @param otp the thread to be switched out
- * @param ntp the thread to be switched in
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
*/
-void port_switch(Thread *otp, Thread *ntp) {
+void port_switch(Thread *ntp, Thread *otp) {
}
/** @} */
diff --git a/os/kernel/templates/chcore.h b/os/kernel/templates/chcore.h index e3fa8f0b9..b6d8550d6 100644 --- a/os/kernel/templates/chcore.h +++ b/os/kernel/templates/chcore.h @@ -159,7 +159,7 @@ extern "C" { void port_enable(void);
void port_wait_for_interrupt(void);
void port_halt(void);
- void port_switch(Thread *otp, Thread *ntp);
+ void port_switch(Thread *ntp, Thread *otp);
#ifdef __cplusplus
}
#endif
diff --git a/os/ports/GCC/ARM7/chcore.h b/os/ports/GCC/ARM7/chcore.h index 4e5707a81..e5aa4c830 100644 --- a/os/ports/GCC/ARM7/chcore.h +++ b/os/ports/GCC/ARM7/chcore.h @@ -18,8 +18,9 @@ */
/**
- * @file ARM7/chcore.h
- * @brief ARM7 architecture port macros and structures.
+ * @file ARM7/chcore.h
+ * @brief ARM7 architecture port macros and structures.
+ *
* @addtogroup ARM7_CORE
* @{
*/
@@ -28,7 +29,7 @@ #define _CHCORE_H_
/**
- * If enabled allows the idle thread to enter a low power mode.
+ * @brief If enabled allows the idle thread to enter a low power mode.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
@@ -36,12 +37,12 @@ #include <wfi.h>
/**
- * Macro defining the ARM7 architecture.
+ * @brief Macro defining the ARM7 architecture.
*/
#define CH_ARCHITECTURE_ARM7
/**
- * Name of the implemented architecture.
+ * @brief Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "ARM"
@@ -51,19 +52,20 @@ #define CH_CORE_VARIANT_NAME "ARM7TDMI"
/**
- * 32 bit stack alignment.
+ * @brief 32 bit stack and memory alignment enforcement.
*/
typedef uint32_t stkalign_t;
/**
- * Generic ARM register.
+ * @brief Generic ARM register.
*/
typedef void *regarm_t;
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * This structure represents the stack frame saved during a preemption-capable
- * interrupt handler.
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
*/
struct extctx {
regarm_t spsr_irq;
@@ -75,11 +77,13 @@ struct extctx { regarm_t r12;
regarm_t lr_usr;
};
-/** @endcond */
+#endif
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * This structure represents the inner stack frame during a context switching.
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
*/
struct intctx {
regarm_t r4;
@@ -94,20 +98,21 @@ struct intctx { regarm_t r11;
regarm_t lr;
};
-/** @endcond */
+#endif
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * In the ARM7 port this structure contains just the copy of the user mode
- * stack pointer.
+ * @brief ATM7 port context structure.
*/
struct context {
struct intctx *r13;
};
-/** @endcond */
+#endif
/**
- * Platform dependent part of the @p chThdInit() API.
+ * @brief Platform dependent part of the @p chThdInit() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
@@ -119,29 +124,38 @@ struct context { }
/**
- * Stack size for the system idle thread.
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p INT_REQUIRED_STACK.
+ * @note In this port it is set to 4 because the idle thread does have
+ * a stack frame when compiling without optimizations.
*/
#ifndef IDLE_THREAD_STACK_SIZE
-#define IDLE_THREAD_STACK_SIZE 0
+#define IDLE_THREAD_STACK_SIZE 4
#endif
/**
- * Per-thread stack overhead for interrupts servicing, it is used in the
- * calculation of the correct working area size.
- * In this port 0x10 is a safe value, it can be reduced after careful generated
- * code analysis.
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ * This value can be zero on those architecture where there is a
+ * separate interrupt stack and the stack space between @p intctx and
+ * @p extctx is known to be zero.
+ * @note In this port 0x10 is a safe value, it can be reduced after careful
+ * analysis of the generated code.
*/
#ifndef INT_REQUIRED_STACK
-#define INT_REQUIRED_STACK 0x10
+#define INT_REQUIRED_STACK 0x10
#endif
/**
- * Enforces a correct alignment for a stack area size value.
+ * @brief Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
- * Computes the thread working area global size.
+ * @brief Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
@@ -149,20 +163,22 @@ struct context { (n) + (INT_REQUIRED_STACK))
/**
- * Macro used to allocate a thread working area aligned as both position and
- * size.
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
- * IRQ prologue code, inserted at the start of all IRQ handlers enabled to
- * invoke system APIs.
- * @note This macro has a different implementation depending if compiled in
- * ARM or THUMB mode.
- * @note The THUMB implementation starts with ARM code because interrupt
- * vectors are always invoked in ARM mode regardless the bit 0
- * value. The switch in THUMB mode is done in the function prologue so
- * it is transparent to the user code.
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
+ * @note This macro has a different implementation depending if compiled in
+ * ARM or THUMB mode.
+ * @note The THUMB implementation starts with ARM code because interrupt
+ * vectors are always invoked in ARM mode regardless the bit 0
+ * value. The switch in THUMB mode is done in the function prologue so
+ * it is transparent to the user code.
*/
#ifdef THUMB
#define PORT_IRQ_PROLOGUE() { \
@@ -179,10 +195,11 @@ struct context { #endif /* !THUMB */
/**
- * IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
- * invoke system APIs.
- * @note This macro has a different implementation depending if compiled in
- * ARM or THUMB mode.
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
+ * @note This macro has a different implementation depending if compiled in
+ * ARM or THUMB mode.
*/
#ifdef THUMB
#define PORT_IRQ_EPILOGUE() { \
@@ -196,20 +213,26 @@ struct context { #endif /* !THUMB */
/**
- * IRQ handler function declaration.
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
*/
#define PORT_IRQ_HANDLER(id) __attribute__((naked)) void id(void)
/**
- * This function is empty in this port.
+ * @brief Port-related initialization code.
+ * @note This function is empty in this port.
*/
#define port_init()
/**
- * Disables the IRQ sources and keeps the FIQ sources enabled.
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port it disables the IRQ sources and keeps FIQ sources
+ * enabled.
*/
#ifdef THUMB
-//#define port_lock() _port_lock_thumb()
#define port_lock() { \
asm volatile ("bl _port_lock_thumb" : : : "r3", "lr"); \
}
@@ -218,10 +241,12 @@ struct context { #endif /* !THUMB */
/**
- * Enables both the IRQ and FIQ sources.
+ * @brief Kernel-unlock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port it enables both the IRQ and FIQ sources.
*/
#ifdef THUMB
-//#define port_unlock() _port_unlock_thumb()
#define port_unlock() { \
asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr"); \
}
@@ -230,22 +255,31 @@ struct context { #endif /* !THUMB */
/**
- * This function is empty in this port.
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ * @note Empty in this port.
*/
#define port_lock_from_isr()
/**
- * This function is empty in this port.
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details This function is invoked after invoking I-class APIs from interrupt
+ * handlers. The implementation is architecture dependent, in its
+ * simplest form it is void.
+ * @note Empty in this port.
*/
#define port_unlock_from_isr()
/**
- * Disables both the IRQ and FIQ sources.
- * @note Implements a workaround for spurious interrupts taken from the NXP
- * LPC214x datasheet.
+ * @brief Disables all the interrupt sources.
+ * @note Of course non maskable interrupt sources are not included.
+ * @note In this port it disables both the IRQ and FIQ sources.
+ * @note Implements a workaround for spurious interrupts taken from the NXP
+ * LPC214x datasheet.
*/
#ifdef THUMB
-//#define port_disable() _port_disable_thumb()
#define port_disable() { \
asm volatile ("bl _port_disable_thumb" : : : "r3", "lr"); \
}
@@ -260,7 +294,10 @@ struct context { #endif /* !THUMB */
/**
- * Disables the IRQ sources and enables the FIQ sources.
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ * @note In this port it disables the IRQ sources and enables the
+ * FIQ sources.
*/
#ifdef THUMB
#define port_suspend() { \
@@ -271,7 +308,8 @@ struct context { #endif /* !THUMB */
/**
- * Enables both the IRQ and FIQ sources.
+ * @brief Enables all the interrupt sources.
+ * @note In this port it enables both the IRQ and FIQ sources.
*/
#ifdef THUMB
#define port_enable() { \
@@ -282,38 +320,44 @@ struct context { #endif /* !THUMB */
/**
- * Performs a context switch between two threads.
- * @param otp the thread to be switched out
- * @param ntp the thread to be switched in
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects <b>directly</b> the context
+ * switch performance so optimize here as much as you can.
+ * @note Implemented as inlined code for performance reasons.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
*/
#ifdef THUMB
#if CH_DBG_ENABLE_STACK_CHECK
-#define port_switch(otp, ntp) { \
- register Thread *_otp asm ("r0") = (otp); \
- register Thread *_ntp asm ("r1") = (ntp); \
+#define port_switch(ntp, otp) { \
+ register Thread *_ntp asm ("r0") = (ntp); \
+ register Thread *_otp asm ("r1") = (otp); \
register char *sp asm ("sp"); \
if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
asm volatile ("mov r0, #0 \n\t" \
"ldr r1, =chDbgPanic \n\t" \
"bx r1"); \
- _port_switch_thumb(_otp, _ntp); \
+ _port_switch_thumb(_ntp, _otp); \
}
#else /* !CH_DBG_ENABLE_STACK_CHECK */
-#define port_switch(otp, ntp) _port_switch_thumb(otp, ntp)
+#define port_switch(ntp, otp) _port_switch_thumb(ntp, otp)
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#else /* !THUMB */
#if CH_DBG_ENABLE_STACK_CHECK
-#define port_switch(otp, ntp) { \
- register Thread *_otp asm ("r0") = (otp); \
- register Thread *_ntp asm ("r1") = (ntp); \
+#define port_switch(ntp, otp) { \
+ register Thread *_ntp asm ("r0") = (ntp); \
+ register Thread *_otp asm ("r1") = (otp); \
register char *sp asm ("sp"); \
if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
asm volatile ("mov r0, #0 \n\t" \
"b chDbgPanic"); \
- _port_switch_arm(_otp, _ntp); \
+ _port_switch_arm(_ntp, _otp); \
}
#else /* !CH_DBG_ENABLE_STACK_CHECK */
-#define port_switch(otp, ntp) _port_switch_arm(otp, ntp)
+#define port_switch(ntp, otp) _port_switch_arm(ntp, otp)
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#endif /* !THUMB */
@@ -322,9 +366,9 @@ extern "C" { #endif
void port_halt(void);
#ifdef THUMB
- void _port_switch_thumb(Thread *otp, Thread *ntp);
+ void _port_switch_thumb(Thread *ntp, Thread *otp);
#else /* !THUMB */
- void _port_switch_arm(Thread *otp, Thread *ntp);
+ void _port_switch_arm(Thread *ntp, Thread *otp);
#endif /* !THUMB */
void _port_thread_start(void);
#ifdef __cplusplus
diff --git a/os/ports/GCC/ARM7/chcoreasm.s b/os/ports/GCC/ARM7/chcoreasm.s index 5e2029019..8726d0c28 100644 --- a/os/ports/GCC/ARM7/chcoreasm.s +++ b/os/ports/GCC/ARM7/chcoreasm.s @@ -105,8 +105,8 @@ _port_switch_thumb: _port_switch_arm:
#ifdef CH_CURRP_REGISTER_CACHE
stmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
- str sp, [r0, #16]
- ldr sp, [r1, #16]
+ str sp, [r1, #16]
+ ldr sp, [r0, #16]
#ifdef THUMB_PRESENT
ldmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
bx lr
@@ -115,8 +115,8 @@ _port_switch_arm: #endif /* !THUMB_PRESENT */
#else /* !CH_CURRP_REGISTER_CACHE */
stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
- str sp, [r0, #12]
- ldr sp, [r1, #12]
+ str sp, [r1, #12]
+ ldr sp, [r0, #12]
#ifdef THUMB_PRESENT
ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
bx lr
diff --git a/os/ports/GCC/ARMCM3/chcore.c b/os/ports/GCC/ARMCM3/chcore.c index 65f71f751..e2caea969 100644 --- a/os/ports/GCC/ARMCM3/chcore.c +++ b/os/ports/GCC/ARMCM3/chcore.c @@ -18,8 +18,9 @@ */
/**
- * @file ARMCM3/chcore.c
- * @brief ARM Cortex-M3 architecture port code.
+ * @file ARMCM3/chcore.c
+ * @brief ARM Cortex-M3 architecture port code.
+ *
* @addtogroup ARMCM3_CORE
* @{
*/
@@ -28,13 +29,13 @@ #include "nvic.h"
/**
- * @brief Halts the system.
- * @note The function is declared as a weak symbol, it is possible to redefine
- * it in your application code.
+ * @brief Halts the system.
+ * @note The function is declared as a weak symbol, it is possible
+ * to redefine it in your application code.
*/
-/** @cond never */
+#if !defined(__DOXYGEN__)
__attribute__((weak))
-/** @endcond */
+#endif
void port_halt(void) {
port_disable();
@@ -55,9 +56,9 @@ void _port_unlock(void) { #endif
/**
- * @brief System Timer vector.
+ * @brief System Timer vector.
* @details This interrupt is used as system tick.
- * @note The timer is initialized in the board setup code.
+ * @note The timer must be initialized in the startup code.
*/
void SysTickVector(void) {
@@ -69,26 +70,26 @@ void SysTickVector(void) { }
/**
- * @brief SVC vector.
+ * @brief SVC vector.
* @details The SVC vector is used for commanded context switch. Structures
* @p intctx are saved and restored from the process stacks of the
* switched threads.
*
- * @param otp the thread to be switched out
- * @param ntp the thread to be switched it
+ * @param[in] ntp the thread to be switched it
+ * @param[in] otp the thread to be switched out
*/
#if !defined(__DOXYGEN__)
__attribute__((naked))
#endif
-void SVCallVector(Thread *otp, Thread *ntp) {
+void SVCallVector(Thread *ntp, Thread *otp) {
(void)otp;
(void)ntp;
#ifdef CH_CURRP_REGISTER_CACHE
asm volatile ("mrs r3, BASEPRI \n\t" \
"mrs r12, PSP \n\t" \
"stmdb r12!, {r3-r6,r8-r11, lr} \n\t" \
- "str r12, [r0, #12] \n\t" \
- "ldr r12, [r1, #12] \n\t" \
+ "str r12, [r1, #12] \n\t" \
+ "ldr r12, [r0, #12] \n\t" \
"ldmia r12!, {r3-r6,r8-r11, lr} \n\t" \
"msr PSP, r12 \n\t" \
"msr BASEPRI, r3 \n\t" \
@@ -97,8 +98,8 @@ void SVCallVector(Thread *otp, Thread *ntp) { asm volatile ("mrs r3, BASEPRI \n\t" \
"mrs r12, PSP \n\t" \
"stmdb r12!, {r3-r11, lr} \n\t" \
- "str r12, [r0, #12] \n\t" \
- "ldr r12, [r1, #12] \n\t" \
+ "str r12, [r1, #12] \n\t" \
+ "ldr r12, [r0, #12] \n\t" \
"ldmia r12!, {r3-r11, lr} \n\t" \
"msr PSP, r12 \n\t" \
"msr BASEPRI, r3 \n\t" \
@@ -137,9 +138,9 @@ void SVCallVector(Thread *otp, Thread *ntp) { #endif
/**
- * @brief Preemption code.
+ * @brief Preemption code.
*/
-#ifndef __DOXYGEN__
+#if !defined(__DOXYGEN__)
__attribute__((naked))
#endif
void PendSVVector(void) {
diff --git a/os/ports/GCC/ARMCM3/chcore.h b/os/ports/GCC/ARMCM3/chcore.h index b5d347a89..f118ba6ef 100644 --- a/os/ports/GCC/ARMCM3/chcore.h +++ b/os/ports/GCC/ARMCM3/chcore.h @@ -18,8 +18,9 @@ */
/**
- * @file ARMCM3/chcore.h
- * @brief ARM Cortex-M3 architecture port macros and structures.
+ * @file ARMCM3/chcore.h
+ * @brief ARM Cortex-M3 architecture port macros and structures.
+ *
* @addtogroup ARMCM3_CORE
* @{
*/
@@ -32,64 +33,66 @@ */
/**
- * Enables the use of the WFI ins.
+ * @brief Enables the use of the WFI ins.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
#endif
/**
- * BASEPRI user level, 0 = disabled.
+ * @brief BASEPRI user level, 0 = disabled.
*/
#ifndef BASEPRI_USER
#define BASEPRI_USER 0
#endif
/**
- * BASEPRI level within kernel lock.
- * Priority levels higher than this one (lower values) are unaffected by
- * the OS activity and can be classified as fast interrupt sources, see
- * @ref interrupt_classes.
+ * @brief BASEPRI level within kernel lock.
+ * @details Priority levels higher than this one (lower values) are unaffected
+ * by the OS activity and can be classified as fast interrupt sources,
+ * see @ref interrupt_classes.
*/
#ifndef BASEPRI_KERNEL
#define BASEPRI_KERNEL 0x40
#endif
/**
- * SVCALL handler priority.
- * @note This priority must always be one level above the @p BASEPRI_KERNEL
- * value.
- * @note It is recommended to leave this priority level for this handler alone.
+ * @brief SVCALL handler priority.
+ * @note This priority must always be one level above the @p BASEPRI_KERNEL
+ * value.
+ * @note It is recommended, but not mandatory, to leave this priority level
+ * for this handler alone.
*/
#ifndef PRIORITY_SVCALL
#define PRIORITY_SVCALL (BASEPRI_KERNEL - 0x10)
#endif
/**
- * SYSTICK handler priority.
+ * @brief SYSTICK handler priority.
*/
#ifndef PRIORITY_SYSTICK
#define PRIORITY_SYSTICK 0x80
#endif
/**
- * PENDSV handler priority.
- * @note It is recommended to leave this priority level for this handler alone.
- * @note This is a reserved handler and its priority must always be the
- * lowest priority in the system in order to be always executed last
- * in the interrupt servicing chain.
+ * @brief PENDSV handler priority.
+ * @note It is recommended to leave this priority level for this handler
+ * alone.
+ * @note This is a reserved handler and its priority must always be the
+ * lowest priority in the system in order to be always executed last
+ * in the interrupt servicing chain.
*/
#ifndef PRIORITY_PENDSV
#define PRIORITY_PENDSV 0xF0
#endif
/**
- * Macro defining the ARM Cortex-M3 architecture.
+ * @brief Macro defining the ARM Cortex-M3 architecture.
*/
#define CH_ARCHITECTURE_ARMCM3
/**
- * Name of the implemented architecture.
+ * @brief Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "ARM"
@@ -99,26 +102,31 @@ #define CH_CORE_VARIANT_NAME "Cortex-M3"
/**
- * 32 bit stack alignment.
+ * @brief 32 bit stack and memory alignment enforcement.
*/
typedef uint32_t stkalign_t;
/**
- * Generic ARM register.
+ * @brief Generic ARM register.
*/
typedef void *regarm_t;
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * Interrupt saved context, empty in this architecture.
+ * @brief Interrupt saved context.
+ * @details This structure represents the stack frame saved during a
+ * preemption-capable interrupt handler.
+ * @note This structure is empty in this port.
*/
struct extctx {
};
-/** @endcond */
+#endif
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * This structure represents the inner stack frame during a context switching.
+ * @brief System saved context.
+ * @details This structure represents the inner stack frame during a context
+ * switching.
*/
struct intctx {
regarm_t basepri;
@@ -142,21 +150,21 @@ struct intctx { regarm_t pc;
regarm_t xpsr;
};
-/** @endcond */
+#endif
-/** @cond never */
+#if !defined(__DOXYGEN__)
/**
- * Cortex-M3 context structure.
+ * @brief Cortex-M3 port context structure.
*/
struct context {
struct intctx *r13;
};
-/** @endcond */
+#endif
/**
- * Platform dependent part of the @p chThdInit() API.
- * This code usually setup the context switching frame represented by a
- * @p intctx structure.
+ * @brief Platform dependent part of the @p chThdInit() API.
+ * @details This code usually setup the context switching frame represented
+ * by an @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
@@ -171,28 +179,37 @@ struct context { }
/**
- * The default idle thread implementation requires no extra stack space in
- * this port but it is set to 4 because the idle thread does have a stack
- * frame when compiling without optimizations.
+ * @brief Stack size for the system idle thread.
+ * @details This size depends on the idle thread implementation, usually
+ * the idle thread should take no more space than those reserved
+ * by @p INT_REQUIRED_STACK.
+ * @note In this port it is set to 4 because the idle thread does have
+ * a stack frame when compiling without optimizations.
*/
#ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 4
#endif
/**
- * This port requires no extra stack space for interrupt handling.
+ * @brief Per-thread stack overhead for interrupts servicing.
+ * @details This constant is used in the calculation of the correct working
+ * area size.
+ * This value can be zero on those architecture where there is a
+ * separate interrupt stack and the stack space between @p intctx and
+ * @p extctx is known to be zero.
+ * @note This port requires no extra stack space for interrupt handling.
*/
#ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 0
#endif
/**
- * Enforces a correct alignment for a stack area size value.
+ * @brief Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
- * Computes the thread working area global size.
+ * @brief Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
@@ -200,20 +217,23 @@ struct context { (n) + (INT_REQUIRED_STACK))
/**
- * Macro used to allocate a thread working area aligned as both position and
- * size.
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
- * IRQ prologue code, inserted at the start of all IRQ handlers enabled to
- * invoke system APIs.
+ * @brief IRQ prologue code.
+ * @details This macro must be inserted at the start of all IRQ handlers
+ * enabled to invoke system APIs.
*/
#define PORT_IRQ_PROLOGUE()
/**
- * IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
- * invoke system APIs.
+ * @brief IRQ epilogue code.
+ * @details This macro must be inserted at the end of all IRQ handlers
+ * enabled to invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
chSysLockFromIsr(); \
@@ -223,17 +243,23 @@ struct context { }
/**
- * IRQ handler function declaration.
+ * @brief IRQ handler function declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
*/
#define PORT_IRQ_HANDLER(id) void id(void)
/**
- * This function is empty in this port.
+ * @brief Port-related initialization code.
+ * @note This function is empty in this port.
*/
#define port_init()
/**
- * Raises the base priority to kernel level.
+ * @brief Kernel-lock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port this it raises the base priority to kernel level.
*/
#if CH_OPTIMIZE_SPEED
#define port_lock() { \
@@ -247,7 +273,10 @@ struct context { #endif
/**
- * Lowers the base priority to user level.
+ * @brief Kernel-unlock action.
+ * @details Usually this function just disables interrupts but may perform
+ * more actions.
+ * @note In this port this it lowers the base priority to kernel level.
*/
#if CH_OPTIMIZE_SPEED
#define port_unlock() { \
@@ -261,22 +290,35 @@ struct context { #endif
/**
- * Same as @p port_lock() in this port.
+ * @brief Kernel-lock action from an interrupt handler.
+ * @details This function is invoked before invoking I-class APIs from
+ * interrupt handlers. The implementation is architecture dependent,
+ * in its simplest form it is void.
+ * @note Same as @p port_lock() in this port.
*/
#define port_lock_from_isr() port_lock()
/**
- * Same as @p port_unlock() in this port.
+ * @brief Kernel-unlock action from an interrupt handler.
+ * @details This function is invoked after invoking I-class APIs from interrupt
+ * handlers. The implementation is architecture dependent, in its
+ * simplest form it is void.
+ * @note Same as @p port_unlock() in this port.
*/
#define port_unlock_from_isr() port_unlock()
/**
- * Disables all the interrupt sources by raising the priority mask to level 0.
+ * @brief Disables all the interrupt sources.
+ * @note Of course non maskable interrupt sources are not included.
+ * @note In this port it disables all the interrupt sources by raising
+ * the priority mask to level 0.
*/
#define port_disable() asm volatile ("cpsid i")
/**
- * Raises/lowers the base priority to kernel level.
+ * @brief Disables the interrupt sources below kernel-level priority.
+ * @note Interrupt sources above kernel level remains enabled.
+ * @note In this port it raises/lowers the base priority to kernel level.
*/
#define port_suspend() { \
register uint32_t tmp asm ("r3") = BASEPRI_KERNEL; \
@@ -285,7 +327,8 @@ struct context { }
/**
- * Lowers the base priority to user level.
+ * @brief Enables all the interrupt sources.
+ * @note In this port it lowers the base priority to user level.
*/
#define port_enable() { \
register uint32_t tmp asm ("r3") = BASEPRI_USER; \
@@ -294,7 +337,12 @@ struct context { }
/**
- * This port function is implemented as inlined code for performance reasons.
+ * @brief Enters an architecture-dependent IRQ-waiting mode.
+ * @details The function is meant to return when an interrupt becomes pending.
+ * The simplest implementation is an empty function or macro but this
+ * would not take advantage of architecture-specific power saving
+ * modes.
+ * @note Implemented as an inlined @p WFI instruction.
*/
#if ENABLE_WFI_IDLE || defined(__DOXYGEN__)
#define port_wait_for_interrupt() { \
@@ -305,25 +353,28 @@ struct context { #endif
/**
- * This port function is implemented as inlined code for performance reasons.
+ * @brief Performs a context switch between two threads.
+ * @details This is the most critical code in any port, this function
+ * is responsible for the context switch between 2 threads.
+ * @note The implementation of this code affects <b>directly</b> the context
+ * switch performance so optimize here as much as you can.
+ * @note Implemented as inlined code for performance reasons.
+ *
+ * @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
*/
+static INLINE Thread *port_switch(Thread *ntp, Thread *otp) {
+ register Thread *_ntp asm ("r0") = (ntp);
+ register Thread *_otp asm ("r1") = (otp);
#if CH_DBG_ENABLE_STACK_CHECK
-#define port_switch(otp, ntp) { \
- register Thread *_otp asm ("r0") = (otp); \
- register Thread *_ntp asm ("r1") = (ntp); \
- register char *sp asm ("sp"); \
- if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
- asm volatile ("movs r0, #0 \n\t" \
- "b chDbgPanic"); \
- asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory"); \
-}
-#else /* !CH_DBG_ENABLE_STACK_CHECK */
-#define port_switch(otp, ntp) { \
- register Thread *_otp asm ("r0") = (otp); \
- register Thread *_ntp asm ("r1") = (ntp); \
- asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory"); \
+ register char *sp asm ("sp");
+ if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp)
+ asm volatile ("movs r0, #0 \n\t"
+ "b chDbgPanic");
+#endif /* CH_DBG_ENABLE_STACK_CHECK */
+ asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory");
+ return _otp;
}
-#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#ifdef __cplusplus
extern "C" {
diff --git a/os/ports/GCC/PPC/chcore.c b/os/ports/GCC/PPC/chcore.c index e0be71e3a..c09d353ad 100644 --- a/os/ports/GCC/PPC/chcore.c +++ b/os/ports/GCC/PPC/chcore.c @@ -48,10 +48,10 @@ void port_halt(void) { * @note The implementation of this code affects <b>directly</b> the context
* switch performance so optimize here as much as you can.
*
- * @param[in] otp the thread to be switched out
* @param[in] ntp the thread to be switched in
+ * @param[in] otp the thread to be switched out
*/
-void port_switch(Thread *otp, Thread *ntp) {
+void port_switch(Thread *ntp, Thread *otp) {
(void)otp;
(void)ntp;
@@ -63,8 +63,8 @@ void port_switch(Thread *otp, Thread *ntp) { asm ("stw %r0, 0(%sp)"); /* CR. */
asm ("stmw %r14, 4(%sp)"); /* GPR14...GPR31. */
- asm ("stw %sp, 12(%r3)"); /* Store swapped-out stack. */
- asm ("lwz %sp, 12(%r4)"); /* Load swapped-in stack. */
+ asm ("stw %sp, 12(%r4)"); /* Store swapped-out stack. */
+ asm ("lwz %sp, 12(%r3)"); /* Load swapped-in stack. */
asm ("lmw %r14, 4(%sp)"); /* GPR14...GPR31. */
asm ("lwz %r0, 0(%sp)"); /* CR. */
diff --git a/os/ports/GCC/PPC/chcore.h b/os/ports/GCC/PPC/chcore.h index 02859afcf..a5466628a 100644 --- a/os/ports/GCC/PPC/chcore.h +++ b/os/ports/GCC/PPC/chcore.h @@ -308,7 +308,7 @@ struct context { extern "C" {
#endif
void port_halt(void);
- void port_switch(Thread *otp, Thread *ntp);
+ void port_switch(Thread *ntp, Thread *otp);
void _port_thread_start(void);
#ifdef __cplusplus
}
diff --git a/os/ports/RC/STM8/chcore.h b/os/ports/RC/STM8/chcore.h index 6df8c5a61..16624fac4 100644 --- a/os/ports/RC/STM8/chcore.h +++ b/os/ports/RC/STM8/chcore.h @@ -252,10 +252,10 @@ struct context { * is responsible for the context switch between 2 threads.
* @note Implemented as a call to a low level assembler routine.
*
- * @param otp the thread to be switched out
* @param ntp the thread to be switched in
+ * @param otp the thread to be switched out
*/
-#define port_switch(otp, ntp) _port_switch(otp)
+#define port_switch(ntp, otp) _port_switch(otp)
#ifdef __cplusplus
extern "C" {
|