From e1b6b9e988d70442e71b520f5a8f43e355688a71 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Jan 2009 14:26:25 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@596 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/AVR-AT90CANx-GCC/board.c | 11 ++-- demos/AVR-ATmega128-GCC/board.c | 11 ++-- ports/AVR/avr_serial.c | 44 +++++++------ ports/AVR/chcore.c | 76 +++++++++++++--------- ports/AVR/chcore.h | 138 ++++++++++++++++++++++++++++++++-------- ports/MSP430/chcore.h | 4 +- 6 files changed, 195 insertions(+), 89 deletions(-) diff --git a/demos/AVR-AT90CANx-GCC/board.c b/demos/AVR-AT90CANx-GCC/board.c index e78360e9a..bd052b9c9 100644 --- a/demos/AVR-AT90CANx-GCC/board.c +++ b/demos/AVR-AT90CANx-GCC/board.c @@ -19,19 +19,18 @@ #include -#include -#include - #include "board.h" #include "avr_serial.h" -ISR(TIMER0_COMP_vect) { +SYS_IRQ_HANDLER(TIMER0_COMP_vect) { - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); chSysTimerHandlerI(); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } /* diff --git a/demos/AVR-ATmega128-GCC/board.c b/demos/AVR-ATmega128-GCC/board.c index 03907d391..96c810b17 100644 --- a/demos/AVR-ATmega128-GCC/board.c +++ b/demos/AVR-ATmega128-GCC/board.c @@ -19,19 +19,18 @@ #include -#include -#include - #include "board.h" #include "avr_serial.h" -ISR(TIMER0_COMP_vect) { +SYS_IRQ_HANDLER(TIMER0_COMP_vect) { - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); chSysTimerHandlerI(); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } /* diff --git a/ports/AVR/avr_serial.c b/ports/AVR/avr_serial.c index 474e9cb20..f60cfb4e6 100644 --- a/ports/AVR/avr_serial.c +++ b/ports/AVR/avr_serial.c @@ -19,9 +19,6 @@ #include -#include -#include - #include "avr_serial.h" static void SetError(uint8_t sra, FullDuplexDriver *com) { @@ -33,7 +30,9 @@ static void SetError(uint8_t sra, FullDuplexDriver *com) { sts |= SD_PARITY_ERROR; if (sra & (1 << FE)) sts |= SD_FRAMING_ERROR; + chSysLockI(); chFDDAddFlagsI(com, sts); + chSysUnlockI(); } #ifdef USE_AVR_USART0 @@ -41,30 +40,35 @@ FullDuplexDriver SER1; static uint8_t ib1[SERIAL_BUFFERS_SIZE]; static uint8_t ob1[SERIAL_BUFFERS_SIZE]; -ISR(USART0_RX_vect) { - uint8_t sra = UCSR0A; +SYS_IRQ_HANDLER(USART0_RX_vect) { + uint8_t sra; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + sra = UCSR0A; if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE))) SetError(sra, &SER1); + chSysLockI(); chFDDIncomingDataI(&SER1, UDR0); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } -ISR(USART0_UDRE_vect) { +SYS_IRQ_HANDLER(USART0_UDRE_vect) { msg_t b; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); b = chFDDRequestDataI(&SER1); + chSysUnlockI(); if (b < Q_OK) UCSR0B &= ~(1 << UDRIE); else UDR0 = b; - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } /* @@ -95,31 +99,35 @@ FullDuplexDriver SER2; static uint8_t ib2[SERIAL_BUFFERS_SIZE]; static uint8_t ob2[SERIAL_BUFFERS_SIZE]; -ISR(USART1_RX_vect) { - - uint8_t sra = UCSR1A; +SYS_IRQ_HANDLER(USART1_RX_vect) { + uint8_t sra; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + sra = UCSR1A; if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE))) SetError(sra, &SER2); + chSysLockI(); chFDDIncomingDataI(&SER2, UDR1); + chSysUnlockI(); - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } -ISR(USART1_UDRE_vect) { +SYS_IRQ_HANDLER(USART1_UDRE_vect) { msg_t b; - chSysIRQEnterI(); + SYS_IRQ_PROLOGUE(); + chSysLockI(); b = chFDDRequestDataI(&SER2); + chSysUnlockI(); if (b < Q_OK) UCSR1B &= ~(1 << UDRIE); else UDR1 = b; - chSysIRQExitI(); + SYS_IRQ_EPILOGUE(); } /* diff --git a/ports/AVR/chcore.c b/ports/AVR/chcore.c index 340843d45..9ae0b4c56 100644 --- a/ports/AVR/chcore.c +++ b/ports/AVR/chcore.c @@ -17,33 +17,40 @@ along with this program. If not, see . */ -#include - -#include - -void _idle(void *p) { +/** + * @addtogroup AVR_CORE + * @{ + */ - while (TRUE) { - asm("sleep"); - } -} +#include /* - * Threads start code. + * This file is a template of the system driver functions provided by a port. + * Some of the following functions may be implemented as macros in chcore.h if + * the implementer decides that there is an advantage in doing so, as example + * because performance concerns. */ -void threadstart(void) { - asm volatile ("sei"); - asm volatile ("movw r24, r4"); - asm volatile ("movw r30, r2"); - asm volatile ("icall"); - asm volatile ("call chThdExit"); +/** + * The default implementation of this function is void so no messages are + * actually printed. + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. + * @param msg pointer to the message string + */ +__attribute__((weak)) +void sys_puts(char *msg) { } -/* - * Context switch. +/** + * Performs a context switch between two threads. + * @param otp the thread to be switched out + * @param ntp the thread to be switched in + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. */ -void chSysSwitchI(Thread *otp, Thread *ntp) { +__attribute__((naked, weak)) +void sys_switch(Thread *otp, Thread *ntp) { asm volatile ("push r2"); asm volatile ("push r3"); @@ -101,21 +108,30 @@ void chSysSwitchI(Thread *otp, Thread *ntp) { asm volatile ("ret"); } -/* - * System console message (not implemented). +/** + * Disables the interrupts and halts the system. + * @note The function is declared as a weak symbol, it is possible to redefine + * it in your application code. */ __attribute__((weak)) -void chSysPuts(char *msg) { +void sys_halt(void) { + + sys_disable(); + while (TRUE) { + } } -/* - * System halt. +/** + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. */ -__attribute__((noreturn, weak)) -void chSysHalt(void) { - - chSysLock(); +void threadstart(void) { - while (TRUE) - ; + asm volatile ("sei"); + asm volatile ("movw r24, r4"); + asm volatile ("movw r30, r2"); + asm volatile ("icall"); + asm volatile ("call chThdExit"); } + +/** @} */ diff --git a/ports/AVR/chcore.h b/ports/AVR/chcore.h index ddeaf33ef..e41ec673f 100644 --- a/ports/AVR/chcore.h +++ b/ports/AVR/chcore.h @@ -17,21 +17,39 @@ along with this program. If not, see . */ +/** + * @addtogroup AVR_CORE + * @{ + */ + #ifndef _CHCORE_H_ #define _CHCORE_H_ +#include +#include + + /* + * Port-related configuration parameters. + */ +#ifndef ENABLE_WFI_IDLE +#define ENABLE_WFI_IDLE 0 +#endif + +/** * Macro defining the AVR architecture. */ #define CH_ARCHITECTURE_AVR -/* +/** * 8 bit stack alignment. */ typedef uint8_t stkalign_t; -/* +/** * Interrupt saved context. + * @note The field @p _next is not part of the context, it represents the + * offset of the structure relative to the stack pointer. */ struct extctx { uint8_t _next; @@ -53,8 +71,10 @@ struct extctx { uint16_t pc; }; -/* +/** * System saved context. + * @note The field @p _next is not part of the context, it represents the + * offset of the structure relative to the stack pointer. */ struct intctx { uint8_t _next; @@ -82,20 +102,23 @@ struct intctx { uint8_t pch; }; -/* - * Port dependent part of the Thread structure, you may add fields in - * this structure. +/** + * Platform dependent part of the @p Thread structure. + * 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. */ typedef struct { struct intctx *sp; } Context; /** - * Platform dependent part of the \p chThdCreate() API. + * Platform dependent part of the @p chThdInit() API. + * This code usually setup the context switching frame represented by a + * @p intctx structure. */ #define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ - tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - 1 - \ - (sizeof(struct intctx) - 1)); \ + tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - \ + sizeof(struct intctx)); \ tp->p_ctx.sp->r2 = (int)pf; \ tp->p_ctx.sp->r3 = (int)pf >> 8; \ tp->p_ctx.sp->r4 = (int)arg; \ @@ -104,48 +127,109 @@ typedef struct { tp->p_ctx.sp->pch = (int)threadstart; \ } +/** + * The default idle thread implementation requires no extra stack space in + * this port. + */ +#ifndef IDLE_THREAD_STACK_SIZE +#define IDLE_THREAD_STACK_SIZE 8 +#endif + +/** + * Per-thread stack overhead for interrupts servicing, it is used in the + * calculation of the correct working area size. In this port the default is + * 32 bytes per thread. + */ #ifndef INT_REQUIRED_STACK #define INT_REQUIRED_STACK 32 #endif +/** + * Enforces a correct alignment for a stack area size value. + */ #define STACK_ALIGN(n) ((((n) - 1) | sizeof(stkalign_t)) + 1) + /** + * Computes the thread working area global size. + */ #define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ (sizeof(struct intctx) - 1) + \ (sizeof(struct extctx) - 1) + \ - (n) + \ - INT_REQUIRED_STACK) + (n) + (INT_REQUIRED_STACK)) +/** + * Macro used to allocate a 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 chSysLock() asm volatile ("cli") +/** + * IRQ prologue code, inserted at the start of all IRQ handlers enabled to + * invoke system APIs. + * This code tricks the compiler to save the specified registers by "touching" + * them. + */ +#define SYS_IRQ_PROLOGUE() { \ +asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ + "r25", "r26", "r27", "r30", "r31"); \ +} + +/** + * IRQ epilogue code, inserted at the end of all IRQ handlers enabled to + * invoke system APIs. + */ +#define SYS_IRQ_EPILOGUE() { \ + if (chSchRescRequiredI()) \ + chSchDoRescheduleI(); \ +} -#define chSysUnlock() asm volatile ("sei") +/** + * IRQ handler function modifier. Note, it just aliases the WinAVR "ISR" + * macro. + */ +#define SYS_IRQ_HANDLER ISR + +/** + * This port function is implemented as inlined code for performance reasons. + */ +#define sys_disable() asm volatile ("cli") -#define chSysEnable() asm volatile ("sei") +/** + * This port function is implemented as inlined code for performance reasons. + */ +#define sys_enable() asm volatile ("sei") -#define chSysIRQEnterI() \ - asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ - "r25", "r26", "r27", "r30", "r31"); +/** + * This port function is implemented as inlined code for performance reasons. + */ +#define sys_disable_from_isr() sys_disable() +/** + * This port function is implemented as inlined code for performance reasons. + */ +#define sys_enable_from_isr() sys_enable() -#define chSysIRQExitI() { \ - if (chSchRescRequiredI()) \ - chSchDoRescheduleI(); \ +#if ENABLE_WFI_IDLE != 0 +/** + * This port function is implemented as inlined code for performance reasons. + */ +#define sys_wait_for_interrupt() { \ + asm volatile ("sleep"); \ } - -#define IDLE_THREAD_STACK_SIZE 8 +#else +#define sys_wait_for_interrupt() +#endif #ifdef __cplusplus extern "C" { #endif - void _idle(void *p) __attribute__((noreturn)); - void chSysHalt(void) __attribute__((noreturn)) ; - void chSysSwitchI(Thread *otp, Thread *ntp); - void chSysPuts(char *msg); - void threadstart(void) __attribute__((naked)); + void sys_puts(char *msg); + void sys_switch(Thread *otp, Thread *ntp); + void sys_halt(void); #ifdef __cplusplus } #endif #endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/ports/MSP430/chcore.h b/ports/MSP430/chcore.h index a4a866f11..42f0c2f71 100644 --- a/ports/MSP430/chcore.h +++ b/ports/MSP430/chcore.h @@ -32,7 +32,7 @@ * Port-related configuration parameters. */ #ifndef ENABLE_WFI_IDLE -#define ENABLE_WFI_IDLE 0 /* Enables the use of the WFI ins. */ +#define ENABLE_WFI_IDLE 0 #endif /** @@ -151,7 +151,7 @@ if (chSchRescRequiredI()) \ } /** - * IRQ handler function modifier. Note it just aliases the WinMSP "interrupt" + * IRQ handler function modifier. Note, it just aliases the WinMSP "interrupt" * macro. */ #define SYS_IRQ_HANDLER interrupt -- cgit v1.2.3