|
|
View previous topic :: View next topic |
Author |
Message |
GreenPic Guest
|
calling from int_global |
Posted: Tue May 02, 2006 8:09 am |
|
|
How can I calling a function from int_global ?
I have
Code: |
#INT_GLOBAL
void isr() {
#asm
btfsc INTCON,TMR0IF
call TMR0_przerwanie
goto apiko
nop
nop
nop
nop
btfsc PIR1,CCP1IF
call CCP1_przerwanie
btfsc PIR2,USBIF
call USB_przerwanie
apiko:
retfie
TMR0_przerwanie:
:
:
:
return
CCP1_przerwanie:
:
:
:
return
usb_przerwanie:
#ENDASM
usb_isr();
#ASM
return
#ENDASM
} |
I have Error: Unprotected call in #INT_GLOBAL
How can I call function 'usb_isr()' (it is write in C) |
|
|
Ttelmah Guest
|
|
Posted: Tue May 02, 2006 9:18 am |
|
|
What you post will work, but with a couple of caveats.
1) You must _never_ call a function in an interrupt, that is being called inside the main code, unless you disable the interrupts before calling it in the main routine, and re-enable them afterwards. If you want to use a function in both places, and not have this restriction, you need to have two copies of the code. This is because the processor structure (without a lot of bodging), does not support 're-entrant' code. The warning you are getting suggests you are trying to call the same routine elsewhere.
2) In INT_GLOBAL, it is _your_ responsibility to save all registers before operations, and restore them afterwards. Your code is changing the bank select at least, and probably more in the other routines.
Best Wishes |
|
|
Guest
|
|
Posted: Tue May 02, 2006 10:14 am |
|
|
Ttelmah wrote: | What you post will work, but with a couple of caveats.
1) You must _never_ call a function in an interrupt, that is being called inside the main code, unless you disable the interrupts before calling it in the main routine, and re-enable them afterwards. If you want to use a function in both places, and not have this restriction, you need to have two copies of the code. This is because the processor structure (without a lot of bodging), does not support 're-entrant' code. The warning you are getting suggests you are trying to call the same routine elsewhere.
2) In INT_GLOBAL, it is _your_ responsibility to save all registers before operations, and restore them afterwards. Your code is changing the bank select at least, and probably more in the other routines.
|
AD.1. Functions called from INT_GLOBAL are not called from other places, they are only for service interrupt events.
Also usb_isr() is not called from other places (only from INT_GLOBAL). I have an error, not warning (so i can't ignore it ) )
AD.2 I'm saving all needed registers in called routines
I'm sorry for my englisch
Have You any other ideas? |
|
|
Ttelmah Guest
|
|
Posted: Tue May 02, 2006 2:44 pm |
|
|
You are not saving the bank register when you start int_global.
The problem here is that the internal assembler will automatically bank switch 'for you', and the jumps may well end up bank switching.
You should not get a problem unless the routine is used elsewhere. This compiles fine:
Code: |
//Add defines here for intcon etc.
void usb_isr(void) {
delay_cycles(1);
}
#INT_GLOBAL
void isr() {
#asm
btfsc INTCON,TMR0IF
call TMR0_przerwanie
goto apiko
nop
nop
nop
nop
btfsc PIR1,CCP1IF
call CCP1_przerwanie
btfsc PIR2,USBIF
call USB_przerwanie
apiko:
retfie
TMR0_przerwanie:
nop
return
CCP1_przerwanie:
nop
return
usb_przerwanie:
#ENDASM
usb_isr();
#ASM
return
#ENDASM
}
void main()
{
while (TRUE);
}
|
The error message you are getting, is saying that _something_ you are calling is being used both inside the ISR, and outside.
Best Wishes |
|
|
Guest
|
|
Posted: Thu May 04, 2006 1:03 am |
|
|
You are right. There are some functions inside usb_isr(), which are called from other places. When i remove it, it compile fine (but doesn't work ofcourse). But.... when i don't use 'int_global', and the compiler makes interrupt service, that is possible (calling functions which are called from other places). Is there any way to do it with 'int_global'? I have to use 'int_global' because of to long time wasted for context saving. BTW is there any way to remove some registers from context saving with compiler's interrupt dispatcher?
Thanks for Your help |
|
|
Ttelmah Guest
|
|
Posted: Thu May 04, 2006 2:22 am |
|
|
Either make two copies of all the routines you want to use, or provide interrupt protection yourself (disable the interrupts, everywhere these routines are used in the main code). You can even write your own 'protection' routine as a macro. Basically test the GIE bit, and if it is set, disable it, and set a flag, then call the required subroutine, otherwise clear the flag, and call the routine. When the routine returns, if the flag is set, re-enable the GIE.
Best Wishes |
|
|
GreenPic
Joined: 02 May 2006 Posts: 7
|
|
Posted: Thu May 04, 2006 2:37 am |
|
|
Thank You for fast answer.
I found that there can be keyword FAST. Is that correct?
"#int_TIMER0 FAST"
I have error - invalid pre-processor directive
"#int_TIMER0 HIGH" compiles fine. Why FAST doesn't want ?
It is ofcourse in standard (not int_global), i have #device HIGH_INTS=1 |
|
|
Ttelmah Guest
|
|
Posted: Thu May 04, 2006 4:21 am |
|
|
There are a whole lot of interactions here:
1). If you use 'high' anywhere, on most chips (all?), 'INT0', will automatically be high priority, and cannot be changed (there is no INT0IP bit).
2). 'FAST', enables the use of RETFIE 1 for this one interrupt, and supports no 'INT_GLOBAL' at the same time. You can only have a _single_ 'FAST' interrupt. Using RETFIE 1, 'solves the need otherwise to protect the status register & accumulator.
3) 'HIGH' changes the interrupt priority (and the handler address being vectored to), for an interrupt (but brings with it the caveat of '1' above). If only one interrupt is 'high', the compiler will not add the testing for interrupt source, _but_ because of '1', if an interrupt other than INT0 is set to 'high', the testing will be added to the handler.
4) Using 'FAST', prevents RETFIE 1 being used by the normal 'HIGH' handler.
I'd suggest builing yourself a list of the following data. The act of geerating it will help to get clear what is needed, and then if you have problems, posting it, will allow us to get a better idea of what you want to do:
A) What interrupts are you using?.
B) What interrupts (if any), must be able to interrupt other events?.
C) What interrupts require quick handling?.
D) For the interrupts needing quick handling, what routines do they call (including system routines)?. What registers are used in these routines?. Are any of these routines used in the main code as well?.
Basically, the compiler handles 'simple' interrupts quite well, in a 'fail safe' manner (saving everything), but for anyone requiring faster handling, it becomes necessary to plan the work yourself. As a seperate comment though, everything you do in the routine you have posted, can be done in C, without using assembler at all. Also you do not show the act of clearing the interrupt flags anywhere, and you must do this.
Best Wishes |
|
|
GreenPic
Joined: 02 May 2006 Posts: 7
|
|
Posted: Thu May 04, 2006 6:47 am |
|
|
I will write exactly what i want to do.
I have an example (from CCS EXAMPLE folder) 'ex_usb_serial2.c'
I'm using 18F2550. It works fine. It is exactly what I need to connect my device to PC via USB and emulate COM port.
My device is radio receiver with implemented keeloq. Program for my device is in asm. I want integrate it together (device's asm + USB C).
I puted my asm code to main() of 'ex_usb_serial2.c'. I changed fuses, etc.
When device see Vbus (usb pluged in), the program jumps to code which is originaly in main() of 'ex_usb_serial2.c' and should conecting with PC.
I'm using 2 interrupts im my asm code:
1. from timer0 (measuring time and multiplexing LED display)
2. from ccp1 (receiving keloq from radio receiver)
The C code uses 1 interrupt (from usb)
Interrupt from timer0 have to have higher priority becouse of measuring time, but it mast be as quick as possible, because of interrupting the receiving routine. If it is to slow it crasch receiving keeloq.
I wrote my own int_global as i puted in erlier post. It works fine, like compiled in asm only.
My problem is tahat I can't jump to usb_isr() (i removed line #int_usb from 'ex_usb_serial2.c'). Functions in usb_isr() are called not from main but from other functions whitch are called from usb_isr() too. You can look to this file 'ex_usb_serial2.c' and pic18_usb.h where the usb_isr()
is.
Please help me, i spend a lot of time on it and i have to finish it. |
|
|
GreenPic
Joined: 02 May 2006 Posts: 7
|
|
Posted: Fri May 05, 2006 12:20 am |
|
|
Ok, i found one function which was called from ISR and from main. I removed it (i think it is doing nothing), and compile fine, but still doesn't work. No interrupt from USB. I'm findig. Thank You very very very very very much Ttelmah. |
|
|
|
|
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
|