EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Interesting Interrupts

Started by Henk Visser March 12, 2006
With my AT91SAM7S256 project the only configuration I do for the AIC is my single call to AT91F_AIC_ConfigureIt().  I set a infinite loop in my interrupt service routine so that I can catch the first occurrence.
__ramfunc void irq_test(void)
{
   while(1)
   {
     spi_pt->SPI_TDR = 0x000D0000;            // Checking on oscilloscope.
   }
}
  

main()
{
...
  AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,   AT91C_ID_SPI,    7  ,     AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,   irq_test )
  AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI );  // Interrupt SPI Enable
  AT91C_BASE_SPI ->SPI_IER = 0X00000002;   // Enable Interrupt flag for TDRE on SPI   
 
  // Nothing should happen yet with the ISR.   But I don't make it to the next line of code. Instead I end up irq_test() !!!
  spi_pt->SPI_TDR = 0x000D00AA; 
 
}
 
Something is obviously causing some irq problems both with and without the debugger running. Even after a power cycle I still see the same behavior. What I don't understand is that the SPI is the only device that I have configured to use the AIC!  What else could be generating this irq? Since I am setting all the SVR[]'s to AT91F_Default_IRQ_handler() could something like the system interrupt be the source of what I am seeing?
 
Cstartup_SAM7.c
---------------------------
In my startup files I have added a write to  AIC_EOICR  to clear pending interrupts after reset along with setting the device
to be in protected mode.
... 
for (i=1;i < 31; i++)
{

     AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler ;  
    AT91C_BASE_AIC->AIC_EOICR = 0;  //clear any pending interrupts after reset.
}
AT91C_BASE_AIC->AIC_DCR = AT91C_AIC_DCR_PROT;   /// Enter protected mode for debugger.
 
From: Miroslav Kostadinov
 
"I just realized that Atmel have fixed their IRQ
handler already so it can support protected mode....
(the earliest version was bugous)"
 
Below is my handler do you mind double checking this?
 
IRQ_Handler_Entry:
 
sub         lr, lr, #4
stmfd       sp!, {lr}
mrs         r14, SPSR
stmfd       sp!, {r14}
stmfd       sp!, {r0}
 
;- Write in the IVR to support Protect Mode 
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
ldr         r14, =AT91C_BASE_AIC
ldr         r0 , [r14, #AIC_IVR]
str         r14, [r14, #AIC_IVR]
msr         CPSR_c, #ARM_MODE_SVC
stmfd       sp!, { r1-r3, r12, r14}
mov         r14, pc
bx          r0
ldmia       sp!, { r1-r3, r12, r14}
msr         CPSR_c, #I_BIT | ARM_MODE_IRQ
ldr         r14, =AT91C_BASE_AIC
str         r14, [r14, #AIC_EOICR]
ldmia       sp!, {r0}
ldmia       sp!, {r14}
msr         SPSR_cxsf, r14
ldmia       sp!, {pc}^
 
 
Thanks!

-Henk
 
 
 
 
What a way to spend a Saturday night! :|


I only want an SPI interrupt generated when the TDRE bit is set.  That is the only time. My assumption was that if I don't send any data then TDRE won't change in the status register and the TDRE interrupt won't fire resulting in my irq handler not being called!  So if I don't send or receive any data - then no spi interrupt.
 
The problem is that whenever I set the interrupt mask, the interrupt handler is called jumping to my service routine.   What is going on here?
 
If I comment out line 2 then I don't jump into the handler/ISR.
 
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SPI,7, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, irq_test); // 1
AT91C_BASE_SPI ->SPI_IER = 0X00000002;  // Enable Interrupt flag for TDRE on SPI    // 2
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI );  // 3
 
I'm sending some data out quickly via SPI using my service routine keeping a close watch on TDRE, but this all gets started after the first valid byte of data is sent out. Do you guys have a clever way on how I can suppress this unwanted interrupt when I set the spi mask? Or maybe before I enable the AIC I could reset the IRQ?
 
Thanks for any suggestions.
 
-Henk
 
----- Original Message -----
From: Henk Visser
To: A...@yahoogroups.com
Cc: m...@yahoo.com
Sent: Saturday, March 11, 2006 7:17 PM
Subject: [AT91SAM] Interesting Interrupts

With my AT91SAM7S256 project the only configuration I do for the AIC is my single call to AT91F_AIC_ConfigureIt().  I set a infinite loop in my interrupt service routine so that I can catch the first occurrence.
__ramfunc void irq_test(void)
{
   while(1)
   {
     spi_pt->SPI_TDR = 0x000D0000;            // Checking on oscilloscope.
   }
}
  

main()
{
...
  AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,   AT91C_ID_SPI,    7  ,     AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,   irq_test )
  AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI );  // Interrupt SPI Enable
  AT91C_BASE_SPI ->SPI_IER = 0X00000002;   // Enable Interrupt flag for TDRE on SPI   
 
  // Nothing should happen yet with the ISR.   But I don't make it to the next line of code. Instead I end up irq_test() !!!
  spi_pt->SPI_TDR = 0x000D00AA; 
 
}
 
Something is obviously causing some irq problems both with and without the debugger running. Even after a power cycle I still see the same behavior. What I don't understand is that the SPI is the only device that I have configured to use the AIC!  What else could be generating this irq? Since I am setting all the SVR[]'s to AT91F_Default_IRQ_handler() could something like the system interrupt be the source of what I am seeing?
 
Cstartup_SAM7.c
---------------------------
In my startup files I have added a write to  AIC_EOICR  to clear pending interrupts after reset along with setting the device
to be in protected mode.
... 
for (i=1;i < 31; i++)
{

     AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler ;  
    AT91C_BASE_AIC->AIC_EOICR = 0;  //clear any pending interrupts after reset.
}
AT91C_BASE_AIC->AIC_DCR = AT91C_AIC_DCR_PROT;   /// Enter protected mode for debugger.
 
From: Miroslav Kostadinov
 
"I just realized that Atmel have fixed their IRQ
handler already so it can support protected mode....
(the earliest version was bugous)"
 
Below is my handler do you mind double checking this?
 
IRQ_Handler_Entry:
 
sub         lr, lr, #4
stmfd       sp!, {lr}
mrs         r14, SPSR
stmfd       sp!, {r14}
stmfd       sp!, {r0}
 
;- Write in the IVR to support Protect Mode 
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
ldr         r14, =AT91C_BASE_AIC
ldr         r0 , [r14, #AIC_IVR]
str         r14, [r14, #AIC_IVR]
msr         CPSR_c, #ARM_MODE_SVC
stmfd       sp!, { r1-r3, r12, r14}
mov         r14, pc
bx          r0
ldmia       sp!, { r1-r3, r12, r14}
msr         CPSR_c, #I_BIT | ARM_MODE_IRQ
ldr         r14, =AT91C_BASE_AIC
str         r14, [r14, #AIC_EOICR]
ldmia       sp!, {r0}
ldmia       sp!, {r14}
msr         SPSR_cxsf, r14
ldmia       sp!, {pc}^
 
 
Thanks!

-Henk
 
 
 
 
What a way to spend a Saturday night! :|


Hi Henk,

It seems your code is working just fine ;-)

The TDRE is set whenever you can write another byte to
TDR. So as soon as you configure yor peripheral you
get a "transmiter reg empty" flag. And if you enable
the interupt it will jump to your ISR asap. 
Note that this applies not only to SPI but to any
other serial stuff like USART,SSC, TWI etc...

The only way to clear the flag is to write something
in TDR. Then TDRE will get cleared for a while and be
set again by the hardware showing that you can write
(send) another byte.

There are different ways how to use this behaviour.
Maybe the most standard way is the following:

In the main() or in a task if you have OS you do the
following:
1) You configure the SPI, but you DO NOT enable TDRE
or TXEMPTY or similar flags..
2) Whenever you want to send something you prepare a
buffer and you just enable TDRE interrupt.
	From the ISR, whenever you see that TDRE is set
**AND** enabled you do the following:
1) if there are more bytes to send you write one in
TDR.
2) if there are no more bytes (transfer completed) you
disable TDRE interrupt. If you do not disable the
interrupt and you do not write TDR, the interrupt
won't clear and will LOOP your ISR...

As you see your assumption that "if you don't send
TDRE won't change" is correct. However TDRE is set by
default so it will stay set and will cause endless
interrupts. 

The following is wrong assumption:
> So if I don't send or receive any data -
> then no spi interrupt.

You see... the transmiters are causing interrupts
"WHENEVER YOU CAN SEND", not "AFTER YOU HAVE SEND" ;-)

Miro
	--- Henk Visser <dutchman1234@dutc...> wrote:

> I only want an SPI interrupt generated when the
TDRE
> bit is set.  That is the only time. My assumption
> was that if I don't send any data then TDRE won't
> change in the status register and the TDRE interrupt
> won't fire resulting in my irq handler not being
> called!  So if I don't send or receive any data -
> then no spi interrupt. 
> 
> The problem is that whenever I set the interrupt
> mask, the interrupt handler is called jumping to my
> service routine.   What is going on here?
> 
> If I comment out line 2 then I don't jump into the
> handler/ISR.
> 
> AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
> AT91C_ID_SPI,7, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
> irq_test); // 1
> AT91C_BASE_SPI ->SPI_IER = 0X00000002;  // Enable
> Interrupt flag for TDRE on SPI    // 2
> AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI ); 
> // 3
> 
> I'm sending some data out quickly via SPI using my
> service routine keeping a close watch on TDRE, but
> this all gets started after the first valid byte of
> data is sent out. Do you guys have a clever way on
> how I can suppress this unwanted interrupt when I
> set the spi mask? Or maybe before I enable the AIC I
> could reset the IRQ?
> 
> Thanks for any suggestions.
> 
> -Henk
> 
>   ----- Original Message ----- 
>   From: Henk Visser 
>   To: AT91SAM@AT91... 
>   Cc: miro_atc@miro... 
>   Sent: Saturday, March 11, 2006 7:17 PM
>   Subject: [AT91SAM] Interesting Interrupts
> 
> 
>   With my AT91SAM7S256 project the only
> configuration I do for the AIC is my single call to
> AT91F_AIC_ConfigureIt().  I set a infinite loop in
> my interrupt service routine so that I can catch the
> first occurrence.
> 
>   __ramfunc void irq_test(void)
>   {
>      while(1)
>      {
>        spi_pt->SPI_TDR = 0x000D0000;            //
> Checking on oscilloscope.
>      }
>   }
>     
>   main()
>   {
>   ...
>     AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,  
> AT91C_ID_SPI,    7  ,    
> AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,   irq_test )
>     AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI
> );  // Interrupt SPI Enable
>     AT91C_BASE_SPI ->SPI_IER = 0X00000002;   //
> Enable Interrupt flag for TDRE on SPI   
> 
>     // Nothing should happen yet with the ISR.   But
> I don't make it to the next line of code. Instead I
> end up irq_test() !!!
>     spi_pt->SPI_TDR = 0x000D00AA;  
> 
>   }
> 
>   Something is obviously causing some irq problems
> both with and without the debugger running. Even
> after a power cycle I still see the same behavior.
> What I don't understand is that the SPI is the only
> device that I have configured to use the AIC!  What
> else could be generating this irq? Since I am
> setting all the SVR[]'s to
> AT91F_Default_IRQ_handler() could something like the
> system interrupt be the source of what I am seeing?
> 
> 
>   Cstartup_SAM7.c
>   ---------------------------
>   In my startup files I have added a write to 
> AIC_EOICR  to clear pending interrupts after reset
> along with setting the device
>   to be in protected mode.
>   ... 
>   for (i=1;i < 31; i++)
>   {
> 
>        AT91C_BASE_AIC->AIC_SVR[i] = (int)
> AT91F_Default_IRQ_handler ;   
> 
>       AT91C_BASE_AIC->AIC_EOICR = 0;  //clear any
> pending interrupts after reset.
>   }
>   AT91C_BASE_AIC->AIC_DCR = AT91C_AIC_DCR_PROT;  
> /// Enter protected mode for debugger.
> 
>   From: Miroslav Kostadinov 
> 
>   "I just realized that Atmel have fixed their IRQ
>   handler already so it can support protected
> mode....
>   (the earliest version was bugous)"
> 
>   Below is my handler do you mind double checking
> this?
> 
>   IRQ_Handler_Entry:
> 
>   sub         lr, lr, #4
>   stmfd       sp!, {lr}
>   mrs         r14, SPSR
>   stmfd       sp!, {r14}
>   stmfd       sp!, {r0}
> 
>   ;- Write in the IVR to support Protect Mode 
>   ;- No effect in Normal Mode
>   ;- De-assert the NIRQ and clear the source in
> Protect Mode
>   ldr         r14, =AT91C_BASE_AIC
>   ldr         r0 , [r14, #AIC_IVR]
>   str         r14, [r14, #AIC_IVR]
>   msr         CPSR_c, #ARM_MODE_SVC
>   stmfd       sp!, { r1-r3, r12, r14}
>   mov         r14, pc
>   bx          r0
>   ldmia       sp!, { r1-r3, r12, r14}
>   msr         CPSR_c, #I_BIT | ARM_MODE_IRQ
>   ldr         r14, =AT91C_BASE_AIC
>   str         r14, [r14, #AIC_EOICR]
>   ldmia       sp!, {r0}
>   ldmia       sp!, {r14}
>   msr         SPSR_cxsf, r14
>   ldmia       sp!, {pc}^
> 
> 
>   Thanks!
> 
>   -Henk
> 
> 
> 
> 
>   What a way to spend a Saturday night! :|
> 
> 
> 
>   SPONSORED LINKS Microcontrollers  Cpu chip  Arms  
>         Development tool  Microprocessor  
> 
> 
>
------
>   YAHOO! GROUPS LINKS 
> 
>     a..   
> 
> 
>
------
> 
>
	__________________________________________________
 

Miro,
 
Thanks again buddy!  Always such great posts from you!  I like your idea of just setting the TDRE interrupt to get things started for transmission. Rather than trying to ignore it.
 
I can disable interrupts on the AIC and also on the SPI itself.  To prevent a loop in my ISR should I disable the interrupt configuratoin for SPI or for the AIC? Or both?
 
Thank you!
 
-Henk
 
----- Original Message -----
From: Miroslav Kostadinov
To: A...@yahoogroups.com
Sent: Sunday, March 12, 2006 2:30 AM
Subject: Re: [AT91SAM] Interesting Interrupts - Update

Hi Henk,

It seems your code is working just fine ;-)

The TDRE is set whenever you can write another byte to
TDR. So as soon as you configure yor peripheral you
get a "transmiter reg empty" flag. And if you enable
the interupt it will jump to your ISR asap.
Note that this applies not only to SPI but to any
other serial stuff like USART,SSC, TWI etc...
--------------------


The only way to clear the flag is to write something
in TDR. Then TDRE will get cleared for a while and be
set again by the hardware showing that you can write
(send) another byte.

There are different ways how to use this behaviour.
Maybe the most standard way is the following:

In the main() or in a task if you have OS you do the
following:
1) You configure the SPI, but you DO NOT enable TDRE
or TXEMPTY or similar flags..
2) Whenever you want to send something you prepare a
buffer and you just enable TDRE interrupt.From the ISR, whenever you see that TDRE is set
**AND** enabled you do the following:
1) if there are more bytes to send you write one in
TDR.
2) if there are no more bytes (transfer completed) you
disable TDRE interrupt. If you do not disable the
interrupt and you do not write TDR, the interrupt
won't clear and will LOOP your ISR...

As you see your assumption that "if you don't send
TDRE won't change" is correct. However TDRE is set by
default so it will stay set and will cause endless
interrupts.

The following is wrong assumption:
> So if I don't send or receive any data -
> then no spi interrupt.

You see... the transmiters are causing interrupts
"WHENEVER YOU CAN SEND", not "AFTER YOU HAVE SEND" ;-)

Miro
--- Henk Visser <d...@hotmail.com> wrote:

> I only want an SPI interrupt generated when the TDRE
> bit is set.  That is the only time. My assumption
> was that if I don't send any data then TDRE won't
> change in the status register and the TDRE interrupt
> won't fire resulting in my irq handler not being
> called!  So if I don't send or receive any data -
> then no spi interrupt.
>
> The problem is that whenever I set the interrupt
> mask, the interrupt handler is called jumping to my
> service routine.   What is going on here?
>
> If I comment out line 2 then I don't jump into the
> handler/ISR.
>
> AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
> AT91C_ID_SPI,7, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
> irq_test); // 1
> AT91C_BASE_SPI ->SPI_IER = 0X00000002;  // Enable
> Interrupt flag for TDRE on SPI    // 2
> AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI );
> // 3
>
> I'm sending some data out quickly via SPI using my
> service routine keeping a close watch on TDRE, but
> this all gets started after the first valid byte of
> data is sent out. Do you guys have a clever way on
> how I can suppress this unwanted interrupt when I
> set the spi mask? Or maybe before I enable the AIC I
> could reset the IRQ?
>
> Thanks for any suggestions.
>
> -Henk
>
>   ----- Original Message -----
>   From: Henk Visser
>   To: A...@yahoogroups.com
>   Cc: m...@yahoo.com
>   Sent: Saturday, March 11, 2006 7:17 PM
>   Subject: [AT91SAM] Interesting Interrupts>   With my AT91SAM7S256 project the only
> configuration I do for the AIC is my single call to
> AT91F_AIC_ConfigureIt().  I set a infinite loop in
> my interrupt service routine so that I can catch the
> first occurrence.
>
>   __ramfunc void irq_test(void)
>   {
>      while(1)
>      {
>        spi_pt->SPI_TDR = 0x000D0000;            //
> Checking on oscilloscope.
>      }
>   }
>    
>   main()
>   {
>   ...
>     AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, 
> AT91C_ID_SPI,    7  ,   
> AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,   irq_test )
>     AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SPI
> );  // Interrupt SPI Enable
>     AT91C_BASE_SPI ->SPI_IER = 0X00000002;   //
> Enable Interrupt flag for TDRE on SPI  
>
>     // Nothing should happen yet with the ISR.   But
> I don't make it to the next line of code. Instead I
> end up irq_test() !!!
>     spi_pt->SPI_TDR = 0x000D00AA; 
>
>   }
>
>   Something is obviously causing some irq problems
> both with and without the debugger running. Even
> after a power cycle I still see the same behavior.
> What I don't understand is that the SPI is the only
> device that I have configured to use the AIC!  What
> else could be generating this irq? Since I am
> setting all the SVR[]'s to
> AT91F_Default_IRQ_handler() could something like the
> system interrupt be the source of what I am seeing?>   Cstartup_SAM7.c
>   ---------------------------
>   In my startup files I have added a write to
> AIC_EOICR  to clear pending interrupts after reset
> along with setting the device
>   to be in protected mode.
>   ...
>   for (i=1;i < 31; i++)
>   {
>
>        AT91C_BASE_AIC->AIC_SVR[i] = (int)
> AT91F_Default_IRQ_handler ;  
>
>       AT91C_BASE_AIC->AIC_EOICR = 0;  //clear any
> pending interrupts after reset.
>   }
>   AT91C_BASE_AIC->AIC_DCR = AT91C_AIC_DCR_PROT; 
> /// Enter protected mode for debugger.
>
>   From: Miroslav Kostadinov
>
>   "I just realized that Atmel have fixed their IRQ
>   handler already so it can support protected
> mode....
>   (the earliest version was bugous)"
>
>   Below is my handler do you mind double checking
> this?
>
>   IRQ_Handler_Entry:
>
>   sub         lr, lr, #4
>   stmfd       sp!, {lr}
>   mrs         r14, SPSR
>   stmfd       sp!, {r14}
>   stmfd       sp!, {r0}
>
>   ;- Write in the IVR to support Protect Mode
>   ;- No effect in Normal Mode
>   ;- De-assert the NIRQ and clear the source in
> Protect Mode
>   ldr         r14, =AT91C_BASE_AIC
>   ldr         r0 , [r14, #AIC_IVR]
>   str         r14, [r14, #AIC_IVR]
>   msr         CPSR_c, #ARM_MODE_SVC
>   stmfd       sp!, { r1-r3, r12, r14}
>   mov         r14, pc
>   bx          r0
>   ldmia       sp!, { r1-r3, r12, r14}
>   msr         CPSR_c, #I_BIT | ARM_MODE_IRQ
>   ldr         r14, =AT91C_BASE_AIC
>   str         r14, [r14, #AIC_EOICR]
>   ldmia       sp!, {r0}
>   ldmia       sp!, {r14}
>   msr         SPSR_cxsf, r14
>   ldmia       sp!, {pc}^>   Thanks!
>
>   -Henk>
>
>   What a way to spend a Saturday night! :|>
>   SPONSORED LINKS Microcontrollers  Cpu chip  Arms 
>         Development tool  Microprocessor >
------
>   YAHOO! GROUPS LINKS
>
>     a..  >
------

__________________________________________________




The 2024 Embedded Online Conference