git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1778 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2010-03-26 07:40:25 +00:00
parent dea859c252
commit 908fe1986f
7 changed files with 143 additions and 82 deletions

View File

@ -102,7 +102,10 @@ struct intctx {
#if !defined(__DOXYGEN__) #if !defined(__DOXYGEN__)
/** /**
* @brief ATM7 port context structure. * @brief Platform dependent part of the @p Thread structure.
* @details In the ARM7 port this structure just holds a pointer to the
* @p intctx structure representing the stack pointer at the time
* of the context switch.
*/ */
struct context { struct context {
struct intctx *r13; struct intctx *r13;

View File

@ -121,7 +121,10 @@ struct intctx {
#if !defined(__DOXYGEN__) #if !defined(__DOXYGEN__)
/** /**
* @brief Cortex-M3 port context structure. * @brief Platform dependent part of the @p Thread structure.
* @details In the Cortex-Mx port this structure just holds a pointer to the
* @p intctx structure representing the stack pointer at the time
* of the context switch.
*/ */
struct context { struct context {
struct intctx *r13; struct intctx *r13;

View File

@ -20,6 +20,7 @@
/** /**
* @file AVR/chcore.c * @file AVR/chcore.c
* @brief AVR architecture port code. * @brief AVR architecture port code.
*
* @addtogroup AVR_CORE * @addtogroup AVR_CORE
* @{ * @{
*/ */
@ -27,16 +28,21 @@
#include "ch.h" #include "ch.h"
/** /**
* Performs a context switch between two threads. * @brief Performs a context switch between two threads.
* @param otp the thread to be switched out * @details This is the most critical code in any port, this function
* @param ntp the thread to be switched in * is responsible for the context switch between 2 threads.
* @note The function is declared as a weak symbol, it is possible to redefine * @note The implementation of this code affects <b>directly</b> the context
* it in your application code. * switch performance so optimize here as much as you can.
* @note The function is declared as a weak symbol, it is possible to
* redefine it in your application code.
*
* @param[in] ntp the thread to be switched in
* @param[in] otp the thread to be switched out
*/ */
/** @cond never */ #if !defined(__DOXYGEN__)
__attribute__((naked, weak)) __attribute__((naked, weak))
/** @endcond */ #endif
void port_switch(Thread *otp, Thread *ntp) { void port_switch(Thread *ntp, Thread *otp) {
asm volatile ("push r2"); asm volatile ("push r2");
asm volatile ("push r3"); asm volatile ("push r3");
@ -59,13 +65,13 @@ void port_switch(Thread *otp, Thread *ntp) {
asm volatile ("push r28"); asm volatile ("push r28");
asm volatile ("push r29"); asm volatile ("push r29");
asm volatile ("movw r30, r24"); asm volatile ("movw r30, r22");
asm volatile ("in r0, 0x3d"); asm volatile ("in r0, 0x3d");
asm volatile ("std Z+6, r0"); asm volatile ("std Z+6, r0");
asm volatile ("in r0, 0x3e"); asm volatile ("in r0, 0x3e");
asm volatile ("std Z+7, r0"); asm volatile ("std Z+7, r0");
asm volatile ("movw r30, r22"); asm volatile ("movw r30, r24");
asm volatile ("ldd r0, Z+6"); asm volatile ("ldd r0, Z+6");
asm volatile ("out 0x3d, r0"); asm volatile ("out 0x3d, r0");
asm volatile ("ldd r0, Z+7"); asm volatile ("ldd r0, Z+7");
@ -95,13 +101,17 @@ void port_switch(Thread *otp, Thread *ntp) {
} }
/** /**
* Disables the interrupts and halts the system. * @brief Halts the system.
* @note The function is declared as a weak symbol, it is possible to redefine * @details This function is invoked by the operating system when an
* it in your application code. * unrecoverable error is detected (as example because a programming
* error in the application code that triggers an assertion while in
* debug mode).
* @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)) __attribute__((weak))
/** @endcond */ #endif
void port_halt(void) { void port_halt(void) {
port_disable(); port_disable();
@ -110,10 +120,11 @@ void port_halt(void) {
} }
/** /**
* Start a thread by invoking its work function. * @brief Start a thread by invoking its work function.
* If the work function returns @p chThdExit() is automatically invoked. * @details If the work function returns @p chThdExit() is automatically
* invoked.
*/ */
void threadstart(void) { void _port_thread_start(void) {
asm volatile ("sei"); asm volatile ("sei");
asm volatile ("movw r24, r4"); asm volatile ("movw r24, r4");

View File

@ -20,6 +20,7 @@
/** /**
* @file AVR/chcore.h * @file AVR/chcore.h
* @brief AVR architecture port macros and structures. * @brief AVR architecture port macros and structures.
*
* @addtogroup AVR_CORE * @addtogroup AVR_CORE
* @{ * @{
*/ */
@ -31,19 +32,19 @@
#include <avr/interrupt.h> #include <avr/interrupt.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 #ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0 #define ENABLE_WFI_IDLE 0
#endif #endif
/** /**
* Macro defining the AVR architecture. * @brief Macro defining the AVR architecture.
*/ */
#define CH_ARCHITECTURE_AVR #define CH_ARCHITECTURE_AVR
/** /**
* Name of the implemented architecture. * @brief Name of the implemented architecture.
*/ */
#define CH_ARCHITECTURE_NAME "AVR" #define CH_ARCHITECTURE_NAME "AVR"
@ -53,13 +54,15 @@
#define CH_CORE_VARIANT_NAME "MegaAVR" #define CH_CORE_VARIANT_NAME "MegaAVR"
/** /**
* 8 bit stack alignment. * @brief 8 bits stack and memory alignment enforcement.
*/ */
typedef uint8_t stkalign_t; typedef uint8_t stkalign_t;
/** @cond never */ #if !defined(__DOXYGEN__)
/** /**
* Interrupt saved context. * @brief Interrupt saved context.
* @details This structure represents the stack frame saved during a
* preemption-capable interrupt handler.
* @note The field @p _next is not part of the context, it represents the * @note The field @p _next is not part of the context, it represents the
* offset of the structure relative to the stack pointer. * offset of the structure relative to the stack pointer.
*/ */
@ -82,11 +85,13 @@ struct extctx {
uint8_t r0; uint8_t r0;
uint16_t pc; uint16_t pc;
}; };
/** @endcond */ #endif
/** @cond never */ #if !defined(__DOXYGEN__)
/** /**
* System saved context. * @brief System saved context.
* @details This structure represents the inner stack frame during a context
* switching.
* @note The field @p _next is not part of the context, it represents the * @note The field @p _next is not part of the context, it represents the
* offset of the structure relative to the stack pointer. * offset of the structure relative to the stack pointer.
*/ */
@ -115,22 +120,24 @@ struct intctx {
uint8_t pcl; uint8_t pcl;
uint8_t pch; uint8_t pch;
}; };
/** @endcond */ #endif
/** @cond never */ #if !defined(__DOXYGEN__)
/** /**
* In the AVR port this structure just holds a pointer to the @p intctx * @brief Platform dependent part of the @p Thread structure.
* structure representing the stack pointer at the time of the context switch. * @details In the AVR port this structure just holds a pointer to the
* @p intctx structure representing the stack pointer at the time
* of the context switch.
*/ */
struct context { struct context {
struct intctx *sp; struct intctx *sp;
}; };
/** @endcond */ #endif
/** /**
* Platform dependent part of the @p chThdInit() API. * @brief Platform dependent part of the @p chThdInit() API.
* This code usually setup the context switching frame represented by a * @details This code usually setup the context switching frame represented
* @p intctx structure. * by an @p intctx structure.
*/ */
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - \ tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - \
@ -139,34 +146,41 @@ struct context {
tp->p_ctx.sp->r3 = (int)pf >> 8; \ tp->p_ctx.sp->r3 = (int)pf >> 8; \
tp->p_ctx.sp->r4 = (int)arg; \ tp->p_ctx.sp->r4 = (int)arg; \
tp->p_ctx.sp->r5 = (int)arg >> 8; \ tp->p_ctx.sp->r5 = (int)arg >> 8; \
tp->p_ctx.sp->pcl = (int)threadstart >> 8; \ tp->p_ctx.sp->pcl = (int)_port_thread_start >> 8; \
tp->p_ctx.sp->pch = (int)threadstart; \ tp->p_ctx.sp->pch = (int)_port_thread_start; \
} }
/** /**
* The default idle thread implementation requires no extra stack space in * @brief Stack size for the system idle thread.
* this port. * @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 8.
*/ */
#ifndef IDLE_THREAD_STACK_SIZE #ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 8 #define IDLE_THREAD_STACK_SIZE 8
#endif #endif
/** /**
* Per-thread stack overhead for interrupts servicing, it is used in the * @brief Per-thread stack overhead for interrupts servicing.
* calculation of the correct working area size. In this port the default is * @details This constant is used in the calculation of the correct working
* 32 bytes per thread. * 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 the default is 32 bytes per thread.
*/ */
#ifndef INT_REQUIRED_STACK #ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 32 #define INT_REQUIRED_STACK 32
#endif #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) #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) + \ #define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
(sizeof(struct intctx) - 1) + \ (sizeof(struct intctx) - 1) + \
@ -174,16 +188,18 @@ struct context {
(n) + (INT_REQUIRED_STACK)) (n) + (INT_REQUIRED_STACK))
/** /**
* Macro used to allocate a thread working area aligned as both position and * @brief Static working area allocation.
* size. * @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)]; #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 * @brief IRQ prologue code.
* invoke system APIs. * @details This macro must be inserted at the start of all IRQ handlers
* This code tricks the compiler to save all the specified registers by * enabled to invoke system APIs.
* "touching" them. * @note This code tricks the compiler to save all the specified registers
* by "touching" them.
*/ */
#define PORT_IRQ_PROLOGUE() { \ #define PORT_IRQ_PROLOGUE() { \
asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \
@ -191,8 +207,9 @@ struct context {
} }
/** /**
* IRQ epilogue code, inserted at the end of all IRQ handlers enabled to * @brief IRQ epilogue code.
* invoke system APIs. * @details This macro must be inserted at the end of all IRQ handlers
* enabled to invoke system APIs.
*/ */
#define PORT_IRQ_EPILOGUE() { \ #define PORT_IRQ_EPILOGUE() { \
if (chSchIsRescRequiredExI()) \ if (chSchIsRescRequiredExI()) \
@ -200,54 +217,81 @@ struct context {
} }
/** /**
* IRQ handler function declaration. Note, it just aliases the WinAVR "ISR" * @brief IRQ handler function declaration.
* macro. * @note @p id can be a function name or a vector number depending on the
* port implementation.
*/ */
#define PORT_IRQ_HANDLER(id) ISR(id) #define PORT_IRQ_HANDLER(id) ISR(id)
/** /**
* This function is empty in this port. * @brief Port-related initialization code.
* @note This function is empty in this port.
*/ */
#define port_init() #define port_init()
/** /**
* Implemented as global interrupt disable. * @brief Kernel-lock action.
* @details Usually this function just disables interrupts but may perform more
* actions.
* @note Implemented as global interrupt disable.
*/ */
#define port_lock() asm volatile ("cli") #define port_lock() asm volatile ("cli")
/** /**
* Implemented as global interrupt enable. * @brief Kernel-unlock action.
* @details Usually this function just disables interrupts but may perform more
* actions.
* @note Implemented as global interrupt enable.
*/ */
#define port_unlock() asm volatile ("sei") #define port_unlock() asm volatile ("sei")
/** /**
* 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 This function is empty in this port.
*/ */
#define port_lock_from_isr() #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 This function is empty in this port.
*/ */
#define port_unlock_from_isr() #define port_unlock_from_isr()
/** /**
* Implemented as global interrupt disable. * @brief Disables all the interrupt sources.
* @note Of course non maskable interrupt sources are not included.
* @note Implemented as global interrupt disable.
*/ */
#define port_disable() asm volatile ("cli") #define port_disable() asm volatile ("cli")
/** /**
* Same as @p port_disable() in this port, there is no difference between the * @brief Disables the interrupt sources below kernel-level priority.
* two states. * @note Interrupt sources above kernel level remains enabled.
* @note Same as @p port_disable() in this port, there is no difference
* between the two states.
*/ */
#define port_suspend() asm volatile ("cli") #define port_suspend() asm volatile ("cli")
/** /**
* Implemented as global interrupt enable. * @brief Enables all the interrupt sources.
* @note Implemented as global interrupt enable.
*/ */
#define port_enable() asm volatile ("sei") #define port_enable() asm volatile ("sei")
/** /**
* 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 This port function is implemented as inlined code for performance
* reasons.
*/ */
#if ENABLE_WFI_IDLE != 0 #if ENABLE_WFI_IDLE != 0
#define port_wait_for_interrupt() { \ #define port_wait_for_interrupt() { \
@ -260,9 +304,9 @@ struct context {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void port_switch(Thread *otp, Thread *ntp); void port_switch(Thread *ntp, Thread *otp);
void port_halt(void); void port_halt(void);
void threadstart(void); void _port_thread_start(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -33,8 +33,8 @@
* @param ntp the thread to be switched in * @param ntp the thread to be switched in
*/ */
__attribute__((used)) __attribute__((used))
static void __dummy(Thread *otp, Thread *ntp) { static void __dummy(Thread *ntp, Thread *otp) {
(void)otp; (void)ntp; (void)ntp; (void)otp;
#if defined(WIN32) #if defined(WIN32)
asm volatile (".globl @port_switch@8 \n\t" \ asm volatile (".globl @port_switch@8 \n\t" \
"@port_switch@8:"); "@port_switch@8:");
@ -49,8 +49,8 @@ static void __dummy(Thread *otp, Thread *ntp) {
"push %esi \n\t" \ "push %esi \n\t" \
"push %edi \n\t" \ "push %edi \n\t" \
"push %ebx \n\t" \ "push %ebx \n\t" \
"movl %esp, 12(%ecx) \n\t" \ "movl %esp, 12(%edx) \n\t" \
"movl 12(%edx), %esp \n\t" \ "movl 12(%ecx), %esp \n\t" \
"pop %ebx \n\t" \ "pop %ebx \n\t" \
"pop %edi \n\t" \ "pop %edi \n\t" \
"pop %esi \n\t" \ "pop %esi \n\t" \

View File

@ -207,7 +207,7 @@ struct context {
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
__attribute__((fastcall)) void port_switch(Thread *otp, Thread *ntp); __attribute__((fastcall)) void port_switch(Thread *ntp, Thread *otp);
__attribute__((fastcall)) void port_halt(void); __attribute__((fastcall)) void port_halt(void);
void threadexit(void); void threadexit(void);
void ChkIntSources(void); void ChkIntSources(void);

View File

@ -73,7 +73,7 @@
- NEW: Added RIDE7 project files to the STM32 demo under a ./ride7 - NEW: Added RIDE7 project files to the STM32 demo under a ./ride7
subdirectory, this should make things easier for RIDE7 users. The normal subdirectory, this should make things easier for RIDE7 users. The normal
makefile is still available of course. makefile is still available of course.
- NEW: New article in the documentation. - NEW: New articles and guides in the documentation.
- NEW: Documentation improvements, now the description goes on top of each - NEW: Documentation improvements, now the description goes on top of each
page, doxygen defaulted it in the middle, not exactly the best for page, doxygen defaulted it in the middle, not exactly the best for
readability. Improved many descriptions of the various subsystems. Fixed readability. Improved many descriptions of the various subsystems. Fixed