modified at91 interrupt code from contiki to use the mc1322x registers

and to produce code that works with THUMB.
This commit is contained in:
Mariano Alvira 2009-04-20 15:42:21 -04:00
parent 4f45e43984
commit cfd985c837
4 changed files with 325 additions and 14 deletions

272
include/interrupt-utils.h Normal file
View file

@ -0,0 +1,272 @@
/*
* Defines and Macros for Interrupt-Service-Routines
* collected and partly created by
* Martin Thomas <mthomas@rhrk.uni-kl.de>
*
* Copyright 2005 M. Thomas
* No guarantees, warrantees, or promises, implied or otherwise.
* May be used for hobby or commercial purposes provided copyright
* notice remains intact.
*/
#ifndef interrupt_utils_
#define interrupt_utils_
/*
The following defines are usefull for
interrupt service routine declarations.
*/
/*
RAMFUNC
Attribute which defines a function to be located
in memory section .fastrun and called via "long calls".
See linker-skript and startup-code to see how the
.fastrun-section is handled.
The definition is not only useful for ISRs but since
ISRs should be executed fast the macro is defined in
this header.
*/
#define RAMFUNC __attribute__ ((long_call, section (".fastrun")))
/*
INTFUNC
standard attribute for arm-elf-gcc which marks
a function as ISR (for the VIC). Since gcc seems
to produce wrong code if this attribute is used in
thumb/thumb-interwork the attribute should only be
used for "pure ARM-mode" binaries.
*/
#define INTFUNC __attribute__ ((interrupt("IRQ")))
/*
NACKEDFUNC
gcc will not add any code to a function declared
"nacked". The user has to take care to save registers
and add the needed code for ISR functions. Some
macros for this tasks are provided below.
*/
#define NACKEDFUNC __attribute__((naked))
/******************************************************************************
*
* MACRO Name: ISR_STORE()
*
* Description:
* This MACRO is used upon entry to an ISR with interrupt nesting.
* Should be used together with ISR_ENABLE_NEST(). The MACRO
* performs the following steps:
*
* 1 - Save the non-banked registers r0-r12 and lr onto the IRQ stack.
*
*****************************************************************************/
#define ISR_STORE() asm volatile( \
"STMDB SP!,{R0-R12,LR}\n" )
/******************************************************************************
*
* MACRO Name: ISR_RESTORE()
*
* Description:
* This MACRO is used upon exit from an ISR with interrupt nesting.
* Should be used together with ISR_DISABLE_NEST(). The MACRO
* performs the following steps:
*
* 1 - Load the non-banked registers r0-r12 and lr from the IRQ stack.
* 2 - Adjusts resume adress
*
*****************************************************************************/
#define ISR_RESTORE() asm volatile( \
"LDMIA SP!,{R0-R12,LR}\n" \
"SUBS R15,R14,#0x0004\n" )
/******************************************************************************
*
* MACRO Name: ISR_ENABLE_NEST()
*
* Description:
* This MACRO is used upon entry from an ISR with interrupt nesting.
* Should be used after ISR_STORE.
*
*****************************************************************************/
#define ISR_ENABLE_NEST() asm volatile( \
"MRS LR, SPSR \n" \
"STMFD SP!, {LR} \n" \
"MSR CPSR_c, #0x1f \n" \
"STMFD SP!, {LR} " )
/******************************************************************************
*
* MACRO Name: ISR_DISABLE_NEST()
*
* Description:
* This MACRO is used upon entry from an ISR with interrupt nesting.
* Should be used before ISR_RESTORE.
*
*****************************************************************************/
#define ISR_DISABLE_NEST() asm volatile( \
"LDMFD SP!, {LR} \n" \
"MSR CPSR_c, #0x92 \n" \
"LDMFD SP!, {LR} \n" \
"MSR SPSR_cxsf, LR \n" )
/*
* The following marcos are from the file "armVIC.h" by:
*
* Copyright 2004, R O SoftWare
* No guarantees, warrantees, or promises, implied or otherwise.
* May be used for hobby or commercial purposes provided copyright
* notice remains intact.
*
*/
/******************************************************************************
*
* MACRO Name: ISR_ENTRY()
*
* Description:
* This MACRO is used upon entry to an ISR. The current version of
* the gcc compiler for ARM does not produce correct code for
* interrupt routines to operate properly with THUMB code. The MACRO
* performs the following steps:
*
* 1 - Adjust address at which execution should resume after servicing
* ISR to compensate for IRQ entry
* 2 - Save the non-banked registers r0-r12 and lr onto the IRQ stack.
* 3 - Get the status of the interrupted program is in SPSR.
* 4 - Push it onto the IRQ stack as well.
*
*****************************************************************************/
#define ISR_ENTRY() asm volatile(" sub lr, lr,#4\n" \
" stmfd sp!,{r0-r12,lr}\n" \
" mrs r1, spsr\n" \
" stmfd sp!,{r1}")
/******************************************************************************
*
* MACRO Name: ISR_EXIT()
*
* Description:
* This MACRO is used to exit an ISR. The current version of the gcc
* compiler for ARM does not produce correct code for interrupt
* routines to operate properly with THUMB code. The MACRO performs
* the following steps:
*
* 1 - Recover SPSR value from stack
* 2 - and restore its value
* 3 - Pop the return address & the saved general registers from
* the IRQ stack & return
*
*****************************************************************************/
#define ISR_EXIT() asm volatile(" ldmfd sp!,{r1}\n" \
" msr spsr_c,r1\n" \
" ldmfd sp!,{r0-r12,pc}^")
/******************************************************************************
*
* Function Name: disableIRQ()
*
* Description:
* This function sets the IRQ disable bit in the status register
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned disableIRQ(void);
/******************************************************************************
*
* Function Name: enableIRQ()
*
* Description:
* This function clears the IRQ disable bit in the status register
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned enableIRQ(void);
/******************************************************************************
*
* Function Name: restoreIRQ()
*
* Description:
* This function restores the IRQ disable bit in the status register
* to the value contained within passed oldCPSR
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned restoreIRQ(unsigned oldCPSR);
/******************************************************************************
*
* Function Name: disableFIQ()
*
* Description:
* This function sets the FIQ disable bit in the status register
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned disableFIQ(void);
/******************************************************************************
*
* Function Name: enableFIQ()
*
* Description:
* This function clears the FIQ disable bit in the status register
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned enableFIQ(void);
/******************************************************************************
*
* Function Name: restoreFIQ()
*
* Description:
* This function restores the FIQ disable bit in the status register
* to the value contained within passed oldCPSR
*
* Calling Sequence:
* void
*
* Returns:
* previous value of CPSR
*
*****************************************************************************/
unsigned restoreFIQ(unsigned oldCPSR);
#endif

31
include/sys-interrupt.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef __SYS_INTERRUPT_H__QIHZ66NP8K__
#define __SYS_INTERRUPT_H__QIHZ66NP8K__
/* Returns true if it handled an activbe interrupt */
typedef int (*SystemInterruptFunc)();
typedef struct _SystemInterruptHandler SystemInterruptHandler;
struct _SystemInterruptHandler
{
SystemInterruptHandler *next;
SystemInterruptFunc handler;
};
void
sys_interrupt_enable();
void
sys_interrupt_disable();
void
sys_interrupt_append_handler(SystemInterruptHandler *handler);
void
sys_interrupt_prepend_handler(SystemInterruptHandler *handler);
void
sys_interrupt_remove_handler(SystemInterruptHandler *handler);
#endif /* __SYS_INTERRUPT_H__QIHZ66NP8K__ */

View file

@ -17,18 +17,29 @@
#define FIQ_MASK 0x00000040
#define INT_MASK (IRQ_MASK | FIQ_MASK)
static inline unsigned __get_cpsr(void)
unsigned __get_cpsr(void)
{
unsigned long retval;
asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );
asm volatile (
".code 32;"
"mrs %0, cpsr;"
".code 16;"
: "=r" (retval) :
);
return retval;
}
static inline void __set_cpsr(unsigned val)
void __set_cpsr(unsigned val)
{
asm volatile (" msr cpsr_c, %0" : /* no outputs */ : "r" (val) );
asm volatile (
".code 32;"
"msr cpsr_c, %0;"
".code 16;"
: : "r" (val)
);
}
unsigned disableIRQ(void)
{
unsigned _cpsr;

View file

@ -1,6 +1,7 @@
#include <sys-interrupt.h>
#include <interrupt-utils.h>
#include <AT91SAM7S64.h>
#include "sys-interrupt.h"
#include "interrupt-utils.h"
#include "embedded_types.h"
#define ATTR
@ -30,24 +31,20 @@ system_int (void) /* System Interrupt Handler */
{
ISR_ENTRY();
system_int_safe();
*AT91C_AIC_EOICR = 0; /* End of Interrupt */
ISR_EXIT();
}
static unsigned int enabled = 0; /* Number of times the system
interrupt has been enabled */
#define DIS_INT *AT91C_AIC_IDCR = (1 << AT91C_ID_SYS)
#define EN_INT if (enabled > 0) *AT91C_AIC_IECR = (1 << AT91C_ID_SYS)
#define INTCNTL 0x80020000
#define DIS_INT *((volatile uint32_t *)INTCNTL) = 3 << 19;
#define EN_INT if (enabled > 0) *((volatile uint32_t *)INTCNTL) = 0;
void
sys_interrupt_enable()
{
if (enabled++ == 0) {
/* Level trigged at priority 5 */
AT91C_AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
/* Interrupt vector */
AT91C_AIC_SVR[AT91C_ID_SYS] = (unsigned long) system_int;
/* Enable */
EN_INT;
}