aboutsummaryrefslogtreecommitdiffstats
path: root/os/ports/GCC/ARM7
diff options
context:
space:
mode:
Diffstat (limited to 'os/ports/GCC/ARM7')
-rw-r--r--os/ports/GCC/ARM7/chcore.h186
-rw-r--r--os/ports/GCC/ARM7/chcoreasm.s8
2 files changed, 119 insertions, 75 deletions
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