This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ADuC Interrupt problem - can't enable interrupts on ADuC7024

Hello, everyone!

I'm having the following problem. I'm using a ADXL345 development board from Analog Devices (with the ADuC7024 MCU and a ADXL345 accelerometer). I would like to implement the algorithm from the following paper:

www.analog.com/.../fall_detector.html
(Hear is a copy of the paper with the source code - www.analog.com/.../AN-1023.pdf)

There is also source code provided with the paper. The problem is that after compilation (and substitution of the __fiq token with the __irg because __fiq is no longer allowed in uVision4) I tested the coded and nothing happened. It looked as if no interrupts were ever generated and/or handled. This is why I decided to write a simple program that uses interrupts generated from Timer0 to toggle a LED on the board. I hereby post the code and the startup code.

Any help or ideas will be greatly appreciated!

Blinky_Interrupt:


#include <ADuC7024.H>                      /* ADuC7024 definitions */

void wait (void)  {                        /* wait function */
  unsigned long i;                         /* Delay var */

  for (i = 0; i < 100000; )  {             /* Delay for 100000 Counts */
    i++;
  }
}

void Interrupt_Init(void)
{
        IRQEN = RTOS_TIMER_BIT;         // Timer 0 => Interrupt
}

void Timer_Init(void)
{
        T0LD  |= 0xFFFF;     // Loads value 0xFFFF in Timer 0
        T0CON |= 0xC0;       // Enabled,Periodic,CLK/1
}

void POW_Init(void)     // POWCON controls the core clock frequency and the power-down mode
{
          POWKEY1 = 0x01;
          //POWCON = 0x03;                       // Selects core frequency 5.22 MHz
          POWCON = 0x07;                         // Selects core frequency 326 kHz
          POWKEY2 = 0xF4;
}

void My_IRQ_Handler(void)__irq // Timer 0 => Interrupt
{
        if((IRQSIG & RTOS_TIMER_BIT)==RTOS_TIMER_BIT){
                T0CLRI = 0xF0;                     /* Clear interrupt */
                GP4DAT ^= 0x00400000;              /* Toggle P4.5 */
        }
}


int main(void) {
        GP4DAT &= 0x00000000;
        GP4DAT |= 0x40000000;                           /* P4.5 defined as outputs */
        GP4DAT ^= 0x00400000;                           /* Toggle LED1 */

        POW_Init();
        Timer_Init();
        Interrupt_Init();
        while(1) {
                ;//if (T0VAL <= 0x00FF) GP4DAT ^= 0x00400000;      /* Toggles LED1 */

        }
}

In the startup code I have:
Startup code:


; Exception Vectors
;  Mapped to Address 0.
;  Absolute addressing mode must be used.
;  Dummy Handlers are implemented as infinite loops which can be modified.

Vectors         LDR     PC, Reset_Addr
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                NOP                            ; Reserved Vector
                LDR     PC, IRQ_Addr
                LDR     PC, FIQ_Addr

                EXTERN Undef_Handler
                EXTERN SWI_Handler
                EXTERN PAbt_Handler
                EXTERN DAbt_Handler
                EXTERN My_IRQ_Handler
                EXTERN FIQ_Handler

Reset_Addr      DCD     Reset_Handler
Undef_Addr      DCD     Undef_Handler
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0                      ; Reserved Address
IRQ_Addr        DCD     My_IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

Undef_Handler   B       Undef_Handler
SWI_Handler     B       SWI_Handler
PAbt_Handler    B       PAbt_Handler
DAbt_Handler    B       DAbt_Handler
;IRQ_Handler     B       IRQ_Handler
FIQ_Handler     B       FIQ_Handler
; Reset Handler

                EXPORT  Reset_Handler
Reset_Handler


When I debug it in Keil, I see that the timer is counting down and starts all over again every 0.2 sec (as expected) and the values of the following registers are:

IRQEN -> 0x00000004
IRQSTA -> 0x00000004
IRQSIG -> 0x00649005

And yet, the interrupt isn't handled and the LED isn't toggled.

Thank you again and sorry if this seems a stupid question!

  • You need to register "My_IRQ_Handler" as an ISR. Check-out your processor user manual (namely, the chapter about the processor's VIC/interrupt controller).

  • Hi, Tamir,

    Thank you for the help! I thought that that part in the startup file:

    ......................
           LDR     PC, IRQ_Addr
    ......................
    
           EXTERN My_IRQ_Handler
    .....................
    IRQ_Addr        DCD     My_IRQ_Handler
    
    

    is what says that my function should be the one to be called when an IRQ request is received?

    Unfortunately the ADI's user manual for this processor doesn't say anything about setting up the ISRs. I think it is something Keil-specific. I know it should be something small and simple but I just can't make it out!

  • I had a quick look in a sample project and the data sheet. You are right, your interrupt controller is not vectored. Did you try the Dimmer sample provided by Keil under ARM/Boards/ADI/ADuC702X/Dimmer?

  • Hi, Tamir,

    Thank you for the suggestion - the problem is that I don't have the ADuC7024 evaluation board but the ADXL345 development kit and as such I don't have a LED connected to the output of the DAC. But I'll try to modify the Dimmer sample program in a more meaningful (in terms of my board) way and will let you know what the result is. Thank you again for the help.

    P.S. I'm sorry for the late reply but I don't have permanent access to the Internet.

  • OK, this is the update - I made a simple test with the Dimmer project. I modified the Dimmer.c source code like that:

    #include <ADuC7026.H>               // ADuC7026 definitions
    
    #define CLOCK   22544384            // CPU configured for 22.544384 MHz clock
    #define T0_FREQ       96            // Timer 0 Reload Frequency
    
    #define T0_LD   ((unsigned short)(CLOCK/16 / T0_FREQ))
    
    
    extern volatile int T0_Tick;        // Timer 0 Current Tick Value
                    int T0_Last;        // Timer 0 Last Tick Value
    
    int main (void) {
      // Veli unsigned char dac;
    
      // Veli DAC1CON = 0x13;                   // Configure DAC1 (LED) Range 0..VDD
    
      GP4DAT &= 0x00000000;                                     // Veli
      GP4DAT |= 0x60000000;                                 /* P4.5 defined as output LED1 */
      GP4DAT ^= 0x00600000;                                 // Veli
    
      IRQEN = 0x00000004;               // Enable Timer 0 Interrupt
      // Veli T0LD  = T0_LD;                    // Timer 0 Load Value
      T0LD = 0xFFFF;
      T0CON = 0xC0;                     // Timer 0 Enabled, Periodic, Prescaler = 16
    
      // Veli dac = 0;                          // Initial DAC (8-bit) Value
      while (1) {                       // Loop forever
        //while (T0_Tick == T0_Last);     // Synchronize to Timer Interrupt
        //T0_Last = T0_Tick;
        // Veli DAC1DAT = dac << 20;            // Update DAC1 Output
        // Veli if ((GP0DAT & 0x10) == 0) {     // Check if IRQ (P0.4) Button is not active
        // Veli   dac++;                        // Increment DAC Value
        // veli   if (dac == 192) dac = 0;      // Check DAC Limit
        //}
      }
    }
    

    And the IRQ.c like that:

    volatile int T0_Tick;               // Timer 0 Current Tick Value
    
    __irq void IRQ_Handler (void) {
      if (IRQSIG & 0x00000004) {        // Timer 0 Interrupt
        T0CLRI = 1;                     // Clear Timer 0 Interrupt
        T0_Tick++;                      // Increment Timer 0 Tick
        GP4DAT ^= 0x00600000;
      }
    }
    

    Now when I debug I have a very strange picture of the T0VAL signal but at the same time the GP4DAT signal is toggled every 0.01 seconds or so. I didn't have time to test it on the board yet.

    I tried to copy the startup and IRQ.c code to my previous project but when I debug I don't toggle the my LED. I'm starting to thing it's all about the assembler stuff in the startup code.

    Any suggestions will be greatly appreciated!

  • This may be relevant.

    The I and F bits in the CPSR need to be cleared for IRQs and FIQs to happen on an ARM7TDMI device like the ADuC7024.

    After a reset, these bits will be set.

    These bits can only be modified directly using assembler code

    The start-up code is where many people clear these bits, normally after the stacks for the various ARM7TDMI modes are set-up.

    The last CPSR write clears these bits to allow interrupts through to the ARM.

    This is a global interrupt enable, this is in addition to the IRQEN write that can enable individual interrupts which is ADuC70xx specific.

    The start-up code will write to the CPSR to cycle through the modes, setting up stacks in each.

    A snippet.

    ;  Enter Supervisor Mode and set its Stack Pointer
                    MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                    MOV     SP, R0
                    SUB     R0, R0, #SVC_Stack_Size
    
    ;  Enter User Mode and set its Stack Pointer
                    MSR     CPSR_c, #Mode_USR
    

    You can view the CPSR in the register window, are the I and F bits set?

  • Hi, Patrick,

    You are a life-saver!!! Yes, indeed this was the problem - in my project the F and I bits were set and when I cleared them, I enabled the interrupts!

    Thank you again!

    For anybody with the same problem - here is the code snippet clearing the F and I bits:

    ;  Enter FIQ Mode and set its Stack Pointer
                    MSR     CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit
                    MOV     SP, R0
                    SUB     R0, R0, #FIQ_Stack_Size
    
    ;  Enter IRQ Mode and set its Stack Pointer
                    MSR     CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit
                    MOV     SP, R0
                    SUB     R0, R0, #IRQ_Stack_Size
    
    ;  Enter Supervisor Mode and set its Stack Pointer
                    MSR     CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
                    MOV     SP, R0
                    SUB     R0, R0, #SVC_Stack_Size
    

  • I have just one final question. I realized that when I start a debug session I have an alert window saying:

    "Load of C:\Keil\ARM\INC\ADI\ADuC7024.sfr failed with Error 3!".

    At the same time this doesn't seem to affect the Debug mode - I could still use all the tools, etc.

    This isn't relevant for my work but still - I'm curious what the reason might be.

    Thanks again for the previous suggestion!

  • A last thing - for me, in order to really clear the I_Bit and F_Bit, I had to modify the Target options from the default ones.

    From Target Options -> Linker tab, check "Use Memory Layout from Target Dialog".

    Hope that help anyone facing the same problem!