CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Unusual problem with delay on while and serial interrupt
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

Unusual problem with delay on while and serial interrupt
PostPosted: Fri Apr 27, 2012 10:40 pm     Reply with quote

Hi guys, I have an unusual problem with the delay on while() and the serial interrupt. The code below doesn't work if the line "delay_ms()", on while(), is not commented. But if the line is commented out, the program woks fine.

I am using the PIC connected to a GSM module, and I call to it, then the serial interrupt should be work, receiving "RING".
Code:

#include <18f452.h>

#use delay(clock=20000000)
#fuses HS
#use rs232(baud=9600, parity=N, bits=8, xmit=PIN_C6, rcv=PIN_C7)

#define use_portb_lcd true
#include <aev_lcd.c>

void intrda();

void main(){

int ct=0;

enable_interrupts( INT_RDA );
enable_interrupts( GLOBAL );

lcd_init();
printf(lcd_putc, "\fIniciado\n");

while(1){

//delay_ms(20000);
//printf(lcd_putc, "f%d", ++ct);

}
}


#INT_RDA
void intrda(){

char a;

disable_interrupts( INT_RDA );
disable_interrupts( GLOBAL );

output_high(PIN_C3);

a = getc();
printf(lcd_putc, "%c", a);

output_low(PIN_C3);

enable_interrupts( INT_RDA );
enable_interrupts( GLOBAL );

}

Why the program works fine without the delay on while() and doesn't work with the delay line?

Thanks!!
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 6:13 am     Reply with quote

In what way does it not work?

You delay is 20 seconds.

Are you sure that you are waiting long enough for it to finish?

Mike
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 6:40 am     Reply with quote

you are printing inside your ISR...thats probably what is causing the hangup.
as usual the general idea is to Get in and get out... _quick_

you are also missing ERRORS in your RS232 .

for hardware serial, having extra long delays should not matter...
you can have the ISR interrupt the delay function... delay is just a well timed loop....

so your problem is not the delay line...


from what i see (read it breifly) ... you are printing each character individually as soon as you get it...

i suggest you fill a buffer (circle buffer) and print that outside of the ISR....



G.-
_________________
CCS PCM 5.078 & CCS PCH 5.093
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 6:44 am     Reply with quote

tips...
1) never use printf(..) in an ISR

2) never control the ISRs from within an ISR

3) always add ERRORS to the use rs232(...) statement

4) always use an interrupt driven routine to rcv UART data(ie ex_sisr.c).
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Sat Apr 28, 2012 7:36 am     Reply with quote

I second temtronic's post, except to change:

Quote:
2) never enable GLOBAL interrupts from within an ISR


It's OK to enable/disable specific interrupts from inside an ISR, but not GLOBAL.
_________________
Andrew
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 8:15 am     Reply with quote

andrewg wrote:
I second temtronic's post, except to change:

Quote:
2) never enable GLOBAL interrupts from within an ISR


It's OK to enable/disable specific interrupts from inside an ISR, but not GLOBAL.


Spot on.

Key is to understand that the interrupt _hardware_ controls the global interrupt bit, clearing it automatically when the handler is called, and re-enabling it _after_ the code returns from the handler (This is the RETFIE instruction 'return from interrupt - enable'). Enabling _before_ the return, potentially can result in recursive calls to the handler, which the chip doesn't support - uurgh - crash.....

There is no 'point' in enabling and disabling INT_RDA, but it won't kill the code.

Best Wishes
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 10:19 am     Reply with quote

Hi everbody, thanks a lot for the reply!!!

Well, I agree with everything you spoke, but I have one question yet. Well, why can't I get all the data on the ISR, with getc() and kbhit() (using 0.5s of timeout to flag the end of transmission, using the timed_getc() of CCS, view on help), and after work the data into the ISR?
Code:

#INT_RDA
void intrda(){

char a, resp[100];
int ct=0;

disable_interrupts( INT_RDA );
output_high(PIN_C3);

// here I receive all the data with just one ISR
while( a = timed_getc() ){ resp[ct] = a; resp[ct++]='\0'; }

// why can not I work the data here, even if the time delay?
// the delay represents the time of one process, for example
delay_ms(2000);

output_low(PIN_C3);
enable_interrupts( INT_RDA );
}

Thanks a lot!!
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 11:10 am     Reply with quote

Code:
while( a = timed_getc() ){ resp[ct] = a; resp[ct++]='\0'; }


you are doing an assignment on the while loop, not a _Comparison_.

below you can see a simple ISR i use in most of my codes with the circular buffer implemented.
Code:
#INT_RDA
void SerialInt()
{
   Recieve_String[counter_read]=getchar();
   counter_read++;
   if(counter_read==Buffer_size)counter_read=0;
}



you can print the buffer any time you want in the main code and it will contain all characters that have arrived through serial...

make your buffer a global variable...

G
_________________
CCS PCM 5.078 & CCS PCH 5.093
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 11:43 am     Reply with quote

Hi Gabriel thank you, but I will explain what do I need to do:

I have an GSM module, and the data that the module send to the PIC doesnt have a fixe length. The data can be small or very large, and I just can work with the data after the receive all. The medule send 2 #10#13 chars to end the transmission normaly, but send 4 #10#13 chars when receive a call, and other logical about the number of END_CHARS (#10#13), then, to I signal that the all message was receive, I need work the data according eith this logical. And to optimize the program, I prefer wait all the message and use a flog variable to signal the end of transmission ant then use it on the main(), becouse if I use the logical of time to signal end of transmission (for example if I dont receive anything in 1s, the transmission eded) the program will be STOPED 1s ever that I receive any data...

Sorry my english, I'm from Brazil...
Do you understand ???


Thank you a lot Gabriel!
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

PostPosted: Sat Apr 28, 2012 11:52 am     Reply with quote

Oh, I forgot...
I use the logical about the time_out too, to signal any problem with the communication, for example if I dont receive any data in 1s, the flag timeout is signaled.

Then, I use two logicals to signaled the end of transmission:

1) the END_CHARS (2 #13#10 OR 4 #13#10 if calling, OR 6 #13#10 if reading SMS..)

2) the timeout (to signal any problem with the communication): is different to each action like:
0.5s if is a normal action
2s if reading SMS
5s if send or receiving GPRS data
...


Thank you!
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

PostPosted: Mon Apr 30, 2012 4:23 pm     Reply with quote

Anybody?
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Tue May 01, 2012 7:58 am     Reply with quote

... hi,

The length of the Cell message does not really matter.
Your Circle buffer (which gets filled on the ISR, as I described earlier) should be long enough to hold the entire message (yes, there are more efficient ways).

Now, your GSM module has something called "Unsolicited Messages"... which basically means that the cell will send a short (10 chars? )string indicating somthing happened... like receiving a TXT message or receiving a call.

So, you set up your GSM module properly, clear the buffer and then you can sit there waiting for the unsolicited message.... basically polling your buffer.

You can tell that the cell has sent the pic a msg by ethier setting a flag on the ISR or by polling the circle buffer counter... using the counter poll method you save yourself a flag.

When you notice that the GSM module sent somthing... wait a bit... 2 seconds? and then check your buffer... and then take the appropiate action.
like reading the SMS ...

always give the GSM module enough time to respond... SMS will vary in length yes... so it will take varying times to read... give a delay long enough to cover your worst case...


... you will probably want to use String functions.... to find commands or specific word in your input buffer....
declare your input buffer for example: size 101 characters... but make it circle at possition 100... and initialize position 101 as '\n'.... so your input buffer is always null terminated....


.... in any case... i suggest you get a clear picture on how to work with serial comm first... if you dont get that straight... you wont be able to work with a GSM module.


Basic question... have you even gotten your pic to talk to the module so far?
just plain AT>OK ?

G.
_________________
CCS PCM 5.078 & CCS PCH 5.093
opvini



Joined: 27 Apr 2012
Posts: 50
Location: Brazil

View user's profile Send private message

PostPosted: Tue May 01, 2012 10:56 am     Reply with quote

Hi Gabriel... thanks again for reply.
My program is communicating with the GSM module with no problem, and synchronous... I am using a flag to indicate the end of transmission and on while() I test this flag, and do actions. But my question is exactly about this. Why the program doesn't work if I process the response of gsm module on ISR (after the message has been fully recovery) the program don't work fine. But if I set a flag on ISR (after the message has been fully recovery too) and process the message on while() it works fine.

The program is working fine, OK, but I really wanted to understand why doesn't work if the process of response is on the ISR...
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue May 01, 2012 11:11 am     Reply with quote

opvini wrote:
Hi Gabriel... thanks again for reply.
My program is communicating with the GSM module with no problem, and synchronous... I am using a flag to indicate the end of transmission and on while() I test this flag, and do actions. But my question is exactly about this. Why the program doesn't work if I process the response of gsm module on ISR (after the message has been fully recovery) the program don't work fine. But if I set a flag on ISR (after the message has been fully recovery too) and process the message on while() it works fine.

The program is working fine, OK, but I really wanted to understand why doesn't work if the process of response is on the ISR...


Probably because characters start to arrive before the 'processing' completes.
Remember the hardware UART only has 2+ characters of buffering. If (for instance) you 'printf' a message in the ISR, that is ten characters long, then the code will effectively have to wait for eight character times, before completing. If meanwhile characters are arriving, then the UART, _will_ overrun. At this point the UART will be _hung_. Unless you add the keyword 'ERRORS' to your RS232 declaration. This adds extra code to clear this condition if it happens. Basically when using the hardware UART, you _must_ have 'ERRORS' in the declaration, unless _you_ yourself deal with the error conditions.
Repeat the 'mantra' - ISR's should _only_ do what they must to handle the hardware condition the interrupt flag signifies. Everything else must be done outside the ISR. Only exceptions to this, are if you know _exactly_ what the implications of staying too long in the ISR are, and handle the effects of this yourself.

Best Wishes
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Tue May 01, 2012 1:14 pm     Reply with quote

.... yeah, what Ttelmah said.
_________________
CCS PCM 5.078 & CCS PCH 5.093
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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