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

I wish I knew a Microchip rep...

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

I wish I knew a Microchip rep...
PostPosted: Mon Jul 18, 2005 10:58 pm     Reply with quote

...so that I could shove this 18F4610 right up his you know what.

I have a device I'm developing. Very complicated, lots of code, can't post it here either. Uses an 18F4610.

My tried & true interrupt driven USART code (can be found here: http://www.ccsinfo.com/forum/viewtopic.php?t=22221&highlight=intrda) works for receive on this pile of crap processor. The transmit doesn't. By the way, if I try the same code on an 18F452, it works flawlessly. Unfortunately, I can't use an 18F452 because I need the extra memory of the 4610.

Anyway, it does work for a very short period of time, then it gives up the ghost and stops transmitting. I've read the errata sheets for the 4610, and they acknowledge a problem when using the EUSART in 9 bit mode, but I'm not using that mode, only the regular old 8 bit.

It's like it works for a few bytes, but if I transmit many in rapid succession, phht. It just stops.

The errata sheets say something about this problem in 9 bit mode screwing up the baud rate generator. I know this isn't the case because the thing keeps receiving long after the transmit is lost, so it seems that maybe this is a new problem.

Argh. Anyone know what my next move should be? Do I contact Microchip or CCS or both?

I hate spending 12+ hours chasing a problem not of my own making.

Evil or Very Mad Evil or Very Mad Evil or Very Mad Evil or Very Mad
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Jul 18, 2005 11:31 pm     Reply with quote

Your code modifies the same variables both inside and ouside of the interrupt handlers. When doing this you need to disable the corresponding interrupt in the mainline. Remember that the PIC can be interrupted inside a single c statement as the statement may produce mutiple assembler instructions. The same applies, abeit to a lesser extent, when testing variables that are modified in the interrupt handler. For this reason your code has race conditions that could cause the effects you are observing.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 18, 2005 11:39 pm     Reply with quote

I looked at the code in your link. I see a problem with the receive
interrupt routine. You're setting a flag if you receive one character.
Then in your main loop, you poll this flag and increment a counter.
But this defeats the whole purpose of an interrrupt-driven receive fifo.
You are forced to poll this flag at a rate faster than 960 Hz, or you'll
miss characters. Suppose 5 bytes come in rapid fire. Suppose you
can't poll your flag in the main loop for a while, because you're
sending chars to your LCD routine which has delays in it, or for
some other reason. Then
your main loop will increment your count by 1, but you really have
5 bytes in the buffer.
Ideally, you should have a counter inside the isr, or do it the way CCS
does it and only fetch chars if the head and tail indexes don't match.

I think you should take out those routines from your current code,
and substitute the CCS code from EX_SISR.C and EX_STISR.C.
I know you said it runs on an 18F452. I would try it anyway.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Jul 19, 2005 4:08 am     Reply with quote

Andrew is right about the race conditions in the transmit functions, especially the manipulation of tx_counter in both the isr and bputc() is very dangerous.

Why do you disable the Tx interrupt when you are finished sending all data? Enable it once at program startup and leave it like that and your code will become smaller, faster and you remove one of the race conditions in doing so.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Jul 19, 2005 9:29 am     Reply with quote

ckielstra wrote:
Why do you disable the Tx interrupt when you are finished sending all data?
I didn't look at any code but to my knowledge you need to disable the transmit interrupt when done or else it will continue to fire. The flag bit is controlled by the hardware when the buffer is empty.
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Tue Jul 19, 2005 9:29 am     Reply with quote

ckielstra wrote:
Why do you disable the Tx interrupt when you are finished sending all data?


The Tx interupt fires when the Tx buffer is empty. If it is enabled while you are not sending you will not run any other code.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Jul 19, 2005 9:30 am     Reply with quote

Beat ya to it Razz
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Jul 19, 2005 11:10 am     Reply with quote

Thanks Mark and Neutone!
My current RS-232 routines only use the Rx interrupt, good to know the Tx is different in this respect.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Tue Jul 19, 2005 11:45 am     Reply with quote

asmallri wrote:
Your code modifies the same variables both inside and ouside of the interrupt handlers. When doing this you need to disable the corresponding interrupt in the mainline. Remember that the PIC can be interrupted inside a single c statement as the statement may produce mutiple assembler instructions. The same applies, abeit to a lesser extent, when testing variables that are modified in the interrupt handler. For this reason your code has race conditions that could cause the effects you are observing.


Andrew,

I promised the wife that someday I'd take her to Australia. I owe you a beer when I go. Hell, I owe you 6.

You're right - tx_counter gets modified in & out of the TBE ISR. That was the issue. I've since modified the bputc() function so that the TBE interrupt, if on, gets turned off immediately, then gets turned back on just before bputc() exits. That fixed it.

And for the record, if any Microchip reps are reading this, I won't try to shove a 44 TQFP up your zhoppa. Very Happy

PCM, the actual code I'm using is based on the one in the link. Mine is slightly different. I use the RDA interrupt to listen for a string from a GPS receiver - no more than about 80 characters maximum. I don't actually assert a flag until the entire string has been received, then I sort through it in the main routine. The GPS spits out this one string once per second. After I get the entire string, there are no incoming characters, so I don't have to worry about missing anything. The RDA routine to grab the GPS string, and the functions to search through it work flawlessly 100% of the time. Now so does the TX routine. And thanks for the pointers to the CCS examples. I'll check them out.

I still don't understand why the code worked on a '452, but not on the '4610. Everything is the same - baud rate (38,400), code, everything. I guess that one processor is a little quicker than the other, or perhaps the compiler inserted extraneous code in one but not the other. Who knows? Oh well, it's fixed, and that's the important part.

In case you're wondering, my app gets the GPS string, as I mentioned. Then it immediately starts transmitting characters to a different device. Up to about 140 bytes can be transmitted, with at least about 30 being sent every time.

If I cut back on the number of bytes being sent, then the code would work. However, if I tried to send more than 6 bytes, then it would cut out. Like I said, it's fixed now.

Thanks to everyone for their input. I should have asked earlier - I would have a few more clumps of hair if I did. Very Happy
asmallri



Joined: 12 Aug 2004
Posts: 1634
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Jul 19, 2005 6:03 pm     Reply with quote

Quote:
I promised the wife that someday I'd take her to Australia. I owe you a beer when I go. Hell, I owe you 6.


I look forward to collecting :-)
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Tue Jul 19, 2005 6:10 pm     Reply with quote

asmallri wrote:
Quote:
I promised the wife that someday I'd take her to Australia. I owe you a beer when I go. Hell, I owe you 6.


I look forward to collecting :-)


Well, if I ever book the plane tickets, you can be sure I'll be in touch. Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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