![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
HIGH interrupt problem |
Posted: Tue Jan 06, 2009 11:48 am |
|
|
Hi all,
I'm having another interesting problem with my project. I am running multiple interrupts on an 18f6723 using the 3.249 version of the compiler. I have had to modify the included CCS header files which I have done by copying the 18f6722 files, changing the name and deselecting the bug in high interrupts that existed for the 18f6722. I get the following problem when I compile for either device (as my programmer doesn't check what the hex was compiled for so I can execute either).
The only tasks running to create the problem are timer1 which performs some medium priority tasks including accessing the I2C bus, timer0 which reads an SPI A2D and accumulates the results and some low level processing in the main while() loop.
Everything performs as expected until I mark the timer 0 interrupt as HIGH, it would be good to do this as the A2D read is timing critical so I want it to interrupt timer1. However, this causes the I2C accesses in the timer1 interrupt to fail. The i2c_write function does cause interrupts to be disabled as I use it in both the interrupt and low level routines although not in the timer0 HIGH interrupt. I would expect this to work as in the worst case:
Timer 1 interrupt is active making a write to the I2C bus
Timer 0 HIGH interrupt tries to trigger but interrupts are disabled
Timer 1 interrupt finishes I2C bus write and interrupts are renabled
Timer 0 HIGH interrupt triggers immediately
Timer 0 HIGH interrupt completes SPI reads and flag setting
Timer 1 interrupt can continue with the I2C bus transaction
The only other sympton I get is that when I insert debugging RS232 outputs into the Timer 1 interrupt routine to examine where the I2C write is failing I get a screen full of drivel like there has been a memory overflow, I guess this is related to the RS232 function now having interrupts disabled while it is active.
I can also fix the problem by reducing the HIGH interrupt down to nothing but the count to set the flag, even adding:
Code: | int16_t i16_result = 0; |
at the beginning of the function causes the failure.
Any suggestions are welcome as always.
cheers
ed |
|
![](templates/subSilver/images/spacer.gif) |
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Tue Jan 06, 2009 1:54 pm |
|
|
Are you using software or hardware I2c?
Why is timer1 disabling timer0?
I2C is a clocked protocol... so it's not really timing critical.
I would recommend that Timer1 sets a FLAG for a routine that does the I2C stuff in a separate function... and don't disable Timer0 if it's critical.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
![](templates/subSilver/images/spacer.gif) |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Tue Jan 06, 2009 4:02 pm |
|
|
Hi Ben,
It's software I2C as I am using both hardware SPI ports, timer1 disables interrupts inside the i2c_write function, the CCS compiler does this as it can't do reentrancy. Although I2C is not that timing sensitive as you suggest, the action it is performing is, that's where the timing requirement comes from, so making a flag setting and performing the task at low-priority is not possible for this situation.
cheers
ed |
|
![](templates/subSilver/images/spacer.gif) |
bkamen
Joined: 07 Jan 2004 Posts: 1611 Location: Central Illinois, USA
|
|
Posted: Tue Jan 06, 2009 6:49 pm |
|
|
Ok, but then why are you doing I2C inside an interrupt. It's not needed since it's a clocked protocol.
If timer0 is that critical, then you can't have another interrupt that way.
What period is timer0 firing interrupts?
I had to do software RS232 in one project (which is completely intolerant of any outside interference). I solved the timing issue because my timer0 interrupt was long and I just used it to do my software RS232 right after a timer0 event.
Would that work for you?
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
![](templates/subSilver/images/spacer.gif) |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Wed Jan 07, 2009 1:41 am |
|
|
Hi Ben,
I don't understand why I2C being a clocked protocol means you would never want to do it in an interrupt? As long as the device it accesses needs to be updated regularly and interrupt the slow low-priority operations surely this is how you do it as setting a flag gives you and undetermined and possibly long delay until you get a response.
Timer0 is the only interrupt marked as HIGH so that it can interrupt other interrupts.
cheers
ed |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Jan 07, 2009 3:48 am |
|
|
What other interrupts are in use?. INT_EXT?.
What actual functions are being used in the interrupts?. Arithmetic?. Delays (these are inherently being used because you are using software I2C inside an interrupt), but are they used in the 'high' interrupt as well?.
Problems here are that on the 18 chips, if any interrupt is set as high priority INT_EXT, will also become high priority. On the delays, if delays are used inside the high priority code, you should consider using the multiple #use delay declaration syntax, one for the high priority interrupt, one for the low priority interrupts, and a third for the 'main', to avoid interrupts being completely disabled in the main delays. You should consider using two anyway, to avoid this being caused by the IC code.
Seriously, I would try to remove the software I2C routines from being inside an interrupt. These are going to take a lot of time, and break the old mantra to "keep ISR's quick".
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Wed Jan 07, 2009 4:34 am |
|
|
Morning,
I'm not actually using int_ext although I am using int_ext1 but this is just a normal priority level interrupt from an RTC.There is some arithmatic in the interrupts but no delays and I get no warnings from the v4 compiler telling me that this is a problem. I don't know the multiple #use delay syntax, is it possible you could point me in the direction of some documentation? My version of the manual just describes using it once. I don't get any warnings about interrupts being disabled in delay functions either.
Ideally I would remove the I2C access from the interrupt but I can't in this case due to hardware constraints. It is still quite short tho and really it shoudn't matter how long the interrupts take as long as the higher priority tasks can interrupt them as required. I am still struggling with the CCS implementation a bit really as I am used to writing for ARM7 where the interrupt scheme is a lot more flexible and the compiler lets me call the same functions in different layers of interrupts. I am considering getting the C18 compiler on the 60 day free trial and see how much work it would be to port my code, although I suspect it would be substantial and I would need to find software I2C routines.
Cheers
ed |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Jan 07, 2009 4:49 am |
|
|
Quite a bit of the interrupt restriction, is hardware, rather than software I'm afraid.
You can always go 'DIY', by just declaring your timer interrupt as 'fast', rather than 'high', and then you will need to save all registers used inside the routine, while for the low priority interrupts, just declarte 'int_global', and again save the registers yourself, test the flags etc..
The multiple #use delay syntax, is findable by a search here. Basically when you create a #use delay, it's values _and routines_are used by all subsequent code, till another is met. Hence if you make one declaration, then declare your interrupt code, then make another delay declaration, _separate_ delay routines will be used in the interrupts and the main...
I can't see what prevents you from using the I2C outside the interrupts. Really this is down to designing your code. If the main code, sits in a tight 'state machine', servicing tasks as they happen, using triggers from flags, and buffers, it can handle the I2C. The problem is that I'd expect unless the remote device is very unusual, there _will_ be significant periods waiting for responses, and the time needed for even quite a simple I2C command, in computing terms is enormous. Put this together, and I'd not be surprised if you are spending a lot longer in this routine than you think.
The thing that might be causing problems, that is worth checking, is whether the remote device does implement clock stretching, if waiting for a reply to be handled. If it doesn't, then my guess would be that the high priority interrupt, is taking long enough that your I2C routines are missing part of the reply. If so, you are going to have to 'think again', and either find out if this is supported, or realise that once an I2C command is started, it needs to be handled as an unbroken sequence...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Wed Jan 07, 2009 5:21 am |
|
|
Hi,
I still disagree with you about some of this really. The use of i2c isn't down to the design of the code, I have a state machine operating at a low-priority to service slow task like, MMC writing, CRC construction, fprintf status to the user. Some of these take a very long time, 10s of milliseconds, when you then have a device that requires frequent attention, in this case it is on the software I2C bus, at say every 5 ms you surely have to service it immediately in the interrupt.
I appreciate that the I2C access is relatively slow although at 400 kHz even a 10 byte access should only be taking around 200 us, only 4% of my processing time (with a 5 ms repeat). (I actually just measured the real function and it is taking 100 us or 2%). All I am doing is writing to a GPIO expander so I don't have to wait for it to perform any tasks itself.
The accesses should be an unbroken sequence, the high priority interrupt does not use I2C and the low-priority functions queue their I2C transactions for the normal-priority interrupt to service (so the longest total combination I can measure takes 415 us at around 1 Hz).
The actual error that I get is that i2c_write returns 1 instead of zero which makes me think it did not receive an acknowledge from the remote device. Do you know any other reasons why it might return failure?
I'll have a try with the multiple #use delay, to be honest I have stopped searching this forum as it indexes all the code people paste in and so you just get every single post with #use returned as an answer. Maybe that could get turned off?
Thanks very much for your responses, I realise you must have your own work to do!
cheers
ed |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed Jan 07, 2009 6:37 am |
|
|
One possibility is that if you put a logic analyser on the I2C, you may find that the remote device handles ACK incorrectly, and does not maintain the level to the next clock edge, but instead only holds it for a limited period. Then if you get your timer interrupt after the clock falling edge, the ACK bit, has 'gone' when you return. Another possibility/probability, is that the hardware SPI routines used in the timer, are interfering with CCS's software I2C. If you do a quick search here, you will find SPI macros I use. These are less intrusive that the CCS routines, and with a lot less to go wrong...
The fact that your remote I2C device doesn't itself generate delays, makes things a lot better. Most do. Conversely however I doubt if you are actually getting 400KHz. Generally the software I2C, 'tops out' at about 250KHz, even on a 40MHz processor.
The other suggestion, if using my SPI macros doesn't help, is to try disabling the high priority interrupts round each individual I2C character transfer. The latency caused by one character won't be too bad.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Mon Jan 12, 2009 9:16 am |
|
|
Hi Ttelmah,
Just to let you know I have found a solution for my problem. I tried the #use delay trick although I could not find the thread you mentioned, when I search for "multiple #use delay" I get 6700+ results for the forum. This just seemed to make my code hang like it was getting trapped somewhere, I didn't investigate much further.
The solution seems to be to move to the v4.042 compiler I have as the same code compiled with that seems to run fine. It is compiling for the 18f6722 rather than the 18f6723 tho (but they are virtually identical).
My concern is that my version of this is a bit old so I will get the latest version and try that as well. I suppose V4.1x will be included in my maintenance package...?
Thanks very much for your help with this. I have just started a new thread about using CCS with another IDE and it would be great to have your input on that as well.
cheers
Ed |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Jan 12, 2009 5:45 pm |
|
|
EdWaugh wrote: | when I search for "multiple #use delay" I get 6700+ results for the forum. | The search function of this forum has problems with some characters like '#'.
My workaround is to use Google with "multiple #use delay site:ccsinfo.com/forum"
This reduces the find results to only 64 hits.
Quote: | My concern is that my version of this is a bit old | True. The v4.03x versions were the first compiler releases in the v4.0xx range starting to produce working code for things that were normal in v3.xxx, new functionality was still a problem. For production quality code I would not recommend anything lower than 4.070, and even better to use v4.078 or newer.
Quote: | I suppose V4.1x will be included in my maintenance package...?
| Looking at the list of changes proposed for the v4.1xx release this looks like a major release. I hate to say it, but CCS has a history of requiring at least half a year to make this stable after the initial first release. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|