View previous topic :: View next topic |
Author |
Message |
artohautala
Joined: 17 Nov 2011 Posts: 187
|
right order to use interrupts |
Posted: Thu May 08, 2014 6:49 am |
|
|
hello,
I'm asking when I use timer1 to interrupt what is right order to use those:
Code: |
SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
set_timer1(55594);
|
My purpose is in infinite loop first activate interrupt timer1
and measure frequency in pin B5 while(!input(pin_b5) // wait pin b5 to go high
and then while(input(pin_b5) // wait pin b5 to go low
and count those pulses in pin B5...
(the time for counting 1 s
frequency varies 10 000 ... 40000 Hz)
and then deactivate it and print result to LCD display and then
activate it again ...
what function activate timer and and what function deactivate it ?
in infinite loop ?
brdgs
-arto- |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu May 08, 2014 7:03 am |
|
|
my belief is that enabling all other ints on the service tree FIRST
and then global ints (GIE) LAST is the correct order.
at least that's how i do it....
Last edited by asmboy on Thu May 08, 2014 8:50 am; edited 1 time in total |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu May 08, 2014 7:14 am |
|
|
Sorry to jump on the bandwagon here.
asmboy, that is the way I always do it as well, but now you've got me thinking and worried.
I got a project where I want to disable and enable ADC interrupts at specific times, would I need to disable/enable GLOBAL everytime before changing the ADC interrupt. I have an SPI interrupt running as well.
Regards |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu May 08, 2014 8:16 am |
|
|
alan wrote: |
I got a project where I want to disable and enable ADC interrupts at specific times, would I need to disable/enable GLOBAL everytime before changing the ADC interrupt. I have an SPI interrupt running as well. |
I enable interrupts like that in my code too: do all the individual sources, then turn on the whole interrupt system. That way, at least you know you are not going to be interrupted while setting up the individual interrupt sources. However, in practice it often doesn't matter much.
Once initialised, when disabling/enabling an interrupt, you can simply disable each source as required without worrying about global interrupt enable. There's generally no need to do anything with GIE. That's largely handled for us by the hardware, or, as we know, on many CCS releases, messed up for us by the compiler behind the scenes driver/support code. GIE is handled automatically in the hardware in ISRs, and user code should (almost) never enable global interrupts in an ISR. Be aware that an interrupt may occur as soon as a source is enabled. All manipulation of the interrupt source, e.g. configuration of hardware, reading of data etc., must be finished by the time the relevant interrupt is enabled.
Classic critical sections, to make code sections atomic, can be implemented by manipulating GIE if they are generic, e.g. to implement semaphores/locks etc. While such things are key to many OSs, they are generally not required in typical PIC code, i.e. single threaded. On the odd occasion where such locking is required, it's often less intrusive to use individual source enables instead, e.g. to interrupt lock peripheral buffer access. The compiler also uses GIE to lock routines used in both main and ISR code, to prevent re-entrancy.
So no it doesn't matter much which order they are enabled - though individuals then global is safest - and no, you don't have to disable/re-enable GIE when you want to disable/enable a particular interrupt source.
PS: Don't forget that disabling the interrupt from a timer doesn't stop it counting.
Last edited by RF_Developer on Thu May 08, 2014 8:23 am; edited 1 time in total |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Thu May 08, 2014 8:21 am |
|
|
Thanks RF_Developer, I was wondering what will spring out of the code if I do that, and now it look as if you are just careful nothing should happen.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Thu May 08, 2014 8:46 am |
|
|
They are individually only bit flags.
None has priority, or matter when it goes off/on.
The logic only checks in the very first state of the instruction, and the sets/clears apply in the last state of the instruction.
It'd might well 'matter' if things tried to all happen at once, but that is why the PIC internally (talking about the PIC16/18), used four clock cycles per instruction. Things that are time critical relative to one another, are done in different parts of the instruction.
The reduction in clock cycles on the PIC33 etc., is why there are some extra timing restrictions (like the need to have a NOP between changing TRIS and read/write on a port).
Best Wishes |
|
|
artohautala
Joined: 17 Nov 2011 Posts: 187
|
|
Posted: Thu May 08, 2014 9:19 am |
|
|
Ttelmah wrote: | They are individually only bit flags.
None has priority, or matter when it goes off/on.
The logic only checks in the very first state of the instruction, and the sets/clears apply in the last state of the instruction.
It'd might well 'matter' if things tried to all happen at once, but that is why the PIC internally (talking about the PIC16/18), used four clock cycles per instruction. Things that are time critical relative to one another, are done in different parts of the instruction.
The reduction in clock cycles on the PIC33 etc., is why there are some extra timing restrictions (like the need to have a NOP between changing TRIS and read/write on a port).
Best Wishes |
I found this code works:
Code: |
SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
i = TRUE;
while(i){
G_KESK_LKM = 0;
taajuus = 0;
set_timer1(55650); //good value in practice, in theory 55530
enable_interrupts(GLOBAL);
while(G_KESK_LKM < 9){
//wait pin B5 to go high
while(!input(PIN_B5));
//wait pin B5 to go low
while(input(PIN_B5));
++taajuus;
}
disable_interrupts(GLOBAL);
if(taajuus > 50000){
clear_lcd();
strcpy(teksti,"humsensor off !");
show_text(1,0 );
delay_ms(2000);
return;
}
//taajuus = frequense
show_taajuus(taajuus );
} |
|
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu May 08, 2014 11:59 am |
|
|
if you have MULTIPLE interrupts enabled - then
disable_interrupts(GLOBAL);
is NOT such a great idea.
if the timer INT is the source of some action you do not wish to repeat
simply disable ONLY the timer INT- NOT the whole global show !
my 2 cents
|
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Mon May 12, 2014 5:03 pm |
|
|
I would concur.
During program init, set up your interrupts as needed with the global interrupt last.
While the program is running, one only needs to disable the interrupts that are needed (like in your case, the ADC) or ones that might be related.
A good example of this is an ISR driven UART TX routine.
How does it work?
you have a send routine that primes the TXREG and then enables the IRQ and then lets the IRQ do the work.
When the IRQ reaches the end of the needed TX buffer, it disables itself.
I've done this on systems with all sorts of other IRQ's enabled and "stuff" going on (like AD AND Timers AND RX/TX IRQ's for another UART).
Cheers,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|