git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1892 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
e53a1a3208
commit
314ba53ca7
|
@ -21,8 +21,11 @@
|
|||
* @page article_interrupts How to write interrupt handlers
|
||||
* Since version 1.1.0 ChibiOS/RT offers a cross-platform method for writing
|
||||
* interrupt handlers. Port-related and compiler-related details are
|
||||
* encapsulated within standard system macros.<br>
|
||||
* An interrupt handler assumes the following general form:
|
||||
* encapsulated within standard system macros.
|
||||
*
|
||||
* <h2>Writing Regular Interrupt handlers</h2>
|
||||
* A Regular Interrupts handler (see @ref interrupt_classes) must be written
|
||||
* using the following general form:
|
||||
* @code
|
||||
CH_IRQ_HANDLER(myIRQ) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
@ -38,15 +41,29 @@ CH_IRQ_HANDLER(myIRQ) {
|
|||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
* @endcode
|
||||
* Note that only interrupt handlers that have to invoke system @ref I-Class
|
||||
* APIs must be written in this form, handlers unrelated to the OS activity can
|
||||
* omit the macros.
|
||||
* Another note about the handler name "myIRQ", in some ports it must be a
|
||||
*
|
||||
* <h2>Writing Fast Interrupt handlers</h2>
|
||||
* In those architectures (@ref ARM7 and @ref ARMCMx) supporting Fast
|
||||
* Interrupts (see @ref interrupt_classes) handlers must be written
|
||||
* using the following general form:
|
||||
* @code
|
||||
CH_FAST_IRQ_HANDLER(myIRQ) {
|
||||
|
||||
// Fast IRQ handling code, preemptable if the architecture supports it.
|
||||
// The invocation of any API is forbidden here because fast interrupt
|
||||
// handlers can preempt the kernel even within its critical zones in
|
||||
// order to minimize latency.
|
||||
}
|
||||
* @endcode
|
||||
*
|
||||
* <h2>Handlers naming</h2>
|
||||
* A note about the handler name "myIRQ", in some ports it must be a
|
||||
* vector number rather than a function name, it could also be a name from
|
||||
* within a predefined set, see the notes about the various ports.
|
||||
*
|
||||
* <h2>Important Notes</h2>
|
||||
* - There is an important application note about ARM7 interrupt handlers,
|
||||
* please read about it in the ARM7 port section: @ref ARM7_IH
|
||||
* .
|
||||
*/
|
||||
|
||||
|
|
@ -154,12 +154,20 @@
|
|||
#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE()
|
||||
|
||||
/**
|
||||
* @brief Standard IRQ handler declaration.
|
||||
* @brief Standard normal IRQ handler declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
|
||||
|
||||
/**
|
||||
* @brief Standard fast IRQ handler declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
* @note Not all architectures support fast interrupts.
|
||||
*/
|
||||
#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -146,6 +146,15 @@ struct context {
|
|||
*/
|
||||
#define PORT_IRQ_HANDLER(id) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Fast IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
* @note Not all architectures support fast interrupts, in this case this
|
||||
* macro must be omitted.
|
||||
*/
|
||||
#define PORT_FAST_IRQ_HANDLER(id) void id(void)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -117,13 +117,13 @@ struct context {
|
|||
* @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 + \
|
||||
wsize - \
|
||||
sizeof(struct intctx)); \
|
||||
tp->p_ctx.r13->r4 = pf; \
|
||||
tp->p_ctx.r13->r5 = arg; \
|
||||
tp->p_ctx.r13->lr = _port_thread_start; \
|
||||
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
|
||||
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
|
||||
wsize - \
|
||||
sizeof(struct intctx)); \
|
||||
tp->p_ctx.r13->r4 = pf; \
|
||||
tp->p_ctx.r13->r5 = arg; \
|
||||
tp->p_ctx.r13->lr = _port_thread_start; \
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,9 +160,9 @@ struct context {
|
|||
/**
|
||||
* @brief Computes the thread working area global size.
|
||||
*/
|
||||
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
|
||||
sizeof(struct intctx) + \
|
||||
sizeof(struct extctx) + \
|
||||
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
|
||||
sizeof(struct intctx) + \
|
||||
sizeof(struct extctx) + \
|
||||
(n) + (INT_REQUIRED_STACK))
|
||||
|
||||
/**
|
||||
|
@ -184,16 +184,16 @@ struct context {
|
|||
* it is transparent to the user code.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define PORT_IRQ_PROLOGUE() { \
|
||||
asm volatile (".code 32 \n\t" \
|
||||
"stmfd sp!, {r0-r3, r12, lr} \n\t" \
|
||||
"add r0, pc, #1 \n\t" \
|
||||
"bx r0 \n\t" \
|
||||
".code 16"); \
|
||||
#define PORT_IRQ_PROLOGUE() { \
|
||||
asm volatile (".code 32 \n\t" \
|
||||
"stmfd sp!, {r0-r3, r12, lr} \n\t" \
|
||||
"add r0, pc, #1 \n\t" \
|
||||
"bx r0 \n\t" \
|
||||
".code 16"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define PORT_IRQ_PROLOGUE() { \
|
||||
asm volatile ("stmfd sp!, {r0-r3, r12, lr}"); \
|
||||
#define PORT_IRQ_PROLOGUE() { \
|
||||
asm volatile ("stmfd sp!, {r0-r3, r12, lr}"); \
|
||||
}
|
||||
#endif /* !THUMB */
|
||||
|
||||
|
@ -205,13 +205,13 @@ struct context {
|
|||
* ARM or THUMB mode.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define PORT_IRQ_EPILOGUE() { \
|
||||
asm volatile ("ldr r0, =_port_irq_common \n\t" \
|
||||
"bx r0"); \
|
||||
#define PORT_IRQ_EPILOGUE() { \
|
||||
asm volatile ("ldr r0, =_port_irq_common \n\t" \
|
||||
"bx r0"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define PORT_IRQ_EPILOGUE() { \
|
||||
asm volatile ("b _port_irq_common"); \
|
||||
#define PORT_IRQ_EPILOGUE() { \
|
||||
asm volatile ("b _port_irq_common"); \
|
||||
}
|
||||
#endif /* !THUMB */
|
||||
|
||||
|
@ -222,6 +222,14 @@ struct context {
|
|||
*/
|
||||
#define PORT_IRQ_HANDLER(id) __attribute__((naked)) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Fast IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define PORT_FAST_IRQ_HANDLER(id) \
|
||||
__attribute__((interrupt("FIQ"))) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Port-related initialization code.
|
||||
* @note This function is empty in this port.
|
||||
|
@ -236,8 +244,8 @@ struct context {
|
|||
* enabled.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define port_lock() { \
|
||||
asm volatile ("bl _port_lock_thumb" : : : "r3", "lr"); \
|
||||
#define port_lock() { \
|
||||
asm volatile ("bl _port_lock_thumb" : : : "r3", "lr"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define port_lock() asm volatile ("msr CPSR_c, #0x9F")
|
||||
|
@ -250,8 +258,8 @@ struct context {
|
|||
* @note In this port it enables both the IRQ and FIQ sources.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define port_unlock() { \
|
||||
asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr"); \
|
||||
#define port_unlock() { \
|
||||
asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define port_unlock() asm volatile ("msr CPSR_c, #0x1F")
|
||||
|
@ -283,16 +291,16 @@ struct context {
|
|||
* LPC214x datasheet.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define port_disable() { \
|
||||
asm volatile ("bl _port_disable_thumb" : : : "r3", "lr"); \
|
||||
#define port_disable() { \
|
||||
asm volatile ("bl _port_disable_thumb" : : : "r3", "lr"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define port_disable() { \
|
||||
asm volatile ("mrs r3, CPSR \n\t" \
|
||||
"orr r3, #0x80 \n\t" \
|
||||
"msr CPSR_c, r3 \n\t" \
|
||||
"orr r3, #0x40 \n\t" \
|
||||
"msr CPSR_c, r3" : : : "r3"); \
|
||||
#define port_disable() { \
|
||||
asm volatile ("mrs r3, CPSR \n\t" \
|
||||
"orr r3, #0x80 \n\t" \
|
||||
"msr CPSR_c, r3 \n\t" \
|
||||
"orr r3, #0x40 \n\t" \
|
||||
"msr CPSR_c, r3" : : : "r3"); \
|
||||
}
|
||||
#endif /* !THUMB */
|
||||
|
||||
|
@ -303,8 +311,8 @@ struct context {
|
|||
* FIQ sources.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define port_suspend() { \
|
||||
asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr"); \
|
||||
#define port_suspend() { \
|
||||
asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define port_suspend() asm volatile ("msr CPSR_c, #0x9F")
|
||||
|
@ -315,8 +323,8 @@ struct context {
|
|||
* @note In this port it enables both the IRQ and FIQ sources.
|
||||
*/
|
||||
#ifdef THUMB
|
||||
#define port_enable() { \
|
||||
asm volatile ("bl _port_enable_thumb" : : : "r3", "lr"); \
|
||||
#define port_enable() { \
|
||||
asm volatile ("bl _port_enable_thumb" : : : "r3", "lr"); \
|
||||
}
|
||||
#else /* !THUMB */
|
||||
#define port_enable() asm volatile ("msr CPSR_c, #0x1F")
|
||||
|
@ -335,29 +343,29 @@ struct context {
|
|||
*/
|
||||
#ifdef THUMB
|
||||
#if CH_DBG_ENABLE_STACK_CHECK
|
||||
#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(_ntp, _otp); \
|
||||
#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(_ntp, _otp); \
|
||||
}
|
||||
#else /* !CH_DBG_ENABLE_STACK_CHECK */
|
||||
#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(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(_ntp, _otp); \
|
||||
#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(_ntp, _otp); \
|
||||
}
|
||||
#else /* !CH_DBG_ENABLE_STACK_CHECK */
|
||||
#define port_switch(ntp, otp) _port_switch_arm(ntp, otp)
|
||||
|
|
|
@ -157,7 +157,16 @@ struct intctx {
|
|||
* @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)
|
||||
#define PORT_IRQ_HANDLER(id) \
|
||||
__attribute__((interrupt("IRQ"))) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Fast IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define PORT_FAST_IRQ_HANDLER(id) \
|
||||
__attribute__((interrupt("IRQ"))) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Port-related initialization code.
|
||||
|
|
|
@ -130,7 +130,16 @@ struct intctx {
|
|||
* @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)
|
||||
#define PORT_IRQ_HANDLER(id) \
|
||||
__attribute__((interrupt("IRQ"))) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Fast IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#define PORT_FAST_IRQ_HANDLER(id) \
|
||||
__attribute__((interrupt("IRQ"))) void id(void)
|
||||
|
||||
/**
|
||||
* @brief Port-related initialization code.
|
||||
|
|
|
@ -67,13 +67,16 @@
|
|||
constants in different address spaces (AVR) because it is assumed that a
|
||||
pointer to a ROMCONST variable is compatible with a normal pointer.
|
||||
- NEW: AT91SAM7 HAL support for the DGBU UART peripheral, as SD3.
|
||||
- NEW: Introduced a new macro CH_FAST_IRQ_HANDLER() for the declaration of
|
||||
fast interrupt handlers on those architectures that support them.
|
||||
- OPT: Internal optimization in the serial driver, it now is a bit smaller
|
||||
and uses less RAM (all architectures).
|
||||
- CHANGE: Modified the STM32 FatFs demo, now it spawns a command shell or
|
||||
the serial port SD2, type "help" for the available commands. More commands
|
||||
can be easily added.
|
||||
- Various documentation fixes, added an article covering debugging under
|
||||
ChibiOS/RT.
|
||||
ChibiOS/RT, updated the article about interrupt handlers to cover also
|
||||
fast interrupt sources.
|
||||
|
||||
*** 1.5.5 ***
|
||||
- FIX: Removed some "dead" code in the old ARMv7-M files (there are new
|
||||
|
|
Loading…
Reference in New Issue