This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Interrupt vector redirection problems

Hello! I use XC167CI and wrote bootloader described in C166: SHARE INTERRUPT VECTOR WITH BOOT LOADER http://www.keil.com/support/docs/2881.htm
Differences with my code are:

VEC_SEG  EQU 192
VEC_OFF  EQU 4000H

my irq_redir.a66 consist of

?PR?irq8 section code
irq8 proc near
  JB   boot,irq8_boot
  JMPS VEC_SEG,VEC_OFF+20H
irq8_boot:
  JMP  irq
irq8 endp
?PR?irq8 ends

When compiling linker gives error:

*** ERROR L121: IMPROPER FIXUP
    MODULE:  .\Object\irq_redir.obj (IRQ_REDIR)
    SECTION: ?PR?IRQ8
    CLASS:
    OFFSET:  000AH


May be I missed something?

  • I believe you need to change from "near" to "far" then you are ok.

    extrn irq:far
    
    ?PR?irq8 section code
    irq8 proc near
      JB   boot,irq8_boot
      JMPS VEC_SEG,VEC_OFF+20H
    irq8_boot:
      JMPS  #SEG irq, #SOF irq
    irq8 endp
    ?PR?irq8 ends
    

    Also the XC16x family allows you to change the vector table to any 64K boundary using the VECSEG register so you can have alternate vector tables.

    Hope this helped
    -Chris

  • Thanks! This solved problem. But now linker places this assembler code to 0x000004-0x00020B

    START     STOP      LENGTH    TYPE  RTYP  ALIGN  TGR  GRP  COMB  CLASS   SECTION NAME
    =====================================================================================
    000004H   0001FFH   0001FCH   CODE  ABS   AT..   ---  ---  PRIV  ---     VECT_TAB
    000200H   00020BH   00000CH   CODE  REL   WORD   ---  ---  PRIV  ---     ?PR?IRQ8
    


    Where I must place VECT_TAB with code?

  • May be I wrote indefinably previous post. I want to place bootloader part into segment 192. What should I do for this?

  • You need to be careful with the memory map. Depending on where you are booting from? You need to make sure have the linker set the VECTAB (0xC00000) control to match (in this case internal memory). You also need to make sure to have the VECSEG register set to the correct segment (have a look to the manual to check the setting you need or expect). I would also change all functions in your interrupt vector table to "far" calls and use "jmps" instruction.

    The example you used placed the memory using the AT command so you need to change this to 0C00004H.

    ; The RESET vector is used by the boot application
    VECT_TAB SECTION CODE AT 0C00004H
    VEC_PROC PROC
    

  • I've checked Your notes and made corrections but linker gives warning:

    assembling irq_redir.a66...
    linking...
    *** WARNING L4: MEMORY SPACE OVERLAP
        FROM:    C00084H.0
        TO:      C00088H.0
    *** WARNING L4: MEMORY SPACE OVERLAP
        FROM:    C000B8H.0
        TO:      C000BCH.0
    


    When OVERLAP occures? This warning points to 4 bytes overlap.
    May be there are different linker processes for assembler- and c- files? My bootloader project consists of some "c"-files.
    I use uVision3 and I can't understand how to obviously check memory map. How to identify the reason of this warning?

  • I think that warning occurs because of conflict between my statement in assembler

    VECT_TAB SECTION CODE AT 0C00004H
    

    and Interrupt Vector Table Address = 0xC00000 (VECTAB) Is it correct?

  • I don't think is causing you the problem.

    VECT_TAB SECTION CODE AT 0C00004H
    

    The VECTAB is telling the compiler where to place the interrupt table that the XC16x hardware is programmed for (expecting). The start_v2.a66 contains the reset vector (0) so this is why you put the AT 0C00004H in the irq_redir.a66 file. I would strongly suggest that you read the manual again and understand how the interrupts work on the XC16x family. Additionally, I am not a fan of using any "AT" command in the code as I would ask the linker/locator to make all placements of code.

    If you are looking for a starting point I would first check to see if you defined multiple interrupts to the same interrupt vector.

    The linker is telling you that at least two sources have requested to be located at the same address. Given the vector table entries I would look to the following:

    CAPCOM Timer 1 is located at xx'0084H
    SSC0 Receive is located at xx'00B8H

    I would assume you have this defined in irq_redir.a66 and some other "C" source?

  • Thank You! You're right - it's my oversight. I have added source file with this interrupt handlers. You recommend not to use "AT" command, can You suggest a better way to tell linker/locator to place

    VECT_TAB SECTION
    

    and

    ?PR?irq8 SECTION
    

    which now declared in assembler file at proper addresses?

  • I wouldn't say better but different and you need to pay attention to near and far.

    So in your code you have...

    ?PR?VECT_TAB SECTION CODE  WORD 'NCODE'
    VEC_PROC PROC
      JMPS VEC_SEG,VEC_OFF+004H
      JMPS VEC_SEG,VEC_OFF+008H
      JMPS VEC_SEG,VEC_OFF+00CH
      JMPS VEC_SEG,VEC_OFF+010H
      JMPS VEC_SEG,VEC_OFF+014H
      JMPS VEC_SEG,VEC_OFF+018H
      JMPS VEC_SEG,VEC_OFF+01CH
      JMPS #SEG irq8, #SOF irq8    ; SOFTBRK
      JMPS VEC_SEG,VEC_OFF+024H
      JMPS VEC_SEG,VEC_OFF+028H
      JMPS VEC_SEG,VEC_OFF+02CH
    VEC_PROC ENDP
    ?PR?VECT_TAB ENDS
    
    ?PR?irq8 section code   word 'NCODE'
    irq8 proc far
      JB   boot,irq8_boot
      JMPS VEC_SEG,VEC_OFF+20H
    irq8_boot:
      JMPS  #SEG irq, #SOF irq
    irq8 endp
    ?PR?irq8 ends
    


    Then in the L166 Locate User Section add (change the address to what you want here).

    ?PR?vect_tab%NCODE(0xC00004),?PR?irq8%NCODE(0xC01000)
    


    Then you see the location in the map file.

    START     STOP      LENGTH    TYPE  RTYP  ALIGN  TGR  GRP  COMB  CLASS   SECTION NAME
    =====================================================================================
    C00000H   C00003H   000004H   ---   ---   ---    ---  ---  ---   * INTVECTOR TABLE *
    C00004H   C0002FH   00002CH   CODE  REL   WORD   ---  ---  PRIV  NCODE   ?PR?VECT_TAB
    C00038H   C0003BH   000004H   CODE  REL   WORD   ---    3  PUBL  NCODE   ?PR?MAIN
    C01000H   C0100BH   00000CH   CODE  REL   WORD   ---  ---  PRIV  NCODE   ?PR?IRQ8
    

    This was just an example.

  • I think that it's more handy method because of united location for all address assignments. I'll try it.
    But my interrupt doesn't work. I added GPT timer T6 to my project and changed assembler file.
    irq_redir.a66

    VEC_SEG  EQU 192
    VEC_OFF  EQU 4000H
    ; The RESET vector is used by the boot application
    VECT_TAB SECTION CODE AT 0C00004H
    VEC_PROC PROC
      JMPS VEC_SEG,VEC_OFF+004H
      JMPS VEC_SEG,VEC_OFF+008H
    ...
      JMPS VEC_SEG,VEC_OFF+094H
      JMPS #SEG irq8, #SOF irq8        ; irq8
      JMPS VEC_SEG,VEC_OFF+09CH
    ...
    VEC_PROC ENDP
    VECT_TAB ENDS
    
    extrn boot:bit
    extrn T6irq:far
    
    ?PR?irq8 section code at 0C00500H
    irq8 proc near
      JB   boot,irq8_boot
      JMPS VEC_SEG,VEC_OFF+098H
    irq8_boot:
      JMPS  #SEG T6irq, #SOF T6irq
    irq8 endp
    ?PR?irq8 ends
    

    and in main.c


    void far T6irq(void) interrupt irq=CACHED
    { P2_8 = !P2_8; // LED on/off
    }

    In the debugger (OCDS) I see proper ports initialisation, T6 runs, T6 inerrupt request flag is set when T6 overflow, program runs (in infinite loop) but there is no entering to T6 interrupt handler.

  • I solved my problem. Chris, thank You very much for support and solutions!