From 48d08ca9476ca38ba936ec7ff5ae3b79d8b02bd2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 18 Jan 2009 13:44:50 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@634 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/ARMCM3-STM32F103-GCC/board.c | 7 +-- docs/Doxyfile | 2 +- docs/ch.txt | 64 +--------------------- ports/ARM7/chcore.c | 4 ++ ports/ARM7/port.dox | 5 +- ports/ARMCM3/chcore.c | 10 ++++ ports/ARMCM3/chcore.h | 45 ++++++++++++++-- ports/ARMCM3/crt0.s | 21 +++----- ports/ARMCM3/nvic.c | 20 ++++++- ports/ARMCM3/nvic.h | 17 ++++++ ports/ARMCM3/port.dox | 108 +++++++++++++++++++++++++++++++++++++ readme.txt | 3 +- 12 files changed, 215 insertions(+), 91 deletions(-) create mode 100644 ports/ARMCM3/port.dox diff --git a/demos/ARMCM3-STM32F103-GCC/board.c b/demos/ARMCM3-STM32F103-GCC/board.c index 7bfa42133..6a13c126b 100644 --- a/demos/ARMCM3-STM32F103-GCC/board.c +++ b/demos/ARMCM3-STM32F103-GCC/board.c @@ -90,12 +90,13 @@ void hwinit1(void) { * NVIC/SCB initialization. */ SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0x3); // PRIGROUP 4:0 (4:4). - SCB_SHPR(2) = 0xF0 << 16; // PendSV at lowest priority. + NVICSetSystemHandlerPriority(HANDLER_SVCALL, PRIORITY_SVCALL); + NVICSetSystemHandlerPriority(HANDLER_SYSTICK, PRIORITY_SYSTICK); + NVICSetSystemHandlerPriority(HANDLER_PENDSV, PRIORITY_PENDSV); /* * SysTick initialization. */ - SCB_SHPR(2) |= 0x40 << 24; // SysTick at priority 4:0. ST_RVR = SYSCLK / (8000000 / CH_FREQUENCY) - 1; ST_CVR = 0; ST_CSR = ENABLE_ON_BITS | TICKINT_ENABLED_BITS | CLKSOURCE_EXT_BITS; @@ -103,7 +104,7 @@ void hwinit1(void) { /* * Other subsystems initialization. */ - InitSerial(0x80, 0x80, 0x80); + InitSerial(0xC0, 0xC0, 0xC0); /* * ChibiOS/RT initialization. diff --git a/docs/Doxyfile b/docs/Doxyfile index 430f4aa8f..582fcc532 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -84,7 +84,7 @@ WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -INPUT = ../src/include ../src/templates ../src ../docs/ch.txt ../src/lib ../ports/ARM7 +INPUT = ../src/include ../src/templates ../src ../docs/ch.txt ../src/lib ../ports/ARM7 ../ports/ARMCM3 INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py *.ddf RECURSIVE = YES diff --git a/docs/ch.txt b/docs/ch.txt index 82789c4b7..fc475ec95 100644 --- a/docs/ch.txt +++ b/docs/ch.txt @@ -77,7 +77,7 @@ * state unless differently specified.
* Examples: @p chThdCreateStatic(), @p chSemSignalI(), @p chIQGetTimeout(). * - * @section interrupts Interrupt Classes + * @section interrupt_classes Interrupt Classes * In ChibiOS/RT there are three logical interrupt classes: * - Regular Interrupts. Maskable interrupt sources that cannot * preempt the kernel code and are thus able to invoke operating system APIs @@ -280,68 +280,6 @@ */ /** @} */ -/** - * @defgroup ARMCM3 ARM Cortex-M3 - * @{ - *

- * The ARM Cortex-M3 port is organized as follow: - *

- * - * @ingroup Ports - */ -/** @} */ - -/** - * @defgroup ARMCM3CONF Configuration Options - * @{ - *

- * The ARMCM3 port allows some architecture-specific configurations settings - * that can be specified externally, as example on the compiler command line: - *

- *

- * @ingroup ARMCM3 - */ -/** @} */ - /** * @defgroup STM32F103 STM32F103 Support * @{ diff --git a/ports/ARM7/chcore.c b/ports/ARM7/chcore.c index d7d51c85b..9ffe94ac5 100644 --- a/ports/ARM7/chcore.c +++ b/ports/ARM7/chcore.c @@ -28,14 +28,18 @@ * Prints a message on the system console. * @param msg pointer to the message */ +/** @cond never */ __attribute__((weak)) +/** @endcond */ void port_puts(char *msg) { } /** * Halts the system. */ +/** @cond never */ __attribute__((weak)) +/** @endcond */ void port_halt(void) { port_disable(); diff --git a/ports/ARM7/port.dox b/ports/ARM7/port.dox index cf3532f96..9a9f319a6 100644 --- a/ports/ARM7/port.dox +++ b/ports/ARM7/port.dox @@ -105,7 +105,7 @@ /** @} */ /** - * @defgroup ARM7CONF Configuration Options + * @defgroup ARM7_CONF Configuration Options * @{ * @brief ARM7 specific configuration options. * @details The ARM7 port allows some architecture-specific configurations @@ -133,7 +133,8 @@ * @brief ARM7 specific port code, structures and macros. * * @ingroup ARM7 - * @file ports/ARM7/chcore.h Port related structures and macros. * @file ports/ARM7/chtypes.h Port types. + * @file ports/ARM7/chcore.h Port related structures and macros. + * @file ports/ARM7/chcore.c Port related code. */ /** @} */ diff --git a/ports/ARMCM3/chcore.c b/ports/ARMCM3/chcore.c index acbc97d9b..3432a6577 100644 --- a/ports/ARMCM3/chcore.c +++ b/ports/ARMCM3/chcore.c @@ -32,7 +32,9 @@ * it in your application code. * @param msg pointer to the message string */ +/** @cond never */ __attribute__((weak)) +/** @endcond */ void port_puts(char *msg) { } @@ -41,7 +43,9 @@ void port_puts(char *msg) { * @note The function is declared as a weak symbol, it is possible to redefine * it in your application code. */ +/** @cond never */ __attribute__((weak)) +/** @endcond */ void port_halt(void) { port_disable(); @@ -53,7 +57,9 @@ void port_halt(void) { * Start a thread by invoking its work function. * If the work function returns @p chThdExit() is automatically invoked. */ +/** @cond never */ __attribute__((naked, weak)) +/** @endcond */ void threadstart(void) { asm volatile ("blx r1 \n\t" \ @@ -79,7 +85,9 @@ CH_IRQ_HANDLER void SysTickVector(void) { /** * The SVC vector is used for commanded context switch. */ +/** @cond never */ __attribute__((naked)) +/** @endcond */ void SVCallVector(Thread *otp, Thread *ntp) { /* { r0 = otp, r1 = ntp } */ /* get the BASEPRI in r3 */ @@ -146,7 +154,9 @@ void SVCallVector(Thread *otp, Thread *ntp) { /** * Preemption invoked context switch. */ +/** @cond never */ __attribute__((naked)) +/** @endcond */ void PendSVVector(void) { Thread *otp; register struct intctx *sp_thd asm("r12"); diff --git a/ports/ARMCM3/chcore.h b/ports/ARMCM3/chcore.h index 831e03527..4ac271c79 100644 --- a/ports/ARMCM3/chcore.h +++ b/ports/ARMCM3/chcore.h @@ -28,16 +28,51 @@ /* * Port-related configuration parameters. */ + +/** Enables the use of the WFI ins. */ +#ifndef ENABLE_WFI_IDLE +#define ENABLE_WFI_IDLE 0 +#endif + +/** BASEPRI user level, 0 = disabled. */ #ifndef BASEPRI_USER -#define BASEPRI_USER 0 /* User level BASEPRI, 0 = disabled. */ +#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. + */ #ifndef BASEPRI_KERNEL -#define BASEPRI_KERNEL 0x10 /* BASEPRI level within kernel lock. */ +#define BASEPRI_KERNEL 0x40 #endif -#ifndef ENABLE_WFI_IDLE -#define ENABLE_WFI_IDLE 0 /* Enables the use of the WFI ins. */ +/** + * 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. + */ +#ifndef PRIORITY_SVCALL +#define PRIORITY_SVCALL (BASEPRI_KERNEL - 0x10) +#endif + +/** 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. + */ +#ifndef PRIORITY_PENDSV +#define PRIORITY_PENDSV 0xF0 #endif /** @@ -233,7 +268,7 @@ typedef struct { /** * This port function is implemented as inlined code for performance reasons. */ -#define port_switch(otp, ntp) { \ +#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)); \ diff --git a/ports/ARMCM3/crt0.s b/ports/ARMCM3/crt0.s index a7ebb59be..d31b36475 100644 --- a/ports/ARMCM3/crt0.s +++ b/ports/ARMCM3/crt0.s @@ -37,6 +37,8 @@ .thumb_func .global ResetHandler ResetHandler: + /* Interrupts globally masked. */ + cpsid i /* * Stack pointers initialization. */ @@ -47,9 +49,7 @@ ResetHandler: msr PSP, r0 // ldr r1, =__process_stack_size__ // sub r0, r0, r1 - /* - * Early initialization. - */ + /* Early initialization. */ bl hwinit0 /* * Data initialization. @@ -76,22 +76,13 @@ bloop: itt lo strlo r0, [r1], #4 blo bloop - /* - * Switches to the Process Stack and disables the interrupts globally. - */ + /* Switches to the Process Stack. */ movs r0, #CONTROL_MODE_PRIVILEGED | CONTROL_USE_PSP msr CONTROL, r0 isb - movs r0, #0x10 - msr BASEPRI, r0 - cpsie i - /* - * Late initialization. - */ + /* Late initialization. */ bl hwinit1 - /* - * main(0, NULL). - */ + /* main(0, NULL). */ movs r0, #0 mov r1, r0 bl main diff --git a/ports/ARMCM3/nvic.c b/ports/ARMCM3/nvic.c index dbb4935c0..a054ed163 100644 --- a/ports/ARMCM3/nvic.c +++ b/ports/ARMCM3/nvic.c @@ -20,9 +20,27 @@ #include #include +/** + * Sets the priority of an interrupt handler and enables it. + * @param n the interrupt number + * @param prio the interrupt priority + * @note The parameters are not tested for correctness. + */ void NVICEnableVector(uint32_t n, uint32_t prio) { - int sh = (n & 3) << 3; + unsigned sh = (n & 3) << 3; NVIC_IPR(n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); NVIC_ISER(n >> 5) = 1 << (n & 0x1F); } + +/** + * Changes the priority of a system handler. + * @param handler the system handler number + * @param prio the system handler priority + * @note The parameters are not tested for correctness. + */ +void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio) { + unsigned sh = (handler & 3) * 8; + + SCB_SHPR(handler >> 2) = (SCB_SHPR(handler >> 2) & ~(0xFF << sh)) | (prio << sh); +} diff --git a/ports/ARMCM3/nvic.h b/ports/ARMCM3/nvic.h index 13a04fe78..3876410e5 100644 --- a/ports/ARMCM3/nvic.h +++ b/ports/ARMCM3/nvic.h @@ -20,6 +20,22 @@ #ifndef _NVIC_H_ #define _NVIC_H_ +/* + * System vector constants for @p NVICSetSystemHandlerPriority(). + */ +#define HANDLER_MEM_MANAGE 0 +#define HANDLER_BUS_FAULT 1 +#define HANDLER_USAGE_FAULT 2 +#define HANDLER_RESERVED_3 3 +#define HANDLER_RESERVED_4 4 +#define HANDLER_RESERVED_5 5 +#define HANDLER_RESERVED_6 6 +#define HANDLER_SVCALL 7 +#define HANDLER_DEBUG_MONITOR 8 +#define HANDLER_RESERVED_9 9 +#define HANDLER_PENDSV 10 +#define HANDLER_SYSTICK 11 + typedef volatile unsigned char IOREG8; typedef volatile unsigned int IOREG32; @@ -132,6 +148,7 @@ typedef struct { extern "C" { #endif void NVICEnableVector(uint32_t n, uint32_t prio); + void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio); #ifdef __cplusplus } #endif diff --git a/ports/ARMCM3/port.dox b/ports/ARMCM3/port.dox new file mode 100644 index 000000000..28372e399 --- /dev/null +++ b/ports/ARMCM3/port.dox @@ -0,0 +1,108 @@ +/** + * @defgroup ARMCM3 ARM Cortex-M3 + * @{ + * @details The ARM Cortex-M3 architecture is quite complex for a + * microcontroller and some explanations are required about the port choices. + * + * @section ARMCM3_STATES Mapping of the System States in the ARM Cortex-M3 port + * The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM + * Cortex-M3 port: + * - Initialization. This state is represented by the startup code and + * the initialization code before @p chSysInit() is executed. It has not a + * special hardware state associated. + * - Normal. This is the state the system has after executing + * @p chSysInit(). In this state the ARM Cortex-M3 has the BASEPRI register + * set at @p BASEPRI_USER level, interrupts are not masked. The processor + * is running in thread-privileged mode. + * - Suspended. In this state the interrupt sources are not globally + * masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking + * any interrupt source with lower or equal priority. The processor + * is running in thread-privileged mode. + * - Disabled. Interrupt sources are globally masked. The processor + * is running in thread-privileged mode. + * - Sleep. This state is entered with the execution of the specific + * instruction @p wfi. + * - S-Locked. In this state the interrupt sources are not globally + * masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking + * any interrupt source with lower or equal priority. The processor + * is running in thread-privileged mode. + * - I-Locked. In this state the interrupt sources are not globally + * masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking + * any interrupt source with lower or equal priority. The processor + * is running in exception-privileged mode. + * - Serving Regular Interrupt. In this state the interrupt sources are + * not globally masked but only interrupts with higher priority can preempt + * the current handler. The processor is running in exception-privileged mode. + * - Serving Fast Interrupt. It is basically the same of the SRI state + * but it is not possible to switch to the I-Locked state because fast + * interrupts can preempt the kernel critical zone. + * - Serving Non-Maskable Interrupt. The Cortex-M3 has a specific + * asynchronous NMI vector and several synchronous fault vectors that can + * be considered to be in this category. + * - Halted. Implemented as an infinite loop after globally masking all + * the maskable interrupt sources. The ARM state is whatever the processor + * was running when @p chSysHalt() was invoked. + * + * @section ARMCM3_NOTES The ARM Cortex-M3 port notes + * The ARM Cortex-M3 port is organized as follow: + * - The @p main() function is invoked in thread-privileged mode. + * - Each thread has a private process stack, the system has a single main + * stack where all the interrupts and exceptions are processed. + * - Only the 4 MSb of the priority level are used, the 4 LSb are assumed + * to be zero. + * - The threads are started in thread-privileged mode with BASEPRI level + * 0x00 (disabled). + * - The kernel raises its BASEPRI level to @p BASEPRI_KERNEL in order to + * protect the kernel data structures. + * - Interrupt nesting and the other advanced NVIC features are supported. + * - The SVC instruction and vector, with parameter #0, is internally used + * for commanded context switching.
+ * It is possible to share the SVC handler at the cost of slower context + * switching. + * - The PendSV vector is internally used for preemption context switching. + * + * @ingroup Ports + */ +/** @} */ + +/** + * @defgroup ARMCM3_CONF Configuration Options + * @{ + * @brief ARM Cortex-M3 Configuration Options. + * The ARMCM3 port allows some architecture-specific configurations settings + * that can be specified externally, as example on the compiler command line: + * - @p INT_REQUIRED_STACK, this value represent the amount of stack space used + * by an interrupt handler between the @p extctx and @p intctx + * structures.
+ * In the current implementation this value is guaranteed to be zero so + * there is no need to modify this value unless changes are done at the + * interrupts handling code. + * - @p BASEPRI_USER, this is the @p BASEPRI value for the user threads. The + * default value is @p 0 (disabled).
+ * Usually there is no need to change this value, please refer to the + * Cortex-M3 technical reference manual for a detailed description. + * - @p BASEPRI_KERNEL, this is the @p BASEPRI value for the kernel lock code. + * The default value is 0x10.
+ * Code running at higher priority levels must not invoke any OS API.
+ * Usually there is no need to change this value, please refer to the + * Cortex-M3 technical reference manual for a detailed description. + * - @p ENABLE_WFI_IDLE, if set to @p 1 enables the use of the @p wfi + * instruction from within the idle loop. This is defaulted to 0 because + * it can create problems with some debuggers. Setting this option to 1 + * reduces the system power requirements. + * + * @ingroup ARMCM3 + */ +/** @} */ + +/** + * @defgroup ARMCM3_CORE ARM Cortex-M3 Core Implementation + * @{ + * @brief ARM Cortex-M3 specific port code, structures and macros. + * + * @ingroup ARMCM3 + * @file ports/ARMCM3/chtypes.h Port types. + * @file ports/ARMCM3/chcore.h Port related structures and macros. + * @file ports/ARMCM3/chcore.c Port related code. + */ +/** @} */ diff --git a/readme.txt b/readme.txt index 3256928b0..3b9b4edba 100644 --- a/readme.txt +++ b/readme.txt @@ -85,8 +85,9 @@ Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process, CH_IRQ_PROLOGUE() and CH_IRQ_EPILOGUE() in order to make very clear that those are not functions but inlined code. Also introduced a new macro CH_IRQ_HANDLER that should be used when declaring an interrupt handler. +- Improved ARM7 and Cortex-M3 support. - Introduced the concept of interrupt classes, see the documentation. -- Introduced the concept of system state, see the documentation. +- Introduced the concept of system states, see the documentation. - Huge improvements to the ports documentation. *** 1.0.0rc2 *** -- cgit v1.2.3