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?
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!