NomadAU
NomadAU

Reputation: 29

Looking for a working function jump table example

I'm struggling to implement a function jump table and hoping someone can help out.

Here's one of the code examples I've tried, without success. It appears that the program just goes off into space when the jump table is called. Here's the setup and call to a function that is meant to set up the jump table call.

        ; call the next routine
movlw   1   ; this should call the second function
movwf   programIndex
call    runCurrentProgram

And here's where the PC should be set up based on the programIndex value. I'm unsure about the need for a multiplier. When I look at the table assembly output, it appears to be just 2 words, so the multiplier seems unnecessary.

runCurrentProgram:
bcf     programIndex, 7     ; clear high bit for rotate
rlf     programIndex, W         ; multiply index by two
addlw   low programTable
movwf   tabLow      ; tabLow is a temporary variable
movlw   high programTable
btfsc   STATUS,STATUS_CARRY_POSITION
addlw   1
movwf   PCLATH
movf    tabLow,w
movwf   PCL

And finally, here's how I defined the jump table.

programTable:
goto    Function1
goto    Function2

As mentioned earlier, both Function1 and Function2 are contained in a separate library. They work just fine if called directly from the control program.

I've found several examples of similar code, using goto's, BRA or BRW but none have been specifically for the PIC16F1503 and have not worked for me.

Can anyone help me out here?

Thanks to @TimRoberts for the suggestion. Replacing with DW did not work. Replacing with BRA DID work. I'm still trying to understand the use of the PCL, PCLATH code, but I can see clearly (from the listing) that DW has rendered the absolute address, i.e. the address the linker allocates to the functions, while BRA generates something else.

The listing shows Function1 loaded at 014B and Function2 at 016F and the code generated with DW and BRA is shown below.

340     0100  324A                  bra Function1

341     0101  326D                  bra Function2

340     0100  014B                  dw  Function1

341     0101  016F                  dw  Function2

I also did some experimentation to try and understand PCL better by loading PCLATH and PCL with the absolute address of one of the functions (obtained from the assembler/linker listing) and was able to satisfy myself that provided PCLATH is set to the correct register bank, and PCL is set to the function address in the bank, then everything works just fine. I'll now spend a bit more time working on the dynamic table entry selection code.

Upvotes: 0

Views: 85

Answers (1)

NomadAU
NomadAU

Reputation: 29

I have the following working code which uses BRA to jump to the required function (using its relative address). The linker option -pprogramTable=100h is used in the build to locate the jump table at 0x100.

    ; The jump table is located on the start of a page boundary 0x100   
global      programTable
psect programTable,global,class=CODE,delta=2    
programTable:
    bra     f1 
    bra     f2
    bra     f3
    bra     endOfTable
    
endOfTable: ; reset the index back to start of table
    clrf    programIndex
    return

Here's the code that uses the jump table.

runCurrentProgram:
    movf    programIndex,w
    addlw   low programTable
    movwf   tabLow      ; tabLow is a temporary variable
    movlw   high programTable
    btfsc   STATUS,STATUS_CARRY_POSITION
    addlw   1
    movwf   PCLATH
    movf    tabLow,w
    movwf   PCL

Upvotes: 1

Related Questions