>I've got a little example working which has interrupt handers >for serial receive and TMR0 and startup code for USART and >TMR0 in "chained segments" and it works fine. Just got back from 10 days (working unfortunately) in sunny Kourou, so catching up on discussions. I get the impression, Peter, that you are setting out to do exactly what I did using Olins development environment. You can see extern labels declared for interrupt handlers that were in other modules (the serial one is a rework of Fr. MacGhees code). below is the code from an interrupt handler I did: - ; This module is based on a concept developed by Olin Lathrop as outlined ; in the following copyright notice. All additional code developed for the ; end use product is copyright 2002, Rutherford Appleton Laboratory. ; ; *************************************************************** ; * Copyright (c) 2001, Embed Inc (http://www.embedinc.com) * ; * * ; * Permission to copy this file is granted as long as this * ; * copyright notice is included in its entirety at the * ; * beginning of the file, whether the file is copied in whole * ; * or in part and regardless of whether other information is * ; * added to the copy. * ; * * ; * The contents of this file may be used in any way, * ; * commercial or otherwise. This file is provided "as is", * ; * and Embed Inc makes no claims of suitability for a * ; * particular purpose nor assumes any liability resulting from * ; * its use. * ; *************************************************************** ; ; Interrupt service and related routines. ; include "hkp.inc" ; noexpand ; no macro expansion extern i2c_intr extern uart_intr_rx extern uart_intr_tx extern_flags ; declare global flag bits EXTERN ; ;*********************************************************************** ; ; Configuration constants. ; save_fsr equ true ; indicate whether ISR must save/restore FSR ; ;********** ; ; Derived constants. ; ; ;*********************************************************************** ; ; Global state. ; ; The following global state is in the normal register bank for global ; state. The bank is GBANK, and GBANKADR is an address guaranteed to ; be within this bank. ; .bank#v(gbank) udata temp1 res 1 ; temp scratch that may be trashed by any routine global temp1 ; ;*********************************************************************** ; ; Local state. This is always in the same register bank as the global ; state. ; ; ; The following state is private to the interrupt service routine, and ; must always be in bank 0. ; if gbank != 0 .bank0 udata endif status_save res 1 ; saved copy of STATUS, nibbles swapped if save_fsr fsr_save res 1 ; saved copy of FSR (if FSR save enabled) endif if ncodepages > 1 pclath_save res 1 ; saved copy of PCLATH (if multiple code pages) endif itmp1 res 1 ; temp storage for use within interrupt routine itmp2 res 1 ; ; This state is private to the interrupt service routine and must always ; be accessible regardless of the current direct register bank setting. ; udata_shr w_save res 1 ; saved W during interrupt, mapped to all banks .intr code ; ;*********************************************************************** ; ; Subroutine INTR_INIT ; ; Initialize the interrupt system and other state managed by this module. ; glbsub intr_init, noregs ; ; Initialize local state. ; ; setup the INTR function dbankif OPTION_REG clrf OPTION_REG ; set defaults for most things ; bcf OPTION_REG,INTEDG ; set to falling edge interrupts ; bsf INTCON,INTF ; allow it to interrupt - turned on after download ; set up timer interrupts ; TMR0 - Not used here ; dbankif TMR0 ; movlw timer0_val ; movwf TMR0 ; bcf OPTION_REG,T0CS ; set to internal clock source ; bcf OPTION_REG,T0SE ; set external clock edge ; bsf OPTION_REG,PSA ; set prescaler to watchdog timer ; bsf INTCON,T0IE ; TMR1 - used for timeout timimg dbankif T1CON clrf T1CON ; default to timer off, Internal Clock, Prescale 1 bsf T1CON,T1CKPS1 ; set to prescale 4 movlw low Timer1_Value movwf TMR1L movlw high Timer1_Value movwf TMR1H dbankif PIE1 bsf PIE1,TMR1IE ; enable interrupts for timer dbankif OPTION_REG bsf OPTION_REG, PEIE ; allow timer interrupts ; TMR2 - not used here ; ; Initialize global state. ; ; dbankif INTCON ; INTCON occurs in all banks bsf INTCON,GIE ; enable global interrupt bit ; to finally awaken the whole system up leaverest ; ;*********************************************************************** ; ; Interrupt service routine. ; ; The processor effectively executes a call to location 4 on an interrupt, ; except that global interrupts are also disabled. These are re-enabled ; at the end of the ISR by the RETFIE instruction. ; ; Note that subroutine calls must be minimized or avoided in the ISR. ; Since an interrupt can come at any time in the main code, any additional ; call stack locations used here are not available anywhere else. ; .intr_svc code 4 ; start at interrupt vector location movwf w_save ; save W intr_trap swapf status,w ; make copy of status without effecting status bits clrf status ; select direct and indirect register banks 0 dbankis 0 ibankis 0 movwf status_save ; save old STATUS value with nibbles swapped dbank intr_led_reg bcf intr_led_pin ; show serial activity LED if save_fsr ; FSR needs to be saved ? movf fsr, w ; save FSR movwf fsr_save endif if ncodepages > 1 ; multiple code pages may be in use ? movf pclath, w ; save PCLATH movwf pclath_save clrf pclath endif ; ; W, STATUS, FSR (if SAVE_FSR set), and PCLATH (if multiple code pages) ; have been saved. Direct and indirect register banks 0 are selected, and ; the bank assumptions have been set accordingly. Program memory page 0 ; is selected. ; dbank pir1 ; check for UART receive interrupt btfss pir1, rcif goto no_uart_recv ;******************** intr_uart_rx nop ; nop for ICD to stop on gjump uart_intr_rx ; will jump to INTR_RET when done ;******************** no_uart_recv dbankif pie1 btfss pie1, txie ; check for UART transmit interrupt allowed goto no_uart_trans ; no so skip check dbankif pir1 btfss pir1, txif ; check if UART tx interrupt occurred goto no_uart_trans ;******************** intr_uart_tx nop ; nop for ICD to halt on gjump uart_intr_tx ; will jump to INTR_RET when done ;******************** no_uart_trans dbankif pir1 ; check for I2C interrupt btfss pir1, sspif goto no_i2c gjump i2c_intr ; will jump to INTR_RET when done ;******************** no_i2c dbankif pir1 btfsc pir1,tmr1if goto tmr1_intr ;******************** intr_chk_inte btfsc INTCON,INTE ; check if interrupt enabled goto intr_ret ; no, so dont look for interrupt bcf INTCON,INTF ; clear the interrupt flag ;; goto intr_ret ; To prevent ALERTS intr_alert dbankif OPTION_REG btfsc OPTION_REG,INTEDG goto Clear_Big_Red_Intr bsf OPTION_REG,INTEDG ; change edge to turn off next time dbankif big_red_reg bcf big_red_pin ; show Panic Interrupt LED dbankif gbankadr bsf flag_Alert ; show an alert occurred goto intr_ret ;******************** Clear_Big_Red_Intr dbankis OPTION_REG bcf OPTION_REG,INTEDG dbankif INTCON bcf INTCON,INTF ; clear the interrupt flag bsf INTCON,INTE ; Enable Interrupt dbankif big_red_reg bsf big_red_pin ; clear Panic Interrupt LED goto intr_ret ; ;******************** ; intr_nonint ; we should never end up here but this ; is a trap point for ICD to check. nop ; ;******************** ; ; Restore state to when the interrupt occurred and return from interrupt. ; glbent intr_ret ; common code to return from the interrupt clrf status ; register bank settings are now 0 dbankis 0 ibankis 0 if ncodepages > 1 ; multiple code pages may be in use ? movf pclath_save, w ; restore PCLATH movwf pclath endif if save_fsr ; FSR needs to be restored ? movf fsr_save, w ; restore FSR movwf fsr endif dbankif intr_led_reg bsf intr_led_pin ; clear interrupt activity LED dbankif 0 swapf status_save,w ; get old STATUS with nibble order restored movwf status ; restore STATUS, register banks now unknown swapf w_save,f ; swap nibbles in saved copy of W swapf w_save,w ; restore original W retfie ; return from interrupt, re-enable global interrupts ;******************************************************************** ;* * ;* Routine "Tmr1_Intr" * ;* Handle the timer 1 timeout by setting the timeout flag, turning * ;* off the timer, and setting up for next time. * ;* * ;******************************************************************** locent Tmr1_Intr dbankif pir1 bcf PIR1,TMR1IF ; clear the interrupt flag dbankif gbankadr bsf flag_timeout ; show that timeout occurred dbankif T1CON bcf T1CON,TMR1ON ; turn timer off nop ; to allow switch off to take effect dbankif TMR1L ; reload timer to 100mS default movlw low Timer1_Value movwf TMR1L dbankif TMR1H ; ready for the next timeout movlw high Timer1_Value movwf TMR1H goto intr_ret ; and return from interrupt end -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist