PDA

View Full Version : Can an asm interrupt contain gosub to a picbasic routine?



sougata
- 16th April 2005, 06:58
Hi there,

I am having an asm interrupt routine that is caused by a timer0 overflow every milisecond. Now I have several variables(word) which should be incremented, decrememted or reset within this loop. I find it difficult to do so with asm. So what I need to know is that can I call (through GOSUB) a picbasic routine from within my asm ISR. Is it at all possible ? How the variables should be defined? Should they be all in bankA or does PBP handles bank switching even while in asm ISR? If it does then do I have to take care of RAM banks when a gosub returns into the ISR again? Please help.

cupajoe
- 16th April 2005, 17:21
Hi,

I write assembly interrupts often and the main reason that I do this is for timing. I would not recommend jumping into, out of, back into and finally out of the ISR just to increment some counters. I have cut part of my ASM ISR out to show how to increment variables.



TOCK
BCF 0x0B,2 ;CLEAR INT FLAG
MOVLW 0x64 ;LOAD (PRELOAD) INTO W
MOVWF 01 ;LOAD W INTO TMR0
INCFSZ _TMR0CNT,1 ;INC LOW BYTE OF COUNTER - SKIP NEXT IF IT ROLLS OVER
RETURN ;LOW BYTE DIDN'T ROLL OVER SO RETURN WITHOUT INC UPPER BYTE
INCF _TMR0CNT + 1,1 ;LOW BYTE ROLLED OVER SO INC HIGH BYTE
RETURN ;RETURN


Note that TMR0CNT is a word variable declared in the basic program body. Hope this helps.

Regards,

Joe.

cupajoe
- 16th April 2005, 17:31
If you are uncomfortable with assembly and don't want to or don't have the time to try and learn it you could try to handle the interrupt from inside your basic program.

To do this you turn the interrupt off and keep polling the interrupt register bit and if it is set then act on it. This may or may not work for you. It really depends on what else your program is doing.

I have done this on simple programs where there aren't any long instructions (like lcdout, serout, pause, etc)

Just an idea.

Joe.

sougata
- 19th April 2005, 10:41
Hi Joe,

Thanks for the reply. In your asm ISR I find that you clear the int flag defined not by PICBASIC. You are directly handling a RAM location defined earlier by you. Another thing that is unclear to me is that when PBP defines a word does it put the higher and lower byte in consecutive location and in the same bank. I am not confident in handling RAM bank switching. Although I am trying to get familiar. I successfully called (a.k.a. call)a picbasic subroutine from within an asm ISR routine to test conditions and take action. I got the idea from the asm file generated by PBP where a sub-routine ends with the "return" statement. (The same for assembly too). My application is time sensitive and I do a little bit multitasking.(I seggregate jobs in different time frame). For example I generate an int. every mili second. Count the mili second to 9 (for e.g.) and use a select case within the main body to do different things at different time. Your and others thoughts on this regards is most most welcome.
Regards
Sougata

cupajoe
- 20th April 2005, 18:27
I use the BANK option when declaring variables to ensure that the entire variable is in a known bank. Here is a sample.



'Variables
aflag var byte 'individual bits are used as flags.
bflag var byte BANK0'individual bits are used as flags.
cflag var byte ' individual bits are used as flags.
adval2 var word 'Value of pot on AN2
adval3 var word 'Value of pot on AN3
i var word BANK0'general purpose variable
pc var word BANK0 'pack counter
TMR0CNT var word BANK0 'number of times TMR0 has overflowed. used to update AD and LCD.
delay var word 'how long we wait to fire valve.
bc var word 'bad count. how many bad barcodes scanned
pct var word 'the percentage of bad scans to packages.


As for clearing the interrupt, I am using assembly language to do that.


BCF 0x0B,2 ;CLEAR INT FLAG

The BCF command is bit clear and 0B is the register that contains the interrupt while the ",2" is the actual bit. I clear the interrupt in the ISR so that there is no chance that it will cause a false trip by being read twice.

Please also look at how I set up registers and define aliases to register bits.


ADCON1 = %10000111 ' Set PORTA and PORTE digital and right justify result
TRISA = %11101100 '
TRISB = %11111001
TRISC = %10001000
OPTION_REG = %10100100 ' Set which edge RB0 int on (falling set).
INTCON = %11110000 ' Enable interrupt for Timer0 AND peripherals
PIE1 = %00100001 'Allow Timer1 & serial in to cause a periheral interrupt.
T1CON = %00000000 'Set Timer1 prescaler to 1

'Aliases for registers
INTF VAR INTCON.1 ' Alias INTF (RB0/INT external interrupt flag) This is RTS!!!
TMR0_EN VAR OPTION_REG.5' CLEAR TO START TIMER0 SET TO STOP.
TMR0IF VAR INTCON.2 ' TIMER0 INTERRUPT FLAG BIT.
TMR1_ON VAR T1CON.0 ' SET TO START TIIMER1 CLEAR TO STOP
TMR1IF VAR PIR1.0 ' TIMER1 INTERRUPT FLAG
RCIF VAR PIR1.5 ' Alias RCIF (USART Receive Interrupt Flag)
OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable)


I hope this is helpful. It really isn't that difficult to increment a variable in assemble that is what my original post showed with the TMR0CNT. I know that you can call a basic subroutine from inside your ISR but I question whether it defeats the purpose of the ISR. Perhaps not but I like to keep my interrupts as short as possible.

Have you considered turning off the interrupts and polling the interrupt bit. Do this in your basic loop and if it is set, clear it and increment your counters. If the loop is small enough you should be able to this almost as quickly as with an iterrupt. Just a thought as this will make for some simple code.

Regards,

Joe

sougata
- 21st April 2005, 19:49
Hi Joe,
Thanks for the post. It is really helpful and I beleive it will be useful to other forum members greatly. Thanks again

Regards
Sougata