AnsweredAssumed Answered

LPC11C14 I2C Bug: SI Flag not Setting after Start Bit Generation, State not Updating

Question asked by Pierce Jensen on Jan 24, 2018
Latest reply on Mar 12, 2018 by Pierce Jensen

I've got an LPC11C14 that refuses to generate an interrupt or set the Serial Interrupt (SI) flag in I2C->CONSET after successfully generating a start condition for a Master Transfer.

 

My current setup has an LPC11C14/301 with nothing on the I2C bus except the external pullups (Note: I can drive the lines manually if I set them to GPIO mode and write the registers, so there's nothing wrong hardware wise). My code compiles and runs, and works with other peripherals, but I've stripped out all of the code to just the I2C Code. No slaves have been initialized.

int main(void) {
    SystemCoreClockUpdate(); // Read clock settings and update SystemCoreClock variable

    Chip_SYSCTL_PeriphReset(RESET_I2C0);
    Chip_I2C_Init(I2C0);

    LPC_I2C_T *I2C = LPC_I2C_BASE;

    Chip_I2C_SetClockRate(I2C0, 100000); //Initialize I2C to 100kHz Clock Rate
   
    I2C->CONSET = I2C_CON_I2EN;

    LPC_IOCON_T *IOCON = LPC_IOCON_BASE;

   /* preemption = 1, sub-priority = 1 */
//  Disabled interrupts to ensure code stays stuck in While Loop. No change with either on or off.
//  NVIC_SetPriority(I2C0_IRQn, 1);
//  NVIC_EnableIRQ(I2C0_IRQn)

//Initialize 0.4 and 0.5 for I2C
//I have tried initializing I2C Fast Mode, No change
   Chip_IOCON_PinMuxSet(IOCON, IOCON_PIO0_4, IOCON_FUNC1 | 0);
   Chip_IOCON_PinMuxSet(IOCON, IOCON_PIO0_5, IOCON_FUNC1 | 0);

    /* Reset STA, STO, SI */
    I2C->CONCLR = I2C_CON_SI | I2C_CON_STO | I2C_CON_STA | I2C_CON_AA;

    /* Enter to Master Transmitter mode */
//Tried inserting a nop for race conditions. No Change
    asm("nop");

//Generate Start Bit
    I2C->CONSET = I2C_CON_STA;

    while(1){}

}

I've also tried inserting dummy writes into the DAT register, which doesn't work either. This code results in CONSET having I2EN and STA set, and everything else reset, the State being stuck at 0xf8. SCLL and SCLH are at 0xf0, which makes sense for a 100kHz rate. Monitor mode is disabled, and no slave addresses have been set.

 

I see SDA drop from high to low, and SCL stay high, which is a valid start condition, but the SI bit and State never change. If I manually set the SI bit, the state updates to 0x00, a bus error, which makes no sense.

 

According to UM10398, Chapter 15, section 10.1:

In the master transmitter mode, a number of data bytes are transmitted to a slave receiver (see Figure 54). Before the master transmitter mode can be entered, I2CON must be initialized as follows:

 

{Table 235 Omitted: Indicates I2EN as 1, rest as 0, AA as don't care}

 

The I2C rate must also be configured in the SCLL and SCLH registers. I2EN must be set to logic 1 to enable the I2C block. If the AA bit is reset, the I2C block will not acknowledge its own slave address or the General Call address in the event of another device becoming master of the bus. In other words, if AA is reset, the I2C interface cannot enter slave mode. STA, STO, and SI must be reset.

 

The master transmitter mode may now be entered by setting the STA bit. The I2C logic will now test the I2C-bus and generate a START condition as soon as the bus becomes free. When a START condition is transmitted, the serial interrupt flag (SI) is set, and the status code in the status register (STAT) will be 0x08. This status code is used by the interrupt service routine to enter the appropriate state service routine that loads DAT with the slave address and the data direction bit (SLA+W). The SI bit in CON must then be reset before the serial transfer can continue.

What I read out of that is: Set I2EN, set STA, SI Bit is set automatically after a start condition is sent.

 

I've tried this on another processor, and the problem still exists, which means it is either in the silicon, or in the software. 

 

The errata only mentions corrupted data in Monitor mode (which is odd, because monitor mode shouldn't affect the bus state).

 

Anybody else see this or have a workaround? Or am I just an idiot?

Outcomes