PDA

View Full Version : Still HSEROUT woes



Charles Linquis
- 9th July 2006, 05:05
I'm using an 18F part and have a 1mSec timer interrupt using TMR0.

I wanted to test everything by building a simple seconds counter. Inside my ISR I would count to 1000, and then set a flag. My PBP program would sit in a tight loop and test for that flag, and when it detected it was set, it would increment a counter and display the running count via the HSEROUT command. The trouble is the interrupt would crash HSEROUT. The first few characters get sent out, then a bunch of garbage. This happens every second, so I have proof that the interrupt is still running.

I thought my trouble was because I was trashing a system variable inside my assembly-language ISR, so I went back to Tim Box's routine where virturally every PBP variable is saved and restored, and I rewrote the ISR in PBP.

I STILL have the same problem. Is there some software timing loop inside HSEROUT that is getting screwed up?

The program is below:

'************************************************* ***************
'* Name : INT_CTRL.BAS *
'* Author : Tim Box *
'* Notice : Copyright (c) 2002 TJBSYSTEMS *
'* : All Rights Reserved *
'* Date : 28-Sep-02 *
'* Version : 1.0 *
'* Notes : *
'* : Modified by C. Linquist for 18F parts 5/1/04 *
'************************************************* ***************

DEFINE OSC 20 ' Set for 20Mhz operation
DEFINE NO_CLRWDT 1
DEFINE _18F8720 1
DEFINE HSER_RCSTA 90H
DEFINE HSER_TXSTA 20H
DEFINE HSER_BAUD 9600
DEFINE HSER_CLROERR 1
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2
DEFINE LOADER_USED 1 ' Bootloader
Define USE_LFSR 1


TRISA = %11111111
TRISB = %11111111
TRISC = %10010001
TRISD = %00111000
TRISE = %00000000
TRISF = %01111111
TRISG = %11111100
TRISH = %00000000
TRISJ = %10010000




ADCON2 = %10000010 ' Right justify 10 bit output, Clock = Fosc/32

ADCON1 = %00010011 ' Set Vref on RA3, 12 chan A/D (AN0-AN11)

ADCON0 = %00000001 ' Set A/D to ON, chan 0

PSPCON = %00000000 ' No PSP
MEMCON = %10000000 ' No External Memory
CMCON = %00000111 ' No Comparator used, turn it off

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' USART 1 receive buffer int enable

CCPR1L = %00010000
CCPR1H = %00000000 ' Initialize to 0, PWM register
PR2 = $1F ' PWM register,158 Khz@20Mhz, 7 bits
T2CON = %00000100 ' Prescale 1 - Needed for PWM
CCP1CON= %00001100 ' Set up for PWM



'************************************************* ***************************************
'* *
'* Declare variables *
'* *
'************************************************* ***************************************




wsave VAR BYTE $20 SYSTEM ' Save location for the W register if in bank0

ssave VAR BYTE Bank0 SYSTEM ' Save location for the STATUS register
psave VAR BYTE Bank0 SYSTEM ' Save location for the PCLATH register
fsave VAR BYTE Bank0 SYSTEM ' Save location for the FSR register

R0_2 var WORD BANK0 ' PBP VARS TO SAVE
R1_2 VAR WORD BANK0
R2_2 VAR WORD BANK0
R3_2 VAR WORD BANK0
R4_2 VAR WORD BANK0
R5_2 VAR WORD BANK0
R6_2 VAR WORD BANK0
R7_2 VAR WORD BANK0
R8_2 VAR WORD BANK0
FLAGS_2 VAR BYTE BANK0
GOP_2 VAR BYTE BANK0
RM1_2 VAR BYTE BANK0
RM2_2 VAR BYTE BANK0
RR1_2 VAR BYTE BANK0
RR2_2 VAR BYTE BANK0

TIMER VAR WORd
X VAR WORD
Y VAR BYTE
SecondsCounter VAR BYTE
TimerFlag VAR BIT
DEFINE INTHAND INT_CODE 'Tell PBP Where your code starts on an interrupt

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' Usart1 int enabled


TimerFlag = 0
Timer = 0
X = 0
SecondsCounter = 0

GOTO OVER_INT_CODE



asm


INT_CODE
MOVF R0,W
MOVWF _R0_2
MOVF R0 + 1,W
MOVWF _R0_2 + 1

MOVF R1,W
MOVWF _R1_2
MOVF R1 + 1,W
MOVWF _R1_2 + 1

MOVF R2,W
MOVWF _R2_2
MOVF R2 + 1,W
MOVWF _R2_2 + 1

MOVF R3,W
MOVWF _R3_2
MOVF R3 + 1,W
MOVWF _R3_2 + 1

MOVF R4,W
MOVWF _R4_2
MOVF R4 + 1,W
MOVWF _R4_2 + 1

MOVF R5,W
MOVWF _R5_2
MOVF R5 + 1,W
MOVWF _R5_2 + 1

MOVF R6,W
MOVWF _R6_2
MOVF R6 + 1,W
MOVWF _R6_2 + 1

MOVF R7,W
MOVWF _R7_2
MOVF R7 + 1 ,W
MOVWF _R7_2 + 1

MOVF R8,W
MOVWF _R8_2
MOVF R8 + 1 ,W
MOVWF _R8_2 + 1


IFDEF T2
MOVF T2,W
MOVWF _T2_2
ENDIF
IFDEF FLAGS
MOVF FLAGS,W
MOVWF _FLAGS_2
ENDIF
IFDEF GOP
MOVF GOP,W
MOVWF _GOP_2
ENDIF
IFDEF RM1
MOVF RM1,W
MOVWF _RM1_2
ENDIF
IFDEF RM2
MOVF RM2,W
MOVWF _RM2_2
ENDIF
IFDEF RR1
MOVF RR1,W
MOVWF _RR1_2
ENDIF
IFDEF RR2
MOVF RR2,W
MOVWF _RR2_2
ENDIF


endasm
;%%%%%%%%%%%%%%%%%%%%%%%%% Interrupt handler written in PBP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
IF INTCON.2 = 1 THEN
TMR0H = $EC
TMR0L = $77
Timer = Timer + 1
IF Timer >= 1000 THEN
TimerFlag = 1
Timer = 0
ENDIF
INTCON.2 = 0
ENDIF
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%``

ASM

MOVF _R0_2,W
MOVWF R0
MOVF _R0_2 + 1,W
MOVWF R0 + 1

MOVF _R1_2,W
MOVWF R1
MOVF _R1_2 + 1,W
MOVWF R1 + 1

MOVF _R2_2,W
MOVWF R2
MOVF _R2_2 + 1,W
MOVWF R2 + 1

MOVF _R3_2,W
MOVWF R3
MOVF _R3_2 + 1,W
MOVWF R3 + 1

MOVF _R4_2,W
MOVWF R4
MOVF _R4_2 + 1,W
MOVWF R4 + 1

MOVF _R5_2,W
MOVWF R5
MOVF _R5_2 + 1,W
MOVWF R5 + 1

MOVF _R6_2,W
MOVWF R6
MOVF _R6_2 + 1,W
MOVWF R6 + 1

MOVF _R7_2,W
MOVWF R7
MOVF _R7_2 + 1,W
MOVWF R7 + 1

MOVF _R8_2,W
MOVWF R8
MOVF _R8_2 + 1,W
MOVWF R8 + 1

IFDEF FLAGS
MOVF _FLAGS_2,W
MOVWF FLAGS
ENDIF
IFDEF FLAGS
MOVF _GOP_2,W
MOVWF FLAGS
ENDIF
IFDEF RM1
MOVF _RM1_2,W
MOVWF RM1
ENDIF
IFDEF RM2
MOVF _RM2_2,W
MOVWF RM2
ENDIF
IFDEF RR1
MOVF _RR1_2,W
MOVWF RR1
ENDIF
IFDEF RR2
MOVF _RR2_2,W
MOVWF RR2
ENDIF

IFDEF T2
MOVF _T2_2,W
MOVWF T2
ENDIF

Movf psave,w ; Restore the PCLATH reg
Movwf PCLATH
swapf ssave,w ; Restore the STATUS reg
movwf STATUS
swapf wsave,f
swapf wsave,w ; Restore W reg
Retfie ; Exit the interrupt routine

ENDASM
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


OVER_INT_CODE:

Topp:
IF TimerFlag = 1 THEN
SecondsCounter = SecondsCounter + 1
HSEROUT ["Seconds = ",#SecondsCounter,13,10]
TimerFlag = 0
INTCON.7 = 1 ; Turn global ints back on
ENDIF
Goto Topp

SteveB
- 9th July 2006, 07:04
Charles,
It's late, so I have only taken the briefest look, but a couple of things jumped out.

1) You never actually saved wsave, ssave, psave and fsave at the beginning of your ISR.

2) You defined wsave, ssave, psave and fsave(and all the rest) as if you are using a PIC16. Change $20 and bank0 to banka for all of the context variables.

3) You should use the movff command for all the context saving. It does not effect the STATUS reg. (see the datasheet example under interrupts)

4) If you need to save a FSR, you should be saving FSRXH and FSRXL. (It doesn't at first glance look like you need to since I didn't see any commands/reference that use that register) Read the datasheet in the Memory Organization section about Data Addressing Modes (particularly Indirect Addressing)

Start with these items. If I have some time tomorrow I'll take a closer look.
Good night,
Steve

Charles Linquis
- 9th July 2006, 18:47
I forgot to modify Tim Box's routine.

Here is the modified version. I went ahead and used movff instructions for ALL the registers, even the PBP ones.

The code below has some strange behavior: It prints
"secsecsecsecsecsec..." on the screen at one second intervals which proves that the interrupt is still running, but HSEROUT apparently gets trashed when an interrupt occurs.

Also, I have added a USART interrupt to the mix. Hitting any key kills the routine.

I'm stuck!

Here is the updated code
---------------------------------------------------------------------


DEFINE OSC 20 ' Set for 20Mhz operation
DEFINE NO_CLRWDT 1
DEFINE _18F8720 1
DEFINE HSER_RCSTA 90H
DEFINE HSER_TXSTA 20H
DEFINE HSER_BAUD 9600
DEFINE HSER_CLROERR 1
DEFINE CCP1_REG PORTC
DEFINE CCP1_BIT 2
DEFINE LOADER_USED 1 ' Bootloader
Define USE_LFSR 1
DEFINE ADC_BITS 10
DEFINE ADC_SAMPLEUS 50


TRISA = %11111111 'AUX1,VM12,V12,V3,V5
TRISB = %11111111 'PDAT,PCLK,TACH6,TACH5,TACH4,TACH3,TACH2,TACH1
TRISC = %10010001 'RX1,TX1,SDO,SDA,LEDTG,PWMOUT,LEDFG,TACH7
TRISD = %00111000 'LED5R,LED3R,TACH8,TACH9,CTS1,RTS1,LED12G,LEDM12G
TRISE = %00000000 'LEDV2R,LEDV2G,LED3G,LED5G,LEDFR,LEDTR,LEDM12R,LED 12R
TRISF = %01111111 'OPTO1,FlowSig,POT2,POT1,Temp4,Temp3,Temp2,Temp1
TRISG = %11111100 'NC,NC,NC,XPGP3,XPCP1,RX2,TX2,OPTO2
TRISH = %00000000 'PINT2,PINT1,LCDRS,LCDRW,LCDDB7,LCDDB6,LCDDB5,LCDD B4
TRISJ = %10010000 'SWitchIN,LEDout,LEDout,XCTSin,XPReset,LCDe,RLY,PI NT3




ADCON2 = %10000010 ' Right justify 10 bit output, Clock = Fosc/32

ADCON1 = %00010011 ' Set Vref on RA3, 12 chan A/D (AN0-AN11)

ADCON0 = %00000001 ' Set A/D to ON, chan 0

PSPCON = %00000000 ' No PSP
MEMCON = %10000000 ' No External Memory
CMCON = %00000111 ' No Comparator used, turn it off

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' USART 1 receive buffer int enable

CCPR1L = %00010000
CCPR1H = %00000000 ' Initialize to 0, PWM register
PR2 = $1F ' PWM register,158 Khz@20Mhz, 7 bits
T2CON = %00000100 ' Prescale 1 - Needed for PWM
CCP1CON= %00001100 ' Set up for PWM



'************************************************* ***************************************
'* *
'* Declare variables *
'* *
'************************************************* ***************************************




wsave VAR BYTE BANKA SYSTEM ' Save location for the W register if in BANKA

ssave VAR BYTE BANKA SYSTEM ' Save location for the STATUS register


R0_2 var WORD BANKA ' PBP VARS TO SAVE
R1_2 VAR WORD BANKA
R2_2 VAR WORD BANKA
R3_2 VAR WORD BANKA
R4_2 VAR WORD BANKA
R5_2 VAR WORD BANKA
R6_2 VAR WORD BANKA
R7_2 VAR WORD BANKA
R8_2 VAR WORD BANKA
FLAGS_2 VAR BYTE BANKA
GOP_2 VAR BYTE BANKA
RM1_2 VAR BYTE BANKA
RM2_2 VAR BYTE BANKA
RR1_2 VAR BYTE BANKA
RR2_2 VAR BYTE BANKA

TIMER VAR WORd
X VAR WORD
Y VAR BYTE

SecondsCounter VAR BYTE
TimerFlag VAR BIT
KeyHitFlag VAR BIT

DEFINE INTHAND INT_CODE 'Tell PBP Where your code starts on an interrupt

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' Usart1 int enabled


TimerFlag = 0
Timer = 0
X = 0
SecondsCounter = 0
KeyHitFlag = 0

GOTO OVER_INT_CODE

asm
MOVFF WREG,wsave ; copy W to wsave register
MOVFF STATUS,ssave
CLRF STATUS ; change to bank 0 regardless of current bank

INT_CODE

MOVFF R0,_R0_2
MOVFF R0+1,_R0_2+1
MOVFF R1,_R1_2
MOVFF R1+1,_R1_2+1
MOVFF R2,_R2_2
MOVFF R2+1,_R2_2+1
MOVFF R3,_R3_2
MOVFF R3+1,_R3_2+1
MOVFF R4,_R4_2
MOVFF R4+1,_R4_2+1
MOVFF R5,_R5_2
MOVFF R5+1,_R5_2+1
MOVFF R6,_R6_2
MOVFF R6+1,_R6_2+1
MOVFF R7,_R7_2
MOVFF R7+1,_R7_2+1
MOVFF R8,_R8_2
MOVFF R8+1,_R8_2+1


IFDEF T2
MOVFF T2,_T2_2
ENDIF
IFDEF FLAGS
MOVFF FLAGS,_FLAGS_2
ENDIF
IFDEF GOP
MOVFF GOP,_GOP_2
ENDIF
IFDEF RM1
MOVFF RM1,_RM1_2
ENDIF
IFDEF RM2
MOVFF RM2,_RM2_2
ENDIF
IFDEF RR1
MOVFF RR1,_RR1_2
ENDIF
IFDEF RR2
MOVFF RR2,_RR2_2
ENDIF


endasm
;%%%%%%%%%%%%%%%%%%%%%%%%% Interrupt handler written in PBP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
IF INTCON.2 = 1 THEN
TMR0H = $EC ; Reload TMR0 to 65535 - 5000
TMR0L = $77
Timer = Timer + 1
IF Timer >= 1000 THEN
TimerFlag = 1
ENDIF

ENDIF

IF PIR1.5 = 1 THEN
KeyHitFlag = 1
ENDIF
INTCON.2 = 0 ; Clear the timer flag
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%``

ASM

MOVFF _R0_2,R0
MOVFF _R0_2 + 1,R0 + 1
MOVFF _R1_2,R1
MOVFF _R1_2 + 1,R1 + 1
MOVFF _R2_2,R2
MOVFF _R2_2 + 1,R2 + 1
MOVFF _R3_2,R3
MOVFF _R3_2 + 1,R3 + 1
MOVFF _R4_2,R4
MOVFF _R4_2 + 1,R4 + 1
MOVFF _R5_2,R5
MOVFF _R5_2 + 1,R5 + 1
MOVFF _R6_2,R6
MOVFF _R6_2 + 1,R6 + 1
MOVFF _R7_2,R7
MOVFF _R7_2 + 1,R7 + 1
MOVFF _R8_2,R8
MOVFF _R8_2 + 1,R8 + 1

IFDEF FLAGS
MOVFF _FLAGS_2,FLAGS
ENDIF
IFDEF FLAGS
MOVFF _GOP_2,FLAGS
ENDIF
IFDEF RM1
MOVFF _RM1_2,RM1
ENDIF
IFDEF RM2
MOVFF _RM2_2,RM2
ENDIF
IFDEF RR1
MOVFF _RR1_2,RR1
ENDIF
IFDEF RR2
MOVFF _RR2_2,RR2
ENDIF

IFDEF T2
MOVFF _T2_2,T2
ENDIF


MOVFF ssave,STATUS ; Restore the STATUS reg
MOVFF wsave,W ; Restore W reg
Retfie ; Exit the interrupt routine

ENDASM

OVER_INT_CODE:

Topp:
IF TimerFlag = 1 THEN
SecondsCounter = SecondsCounter + 1
HSEROUT ["Seconds = ",#SecondsCounter,13,10]
TimerFlag = 0
Timer = 0
ENDIF
IF KeyHitFlag = 1 THEN
HSERIN [Y]
HSEROUT[Y]
KeyHitFlag = 0
ENDIF

INTCON.7 = 1 ; Turn global Ints back on
Goto Topp

mister_e
- 9th July 2006, 18:55
i'm out of stock of this PIC but i'd notice few things here..


DEFINE _18F8720 1 ' <- What is the purpose of this one
'
'
Define USE_LFSR 1 ' <- try to remove it

i'll try to surf in the ASM... i'll try. Yuk! i agree sometimes we don't have choice ;)

mister_e
- 9th July 2006, 19:07
mmm,


asm
MOVFF WREG,wsave ; copy W to wsave register
MOVFF STATUS,ssave
CLRF STATUS ; change to bank 0 regardless of current bank

INT_CODE

MOVFF R0,_R0_2
MOVFF R0+1,_R0_2+1


should be..


asm
INT_CODE
MOVFF WREG,wsave ; copy W to wsave register
MOVFF STATUS,ssave
CLRF STATUS ; change to bank 0 regardless of current bank



MOVFF R0,_R0_2
MOVFF R0+1,_R0_2+1

Charles Linquis
- 9th July 2006, 19:40
Steve, you are absolutely correct. One of my edits went awry.

Unfortunately, when I put the INT_CODE line in the correct place,
nothing changes. Still no joy.


And mister_e,

The lines are part of my "standard" header file. I can't tell you why they
are there. Probably some legacy issue. Anyway. I took them out.
No change in behavior.

mister_e
- 9th July 2006, 20:03
O.k then i'll try again ;)

Beeing said i already heard of some care about the Tim's routine.. i just don't remind where but.. humm.

Now i'm very bad and slow in assembler debugging so, apologies..

mister_e
- 9th July 2006, 20:08
just an idea... how about replacing the Hserout by a TXREG=Char loop. Just by seeing the output of it, it seems the routine just redo the Hserout line without keeping track of what have been already sent...

OR it have to exist a character pointer variable in the HSEROUT macro somewhere... if so, you probably didn't save it in the INT Handler... mmm interesting....

mister_e
- 9th July 2006, 20:40
pfff... maybe


IF TimerFlag = 1 THEN
SecondsCounter = SecondsCounter + 1
INTCON = 0
HSEROUT ["Seconds = ",#SecondsCounter,13,10]
INTCON = %11100000
TimerFlag = 0
Timer = 0
ENDIF

IF KeyHitFlag = 1 THEN
INTCON = 0
HSERIN [Y]
HSEROUT[Y]
INTCON = %11100000
KeyHitFlag = 0
ENDIF

mister_e
- 9th July 2006, 20:45
ah come on brain cell (no s)... wake up...


IF INTCON.2 = 1 THEN
TMR0H = $EC ; Reload TMR0 to 65535 - 5000
TMR0L = $77
Timer = Timer + 1
IF Timer >= 1000 THEN
TimerFlag = 1
ENDIF

ENDIF

IF PIR1.5 = 1 THEN
KeyHitFlag = 1
ENDIF
INTCON.2 = 0 ; Clear the timer flag

where the PIR1.5 is cleared?

Charles Linquis
- 9th July 2006, 21:01
In the PBP program. HSERIN clears the flag.

mister_e
- 9th July 2006, 21:05
yeah right but how about if you move the main HSERIN to the interrupt routine?

SteveB
- 9th July 2006, 21:10
What happens if you remove the line?:

DEFINE NO_CLRWDT 1

When I plugged you code into MPLAB and ran the sim, it gave me a watchdog timeout.

Steve

mister_e
- 9th July 2006, 21:14
but if the watchdog timer is not set in the config fuse, it won't change anything... at least i guess.

Charles Linquis
- 9th July 2006, 21:21
mister_e,

You insight is very helpful! Interrupts were, indeed killing the HSEROUT routine. Setting INTCON to "0" just before the HSEROUT allows the characters to be output properly.

Grabbing the character with HSERIN inside the ISR works as well!

This helps a lot, but I don't believe that I can disable ints during serial transmission. MAYBE I can work around this.

It would be nice to know if I have a bug in my ISR, or if PBP itself has a bug that prevents HSEROUT from being an interruptable routine.

By the way. Everyone else seems to have found a nice way to include formatted code without putting it "in line". Could you please tell me how to do that?

mister_e
- 9th July 2006, 21:28
Great!!!

look the following link for VB code
http://www.picbasic.co.uk/forum/misc.php?do=bbcode

Charles Linquis
- 10th July 2006, 00:34
Just to answer the random notes around the thread and also to summarize:

The watchdog timer was disabled during programming.
The interrupt worked exactly as expected (that is, it DID provide a 'tick' every
millisecond).

Writing the interrupt in pure assembly, saving Wreg,STATUS, FSR0L, and FSR0H
produced EXACTLY the same result as using a modified "Tim Box" routine which saves the same registers as above PLUS all the PBP registers.

Does this prove that HSEROUT cannot be interrupted? I have a question in to MELabs.

SteveB
- 10th July 2006, 02:16
Charles and Steve,
I took Charles code and made a couple of slight changes (in italics) to accomadate a different PIC (PIC18F4620) and to send out a longer string of serial data. It ran just as expected.

Here is the code I ran:


DEFINE OSC 40 'Oscillator speed in MHz: 3(3.58) 4 8 10 12 16 20 24 25 32 33 40
;define LOADER_USED 1
@ __CONFIG _CONFIG1H, _OSC_HSPLL_1H
@ __CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
@ __CONFIG _CONFIG3H, _PBADEN_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L

;DEFINE NO_CLRWDT 1
DEFINE HSER_RCSTA 90H
DEFINE HSER_TXSTA 20H
DEFINE HSER_BAUD 9600
DEFINE HSER_CLROERR 1
DEFINE LOADER_USED 1 ' Bootloader
Define USE_LFSR 1

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' USART 1 receive buffer int enable

'************************************************* ***************************************
'* *
'* Declare variables *
'* *
'************************************************* ***************************************


W_HP_Save var byte BANKA ' Save location for W in BANKA
STATUS_HP_Save var byte BANKA ' Save location for STATUS register in BANKA
BSR_HP_Save var byte BANKA ' Save location for BSR register in BANKA

R0_2 var WORD BANKA ' PBP VARS TO SAVE
R1_2 VAR WORD BANKA
R2_2 VAR WORD BANKA
R3_2 VAR WORD BANKA
R4_2 VAR WORD BANKA
R5_2 VAR WORD BANKA
R6_2 VAR WORD BANKA
R7_2 VAR WORD BANKA
R8_2 VAR WORD BANKA
FLAGS_2 VAR BYTE BANKA
GOP_2 VAR BYTE BANKA
RM1_2 VAR BYTE BANKA
RM2_2 VAR BYTE BANKA
RR1_2 VAR BYTE BANKA
RR2_2 VAR BYTE BANKA

TIMER VAR WORd
X VAR WORD
Y VAR BYTE

SecondsCounter VAR BYTE
TimerFlag VAR BIT
KeyHitFlag VAR BIT

DEFINE INTHAND INT_CODE 'Tell PBP Where your code starts on an interrupt

T0CON = %10001000
INTCON = %11100000 ' Timer0 and Peripheral interrupts enabled
PIE1 = %00100000 ' Usart1 int enabled


TimerFlag = 0
Timer = 0
X = 0
SecondsCounter = 0
KeyHitFlag = 0

GOTO OVER_INT_CODE

asm

INT_CODE
movwf _W_HP_Save ; 1 copy W to W_HP_Save register
movff STATUS, _STATUS_HP_Save ; 2 copy status reg to STATUS_HP_Save
movff BSR, _BSR_HP_Save ; 3 copy BSR to BSR_HP_Save

MOVFF R0,_R0_2
MOVFF R0+1,_R0_2+1
MOVFF R1,_R1_2
MOVFF R1+1,_R1_2+1
MOVFF R2,_R2_2
MOVFF R2+1,_R2_2+1
MOVFF R3,_R3_2
MOVFF R3+1,_R3_2+1
MOVFF R4,_R4_2
MOVFF R4+1,_R4_2+1
MOVFF R5,_R5_2
MOVFF R5+1,_R5_2+1
MOVFF R6,_R6_2
MOVFF R6+1,_R6_2+1
MOVFF R7,_R7_2
MOVFF R7+1,_R7_2+1
MOVFF R8,_R8_2
MOVFF R8+1,_R8_2+1


IFDEF T2
MOVFF T2,_T2_2
ENDIF
IFDEF FLAGS
MOVFF FLAGS,_FLAGS_2
ENDIF
IFDEF GOP
MOVFF GOP,_GOP_2
ENDIF
IFDEF RM1
MOVFF RM1,_RM1_2
ENDIF
IFDEF RM2
MOVFF RM2,_RM2_2
ENDIF
IFDEF RR1
MOVFF RR1,_RR1_2
ENDIF
IFDEF RR2
MOVFF RR2,_RR2_2
ENDIF


endasm
;%%%%%%%%%%%%%%%%%%%%%%%%% Interrupt handler written in PBP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
IF INTCON.2 = 1 THEN
TMR0H = $EC ; Reload TMR0 to 65535 - 5000
TMR0L = $77
Timer = Timer + 1
IF Timer >= 1000 THEN
TimerFlag = 1
ENDIF

ENDIF

IF PIR1.5 = 1 THEN
KeyHitFlag = 1
ENDIF
INTCON.2 = 0 ; Clear the timer flag
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%``

ASM

MOVFF _R0_2,R0
MOVFF _R0_2 + 1,R0 + 1
MOVFF _R1_2,R1
MOVFF _R1_2 + 1,R1 + 1
MOVFF _R2_2,R2
MOVFF _R2_2 + 1,R2 + 1
MOVFF _R3_2,R3
MOVFF _R3_2 + 1,R3 + 1
MOVFF _R4_2,R4
MOVFF _R4_2 + 1,R4 + 1
MOVFF _R5_2,R5
MOVFF _R5_2 + 1,R5 + 1
MOVFF _R6_2,R6
MOVFF _R6_2 + 1,R6 + 1
MOVFF _R7_2,R7
MOVFF _R7_2 + 1,R7 + 1
MOVFF _R8_2,R8
MOVFF _R8_2 + 1,R8 + 1

IFDEF FLAGS
MOVFF _FLAGS_2,FLAGS
ENDIF
IFDEF FLAGS
MOVFF _GOP_2,FLAGS
ENDIF
IFDEF RM1
MOVFF _RM1_2,RM1
ENDIF
IFDEF RM2
MOVFF _RM2_2,RM2
ENDIF
IFDEF RR1
MOVFF _RR1_2,RR1
ENDIF
IFDEF RR2
MOVFF _RR2_2,RR2
ENDIF

IFDEF T2
MOVFF _T2_2,T2
ENDIF


movff _BSR_HP_Save, BSR ; Restore the BSR reg
movf _W_HP_Save, W ; Restore W
movff _STATUS_HP_Save, STATUS ; Restore the STATUS reg
Retfie ; Exit the interrupt routine

ENDASM

OVER_INT_CODE:

Topp:
IF TimerFlag = 1 THEN
SecondsCounter = SecondsCounter + 1
HSEROUT ["Seconds = ",#SecondsCounter,13,10]
HSEROUT ["abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN OPQRSTUVWZYZ1234567890",_
rep "1"\10,rep "2"\10,rep "3"\10,rep "4"\10,rep "5"\10,13,10]
TimerFlag = 0
Timer = 0
ENDIF
IF KeyHitFlag = 1 THEN
HSERIN [Y]
HSEROUT[Y]
KeyHitFlag = 0
ENDIF
INTCON.7 = 1 ; Turn global Ints back on
Goto Topp

Here is the output:
956

So...
I don't think it's a problem with the HSEROUT being interrupted.

Steve

mister_e
- 10th July 2006, 02:31
Nicely done! That show and confirm my assembler limitation and some basic register knowledge. I really have to work harder on that.

SteveB
- 10th July 2006, 02:56
Correction: The HSEROUT works as expected, the HSERIN does not. But I was really only looking at the interaction between interrupts and HSEROUT to begin with. I'll take a closer look at the HSERIN now.

Steve

SteveB
- 10th July 2006, 03:06
Well, Just moving
HSERIN [Y]
HSEROUT[Y]
into the ISR solved the HSERIN as mentioned.

Despite getting it working on my equipment, we still don't know why it isn't working for Charles. I'd like to know why the difference.

Steve

mister_e
- 10th July 2006, 03:17
well let's see it in the simplest way... an Interrupt flag have been set, it jump to the ISR but he's not clear before going out... what happen? it return back to the ISR as soon as possible.

As it's just a single character.. HSERIN can be changed to


x=RCREG
While RCREG : Discard=RCREG : Wend


or few lines of assembler...

OUF, at least i wasn't too far.. that's good for my own self esteem :)

Charles Linquis
- 10th July 2006, 05:06
I can deal with the requirement to read the RCREG from within the ISR, but having to shut off the interrupts while running HSEROUT is more problematic. I have to run full-duplex in my application. That is why I needed it interrupt-driven in the first place!

Charles Linquis
- 10th July 2006, 05:34
SteveB:

Confirming - I took your code and loaded it into my 8720. It works as expected, except that it doesn't handle USART interrupts (as you mentioned). I'm thinking that your routine works better because you saved/restored BSR, while I was was saving/restoring FSR0L and FSR0H.

I have an email to MELABS. Maybe they can shed some light on this.

When we are done, I think we will have a good framework for how to deal with interrupts in the 18F series!

Charles Linquis
- 10th July 2006, 16:33
PROBLEM SOLVED!

I have been conversing with Tim Box. Although he no longer writes in PBP, he had some great insights.

I'll be able to write a short tutorial on using interrupts with 18F parts and PBP tonight.

Many thanks to all who contributed!

BigWumpus
- 10th July 2006, 19:52
...I'm using interrupts with the 18Fxxxx and...

the WSAVE...etc-part in front of a interrupt-handler is ONLY neccessary for PICs with up to 2048 words ? (PIC16F872). Bigger PICs don't need the code in the beginning, it is placed by PBP. The restore-code before the retfie is only used for PICs <PIC18, because they know the "retfie 1"-solution to restore all this silly registers, saved by an interrupt... (PBP doesn't support high/low-priority-Ints, so no other interrupt is used!)

But don't try to use PBP inside a interrupt-service-routine !

mister_e
- 10th July 2006, 22:01
Once all PBP variable saved.. you can use PBP statement inside the ISR
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=960&stc=1&d=1152565276">

18Fs are different right, but how... i can't say, as now the regular method work for my requirement... as now. So i guess i should look deeper in that one in case i need something like this.

In this case, there's no big stuff to do in the ISR... so, my question is... is this longer to do only a pure assembler routine... or messing 'round with the known 'once the PBP variables are saved...' stuff. mmm

I miss something in that one anyways... i'll go deeper on my side too. Maybe i could help.

SteveB
- 10th July 2006, 22:52
OK, I've been using an 18F4620 with multiple, prioritized interrupts for a while without any problems. So here a couple of things I know for sure regarding assembly interrupts.

PBP does not save context for the 18F4620 (and presumably all the PIC18s), which has >2K program space (The PIC18F2620 and PIC18F4620 each have 64 Kbytes of Flash memory and can store up to 32,768 single-word instructions.). Here are some snippets from the .lst file with some explanatory comments. It clearly shows that PBP does not enter any additional code into Assembly Interrupts.


Here are the Defines

00008 ; Define statements.
00009 ; C:\PIC_CODE\MICROC~1\PIC18F~1\CUR\MAIN.BAS 00013 DEFINE OSC 40 'Oscillator speed in MHz: 3(3.58)
4 8 10 12 16 20 24 25 32 33 40
00010 #define OSC 40
00011 ; C:\PIC_CODE\MICROC~1\PIC18F~1\CUR\INTERRUPT_HANDLE R.BAS 00009 DEFINE INTHAND HP_INT_ENTRY
00012 #define INTHAND HP_INT_ENTRY
00013 ; C:\PIC_CODE\MICROC~1\PIC18F~1\CUR\INTERRUPT_HANDLE R.BAS 00010 DEFINE INTLHAND LP_INT_ENTRY
00014 #define INTLHAND LP_INT_ENTRY

Here is the beginning of the program (000000) with the interrupt vectors making an immediate jump to the interrupt routines

00125 ; Oscillator is 40MHz
000000 01132 ORG RESET_ORG ; Reset vector at 0
000000 6A18 01137 clrf FLAGS ; Clear all flags on reset
000002 EFC1 F001 01142 goto INIT ; Finish initialization
000008 01153 ORG RESET_ORG + 8 ; High priority interrupt vector at 8
000008 EFCF F001 01154 goto INTHAND ; Goto high priority user interrupt handler
000018 01167 ORG RESET_ORG + 18h ; Low priority interrupt vector at 18h
000018 EFDC F001 01168 goto INTLHAND ; Goto low priority user interrupt handler


Here is the beginning of the Interrupt handlers. The code you see is all generated from my original code, no PBP code has been inserted to save context

00394 ;---[This creates the Hight Priority Interrupt Service Routine (HPISR)]---------
00039E 00395 HP_INT_ENTRY
00039E 6E49 00396 movwf _W_HP_Save ; 1 copy W to W_HP_Save register
0003A0 CFD8 F042 00397 movff STATUS, _STATUS_HP_Save ; 2 copy status reg to STATUS_HP_Save
0003A4 CFE0 F028 00398 movff BSR, _BSR_HP_Save ; 3 copy BSR to BSR_HP_Save
00399 ;Interrupt Code
0003A8 EFF2 F001 00400 goto CountTicks
0003AC 00401 ReturnFromHP
0003AC C028 FFE0 00402 movff _BSR_HP_Save, BSR ; Restore the BSR reg
0003B0 5049 00403 movf _W_HP_Save, W ; Restore W
0003B2 C042 FFD8 00404 movff _STATUS_HP_Save, STATUS ; Restore the STATUS reg
0003B6 0010 00405 Retfie ; Exit the interrupt routine
00406 ;-------------------------------------------------------------------------------
00407
00408
00409 ENDASM?
00410
00411
00412 ; C:\PIC_CODE\MICROC~1\PIC18F~1\CUR\INTERRUPT_HANDLE R.BAS 00040 ASM
00413
00414 ASM?
M RST?RP
M if (PREV_BANK != 0)
M movlb 0
M PREV_BANK = 0
M endif
00415
00416 ;---[This creates the Low Priority Interrupt Service Routine (LPISR)]-----------
0003B8 00417 LP_INT_ENTRY
0003B8 6E4A 00418 movwf _W_LP_Save ; 1 copy W to W_LP_Save register
0003BA CFD8 F043 00419 movff STATUS, _STATUS_LP_Save ; 2 copy status reg to STATUS_LP_Save
0003BE CFE0 F029 00420 movff BSR, _BSR_LP_Save ; 3 copy BSR to BSR_LP_Save
0003C2 EF3C F002 00421 goto StartSerialBuffer
0003C6 00422 ReturnFromLP
0003C6 C029 FFE0 00423 movff _BSR_LP_Save, BSR ; Restore the BSR reg
0003CA 504A 00424 movf _W_LP_Save, W ; Restore W
0003CC C043 FFD8 00425 movff _STATUS_LP_Save, STATUS ; Restore the STATUS reg
0003D0 0010 00426 Retfie ; Exit the interrupt routine
00427 ;-------------------------------------------------------------------------------

W, and STATUS must be saved and restored, along with any other variable/register you may change inside your ISR. Why? There is normally no way to know exactly when an interrupt will occur (hence the name). So, there is no way for the ISR to really know what the current code is doing with items like W, STATUS, FSRs, BSR (or PCLATH for PIC16), etc. Without saving and restoring these items, when the ISR gets done, the state of these things may be different than when it began, and the program will behave unpredictably

With PIC18s, if High/Low priority interrupts are used, you need to save the context separately for both. See above, but with the addition that the low priority ISR can be interrupted by the high priority ISR. (See the bottom of the above code snippet)

What makes PIC18s interrupts different than PIC16s? A couple of items (though not exhaustive by any means):

Interrupts can be prioritized into high and low. If not using low priority interrupts, then it is very similar to how PIC16s handle interrupts
Memory Organization: The way the Banks and SFR are organized in the PIC18s is fundamentally different than PIC16s. If you don't understand the difference you are bound to have some problems.


Unless the PBP command has a critical timing issue (like with the software comm items), interrupts should not create any problems with the commands if the context is saved properly. Now, if the command does not rely on critical timing, but is used in a time critical manner, interrupts could create some problems related with delays (In this case, you could use INTCON to disable interrupts until the time critical bit of code was done, then re-enable). I would venture to say that most delays, if the ISR is kept as short as possible, will be completely transparent, especially if running at a fast clock rate.

If PBP code is used inside the ISR, the special PBP variables should be saved for the save reasons stated above for W, STATUS, etc. The way I have done this is to start with the items listed in PBPPIC18.RAM, then once the code has been compiled, look at the .lst file and see if I've missed any. It's a bit tedious, but I end up pretty sure I got them all.

I will be curious to see what Charles posts from his conversations with Tim Box. As I said earlier, I've been using assembly interrupts in my project with no issues on the PIC18F4620. I've got a Timer using high priority interrupts and a serial buffer using low priority interrupts. It runs at 40MHz, and the serial baud is 115200. Apart from the interrupts, some of the other items include the ubiquitous LCD (actually a salvaged VFD:)), an I2C RTC and EEPROM, button matrix, and some ADC inputs. So, I would have figured if the interrupts were causing problems, they would have showed up by now.


Steve

mister_e
- 11th July 2006, 00:19
Neat explanation to me. i'm waiting for some PIC18F8720 even if not recommended for new design) and some PIC18F8722 as suggested.

I saw some Errata one the 8720 so far... maybe a cause but at this point unsure... so no flame please :)

Ii have ton's of assumptions but i keep'em for me now.. just to keep things quiete.

I have a stupid test to suggest... it's a test ONLY... how about using ON INTERRUPT to see if there's any progress.. from what i feel, as now the snip we have shouldn't have so much problem to work with... if there's progress... an ASM file is still generated... NO?

Forget me if i'm wrong.

Charles Linquis
- 11th July 2006, 02:31
This is all good stuff, and I wanted to compile all that I have learned over the past few days and present it tonight. But now, I'm waiting for an explanation of a few more things from Leonard Zerman, one of the writers of PBP. I should have some really neat tips to post tomorrow night.

mister_e
- 11th July 2006, 03:51
it's just pretty bad none of the Melabs team post few time in here... At least, having using it few times before, i agree that they provide a pretty nice e-mail support.

Darrel Taylor
- 11th July 2006, 10:48
Maybe this will help. :)

DT_INTS-18
http://www.picbasic.co.uk/forum/showthread.php?p=23031
<br>

mister_e
- 11th July 2006, 14:50
Why i had that feeling that you already worked on that and... harder on the last days :)

<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=881&d=1148640458">

Thanks Darrel!

Darrel Taylor
- 11th July 2006, 15:33
Yes I did! &nbsp; On both accounts. :)

Thanks Steve!
<br>

SteveB
- 11th July 2006, 21:13
Darrel,
I think your link to DT_INTS-18 is worth a separate post in the Code Examples section. (Possibly even in the PBP Extensions section as well;))

Based on the time on your post, it looks like you have spent at least one late night/early morning (no doubt more) getting this ready for "Prime Time". Know that there are many who appreciate your time and effort. I recall a post where Melanie suggested to someone to look into how many solutions vs. questions folks like yourself, Bruce, and the like, post. It certainly drives home the point that this forum is fortunate to have generous, knowledgeable people involved.

More than just use your code, let's hope folks actually take a good look at the inner workings and learn from it.

Thanks,
(Sorry, I haven't got any cool dancing letter's :D LOL.)
Steve