OT: Reformatted update on table call problem

LIST p=P16F648A #include P16F648A.inc ; Was P16F628A __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _HS_OSC & _LVP_OFF & _MCLRE_OFF & _BOREN_OFF __IDLOCS 0x0001

; VARIABLES ptrlo EQU 0x20 ; table pointer ptrhi EQU 0x21 COUNT1 EQU 0x22 ; delay counter COUNT2 EQU 0x23 COUNT3 EQU 0x24 sSTATUS EQU 0x25 sW EQU 0x26 ; ORG 0x0000 GOTO start GOTO start GOTO start GOTO start ORG 0x0010 start: ;** setup I/O ; All pins have 10K in series with an LED to GND except OSC pins (and GND)

CLRF PORTB ; Set all Port B pins to logic 0 BSF RB3,RB5 ; Bank 1 command comes next STATUS RP0 set CLRF PORTB ; sel all Port B pins as outputs BCF RB3,RB5 ; Bank 0 command comes next STATUS RP0 clear

CLRF ptrlo ; start offset pointers at zero CLRF ptrhi

CLRW MOVWF PORTB ; Port B to zero CALL DELAY ; "freeze" LEDs

MOVLW 0xFF MOVWF PORTB ; Port B ones CALL DELAY ; "freeze" LEDs

repeat: INCF ptrlo ; next loc MOVF ptrlo,W CALL tab1 ;;*REMoving this, one sees 0x00 0xFF (counting) ; otherwise,one sees only repeating 0x00 0xFF MOVWF PORTB ; Port B from W CALL DELAY ; "freeze" LEDs GOTO repeat ; ---------------------------------------------- DELAY MOVWF sW ; MOVF STATUS,W ; MOVWF sSTATUS CLRF COUNT1 CLRF COUNT2 MOVLW d'45' ; fudge for about 4 Sec delay MOVWF COUNT3 LUPINR DECFSZ COUNT1 GOTO LUPINR DECFSZ COUNT2 GOTO LUPINR DECFSZ COUNT3 GOTO LUPINR DEXIT: ; MOVF sSTATUS,W ; MOVWF STATUS MOVF sW,W RETURN ; ---------------------------------------------- sine ORG 0x0100 tab1: ;; RETLW 0x01 ; [0] t=0.7500 r=0.0000 ADDWF PCL,F RETLW 0x15 ; [1] t=0.7539 r=0.0240 RETLW 0x14 ; [2] t=0.7578 r=0.0964 RETLW 0x13 ; [3] t=0.7617 r=0.2173 RETLW 0x12 ; [4] t=0.7656 r=0.3865

Note the CALL tab1 does not work. Why?

Reply to
Robert Baer
Loading thread data ...

Which part of the call does not work for you, the return of a value in W or the return of program flow?

Why not try something like this: tab1: movlw 0x55 ; or other plainly visible pattern return

and then report back to the group.

Alternatively try simulating inside MPLAB without having to reflash any hardware at all.

piglet

Reply to
piglet

PCLATH is still zero! Single step it in the emulator!!!

Try this for a concrete example of what you seem to be trying to do:

formatting link

--
Regards, 
Martin Brown
Reply to
Martin Brown

Well spotted Martin!

The Call instruction loads 11 of the 13 PC bits so PCLATH only needs to be set for distant calls but the add-to-pc instruction only loads the lower 8 bits of PC so PCLATH cannot be ignored. See section 4.3 of the datasheet page 30.

piglet

Reply to
piglet

When PCL is updated, PCH ==> PCLATH. Besides his table is at 100h, move it to 50h and it works.

Cheers

Reply to
Martin Riddle

  • If the CALL is left in, i cannot determine _what_ the actual program flow *is* (see comment below).
  • That works.

  • Emulators, simulators: can the PIC16F648A "work" with one of those, or must one use their "debug header" monster(about twice as long, 30% wider and 3-4 times taller) with a *different* interface to the PICkit3.
  • I now (as of yesterday) have a new PCB that can physically accept that monster.
  • That means i will have to learn how to use the simulator from scratch...

Note the commented lines in this snippet: repeat: INCF ptrlo ; next loc MOVF ptrlo,W CALL tab1 ;;*REMoving this, one sees 0x00 0xFF (counting) ; otherwise,one sees only repeating 0x00 0xFF MOVWF PORTB ; Port B from W CALL DELAY ; "freeze" LEDs GOTO repeat

One sees it counting IF one REMoves the CALL (first detail comment). HOWEVER, all is lost if the CALL is left in; program acts as if a reset happens at the CALL (the repeating 0x00 0xFF).

Reply to
Robert Baer

If that is true,no wonder it acts like a system reset every time thru the loop! SO that means the CALL instruction is lame as all hell, and the "working" examples are useless.

"Documentation" on the CALL shows that an eleven-bit address is used for the jump; the doc for the PIC shows: (PC)+1-->TOS k-->PC, (PCLATH)-->PC So...you are right, PCLATH remains zero, as that was the page the program was on at the CALL.

So the CALL allows one to jump to ANY 4K address within a 2K block as set by PCLATH. But after that, ignoring a return, one is stuck with addressing within a 256 location range at best. And if that puts one on a different page (16 of them in each aligned block), then tough tissue paper as they say in Southern Russia.

Gee..i can, with seven-league boots, walk around 1/2 of the world, but then must mince on tippie-toes afterwords. Not exactly conducive to sanity.

Thanks! PS: I bet that NONE of the samples in that reference actually work.

Reply to
Robert Baer

Check; confirms that the CALL instruction can f* you royally.

Reply to
Robert Baer

Yes, ONLY because it would be in the first page, aka 0X0000.

DAMN, the 6502 was infinitely better.......................

Reply to
Robert Baer

Thanks everyone for the solution to my hair-puller.

Reply to
Robert Baer

Robert Baer wrote:

** clipped out **

Well, I coded Example 4 from AN556 and had to fix a number of coding problems. But saw the exact same problem. Decided to "snoop" PCLTH and...the CALL does indeed set PCLATH from the CALL contents. Curious. And also found an anomaly that is puzzling... The program will indeed "roll over" into the next page with nary an eyeblink. THAT is decidedly _different_ than what their comment states.

Program:

LIST p=P16F648A #include P16F648A.inc ; Was P16F628A __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_OFF & _HS_OSC & _LVP_OFF & _MCLRE_OFF & _BOREN_OFF __IDLOCS 0x0001

; VARIABLES ptrlo EQU 0x20 ; table pointer ptrhi EQU 0x21 COUNT1 EQU 0x22 ; DISPL counters COUNT2 EQU 0x23 COUNT3 EQU 0x24 sSTATUS EQU 0x25 ; save STATUS here sW EQU 0x26 ; save W here ; ORG 0x0000 GOTO start GOTO start GOTO start GOTO start ORG 0x0010 start: ;** setup I/O ; All pins have 10K in series with an LED to GND except OSC pins and GND CLRF PORTB ; Set all Port B pins to logic 0 BSF RB3,RB5 ; Bank 1 command comes next STATUS RP0 set CLRF PORTB ; sel all Port B pins as outputs BCF RB3,RB5 ; Bank 0 command comes next STATUS RP0 clear CLRF ptrlo ; start offset pointers at zero CLRF ptrhi CLRW CALL DISPL ; "freeze" LEDs MOVLW 0xFF CALL DISPL ; "freeze" LEDs ;* remember PCLATH=0 as we are in page zero (ORG 0x0010)

repeat: ; From AN556 page 3, EXAMPLE 4: org 0x80 ;code location in page 0 movlw HIGH Table ;load PCLATH with hi address movwf PCLATH ; / ; movlw ptrlo,F ;load offset in w reg ; ^----- NOTE illegal character ; NOTE "offset" not defined in example; used own defined variable movlw ptrlo ;Used CORRECT form to load offset in w reg call Table CALL DISPL ; "freeze" LEDs ; NOTE: Does NOT work; displays 0x00, 0xFF, 0xFF, 0xFF etc GOTO start ; ---------------------------------------------- DISPL MOVWF PORTB ; Port B from W for display MOVWF sW MOVF STATUS,W MOVWF sSTATUS CLRF COUNT1 CLRF COUNT2 MOVLW d'50' ; fudge for about 2 Sec display MOVWF COUNT3 LUPINR DECFSZ COUNT1 GOTO LUPINR DECFSZ COUNT2 GOTO LUPINR DECFSZ COUNT3 GOTO LUPINR DEXIT: MOVF sSTATUS,W MOVWF STATUS MOVF sW,W RETURN ; ---------------------------------------------- ; From AN556 page 3, EXAMPLE 4: org 0x02ff ;Table located end of page 2 Table: MOVF PCLATH,W CALL DISPL ; "freeze" LEDs MOVLW 0xA5 CALL DISPL ; "freeze" LEDs GOTO start ; !!! See 0x00 0xFF 0x02 0xA5 repeat (!!) addwf PCL,F ;value in pc will not roll over to page 3 retlw d'65' ;NOTE assembler doesn't recognize 'A' etc.. retlw d'66' ; so assembler will crash. retlw d'67' ; Therefore used decimal equivalent. END

** Note indented code is added for "snooping" PCLATH right at entry to table.
Reply to
Robert Baer

You should be able to. You may not understand what you are seeing but your call with PCLATH=0 is the same as Call 0 which apart from leaving a return address on the stack is the same as a cold start.

You run the entire code inside a PC with no physical hardware at all. It is a full software simulation with cycle counting and timing if you bother to tell it what the clock rate is.

The simulation doesn't require any hardware and is the method of choice for debugging errant code. Crash and burn isn't anything like as effective at finding minor errors (typically fence post mistakes).

It is doing exactly what you told it to do nothing more nothing less. It cannot guess your intentions.

--
Regards, 
Martin Brown
Reply to
Martin Brown

  • I have proven that PCLATH is set by the CALL - in this case to 0x0100 and not the zero that would conveniently explain the apparent reset/cold start.
Reply to
Robert Baer

Are you sure? Have you mixed up PCH and PCLATH.

What happens during a CALL is 11 bits of PC are loaded from the opcode (all of PCL and 3 low bits of PCH) and two bits from PCLATH go to PCH. During arith on pc then the arith changes 8 bits of PCL and all 5 bits of PCH are loaded from PCLATH. Neither arith nor CALL writes or changes the value in PCLATH. Unless you restrict your table and code using it to the first 255 locations then PCLATH has to be written to by your code before doing the table lookup.

It is all in the chip datasheet.

piglet

Reply to
piglet

Concerning "datasheets, here is a code snippet: ; ---------------------------------------------- ; From AN556 page 3, EXAMPLE 4: org 0x02ff ;Table located end of page 2 Table: addwf PCL,F ;value in pc will not roll over to page 3 retlw d'65' ;NOTE assembler doesn't recognize 'A' etc.. retlw d'66' ; so assembler will crash. retlw d'67' ; Therefore used decimal equivalent ; *Also discovered that PC _CAN_ indeed "rollover" to page 3, I modified the ; code to show that fact thus: ;Table: MOVF PCLATH,W ; CALL DISPL ; to show that CALL sets PCLATH (documentation ; does NOT state this fact). ; MOVLW 0xA5 ; CALL DISPL ; use unique "marker" ; GOTO start ; !!! See 0x00 0xFF 0x02 0xA5 repeat (!!)

Reply to
Robert Baer

Seems unlikely since it can only hold values in the range 0x00 to 0xff.

WTF don't you use the software PIC emulator and single step it?

Then you can watch all the registers and understand the thing properly.

You might find this page informative if you are still struggling:

formatting link

The problem you are having is because PCL & PCH are both 8 bits wide whereas the CALL and GOTO locations are 11 bits and 2bits from PCLATH.

It is quite a nasty gotcha for the unwary. It is good practice to keep PCLATH pointed at the page where you intend to execute instructions.

--
Regards, 
Martin Brown
Reply to
Martin Brown

  • Not true; I have proven that PCLATH is indeed altered by a CALL.

Unless you restrict your table and code using it to

  • NOPE.

What i have discovered about PCLATH with my LED display system is that ORG 0x00h BCF PCLATH, 4 ;

Reply to
Robert Baer

I wonder whether you have some assembler feature turned on that is generating extra code for page crossing jumps ? - have you looked at the disassembly listing to check it agrees with what you wrote?

What to mean by "roll over"? - Instruction execution will always roll-over, the pc is a 13 bit wide presettable up counter, the debate is about behavior during presetting.

piglet

Reply to
piglet

I don't think he is smart enough to understand the difference :(

We are flogging a dead horse. I hope there isn't money riding on this.

--
Regards, 
Martin Brown
Reply to
Martin Brown

Spoilsport! I was looking forward to seeing Microchip forced into recalling a billion pic chips for having code installed that cheated on published specification.

piglet

Reply to
piglet

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.