Use __fiq instead of __irq.
From Keil help:
Fast Interrupt Functions (__fiq)
Fast Interrupt Functions can be directly defined using the __fiq
function attribute:
void funcname (void) __fiq
Where
funcname
is the name of the function.
__fiq
indicates the function as fast interrupt function.
The __fiq attribute affects the generated code of the function as follows:
The function is generated using ARM instructions, even when the THUMB
directive is specified.
On function entry the registers R0 - R7 (when modified) are saved on
the stack.
When exiting the function all register contents saved on the stack are
restored.
The instruction SUBS PC,R14,#4 is used to return from the __fiq function.
The ARM device jumps to the __fiq vector location (some ARM devices
provide an Vectored Interrupt Controller that supports also fiq
interrupts). By default, the CPU startup code (STARTUP.S) jumps to the
function FIQ_Handler. When the __fiq function in the application code
is named FIQ_Handler no modification to the STARTUP.S file is required.
The following sample program shows how to use the __fiq attribute. The
code sequences generated are shown in the Assembler Listing section.
stmt level source
1 /*
2 * IRQ Handler for ADuC7000 Timer0 Interrupt
3 */
4
5 #include <ADuC7024.H>
6
7 volatile int T0_ticks;
8
9 void IRQ_Handler (void) __fiq {
10 1 if (IRQSIG & 0x00000004) { // Timer0 Interrupt
11 2 T0CLRI = 1;
12 2 T0_ticks++;
13 2 }
14 1 }
ASSEMBLY LISTING OF GENERATED OBJECT CODE
*** PUBLICS:
PUBLIC IRQ_Handler?A
PUBLIC T0_ticks
*** DATA SEGMENT '?DT0?irq':
00000000 T0_ticks:
00000000 DS 4
*** CODE SEGMENT '?PR?IRQ_Handler?A?irq':
9: void IRQ_Handler (void) __irq {
00000000 E92D0003 STMDB R13!,{R0-R1}
10: if (IRQSIG & 0x00000004) { // Timer0 Interrupt
00000004 E5100000 LDR R0,=0xFFFF0004
00000008 E5900000 LDR R0,[R0,#0x0]
0000000C E3A01004 MOV R1,#0x4
00000010 E1100001 TST R0,R1
00000014 0A000006 BEQ L_1 ; Targ=0x34
11: T0CLRI = 1;
00000018 E3A01001 MOV R1,#0x1
0000001C E5100000 LDR R0,=0xFFFF030C
00000020 E5801000 STR R1,[R0,#0x0]
12: T0_ticks++;
00000024 E5100000 LDR R0,=T0_ticks ; T0_ticks
00000028 E5901000 LDR R1,[R0,#0x0] ; T0_ticks
0000002C E2811001 ADD R1,R1,#0x0001
00000030 E5801000 STR R1,[R0,#0x0] ; T0_ticks
13: }
00000034 L_1:
00000034 E8BD0003 LDMIA R13!,{R0-R1}
00000038 E25EF004 SUBS R15,R14,#0x0004
0000003C ENDP ; 'IRQ_Handler?A'
Note
The __fiq attribute is not allowed when declaring or prototyping
external functions. For example, the following function prototype is
invalid:
extern void func (void) __fiq;
Passing parameters to interrupt function is not possible. Any attempt
to define an interrupt function with arguments generates an error
message.
Interrupt function declarations may not include a return value. They
must be declared with a void return type. The compiler generates an
error message if an attempt to define a return value for the interrupt
function is made.
The run-time library of the CARM Compiler contains a default
FIQ_Handler that generates an end-less loop using the instruction B $.
--- In , "Pete" <peterbrown_abroad@y...> wrote:
>
> Hi Peter
> Interesting to hear this as I too am using Keil, but wasnt aware
> that you could do this!
>
> For my info, how do you tell Keil that you want the interrupt to be
> a Fast interrupt rather than the normal type?
>
> sorry i didnt help fix the problem, and hope someone else can help u
> out.
> rgds
> pete
>
> --- In , "peterburdine" <lordofdawn@h...>
> wrote:
> >
> > Pete,
> >
> > The Keil's compilier does not require such initialization. I have
> a
> > timer isr that works just fine being declared as
> >
> > void timer_isr (void);
> >
> > void timer_isr (void) __irq {....}
> >
> > I do now have the VicVectAddr = 0;, but that doesn't help if
it
> > doesn't get called.
> >
> > --Peter
> >
> > --- In , "Pete" <peterbrown_abroad@y...>
> wrote:
> > >
> > > peter
> > >
> > > i think also that you need to initialise the isr function
> > > differently...
> > > something like this:
> > > void uart0_isr(void) __attribute__
((interrupt("IRQ")));
> > >
> > > rather than:
> > > void uart0_isr (void);
> > >
> > > see the user manual section on interrupt handling....
> > >
> > > also, add the:
> > > VICVectAddr = 0;//Dummy write to signal end of interrupt
> > >
> > > to the end of the isr...
> > > does this help?
> > >
> > > kind regards
> > > Pete
> > >
> > >
> > > --- In , "peterburdine" <lordofdawn@h...>
> > > wrote:
> > > >
> > > > I am sure the might help, if the ISR was called in the first
> > > place.
> > > > But it isn't.
> > > > Also, according to the user manual I have,, it states that
> only
> > > U0IIR
> > > > must be accessed to clear the IRQ (for TXRE anyways).
> > > >
> > > > --Peter
> > > >
> > > > --- In , "Pete"
> <peterbrown_abroad@y...>
> > > wrote:
> > > > >
> > > > > In an interrupt service routine:
> > > > > in order to exit it properly you must, Clear the
interrupt
> flag
> > > that
> > > > > triggered it (write a 1 to the flag?) eg:
> > > > > U0IIR = 0x0000000A; //Clear the interrupt register
> > > > >
> > > > > anyway, most importantly you also need to write to teh
> vector
> > > > > address register:
> > > > > eg:
> > > > > VICVectAddr = 0x00000000;//Dummy write to signal end of
> > > interrupt
> > > > >
> > > > > failure to do these will lead to continuous
interrupts.....
> > > > >
> > > > >
> > > > > Does this help???
> > > > >
> > > > > rgds
> > > > > pete
> > > > >
> > > > >
> > > > > --- In , "peterburdine"
> <lordofdawn@h...>
> > > > > wrote:
> > > > > >
> > > > > > I think I may be missing something stupid, but can
anyone
> help
> > > me?
> > > > > > I am tring to write to UART0, but it doesn't
seem to
> work. I
> > > am
> > > > > > trying to write a software buffer to help out the
one byte
> > > hardware
> > > > > > buffer. Specifically I am using the LPC 2294.
Below is
> my
> > > code.
> > > > > >
> > > > > > I am using the Keil toolset
> (compiler/debugger/simulator).
> > > The
> > > > > code
> > > > > > works perfectly fine when running it on the
simulator, but
> > > when I
> > > > > try
> > > > > > to run it on the chip, I will only get
"ho" instead
> > > of "hello". I
> > > > > put
> > > > > > some break points in it when using JTAG to debug,
but the
> ISR
> > > is
> > > > > never
> > > > > > called when running on the real hardware, it is
called on
> the
> > > > > > simulator. Also, when I debug on JTAG I never se
the THRE
> or
> > > TEMT
> > > > > > clear. Can you see anything obviously wrong? I
think I
> put in
> > > > > > everything that you need to compile it.
> > > > > >
> > > > > > #include <stdio.h>
> > > > > > #define TX_BUFFER_LENGTH 64
> > > > > > #define UART0_THRE (U0LSR & 0x20)
> > > > > > #define PINSEL0_00_TxD (0x01)
> > > > > > #define PINSEL0_01_GPIO (0x00 << 2)
> > > > > > #define U0RBR (*((volatile unsigned char *)
> > > 0xE000C000))
> > > > > > #define U0THR (*((volatile unsigned char *)
> > > 0xE000C000))
> > > > > > #define U0IER (*((volatile unsigned char *)
> > > 0xE000C004))
> > > > > > #define U0IIR (*((volatile unsigned char *)
> > > 0xE000C008))
> > > > > > #define U0FCR (*((volatile unsigned char *)
> > > 0xE000C008))
> > > > > > #define U0LCR (*((volatile unsigned char *)
> > > 0xE000C00C))
> > > > > > #define U0MCR (*((volatile unsigned char *)
> > > 0xE000C010))
> > > > > > #define U0LSR (*((volatile unsigned char *)
> > > 0xE000C014))
> > > > > > #define U0MSR (*((volatile unsigned char *)
> > > 0xE000C018))
> > > > > > #define U0SCR (*((volatile unsigned char *)
> > > 0xE000C01C))
> > > > > > #define U0DLL (*((volatile unsigned char *)
> > > 0xE000C000))
> > > > > > #define U0DLM (*((volatile unsigned char *)
> > > 0xE000C004))
> > > > > > #define VICVectAddr6 (*((volatile unsigned long *)
> > > 0xFFFFF118))
> > > > > > #define VICVectCntl6 (*((volatile unsigned long *)
> > > 0xFFFFF218))
> > > > > > #define VICIntSelect (*((volatile unsigned long *)
> > > 0xFFFFF00C))
> > > > > > #define VICIntEnable (*((volatile unsigned long *)
> > > 0xFFFFF010))
> > > > > > #define VICIntEnClr (*((volatile unsigned long *)
> > > 0xFFFFF014))
> > > > > > static Uint16 txBytes = 0;
> > > > > > static Uint16 txRdPos = 0;
> > > > > > static Uint16 txWrPos = 0;
> > > > > > static Uint16 txBuffer[TX_BUFFER_LENGTH];
> > > > > >
> > > > > > void uart0_config (void);
> > > > > > void uart0_isr (void);
> > > > > > void uart0_sendByte (Uint8);
> > > > > > int putchar(int);
> > > > > > int main (void);
> > > > > >
> > > > > > void uart0_config (void) {
> > > > > > // Setup UART 0
> > > > > > U0LCR = 0x80; // Enable DLAB
> > > > > > U0DLL = 0x16; // Setup BGR
> > > > > > U0DLM = 0x05; // ~2400 Bit/s @ 50 Mhz
> > > > > > U0LCR = 0x03; // Enable UART 0, 8 bits, no parity,
1
> stop bit
> > > > > >
> > > > > > // Reset the FIFOs
> > > > > > U0FCR = 0xC7; // RX FIFO trigger level 8 chars,
> reset tx and
> > > > > rx fifo,
> > > > > > enable fifos
> > > > > >
> > > > > > // Setup Interrupts for UART0
> > > > > > U0IER = 0x7;
> > > > > > VICIntSelect &= 0x0;
> > > > > > VICVectCntl6 = 0x20 | 6;
> > > > > > VICVectAddr6 = (unsigned long) uart0_isr;
> > > > > > VICIntEnable |= (0x1 << 6); // Enable Uart0
Interrupt
>
> > > > > > }
> > > > > >
> > > > > > void uart0_isr (void) __irq {
> > > > > > switch((U0IIR>>1)&0x7) {
> > > > > > // THRE
> > > > > > case 001:
> > > > > > if(txBytes != 0) {
> > > > > > U0THR = txBuffer[txRdPos];
> > > > > > txRdPos++;
> > > > > > txRdPos = (txRdPos ==
> > > > > TX_BUFFER_LENGTH)?0:txRdPos;
> > > > > > txBytes--;
> > > > > > }
> > > > > > break;
> > > > > > }
> > > > > > }
> > > > > >
> > > > > > void uart0_sendByte(Uint8 byte) {
> > > > > > // Wait until there is room in the buffer
> > > > > > while(txBytes == TX_BUFFER_LENGTH);
> > > > > > VICIntEnClr |= (1 << 6);
> > > > > > if(!UART0_THRE) { // Put it in the software buffer
> > > > > > txBuffer[txWrPos] = byte;
> > > > > > txWrPos++;
> > > > > > txWrPos = (txWrPos == TX_BUFFER_LENGTH)?
> 0:txWrPos;
> > > > > > txBytes++;
> > > > > > }
> > > > > > else { // If the chip buffer is empty, put it
there
> > > > > > U0THR = byte;
> > > > > > }
> > > > > > VICIntEnable |= (1 << 6);
> > > > > > }
> > > > > >
> > > > > > int putchar(int a) {
> > > > > > uart0_sendByte((int)a);
> > > > > > }
> > > > > >
> > > > > > int main (void) {
> > > > > > PINSEL0 = PINSEL0_00_TxD | PINSEL0_01_RxD;
> > > > > > printf("hello");
> > > > > > }
|