Performance optimization (not complete yet).
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1739 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
f1bb1a01ca
commit
075b89133e
|
@ -1,6 +1,6 @@
|
|||
|
||||
<ApplicationBuild Header="ch" Extern=".\ch.rapp" Path=".\ch.rapp" OutputFile="..\STM8S-STM8S208-RC/bin\ch.aof" sate="98" >
|
||||
<Group Header="kernel" Marker="-1" OutputFile="" sate="0" >
|
||||
<ApplicationBuild Header="ch" Extern=".\ch.rapp" Path=".\ch.rapp" OutputFile="..\STM8S-STM8S208-RC/bin\ch.aof" sate="2" >
|
||||
<Group Header="kernel" Marker="-1" OutputFile="" sate="96" >
|
||||
<NodeC Path="..\..\os\kernel\src\chcond.c" Header="chcond.c" Marker="-1" OutputFile="..\STM8S-STM8S208-RC/bin\chcond.obj" sate="0" />
|
||||
<NodeC Path="..\..\os\kernel\src\chdebug.c" Header="chdebug.c" Marker="-1" OutputFile="..\STM8S-STM8S208-RC/bin\chdebug.obj" sate="0" />
|
||||
<NodeC Path="..\..\os\kernel\src\chevents.c" Header="chevents.c" Marker="-1" OutputFile="..\STM8S-STM8S208-RC/bin\chevents.obj" sate="0" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
<Project Header="Project 'ch'" Path=".\ch.rprj" Project="Yes" OutputFile="" sate="96" ActiveApp="ch" >
|
||||
<ApplicationBuild Header="ch" Extern=".\ch.rapp" Path=".\ch.rapp" OutputFile="..\STM8S-STM8S208-RC/bin\ch.aof" sate="98" />
|
||||
<ApplicationBuild Header="ch" Extern=".\ch.rapp" Path=".\ch.rapp" OutputFile="..\STM8S-STM8S208-RC/bin\ch.aof" sate="2" />
|
||||
</Project>
|
|
@ -5,9 +5,12 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
|
||||
*** ChibiOS/RT test suite
|
||||
***
|
||||
*** Kernel: 1.3.8unstable
|
||||
*** Architecture: ARM7TDMI
|
||||
*** Kernel: 1.5.4unstable
|
||||
*** GCC Version: 4.4.2
|
||||
*** Architecture: ARM
|
||||
*** Core Variant: ARM7TDMI
|
||||
*** Platform: LPC214x
|
||||
*** Test Board: Olimex LCP-P2148
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 1.1 (Threads, enqueuing test #1)
|
||||
|
@ -89,31 +92,31 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.1 (Benchmark, messages #1)
|
||||
--- Score : 144506 msgs/S, 289012 ctxswc/S
|
||||
--- Score : 148086 msgs/S, 296172 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.2 (Benchmark, messages #2)
|
||||
--- Score : 114706 msgs/S, 229412 ctxswc/S
|
||||
--- Score : 116100 msgs/S, 232200 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.3 (Benchmark, messages #3)
|
||||
--- Score : 114706 msgs/S, 229412 ctxswc/S
|
||||
--- Score : 116100 msgs/S, 232200 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.4 (Benchmark, context switch)
|
||||
--- Score : 501520 ctxswc/S
|
||||
--- Score : 509520 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.5 (Benchmark, threads, full cycle)
|
||||
--- Score : 107731 threads/S
|
||||
--- Score : 87287 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.6 (Benchmark, threads, create only)
|
||||
--- Score : 150417 threads/S
|
||||
--- Score : 122334 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.7 (Benchmark, mass reschedulation, 5 threads)
|
||||
--- Score : 36514 reschedulations/S, 219084 ctxswc/S
|
||||
--- Score : 36238 reschedulations/S, 217428 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.8 (Benchmark, round robin context switching)
|
||||
|
@ -121,7 +124,7 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.9 (Benchmark, I/O Queues throughput)
|
||||
--- Score : 357308 bytes/S
|
||||
--- Score : 357312 bytes/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.10 (Benchmark, virtual timers set/reset)
|
||||
|
@ -133,12 +136,12 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.12 (Benchmark, mutexes lock/unlock)
|
||||
--- Score : 380408 lock+unlock/S
|
||||
--- Score : 383452 lock+unlock/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.13 (Benchmark, RAM footprint)
|
||||
--- System: 324 bytes
|
||||
--- Thread: 60 bytes
|
||||
--- System: 356 bytes
|
||||
--- Thread: 68 bytes
|
||||
--- Timer : 20 bytes
|
||||
--- Semaph: 12 bytes
|
||||
--- EventS: 4 bytes
|
||||
|
|
|
@ -5,9 +5,12 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
|
||||
*** ChibiOS/RT test suite
|
||||
***
|
||||
*** Kernel: 1.3.5unstable
|
||||
*** Architecture: ARM7TDMI
|
||||
*** Kernel: 1.5.4unstable
|
||||
*** GCC Version: 4.4.2
|
||||
*** Architecture: ARM
|
||||
*** Core Variant: ARM7TDMI
|
||||
*** Platform: LPC214x
|
||||
*** Test Board: Olimex LCP-P2148
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 1.1 (Threads, enqueuing test #1)
|
||||
|
@ -89,56 +92,56 @@ Settings: CCLK=48, MAMCR=2, MAMTIM=3 (3 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.1 (Benchmark, messages #1)
|
||||
--- Score : 104991 msgs/S, 209982 ctxswc/S
|
||||
--- Score : 106455 msgs/S, 212910 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.2 (Benchmark, messages #2)
|
||||
--- Score : 87494 msgs/S, 174988 ctxswc/S
|
||||
--- Score : 88190 msgs/S, 176380 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.3 (Benchmark, messages #3)
|
||||
--- Score : 87494 msgs/S, 174988 ctxswc/S
|
||||
--- Score : 88190 msgs/S, 176380 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.4 (Benchmark, context switch)
|
||||
--- Score : 410488 ctxswc/S
|
||||
--- Score : 412496 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.5 (Benchmark, threads, full cycle)
|
||||
--- Score : 87176 threads/S
|
||||
--- Score : 67800 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.6 (Benchmark, threads, create only)
|
||||
--- Score : 120330 threads/S
|
||||
--- Score : 100842 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.7 (Benchmark, mass reschedulation, 5 threads)
|
||||
--- Score : 29561 reschedulations/S, 177366 ctxswc/S
|
||||
--- Score : 29488 reschedulations/S, 176928 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.8 (Benchmark, round robin context switching)
|
||||
--- Score : 257160 reschedulations/S, 257160 ctxswc/S
|
||||
--- Score : 257308 reschedulations/S, 257308 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.9 (Benchmark, I/O Queues throughput)
|
||||
--- Score : 265328 bytes/S
|
||||
--- Score : 265488 bytes/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.10 (Benchmark, virtual timers set/reset)
|
||||
--- Score : 303348 timers/S
|
||||
--- Score : 326324 timers/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.11 (Benchmark, semaphores wait/signal)
|
||||
--- Score : 353248 wait+signal/S
|
||||
--- Score : 353452 wait+signal/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.12 (Benchmark, mutexes lock/unlock)
|
||||
--- Score : 249168 lock+unlock/S
|
||||
--- Score : 255980 lock+unlock/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.13 (Benchmark, RAM footprint)
|
||||
--- System: 324 bytes
|
||||
--- Thread: 60 bytes
|
||||
--- System: 356 bytes
|
||||
--- Thread: 68 bytes
|
||||
--- Timer : 20 bytes
|
||||
--- Semaph: 12 bytes
|
||||
--- EventS: 4 bytes
|
||||
|
|
|
@ -5,7 +5,7 @@ Settings: SYSCLK=72, ACR=0x12 (2 wait states)
|
|||
|
||||
*** ChibiOS/RT test suite
|
||||
***
|
||||
*** Kernel: 1.5.3unstable
|
||||
*** Kernel: 1.5.4unstable
|
||||
*** GCC Version: 4.4.2
|
||||
*** Architecture: ARM
|
||||
*** Core Variant: Cortex-M3
|
||||
|
@ -92,31 +92,31 @@ Settings: SYSCLK=72, ACR=0x12 (2 wait states)
|
|||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.1 (Benchmark, messages #1)
|
||||
--- Score : 223892 msgs/S, 447784 ctxswc/S
|
||||
--- Score : 226004 msgs/S, 452008 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.2 (Benchmark, messages #2)
|
||||
--- Score : 187652 msgs/S, 375304 ctxswc/S
|
||||
--- Score : 188141 msgs/S, 376282 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.3 (Benchmark, messages #3)
|
||||
--- Score : 187652 msgs/S, 375304 ctxswc/S
|
||||
--- Score : 188141 msgs/S, 376282 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.4 (Benchmark, context switch)
|
||||
--- Score : 696944 ctxswc/S
|
||||
--- Score : 707232 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.5 (Benchmark, threads, full cycle)
|
||||
--- Score : 146984 threads/S
|
||||
--- Score : 147284 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.6 (Benchmark, threads, create only)
|
||||
--- Score : 203030 threads/S
|
||||
--- Score : 204767 threads/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.7 (Benchmark, mass reschedulation, 5 threads)
|
||||
--- Score : 56954 reschedulations/S, 341724 ctxswc/S
|
||||
--- Score : 57181 reschedulations/S, 343086 ctxswc/S
|
||||
--- Result: SUCCESS
|
||||
----------------------------------------------------------------------------
|
||||
--- Test Case 11.8 (Benchmark, round robin context switching)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* @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
|
||||
#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,14 +163,16 @@ 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.
|
||||
* @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
|
||||
|
@ -179,8 +195,9 @@ struct context {
|
|||
#endif /* !THUMB */
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @note This macro has a different implementation depending if compiled in
|
||||
* ARM or THUMB mode.
|
||||
*/
|
||||
|
@ -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.
|
||||
* @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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* @file ARMCM3/chcore.c
|
||||
* @brief ARM Cortex-M3 architecture port code.
|
||||
*
|
||||
* @addtogroup ARMCM3_CORE
|
||||
* @{
|
||||
*/
|
||||
|
@ -29,12 +30,12 @@
|
|||
|
||||
/**
|
||||
* @brief Halts the system.
|
||||
* @note The function is declared as a weak symbol, it is possible to redefine
|
||||
* it in your application code.
|
||||
* @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();
|
||||
|
@ -57,7 +58,7 @@ void _port_unlock(void) {
|
|||
/**
|
||||
* @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) {
|
||||
|
||||
|
@ -74,21 +75,21 @@ void SysTickVector(void) {
|
|||
* @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" \
|
||||
|
@ -139,7 +140,7 @@ void SVCallVector(Thread *otp, Thread *ntp) {
|
|||
/**
|
||||
* @brief Preemption code.
|
||||
*/
|
||||
#ifndef __DOXYGEN__
|
||||
#if !defined(__DOXYGEN__)
|
||||
__attribute__((naked))
|
||||
#endif
|
||||
void PendSVVector(void) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* @file ARMCM3/chcore.h
|
||||
* @brief ARM Cortex-M3 architecture port macros and structures.
|
||||
*
|
||||
* @addtogroup ARMCM3_CORE
|
||||
* @{
|
||||
*/
|
||||
|
@ -32,49 +33,51 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @brief 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.
|
||||
* @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.
|
||||
* @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.
|
||||
|
@ -84,12 +87,12 @@
|
|||
#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"); \
|
||||
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;
|
||||
}
|
||||
#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"); \
|
||||
}
|
||||
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "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. */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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" {
|
||||
|
|
Loading…
Reference in New Issue