|
|
View previous topic :: View next topic |
Author |
Message |
samus111
Joined: 28 Aug 2014 Posts: 29 Location: Colombia
|
Interruption function problem when it needs call functions |
Posted: Thu Apr 30, 2015 9:09 am |
|
|
Hi to everybody, I am working on a GPS-satellite tracker project, and is almost done. Currently, I am only adapting the last feature, but I have found a really great problem that I never thought could happen. I am trying to insert a pulser that can stop the process no matter what the device were doing. My code is very very large, so I will explain the structure in the next way:
Code: |
#include <12f1840.h>
#include <string.h>
#include <stdlib.h>
//GLOBAL VARS//
#use delay (internal=2000000)
#fuses noput, INTRC_IO, nowdt, nomclr,
#int_TIMER1
#int_EXT
//DEFINE PINS//
void TIMER1_isr(void) //timmer function
FUNCTION 1
FUNCTION 2
FUNCTION 3
FUNCTION 4
void EXT_isr(void) //My interruption function
void main(void)
|
The problem comes with the positioning of the functions. I need to call function 4 and 3 from the interruption, and you know, to make this possible, the function have to stay below the other functions that it will call. But it seems that the interruption function ALWAYS must to be at the header, I say this because the CCS does not recognize the function if I write it in the position that I showed (below the common functions). What can I do? I hope you can help me. Thanks. |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Thu Apr 30, 2015 10:32 am |
|
|
to fix this
Code: |
#include <12f1840.h>
#include <string.h>
#include <stdlib.h>
//GLOBAL VARS//
void funtion1(void);
void funtion2(void);
void funtion3(void);
void funtion4(void);
#use delay (internal=2000000)
#fuses noput, INTRC_IO, nowdt, nomclr,
#int_TIMER1
#int_EXT
//DEFINE PINS//
void TIMER1_isr(void) //timmer function
FUNCTION 1
FUNCTION 2
FUNCTION 3
FUNCTION 4
void EXT_isr(void) //My interruption function
void main(void) |
now you can call any function from the interrupt funtion |
|
|
drolleman
Joined: 03 Feb 2011 Posts: 116
|
|
Posted: Thu Apr 30, 2015 10:51 am |
|
|
the prototypes must be the same as your function. if you have overloaded functions you have to include all versions of them. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Apr 30, 2015 12:12 pm |
|
|
The order of your program is pretty off as well. You are including regular files before your FUSES and clock settings which can lead to problems and you don't even have your ISR functions near their preprocessor directives which is mandatory.
Try:
Code: |
#include <12f1840.h>
#fuses noput, INTRC_IO, nowdt, nomclr,
#use delay (internal=2000000)
//DEFINE PINS//
#include <string.h>
#include <stdlib.h>
//GLOBAL VARS//
FUNCTION 1
FUNCTION 2
FUNCTION 3
FUNCTION 4
void main(void)
#int_TIMER1
void TIMER1_isr(void) //timmer function
#int_EXT
void EXT_isr(void) //My interruption function
|
That said, you shouldn't be calling functions in an ISR that are called in other places. That leads to trouble (the compiler might disable interrupts during the calls at the very least).
The prototypes mentioned by the above poster will help, but you really need to structure your program better. |
|
|
samus111
Joined: 28 Aug 2014 Posts: 29 Location: Colombia
|
|
Posted: Thu Apr 30, 2015 1:37 pm |
|
|
Thanks guys for your help, well I have tried with all the structures you both have given me, the Drolleman's one (I suppose it has a mistake because the functions are written twice in the example) has allowed me to program the PIC, but now the CCs compiler shows me this warning: Interrupts disabled to prevent re-entrancy; how Jeremias had said, The compiler does not allow to call a function inside a interrupt routine if this one is also called outside of the interrupt. Well, a restructuration of the program is very tedious, but it seems that is the only way to fix this issue, thanks for your help |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Apr 30, 2015 2:03 pm |
|
|
samus111 wrote: | Thanks guys for your help, well I have tried with all the structures you both have given me, the Drolleman's one (I suppose it has a mistake because the functions are written twice in the example) |
Drollman's example isn't really a mistake. The key thing to understand about functions is they have two parts:
1. Declaration
2. Definition
What Drollman highlighted was the Declaration part. Previously you only provided the Definition. This is a key concept for C programming that you should understand, so I really really suggest picking up some C books and reading them to learn more. I'll give an example of what the two look like:
Code: |
//This is a function declaration. It provides no implementation,
//but it does provide a contract to the rest of the code that says
//what the function looks like (name, input parameters, and return type)
//so other parts of the code can go ahead and use it without needing it
//to be defined just yet. It will eventually have to be defined though.
void someFunction(int a, int b);
....<other functions, code, etc.>
//This is a function definition. It provides the actual implementation of
//the function. Because there is an explicit declaration above, this
//definition can be anywhere in the code and still work right. If the
//declaration above was not there, then this has to be above any
//other code that needs to use it.
void someFunction(int a, int b){
printf("%d = %d + %d\r\n",a+b,a,b);
}
|
The function isn't there twice. It is two different (but important) parts. Notice how the declaration ends in a semicolon while the definition uses
the {} brackets and has actual code in it. You can get away without using the declaration part, but as noted above you have to place the function in specific spots of your code for it to work. Giving the declaration first gives you the freedom to put your implementation wherever you want and removes the issue of functions criss cross calling each other.
Using the declaration won't remove the "interrupts disabled" warnings (That comes from what I mentioned in the previous post), but it lets you not have to worry about where to put the functions in the file. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Thu Apr 30, 2015 2:06 pm |
|
|
The key thing is that it depends what the function actually does.
If (for instance), the function controls a piece of hardware, then the function must not be called in both the interrupt and outside (even ignoring the PIC limitations on this), since you could then be halfway through doing something in the 'outside' function, when the ISR is called. Result complete disaster.....
Same applies to anything dealing with writing values 'to' variables, where these could be half updated by the external code, then updated by the internal, and then the second half updated by the external code... Retch.
The other thing is if the function is more than a very few instructions, it should not be being called in the interrupt at all. Mantra for interrupt handlers _do as little as possible_.
All of these apply to other processors just as much as to the PIC (except that some do offer hardware protection for updating of individual variables - however still applies to multiple variables).
If the function is tiny, then simply duplicate it. function_1, and i_function_1. Call the latter in the interrupt.
If it is any larger, then 'think again', and instead set a flag in the interrupt 'call_function_1', and have the main code test this, and if it is set, call the function (and clear the flag).
The other possibility is not to do it in the interrupt at all.
Instead of enabling the interrupt concerned, just have a test in the main code 'if (interrupt_active(THE_INTERRUPT_CONCERNED)', and have this call the code required by the interrupt (and clear the interrupt). If this is at logical places in the code, the service is actually faster than calling an interrupt handler, and has the advantage that all the calls are in the 'main' body, so no problems with trying to call things inside each other. |
|
|
samus111
Joined: 28 Aug 2014 Posts: 29 Location: Colombia
|
|
Posted: Thu Apr 30, 2015 2:47 pm |
|
|
Wow, I did not know about the declaration of the functions, thanks.
I have wrote this below the global vars declaration:
Code: |
void TIME(void);
int CONVERTER(void);
int MGPS(void);
int MI(void);
void COORDINATE (void );
void HELP (void);
|
But the compiler answer me with a lot of errors, the first one says "invalid overload function TIME". I have tried to figure out whats it means, and it says this happens when the function is twice, so I don't get what is wrong. In the other hand, the program you provided me, ignores the interruption routine because is located after the main function. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Thu Apr 30, 2015 5:15 pm |
|
|
samus111 wrote: | Wow, I did not know about the declaration of the functions, thanks.
I have wrote this below the global vars declaration:
Code: |
void TIME(void);
int CONVERTER(void);
int MGPS(void);
int MI(void);
void COORDINATE (void );
void HELP (void);
|
But the compiler answer me with a lot of errors, the first one says "invalid overload function TIME". I have tried to figure out whats it means, and it says this happens when the function is twice, so I don't get what is wrong.
|
That means either your declaration and definition don't match or TIME is defined somewhere else.
samus111 wrote: |
In the other hand, the program you provided me, ignores the interruption routine because is located after the main function. |
If your program isn't running the interrupt when it is placed after main() that lends back to you not pairing it with the preprocessor directive correctly or a different issue. I've placed interrupts after main plenty of times and they still work. Did you check to see if the LST file shows code for the ISR?
Here is a small example program of both function declarations and interrupts after main:
Code: |
#include <12f1840.h>
#fuses NOPUT, INTRC_IO, NOWDT, NOMCLR
#use delay (internal=2000000)
void time(void);
void blah(int a);
void someFunction(){
time();
blah(23);
}
void time(void){
int b = 0;
b++;
}
void blah(int a){
int g = 100;
g += a;
}
void main(){
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
someFunction();
while(TRUE);
}
#INT_TIMER1
void timer_isr(){
int c;
c = 2;
}
#INT_EXT
void ext_isr(){
int d;
d = 3;
}
|
LST file confirms the ISR's are there and called by the global header if their flags are set. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Fri May 01, 2015 6:26 am |
|
|
If you look at his original post, the key problem is that he moves the function itself, and _not_ the declaration that says 'this is the interrupt handler'. So he leaves #INT_TIMER1, and #INT_EXT up at the top of the code, and expects the compiler to magically 'know' that routine he call EXT_ISR is the interrupt handler!... Duh.....
The old read the manual:
"These directives specify the following function is an interrupt function".
Note the word 'following'.
Not exactly going to work when they are separated from the functions..... |
|
|
samus111
Joined: 28 Aug 2014 Posts: 29 Location: Colombia
|
|
Posted: Fri May 01, 2015 6:25 pm |
|
|
Thanks guys for you time, I have a most clear idea now. One of my mistakes were to not put the #int_TIMER1 and #int_EXT just before the definition of each interruption. Now only for evaluation issues, I am trying only to turn on a Led every time the pulser is pressed. Although at the begining when the program is running the interruption is recognized, always in a determined time the interrupt is not recognized any more.
I don't understand, I am only turning on a LED, I am not calling any function or anything like so. I am using the structure that Jeremiah used in his example, the only problem I see is that I get the error "invalid overload function". But is not only with TIME function, its with everything I try to define using the declaration format that you provided and explained to me. What could be happening? or What kind of mistake am I doing?:
Code: |
#include <12f1840.h>
#include <string.h>
#include <stdlib.h>
GLOBAL VARS
#use delay (internal=2000000)
#fuses noput, INTRC_IO, nowdt, nomclr,
PINES DEFINES
#SEPARATE
void TIEMPO(void) {...
#SEPARATE
int CONVERTER(void){...
#SEPARATE
int MGPS(void){ ...
#SEPARATE
int MI(void){ ...
#SEPARATE
void COORDENADA (void ){ ...
void HELP (void) {...
#SEPARATE
void main() {...
#int_TIMER1
#SEPARATE
void TIMER1_isr(void) {...
#int_EXT
#SEPARATE
void EXT_ISR (void) {... |
I must add that I am using 98% from the PIC's ROM. I suppose this does not affect anything inside the program. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Fri May 01, 2015 7:18 pm |
|
|
Does the test program I provided generate the "invalid overload function" error?
Also, why all the #separate directives? Those are normally (like 90% of the time or more) not needed at all. I'm not sure how they interact with the #int_xxx directives offhand. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19568
|
|
Posted: Sat May 02, 2015 4:34 am |
|
|
I don't think it is wise to use #SEPARATE with an ISR. An ISR already has a very special meaning, and in fact has to be part of the code generated by the compiler for the main interrupt handler. Declaring a routine as an ISR, is a specific thing which configures a whole lot of settings, and trying to then declare it as #SEPARATE, is dangerous (and very unwise).
An ISR routine, is an ISR routine. It can never be 'inline', _or_ 'separate'.
Then remember if a routine is declared as separate in it's actual declaration, is _must_ be declared as separate in it's prototype as well. |
|
|
samus111
Joined: 28 Aug 2014 Posts: 29 Location: Colombia
|
|
Posted: Tue May 05, 2015 9:17 am |
|
|
I have tested the example you provided, and this one did not send any error, I do not get to figure out why in my program shows overload error, I have also tried removing the #SEPARATE sentence from both interrupts, but still the problems are going on (at certain time the PIC does no recognize the interrupt). I am using so many #SEPARATE sentence, because by requested specifications, I have to use a 8 pins PIC that supports USART communications, the only one with this feature is the 12F1840, and has only 256 ROM memory, my code is very complex (get communication between a satellite module and a GPS module with a plenty of configurations and features) and at this time, I am using 98% from its ROM, and without specify the separation of all the functions from the memory addresses, the CCS shows a overload memory error. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1358
|
|
Posted: Tue May 05, 2015 9:45 am |
|
|
It sounds like you have quite a few things working against you here.
1. Somewhere in your program something is not done correct and while it might compile in some configurations, other valid configurations can cause compile errors like your overloaded function error. The only way to really figure this out is for you to whittle down your program to as small as it can get and still generate the error. Start by removing functions one by one and any calls to them (so the calls don't generate an error). Don't worry so much about the program working as much as compiling. Once you get it down to a few functions (hopefully only like 20-30 lines of code), we can probably help identify what causes it (probably something in the wrong order or misplaced if based off your previous posts).
2. Your chip might not be the best solution for what you want to do. If you are running that high on ROM, then your application might really need a better chip selection.
3. You still need some more experience in programming C. You definitely don't have the full background, so you still need to spend some time studying C from a good book.
4. The interrupt issue. Similar to #1, you want to create a new project and just setup the main and interrupts and have a simple way of seeing if the interrupts get called. Try to reproduce your interrupt issue but with a much smaller chunk of code. It could be something as simple as your setup or the interrupt itself. Right now we are kinda flying blind with what has been posted so far.
I think the gist of this is we really need you to get some small example codes that reproduce the issues so we can help you debug what they are. We can't really look at the whole program and in some cases it might not be good for you to give us the whole code anyways (company secerets etc.) |
|
|
|
|
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
|