I've found a problem with the scheme used poll the
device interrupt flags .
My C code has these definitions for the signal handlers.
/* Set up the interrupt handlers */
The order of the lines above is CRITICAL as it
determines the order the interrupt flags are checked.
Here is the corresponding code in the .asm file
; ; Starting pCode block
btfsc _PIR1, 0x5
btfsc _PIR1, 0x4
btfsc _PIR1, 0x1
btfsc _INTCON, 0x2
The problem concerns the fact that only the TXIE bit
(_PIR1:4) is checked before jumping to the handler.
The Microchip application note
Asynchronous Communications with the PICmicroŽ USART
AN774 contains example code for using the transmit
interrupt which contains this section
btfss PIR1,TXIF ;test for TXIF
transmit interrupt flag
bra LowInt1 ;if TXIF is not set,
done with test
btfsc PIE1,TXIE ;else test if Tx
interrupt is enabled
bra PutData ;if so, go transmit data
;can do special error handling here - an unexpected
PutData: btfss Flags,TxBufEmpty ;check if transmit
buffer is empty
bra PutDat1 ;if not then go transmit
bcf PIE1,TXIE ;else disable Tx
PutDat1: rcall GetTxBuffer ;get data from
movwf TXREG ;and transmit
When there is nothing more to send, TXIE is cleared to
prevent the transmitter triggering any more interrupts
but TXIF is not reset because no character is written
to TXREG. When the next character is available all
that is required is to set TXIE and because TXIF is
still set an interrupt will occur.
The sdcc signal handler code does NOT allow for the
possibility that TXIF may be set even though it was not
the USART that triggered the interrupt. If TXIF is set
it always jumps to the handler. If the correct handler
is further down the list an interrupt dead lock occures.
My solution is an extended version of the DEF_HANDLER
macro which allows both **IE and **IF bits to be
checked before jumping to a handler. (Note I've used
the SIG_ prefixes to avoid clashes as I detailed in an
#define SIG_TXIF 0x4
#define SIG1_TX _PIR1, SIG_TXIF
#define SIG2_TX _PIE1, SIG_TXIF
#define DEF_HANDLER2(sig1,sig2, handler) \ btfss sig1 \n\ bra $+8 \n\ btfsc sig2 \n\ goto _ ## handler
It is used like this...