PDA

View Full Version : PBP array in ASM statements



pedja089
- 28th May 2011, 20:28
I have defined a variable Counters VAR BYTE [4] bankA, and I'm using it in ISR.
Instead Counters[0] = Counters[0] +1, I want to use @ INCF _Counters, F because it is faster.
This is for first byte in array
@ INCF _Counters, F
and it works.
For the second byte in array I tried this:
@ INCF _Counters+1, F
But does not work, if I use Counters[1] = Counters[1] +1 then it works.
How to fix that?

mister_e
- 28th May 2011, 20:41
...nevermind... keep thinking...

pedja089
- 28th May 2011, 20:54
The same is happening with @ CLRF _Counter +1.
And ISR stops, sometimes begins to run, sometimes I have to reset my pic:confused:

mister_e
- 28th May 2011, 21:00
I'm tad rusty, for ease... I would bet your should assign your array to BANK0 instead...

post your PIC model and code, we'll try to help

pedja089
- 28th May 2011, 21:11
Here it is ISR

if PIR2.1=1 then
T3CON=%00000110
Wp= Wp & uwp
Xn.0=IN1
Xn.1=IN2


IF (Xn.0<Xs.0 AND Trf=0) OR (Xn.0<Xs.0 AND Xn.1=1 AND Trf=1) THEN
@ INCF _Counter,F 'this work
IF Counter[0] = Mtp2[0] OR (Counter=256 AND Mtp2[0]=0)THEN
@ CLRF _Counter ' and this
CNT[0]=CNT[0] + Add[0]
ENDIF
ENDIF

IF (Xn.1<Xs.1 AND Trf=0) OR (Xn.0<Xs.0 AND Trf=1 AND Xn.1=0) THEN
@ INCF _Counter+1,F 'Counter[1] = Counter[1] + 1 'won't work
IF Counter[1] = Mtp2[1] OR (Counter[1]=256 AND Mtp2[1]=0)THEN
@ CLRF _Counter+1'Counter[1]=0 'won't work
CNT[1]=CNT[1]+Add[1]
ENDIF
ENDIF
Xs=Xn

@ CLRF PIR2
endif
Pic is 18LF14K50
EDIT:
bank0 or bankA is same...
I tried RTC,it works fine with both.

mister_e
- 28th May 2011, 21:29
weird... a simple loop works here,


start:
asm
incf _MyArray,F
incf _MyArray+1,F
endasm
myvar=myarray[0]
myvar2=myarray[1]
goto startbut as you're using a blend mix of ASM and PBP in an ISR, you must make sure you're always on the good BANK case not, hell yeah it may goes to lalaland... what you could try is to set all variable that goes in the ISR to BANKA.

And yes I know I miss something ;)

EDIT: The more I think, the more it looks like a bank switching issue,

MyArray VAR BYTE[8] BANK1

MyVar var byte BANK0
MyVar2 var byte BANK0
clear

start:
asm
CHK?RP _MyArray
incf _MyArray,F
incf _MyArray+1,F
endasm
pause 500
myvar=myarray[0]
myvar2=myarray[1]
goto startThe above work... commentout the CHK?RP line.. and nope... it doesn't.

And NOPE, BANK0 !=BANKA

BANKA $0000, $005F
BANK0 $0060, $00FF
Finger crossed before the real ASM/Compiler gurus came here and slap me a good one :eek:

pedja089
- 28th May 2011, 21:55
As you can see, my isr have both and asm and pbp... All variables is in bankA.
Somewhere i read that bank for 18F doesn't matter...
How to setup correctly banks?
But if I use i = i +1 instead INCF everything works. INCF and CLRF work if I make a array to separate variables...

mister_e
- 28th May 2011, 22:29
Since we don't have the full code, or .LST file, I'll leave the more in deep & technical explanation of Access Ram, BSR and plah plah plah of section 3.3.3 to better guys (I hope I'm right though ;)).

Again, the compiler keep track of everything for you, hence why the PBP lines will always works.

add
@ CHK?RP _Counter
just before your INCF, DECF and or CLRF to see what happen

Bruce
- 28th May 2011, 22:52
Are all of your variables in the same bank?

pedja089
- 28th May 2011, 22:53
Same thing...
Here it's complite code

DEFINE OSC 4 ' We're using a 10MHz oscillator
Define INTHAND myint ' Define interrupt handler
DEFINE HSER_BAUD 2400
OSCCON=%01010110
OSCCON2.2=0
OSCTUNE.7=1
OSCTUNE.6=1
REFCON0=0
REFCON1=0
ADCON1=0
ADCON2=0
ANSEL =0
ANSELH=0
CM1CON0=0
CM2CON0=0
SRCON0=0
SRCON1=0
WPUA=0
WPUB=0
WDTCON=0
SLRCON=0
RCON.7=0
RCON.6=0
UCON=0
IOCA=0
IOCB=0
T0CON=0
T1CON=%00001111
T2CON=0
T3CON=%00000110
INTCON=192
INTCON2=0
INTCON3=0
PIR1=0
PIR2=0
PIE1=1
PIE2=2
IPR1=0
IPR2=0
porta=0
portb=0
portc=0
trisa=255
trisb=255
trisc=255
'RTC_________________________
Seconds VAR BYTE bankA ' variables within myint must be in bank 0.
Minutes VAR Byte bankA ' Elapsed minutes
Hours var byte bankA
Day var byte bankA
Month var byte bankA
Year var byte bankA
Ticks var byte bankA
DMonth var byte bankA
'IO________________
SYMBOL Ul1 =PORTB.5
SYMBOL Ul2 =PORTB.6
SYMBOL Pull =PORTC.4
SYMBOL UWp =PORTC.3
'TRIS______________
INPUT Ul1
INPUT Ul2
OUTPUT Pull
INPUT uwp
'Brojaci___________
Brojac VAR LONG[3] bankA
PomBroj VAR WORD[2] bankA
Mtp1 VAR BYTE[2] bankA
Mtp2 VAR BYTE[2] bankA
Add VAR BYTE[2] bankA
Xn VAR BYTE bankA
Xs VAR BYTE bankA
Wp VAR BIT bankA
Trf var byte bankA


year=0
month=0
day=0
hours = 4
minutes = 0 ' Pre Set time here then add seconds to clock using button
seconds = 0
ticks=0
PomBroj[0]=0
PomBroj[1]=0
Brojac[0]=0
Brojac[1]=0
mtp1[0]=1
mtp1[1]=1
mtp2[0]=1
mtp2[1]=1
add[0]=1
add[1]=1
Trf=0
GoTo mainloop

@myint
If PIR1.0 =1 then
TMR1H=252
@ INCF _Ticks,F
if ticks=32 then
@ INCF _Seconds,F
@ CLRF _Ticks
if seconds > 59 then
@ CLRF _Seconds
@ INCF _Minutes,F
if minutes > 59 then
@ CLRF _Minutes
@ INCF _Hours,F
if hours > 23 then
@ CLRF _Hours
@ INCF _Day,F
If month=2 then
If year//4<>0 then
DMonth=29
else
DMonth=28
endif
else
Dmonth=30+month.0
endif
If day>Dmonth then
@ CLRF _Day
@ INCF _Month,F
If month>12 then
@ CLRF _Month
@ INCF _Year,F
if year>99 then year=0
endif
endif
endif
endif
endif
endif
Pull=1
TMR3H=255
TMR3L=207
T3CON=%00000111
@ CLRF PIR1
endif
if PIR2.1=1 then
T3CON=%00000110
Wp= Wp & uwp
Xn.0=ul1
Xn.1=ul2
Pull=0

IF (Xn.0<Xs.0 AND Trf=0) OR (Xn.0<Xs.0 AND Xn.1=1 AND Trf=1) THEN
@ INCF _PomBroj,F 'PomBroj[0] = PomBroj[0] + 1
IF PomBroj[0] = Mtp2[0] OR (PomBroj=256 AND Mtp2[0]=0)THEN
Brojac[0]=Brojac[0] + Add[0]
@ CLRF _PomBroj'PomBroj[0]=0
ENDIF
ENDIF

IF (Xn.1<Xs.1 AND Trf=0) OR (Xn.0<Xs.0 AND Trf=1 AND Xn.1=0) THEN
PomBroj[1] = PomBroj[1] + 1 ' @ INCF _PomBroj+1,F '
IF PomBroj[1] = Mtp2[1] OR (PomBroj[1]=256 AND Mtp2[1]=0)THEN
Brojac[1]=Brojac[1]+Add[1]
@ CHK?RP _PomBroj
@ CLRF _PomBroj+1'PomBroj[1]=0'
ENDIF
ENDIF
Xs=Xn

@ CLRF PIR2
endif
@ retfie FAST


mainloop:
if ticks = 0 then
trisb.7=0
hserout ["B1: ",dec9 brojac[0]," B2: ",dec9 brojac[1],13,10]'["Time: ",DEC hours, ":", DEC2 minutes, ":", DEC2 seconds,13,10]
endif

GoTo mainloop

EndIf i don't use PBP for clearing and increment variable here

IF (Xn.1<Xs.1 AND Trf=0) OR (Xn.0<Xs.0 AND Trf=1 AND Xn.1=0) THEN
PomBroj[1] = PomBroj[1] + 1 ' @ INCF _PomBroj+1,F '
IF PomBroj[1] = Mtp2[1] OR (PomBroj[1]=256 AND Mtp2[1]=0)THEN
Brojac[1]=Brojac[1]+Add[1]
@ CHK?RP _PomBroj
@ CLRF _PomBroj+1'PomBroj[1]=0'
ENDIF
ENDIFCounter(Brojac) Is incremented only on first falling edge. If I use PBP, everything work fine, but code is larger for 6 bytes. I need 4 counter. Becouse device have cr3203 batery, I'm trying to make smallest possible code. Maybe I can save on space by removing or's from IF's.

mister_e
- 28th May 2011, 23:18
STOP THE PRESS! your problem is right here

Define INTHAND myint ' Define interrupt handler

In theory, this is valid only for 100% Assembler ISR.

Check for ON INTERRUPT or Darrel Taylor's INST interrupts (http://www.pbpgroup.com/modules/wfsection/article.php?articleid=19)

pedja089
- 28th May 2011, 23:35
Hm...
I did not know ...
I've seen in the example for the RTC, so I assume...
I will try dt_int...
By the way banksel isn't help either.
Thank you very much:)

mister_e
- 28th May 2011, 23:42
BANKSEL is an MPASM directive, and PBP compiler doesn't keep track of it.

CHK?RP is an equivalent Macro to use with PBP.

pedja089
- 28th May 2011, 23:48
I tried, but problem stays....
Maybe with DT_int will work.
I will test now, and come back with the results.

pedja089
- 28th May 2011, 23:57
Same with DT_INT...


INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; Include if using PBP interrupts

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _RTC, PBP, yes
INT_Handler TMR3_INT, _CNT, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM


DEFINE OSC 4 ' We're using a 10MHz oscillator
'Define INTHAND myint ' Define interrupt handler
DEFINE HSER_BAUD 2400
OSCCON=%01010110
OSCCON2.2=0
OSCTUNE.7=1
OSCTUNE.6=1
REFCON0=0
REFCON1=0
ADCON1=0
ADCON2=0
ANSEL =0
ANSELH=0
CM1CON0=0
CM2CON0=0
SRCON0=0
SRCON1=0
WPUA=0
WPUB=0
WDTCON=0
SLRCON=0
RCON.7=0
RCON.6=0
UCON=0
IOCA=0
IOCB=0
T0CON=0
T1CON=%00001111
T2CON=0
T3CON=%00000110
INTCON=192
INTCON2=0
INTCON3=0
PIR1=0
PIR2=0
PIE1=1
PIE2=2
IPR1=0
IPR2=0
porta=0
portb=0
portc=0
trisa=255
trisb=255
trisc=255
'RTC_________________________
Seconds VAR BYTE bankA ' variables within myint must be in bank 0.
Minutes VAR Byte bankA ' Elapsed minutes
Hours var byte bankA
Day var byte bankA
Month var byte bankA
Year var byte bankA
Ticks var byte bankA
DMonth var byte bankA
'IO________________
SYMBOL Ul1 =PORTB.5
SYMBOL Ul2 =PORTB.6
SYMBOL Pull =PORTC.4
SYMBOL UWp =PORTC.3
'TRIS______________
INPUT Ul1
INPUT Ul2
OUTPUT Pull
INPUT uwp
'Brojaci___________
Brojac VAR LONG[3] bankA
PomBroj VAR WORD[2] bankA
Mtp1 VAR BYTE[2] bankA
Mtp2 VAR BYTE[2] bankA
Add VAR BYTE[2] bankA
Xn VAR BYTE bankA
Xs VAR BYTE bankA

Wp VAR BIT bankA
Trf VAR BIT bankA
Smpl VAR BIT bankA



year=0
month=0
day=0
hours = 4
minutes = 0 ' Pre Set time here then add seconds to clock using button
seconds = 0
ticks=0
smpl=0
PomBroj[0]=0
PomBroj[1]=0
Brojac[0]=0
Brojac[1]=0
mtp1[0]=1
mtp1[1]=1
mtp2[0]=1
mtp2[1]=1
add[0]=1
add[1]=1
Trf=0
@ INT_ENABLE TMR3_INT
@ INT_ENABLE TMR1_INT
GoTo mainloop ' jump over the interrupt handler and sub

RTC:
TMR1H=252
@ INCF _Ticks,F
if ticks=32 then
@ INCF _Seconds,F
@ CLRF _Ticks
if seconds > 59 then
@ CLRF _Seconds
@ INCF _Minutes,F
if minutes > 59 then
@ CLRF _Minutes
@ INCF _Hours,F
if hours > 23 then
@ CLRF _Hours
@ INCF _Day,F
If month=2 then
If year//4<>0 then
DMonth=29
else
DMonth=28
endif
else
Dmonth=30+month.0
endif
If day>Dmonth then
@ CLRF _Day
@ INCF _Month,F
If month>12 then
@ CLRF _Month
@ INCF _Year,F
if year>99 then year=0
endif
endif
endif
endif
endif
endif
Pull=1
TMR3H=255
IF Smpl=1 then
TMR3L=207
else
TMR3L=240
endif
T3CON=%00000111
@ INT_RETURN

CNT:
T3CON=%00000110
Wp= Wp & uwp
Xn.0=ul1
Xn.1=ul2
Pull=0

IF (Xn.0<Xs.0 AND Trf=0) OR (Xn.0<Xs.0 AND Xn.1=1 AND Trf=1) THEN
@ INCF _PomBroj,F 'PomBroj[0] = PomBroj[0] + 1
IF PomBroj[0] = Mtp2[0] OR (PomBroj=256 AND Mtp2[0]=0)THEN
Brojac[0]=Brojac[0] + Add[0]
@ CLRF _PomBroj'PomBroj[0]=0
ENDIF
ENDIF

IF (Xn.1<Xs.1 AND Trf=0) OR (Xn.0<Xs.0 AND Trf=1 AND Xn.1=0) THEN
PomBroj[1] = PomBroj[1] + 1 ' @ INCF _PomBroj+1,F '
IF PomBroj[1] = Mtp2[1] OR (PomBroj[1]=256 AND Mtp2[1]=0)THEN
Brojac[1]=Brojac[1]+Add[1]
@ CLRF _PomBroj+1 'PomBroj[1]=0
ENDIF
ENDIF
Xs=Xn
@ INT_RETURN

mainloop:
if ticks = 0 then
trisb.7=0
' 2 portb.7,84,
hserout ["B1: ",dec9 brojac[0]," B2: ",dec9 brojac[1],13,10]'["Time: ",DEC hours, ":", DEC2 minutes, ":", DEC2 seconds,13,10]

endif

GoTo mainloop ' Repeat main loop

End
Edit:
With the DT_INT code is twice bigger than it was. Maybe I could try to get rid of arrays.
But it complicates the rest of my code... But on the other hand we will slightly extend the battery life...

cncmachineguy
- 29th May 2011, 01:49
It is likely when you enter your ISR, BSR is not 0. You can use PBP stuff in your ASM interrupt as long as you don't use any PBP stuff that uses system variables. These are things like serin/out, adcin, debug etc.

The thing you MUST do when you first enter is BSR =0. Doesn't matter if you have all ASM or a mix. PBP assumes it is set to bank 0, when it needs a different bank, it will change to it, then change back when done that command. When your interrupt occurs, you may be in a different bank. Then none of you interrupt stuff will work correct. In fact, you may not even be able to clear the interrupt flag.

This MAY not be the problem right now, but it will be. I spent 2 weeks trying to figure this out. Since then my interrupts work great! Give this a try.

Now no need to worry if using on interrupt or DT_INT.

pedja089
- 29th May 2011, 22:26
I know that I can't use any PBP stuff that uses system variables. In myint I'm only using PBP If's and basic math function...
Now I'm back to Define INTHAND. And I added BSR = 0 after @myint
I didn't know how pbp handle banks. Thank you for your notification :)
Is there need to return to the bank where he was?
eg:

@myint
BSR_Save=BSR
BSR=0
ISR routine
BSR=BSR_Save

cncmachineguy
- 29th May 2011, 23:18
If you are using 1 of the cool autocontex saving chips (interrupt section of the datasheet) BSR should be one of the registers saved and restored. If not, add it in to where you save w, status, and pcl. Then restore it with them.

pedja089
- 29th May 2011, 23:31
From datasheet:
During interrupts, the return PC address is saved on
the stack. Additionally, the WREG, STATUS and BSR
registers are saved on the fast return stack.
I have not thought before I asked that... Sorry...
But I still can not find what causes problemon CLRF and INCF:confused:

pedja089
- 30th May 2011, 20:04
Ok...
Let say that PomBroj is WORD not byte:eek::eek:
And i figure out reading .asm file... I need glasses!
Thanks everybody.