Electronic – PIC16 I2C interrupt does not occur if serial port enabled

i2cinterruptspicuart

I'm using a PIC16F1825 mid range PIC and I've used it with a UART and SPI for a good while without issues. When I added code to handle I2C (instead of SPI – it's either one or the other on this PIC) I ran into problems with not receiving the I2C interrupt – thus SCL would remain stretched forever.

After some considerable debugging I figured out that removing the code that activated the serial port fixed the issue – the I2C ISR gets called and acts normally.

All I'm doing in the serial init is setting SPBRG and then:

 bcf         TXSTA, SYNC             ; Async (default)
 bsf         RCSTA, SPEN             ; Active serial port

 bsf         TXSTA, TXEN             ; Enable TX
 bsf         RCSTA, CREN             ; Enable RX

That it. No interrupts are enabled (I just set the flag on transmit)

I've searched the docs and the errata and find no hint that enabling the serial port would mangle I2C functionality like this. Is this my misunderstanding or there an actual silicon bug here?

Best Answer

This is not a silicon bug. This is me being a complete idiot.

What is happening is that my uart code was written a year ago and relied on the fact that PIR1, TXIF was high if the UART transmit buffer was empty. My code shovels data pointed to by FSR0 until it hits a "\0" and then disables TXIE. Thus when I load FSR and set TXIE, the data is automatically transmitted A year passes and I write an ISR like this:

    .intr   CODE        4

    ; Enhanced Midrange CPU does a context save on:
    ; W, STATUS, BSR, FSR, PCLATH
    ; retfie restores context

    pagesel     $

    ifbset      INTCON, TMR0IF          ; Timer0
      goto      Timer0_Entry

    banksel     PIR1                    ; Bank #0
    ifbset      PIR1, TXIF              ; Serial transmit
      goto      SerialTX_Entry

    ifbset      PIR1, SSP1IF
      goto      I2C_Entry               ; I2C Peripheral

    retfie                              ; Nothing else

Well that's total and utter nonsense. If any interrupt is received other than a timer one - so either UART or I2C, the SerialTX_Entry will be called. TXIF is always set if the UART is enabled and no character is beng held for transmission. So in the above example, I2C_Entry will never be reached.