Hi Guys,
I am simulating delayed pulses for a stepper motor, and I am using timer0 on MCB2300. I setup my interrupt timer and I want it to be updated every time a pulse is fired. When I simulated my code it does not look the timer0 gets updated at all: Timer0 retain the initial value I set it to which is 1second all the time.
Below is copy of my code, please advise on how I can get the timer updated and why it does not update.
//source code:
volatile unsigned int delay_constant;
/* Function that turns on requested LED */ void LED_On (unsigned int num) { FIO2SET = (1 << num); }
/* Function that turns off requested LED */ void LED_Off (unsigned int num) { FIO2CLR = (1 << num); }
/* Function that initializes LEDs */ void LED_Init(void) {
PINSEL10 = 0; /* Disable ETM interface, enable LEDs */ FIO2DIR = 0x000000FF; /* P2.0..7 defined as Outputs */ FIO2MASK = 0x00000000; }
__irq void T0_IRQHandler (void) {
int i;
LED_On (0x07);
for( i=0; i<100; i++) { ; } LED_Off (0x07); T0IR = 1; /* Clear interrupt flag */ VICVectAddr = 0; /* Acknowledge Interrupt */
} float fastsqrt(float val) { long tmp = *(long *)&val; tmp -= 127L<<23; /* Remove IEEE bias from exponent (-2^23) */ /* tmp is now an appoximation to logbase2(val) */ tmp = tmp >> 1; /* divide by 2 */ tmp += 127L<<23; /* restore the IEEE bias from the exponent (+2^23) */ return *(float *)&tmp; }
void timer0_initialize (void){
T0MR0 = delay_constant; /* 1msec = 12000-1 at 12.0 MHz */ T0MCR = 3; /* Interrupt and Reset on T0TCR = 1; /* Timer0 Enable */ VICVectAddr4 = (unsigned long ) T0_IRQHandler; /* Set Interrupt Vector */ VICVectCntl4 = 15; /* use it for Timer0 Interrupt */ VICIntEnable = (1 << 4); /* Enable Timer0 Interrupt */ }
int main (void) {
float temp0; static float temp1, temp2, temp3; unsigned int step=0; unsigned int denom;
delay_constant=12000000;
LED_Init(); /* LED Initialization */
/* Enable and setup timer interrupt, start timer */ timer0_initialize();
/*C0 equation: C0=frequency*sqrt(2*motor_step_angle/angular_accel)*/ temp0= motor_step_angle+motor_step_angle; temp0=temp0/angular_accel; temp0=fastsqrt(temp0); temp0=temp0*frequency; step++;
do{ /*Cn equation: Cn= (Cn-1)-(2*Cn-1/(4*step+1))*/ denom=(step<<2)+1; temp1=(temp0+temp0)/denom; temp0=temp0- temp1; step++;
/* normalization so that delays are obtained in Microseconds */ temp3=temp0*1000000; temp3=ceil(temp3/frequency); delay_constant=temp3;
}while(step> 0 && step<31);
}
Hi Guys!
I am still debugging the issue I discussed in my previous posting. so far I found that the interrupt does not get cleared it just keeps looping inside _IRQ function. Can anybody give any feedback as to why this is happening? Thank you all in advance. I pasted a copy of my modified code.
/******************************************************************************/ /* BLINKY.C: LED Flasher */ /******************************************************************************/ /* This file is part of the uVision/ARM development tools. */ /* Copyright (c) 2005-2006 Keil Software. All rights reserved. */ /* This software may only be used under the terms of a valid, current, */ /* end user licence from KEIL for a compatible version of KEIL software */ /* development tools. Nothing else gives you the right to use this software. */ /******************************************* ***********************************/
#include <stdio.h> #include <LPC23xx.H> /* LPC23xx definitions */ #include "LCD.h" /* Graphic LCD function prototypes */ #include "motor.h" #include <math.h>
/* Macro Definitions */ #define TEMT (1<<6) #define LINE_FEED 0x0A #define CARRIAGE_RET 0x0D
unsigned int delay_constant; volatile static unsigned char flag; volatile unsigned int step=0;
/* Function that outputs value to LEDs */ void LED_Out(unsigned int value) { FIO2CLR = 0xFF; /* Turn off all LEDs */ FIO2SET = (value & 0xFF); /* Turn on requested LEDs */ }
LED_On (0x07); LED_On (0x06);
for( i=0; i<120; i++) { ; }
LED_Off (0x07);
printf("test %d\n", delay_constant);
flag=1;
VICVectAddr = 0; /* Acknowledge Interrupt */ T0IR = 1; /* Clear interrupt flag */
void UartInit() {
PINSEL0 |= 0x40000000; /* Enable TxD1 in P0.15 */ PINSEL1 |= 0x00000001; /* Enable RxD1 in P0.16 */ U1LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ U1FDR = 0; /* Fractional divider not used */ U1DLM = 0x00; U1DLL = 78; /* 9600 Baud Rate @ 12MHz Clock */ U1LCR = 0x03; /* DLAB = 0 */ U1FCR = 0x07; /* enable TX amp RX FIFO ,clears TX amp RX FIFO */ }
/* Implementation of putchar (also used by printf function to output data) */ int sendchar(int ch) { /* Write character to Serial Port */
while (!(U1LSR & 0x20));
return (U1THR = ch); }
int getkey (void) { /* Read character from Serial Port */
while (!(U1LSR & 0x01));
return (U1RBR); }
void UartTx(void) { int i=0;
char c[]= "I am .. ";
/* Keep Transmitting until Null character('\0') is reached */ while(c[i]) { U1THR=c[i]; i++; }
U1THR=LINE_FEED; U1THR=CARRIAGE_RET; }
float temp0; static float temp1, temp2, temp3; unsigned int denom; //volatile unsigned int delay_constant; //volatile int flag=0;
LED_Init(); /* LED Initialization */ UartInit();
//LED_On (0x06);
/* initialize Interrupt */ T0MCR = 3; /* Interrupt and Reset on MR0 */ T0TCR = 1; /* Timer0 Enable */ VICVectAddr4 = (unsigned long ) T0_IRQHandler;/* Set Interrupt Vector */ VICVectCntl4 = 15; /* use it for Timer0 Interrupt */ VICIntEnable = (1 << 4);
/*C0 equation: C0=frequency*sqrt(2*motor_step_angle/angular_accel)*/
temp0=2*motor_step_angle; temp0=temp0/angular_accel; temp0=fastsqrt(temp0); temp0=temp0*frequency; step++; flag=1;
while(flag) { flag=0;
/*Cn equation: Cn= (Cn-1)-(2*Cn-1/(4*step+1))*/ denom=(step<<2)+1; temp1=(temp0+temp0)/denom; temp0=temp0- temp1; step++;
if(step==4) { LED_On(0x5); }
/* normalization so that delays are obtained in Microseconds */ temp3=temp0; temp3=ceil(temp3/12); delay_constant=temp3; T0MR0 = delay_constant;
} }
Wouldn't life be so much easier if you spent the time checking up on how to post source code to make it readable?
__irq void T0_IRQHandler (void) { int i; LED_On (0x07); LED_On (0x06); for( i=0; i<120; i++) { ; } LED_Off (0x07); printf("test %d\n", delay_constant); flag=1; VICVectAddr = 0; /* Acknowledge Interrupt */ T0IR = 1; /* Clear interrupt flag */ }
Note that you should clear the timer interrupt flag before you acknowledge the interrupt - the timer and the interrupt controller are two separate parts of the processor.
Next thing - you shouldn't do delay loops inside interrupt handlers. Only do extremely short delays if you maybe have to fulfill some settle time for a data signal.
And printf() isn't a function suitable for use from interrupt handlers. Consider the potentially huge number of instructions and call nesting that may be required for a single printf() call. And printf() could potentially have to wait for a UART to be ready to receive more characters, which could make the ISR take huge amounts of time.
Your response started with a rude comment and ended with a useless feedback! would not have been easier if you had just kept silent!
Well, if you think "Note that you should clear the timer interrupt flag before you acknowledge the interrupt [...]" is useless...
And printf() in an ISR can really get you into big troubles - if there is one single line inside the big printf() call tree that isn't interrupt-safe then you can get almost impossible-to-locate bugs in your program. An ISR just can't expect to have access to the full CRTL. It isn't enough if printf() is thread-safe and re-entrant for it to be allowed in an ISR. There can be multiple ways that the printf() call tree can have blocking constructs - not just for emitting the characters to the specific "stdout".
That's a very bad attitude there chum.
What Per gave you was factually correct and I'd say extremely helpful.
Not at all bad for someone who is posting to assist you. Remember, nobody here is required to look at (or even respond to) posts.
So why not take a breath, read what was written and consider it carefully. If you think you're too good to do so, then you probably didn't need to post a question in the first place.
Forget about my attitude and reply to my question if you could otherwise silence is always a virtue. Per does not need someone to speak on his behalf. Thank you Chum!
Forget about my attitude and reply to my question if you could otherwise silence is always a virtue. Per does not need someone to speak on his behalf.
On one point we agree: Per is quite capable of responding very well. However, I say that after reading and taking note of many of his answers. It seems that you cannot say the same.
Given your atrocious attitude and clear inability to post code so others can view it, I see no point in spending time looking at your problems.
Goodbye chum.
Forget about my attitude
How could we, given how insistent you are about rubbing it into everyone's faces?
and reply to my question if you could
Per did, and got back uncalled-for abuse from you for his troubles.
otherwise silence is always a virtue.
Now if you had only heeded your own advice, your chances of getting exactly the reply you so aggressively insist on might still be considerable. As it is, I trust you've managed to reduce them to just about zero.
The best way to hope that people will read through the full code is to make a new post where the code has the proper tags. While the tags aren't 100% required, they tend to be very important for anyone who expects any help - since history shows that the amount of answers depends on if the code is easy to read or not.
Without the proper tags to indicate that code is formatted text, white space gets destroyed because of standard HTML rules. So it is only when forum code explicitly requests a hard line break - or when the viewers browser runs out of screen estate - that there will be a visible line break. Most forum code only inserts hard line breaks if they think there is a paragraph break - and that would normally only happen if there is an empty line between two sections of text.
Threads where the poster doesn't use PRE tags tends to get very few answers, because most people don't care to spend the time reading unformatted code. Especially since lots of posters makes use of end-of-line // comments that gives ambiguities when the original line break is lost. Code reading skills is very much about pattern matching - and the indentation is an important part of the pattern matching our brains have been trained on.