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.
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!