[EDIT] Fixed the problem. Turns out I needed to enable the SION bit in the IOMUX configuration.
/* FIXED */
Got my custom i.MXRT1051 board up and running (600 MHz, Rev. A1 silicon) and now troubleshooting LPI2C1 configured on pins GPIO_AD_B1_00 (SCL) and GPIO_AD_B1_01 (SDA).
The problem is that after issuing the start bit, the device's I2C address is not sent. The I2C clock continues indefinitely but the 4 octet FIFO never shifts out data. The device's I2C address has been verified to make its way through the function calls and is indeed a part of the MTDR register (verified by copying to a 32-bit intermediate register and snooping with the debugger before being written to MTDR).
Baud rate is programmed to be 100 kbps and actual rate comes in at about 98 kbps, so the baud rate and divisors appear to be working properly.
Upon issue of the first programming command for the CODEC, the LPI2C1 module (MCUXpresso) issues a start condition on the I2C line. The SDA line drops for one bit time and then returns high, and the SCL clock line continues ad infinitum--no device address is sent out the SDA line following the I2C start bit.
Tracking through the code with the debugger shows propagation through the I2C state machines until we get to the
LPI2C_MasterStop function at which time the stop bit never is issued. Status code from LPI2C_MasterGetStatus() is 0x3000000 which is BBF | MBF flags. Stop is waiting for 0x200 flag. I've turned on a timeout mechanism so that my code doesn't get hung up.
In general, the FIFO doesn't transmit data out, so after two such calls the 4-octet FIFO becomes full and then no further state machine propagation happens. But for the first two (2-byte) transactions, the SCL line repeats forever and the only bit visible on SDA is the initial start bit, then SDA remains HIGH while SCL toggles.
My LPI2C_MasterGetDefaultConfig initializer is configured as:
masterConfig->enableMaster = true;
masterConfig->debugEnable = true;
masterConfig->enableDoze = true;
masterConfig->ignoreAck = false;
masterConfig->pinConfig = kLPI2C_2PinOpenDrain;
masterConfig->baudRate_Hz = 100000U;
masterConfig->busIdleTimeout_ns = 0;
masterConfig->pinLowTimeout_ns = 0;
masterConfig->sdaGlitchFilterWidth_ns = 0;
masterConfig->sclGlitchFilterWidth_ns = 0;
masterConfig->hostRequest.enable = false;
masterConfig->hostRequest.source = kLPI2C_HostRequestExternalPin;
masterConfig->hostRequest.polarity = kLPI2C_HostRequestPinActiveHigh;
The initializer code automatically negates the enableDoze flag to make it 0 when putting it in the configuration register. I'm only using two-wire I2C mode.
FWIW code is copied from Flash into ITCM and DTCM memories. Also, I've disabled both ITCM and DTCM caches (although only DTCM cache I disabled if I'm not using the debugger). The variables are all stored in DTCM and appear to be working properly.
Can anyone think of why the device I2C address won't get set on the initial push of the start bit or why the FIFO won't transmit any data out? I think I've enabled the clock gates as expected. Also, my clock source is USB1PLL and has been configured for 10 MHz for I2C. The divisor in the clock_config is originally 0 (/1) and the prescaler is /8 giving an I2C base clock of 60 MHz if I don't override the divisor to 6 yielding a 10 MHz I2C base clock. I've also tried using a 60 MHz base clock with exactly the same results.
Thoughts? Thanks in advance.
--Scott Thompson, TC Helicon