|
|
View previous topic :: View next topic |
Author |
Message |
gpaolo79
Joined: 31 Dec 2007 Posts: 2
|
Address error on 30F3011 |
Posted: Mon Dec 31, 2007 4:25 pm |
|
|
Hello!
I'm experiencing serious problems with the software I'm writing for a 30F3011 dsPIC.
In particular, even disabling interrupt nesting, my PIC still resetting itself with the ADDRERR exception. The problem appears when I try to use Timer1, 4 and 5 with a short interval between each interrupt.
In particular, I have a printf in timer1 interrupt handle and two PWM routines in timer 4 and 5. Except for the printf routine, there are few instructions in each interrupt handles, but I'm quite sure that that the problem is in the time taken by the printf to perform the write on the serial port.
So, I have timer1 configured to give an interrupt every 0.85 sec and the printf has to transmit more or less 120 characters @38400bps; if I set the timer 4 and 5 with a long period -more than 0.5msec-, I get no problem at all.
When the period begins to be short (in my case, when I want to update the PWM often, about 0.3msec) I begin to get garbage character on serial port even with the DISABLE_INT command in the #use rs232 directive, and when the period is *really* short -less than 0.3msec- the PIC "panics" and resets itself entering in the ADDRERR trap.
Setting interrupts priorities had no effect...
Do you have any idea about how to solve this problem?
Well, of course, sorry for my english, I hope that my problem is clear enough! |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Mon Dec 31, 2007 5:48 pm |
|
|
First of all, one thing about interrupts, they should be short and sweet.
You stated that you 'only' have one printf in your interrupt. Never _ever_ place a printf in an interrupt. Printf generates a ton of code and your processor will puke. Interrupts should contain as little code as possible. Something like setting a few flags or variables and then exit. Don't do any interrupt_enable() or interrupt_disable() commands inside and interrupt either.
Without seeing any code it's hard to know what else there might need to be changed.
Ronald |
|
|
gpaolo79
Joined: 31 Dec 2007 Posts: 2
|
|
Posted: Mon Dec 31, 2007 7:09 pm |
|
|
rnielsen wrote: | First of all, one thing about interrupts, they should be short and sweet.
You stated that you 'only' have one printf in your interrupt. Never _ever_ place a printf in an interrupt. Printf generates a ton of code and your processor will puke. Interrupts should contain as little code as possible. Something like setting a few flags or variables and then exit. Don't do any interrupt_enable() or interrupt_disable() commands inside and interrupt either.
Without seeing any code it's hard to know what else there might need to be changed.
Ronald |
Eheh, ok, thanks for the answer, I had the idea that the problem was in the lenght of that interrupt.
But I choose to do that because I knew no way to do it otherwise... I mean, what I need to have is telemetry sent at regular intervals in background, and the only way I found to do it -no matter what the PIC was doing- was to put the printf in the interrupt.
Maybe with some suggestion about how to solve the telemetry problem, I may change the interrupt routine.
These are the interrupt routines:
Code: |
#INT_EXT0 //Switch anteriore
void switch1_check() {
if (input(PIN_E8)) {toccato_av=1; INTCON2=INTCON2|0x0001;}
else {toccato_av=0; bloccato_av=0; INTCON2=INTCON2&0xFFFE;}
}
#INT_EXT2 //TX Occupato
void TX_check() {
if (input(PIN_D1)) {tx_busy=1; INTCON2=INTCON2|0x0004;}
else {tx_busy=0; INTCON2=INTCON2&0xFFFB;}
}
(NOTE: I had to take TIMER2 offline because it caused the address error too...)
/*#INT_TIMER2 //Tempo esecuzione istruzione
void time()
{time_index++;
#asm
DISI #1
#endasm
}*/
#INT_TIMER1
void invia_telemetria()
{if (tx_busy==0)
{if (strlen(buffer_tx)>0)
{TRISD=TRISD&0xFFFD;
output_bit( PIN_D1, 1); //RD1 diventa output e portato ad 1
printf("%s",buffer_tx);
TRISD=TRISD|0x0002;
buffer_tx[0]=0x00;
}
}
#asm
DISI #4
#endasm
}
#INT_TIMER4
void speed_control_x()
{if (toccato_av==0) // GESTIRE IL TOCCO AVANTI E INDIETRO??
{if (posizione_x>PDC1) PDC1++;
else if (posizione_x<PDC1) PDC1--;
else if (posizione_x==PDC1) T4CON=T4CON&0x7FFF; //Disabilita timer4
}
else {if ((PDC2+1)<MAX_SU) {PDC2++; delay_ms(1);}
else {bloccato_av=1; posizione_x=PDC1; T4CON=T4CON&0x7FFF;}
}
#asm
DISI #4
#endasm
}
#INT_TIMER5
void speed_control_y()
{if (posizione_y==PDC2) T5CON=T5CON&0x7FFF; //Disabilita timer4
else if (posizione_y>PDC2) PDC2++;
else if (posizione_y<PDC2) PDC2--;
#asm
DISI #4
#endasm
}
#INT_RDA
void serial_rx()
{buffer_rx[rx_idx]=getc();
if (buffer_rx[rx_idx]<0x7F)
{if (buffer_rx[rx_idx]==0x0A)
rx_complete_stat=1;
else if ((rx_idx+1)<MAX_BUFFER) rx_idx++;}
}
|
Tell me if you need other code, the program is quite long and I still working on it, so it may be not too clear right now... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|