View previous topic :: View next topic |
Author |
Message |
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
More on the automatic disabling of interrupts |
Posted: Mon Dec 22, 2008 9:24 am |
|
|
Hi all,
Further to my previous queries I have tried my code with v4.042 (the newest I have) up from v3.249 and it does generate a lot of warnings to do with the disabling of interrupts to prevent rentrancy. v3 generates no warnings at all, does anyone know if it should? I have ignore warnings set to none.
What I'm looking for is a strategy to help me code around this problem, I'm not that keen on making two copies of every function but maybe I should just pick some that are slow. How can I get the compiler to make two copies of its own functions for me? For example, PRINTF_LU or DIV_3232? Is there a compiler setting to do this? Or should there be?
I'm also interested in the fundamental design of the compiler that creates this problem, I'm not suggesting it is wrong, just that I am curious about it. I notice from the CCS website that the Microchip C compiler does support recursion so it should be possible to maintain a stack like a normal processor. Does CCS avoid this to improve performance and allow a smaller RAM footprint? Is this really a big advantage on the higher end devices?
anyway, suggestions are very welcome
thanks
ed |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: More on the automatic disabling of interrupts |
Posted: Mon Dec 22, 2008 11:24 am |
|
|
Quote: | ...I'm also interested in the fundamental design of the compiler that creates this problem, I'm not suggesting it is wrong, just that I am curious about it. I notice from the CCS website that the Microchip C compiler does support recursion so it should be possible to maintain a stack like a normal processor. Does CCS avoid this to improve performance and allow a smaller RAM footprint? Is this really a big advantage on the higher end devices?
|
I don't know about the high end devices, but the stack limitations are an inherent limitation on the 12 and 14 bit cores. In addition to being small, the stack is inherently unable to provide automatic variables because there is no data access to the stack. Therefore automatic variables must be statically allocated at compile time. By ruling out recursion, CCS makes it possible to completely analyze the call tree and make the static allocations of automatic variables overlap as much as possible.
Regarding your initial problem of functions called from both interrupts and main code, you should probably re-examine your application architecture. It is usually bad design to be doing complicated things in the interrupt code that require extensive use of library functions. Your application will benefit from a re-assignment of duties that gives the interrupt code only the bare minimum necessary to be done at interrupt time, and leaves the rest for main code. In this way the conflict you speak of will never arise. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Mon Dec 22, 2008 11:46 am |
|
|
Hi Robert,
Now I've got some warnings to look at I have managed to go through my code and eliminate almost all of the instances where library functions are used. This was less hassle than I expected and mostly down to a couple of rogue functions that I rarely use.
I found the link to the math library code (Thanks PCM Programmer) although it looks like I shouldn't need it now having eliminated some unnecessary calculations. My only remaining library functions are i2c_write and i2c_read which I guess are pretty fast but it would be nice to be able to use them in both interrupts and not without incurring the disabling overhead. I guess I could create a second instance of these functions in a similar way to the math library ones? I wonder if you can use several #use i2c statements with different stream names to get this effect on a single port..?
I think maybe I'll renew my subscription and get the latest v4 compiler and try to move over to that as the warning messages alone make a lot of difference.
Cheers
ed |
|
|
Ttelmah Guest
|
|
Posted: Mon Dec 22, 2008 4:13 pm |
|
|
No, leave the disable present for these.
You really need to move these either all inside, or all outside the interrupts. The problem here is that I2C, is not just a single command, but a _sequence_. Once you have sent an I2C start, you are generating a complete command packet, that needs to be unbroken. If you entered an interrupt, and called a read, or write function inside here, how is the hardware, every going to get 'back' to the correct state for the command you have started outside?.
You need to rethink your I2C, possibly treating it like the interrupt buffered serial comms, and performing the entire transmission either inside or outside the interrupt. Both is asking for trouble....
Best Wishes |
|
|
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Mon Dec 22, 2008 4:45 pm |
|
|
Hi Ttelmah,
That's an excellent point, I've actually had to work around this problem on different hardware using a high priority I2C transaction system, the reason it doesn't become a problem with the PIC code I have, is that the I2C calls are shared between different modes of operating, i.e. when the user is interacting with the device (functions not called by interrupts) and when it is actually running (functions called by interrupts) so I never get the kind of race condition you describe.
I'm not sure I'm that keen to build an interrupt driven I2C handler as it would be a lot of work to implement with all the existing devices I support, although I guess this is the best solution really.
cheers
ed |
|
|
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Mon Dec 22, 2008 5:19 pm |
|
|
Actually it just occurred to me that I couldn't implement an interrupt driven I2C routine as I am using the software I2C as the hardware is used for two SPI ports.
Does anyone have a good solution for this problem when some of the I2C access will be high priority (so queuing and waiting for a low level task would not be an option)? I guess a timer could repeatedly check the I2C status but that seems like a lot of processing... |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Mon Dec 22, 2008 8:38 pm |
|
|
Quote: | Actually it just occurred to me that I couldn't implement an interrupt driven I2C routine as I am using the software I2C.... |
If you are using the software I2C, then in which interrupt routine do you wish to call I2C functions? _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
EdWaugh
Joined: 07 Dec 2004 Posts: 127 Location: Southampton, UK
|
|
Posted: Tue Dec 23, 2008 2:20 am |
|
|
I was thinking of the SSP interrupt except I think from looking at it, it is for slave mode where a character might arrive on the I2C? I was imagining an I2C buffer empty interrupt so I would chuck a byte at the peripheral and when it had done the transmission I would get an interrupt.
Part of the problem is the flexibility in the system, the hardware is the same but the configuration varies greatly and can even be set at run time by the user. My specific problem is a timer interrupt calling I2C functions to control a remote GPIO expander, there are then various low priority I2C access such as FRAM and RTC that occur while this goes on. I guess I could create a transaction buffer for the low priority tasks and then have the timer interrupt execute that transaction every time it is called, I would need to keep this timer running even when the peripheral it normally deals with is not active but I guess that should be acceptable. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Tue Dec 23, 2008 8:39 am |
|
|
Quote: | I was thinking of the SSP interrupt except I think from looking at it, it is for slave mode where a character might arrive on the I2C?..
|
Actually the SSP interrupt is for either slave or master mode, but it only works for the hardware I2C. The software I2C has no means to generate an interrupt.
Quote: |
I was imagining an I2C buffer empty interrupt so I would chuck a byte at the peripheral and when it had done the transmission I would get an interrupt.
|
When you "chuck a byte" at the peripheral using the software I2C, the i2c_write() function does not return until the job is done and the byte has been sent.
Quote: |
Part of the problem is the flexibility in the system, the hardware is the same but the configuration varies greatly and can even be set at run time by the user. My specific problem is a timer interrupt calling I2C functions to control a remote GPIO expander, there are then various low priority I2C access such as FRAM and RTC that occur while this goes on. I guess I could create a transaction buffer for the low priority tasks and then have the timer interrupt execute that transaction every time it is called, I would need to keep this timer running even when the peripheral it normally deals with is not active but I guess that should be acceptable. |
That sounds very good. It solves a number of problems, including the one for which this thread is named, and the one Ttelmah pointed out concerning the sharing of the I2C port among different processes. By funneling all I2C requests through one intelligent "driver" in your timer ISR, you can ensure the requests do not interfere with each other. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
|