I3C SDA and SCL pin configured for Pullup Enabled, but output stays low

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

I3C SDA and SCL pin configured for Pullup Enabled, but output stays low

871 Views
aberger
Contributor V

I am using the FRDM-MCXA153 board and have routed I3C0_SDA to pin 2  (Port1, Pin8) and I3C0_SCL to pin 3 (Port1, Pin9). Using Config Tools, I have configured the SDA and SCL pins as follow

Slew Rate = Fast
Open Drain = Enabled
Drive Strength = Low
Drive Strength 1 = Normal
Pull select = Pullup
Pull enable = Enabled
Passive filter = Disabled
(and for SDA, Pull value = Low)

(Generated code in pin_mux.c for I3C0_SDA is shown below)

 

 

 /* PORT1_8 (pin 2) is configured as I3C0_SDA */
    PORT_SetPinMux(BOARD_INITPINS_BMS2_SDA_PORT, BOARD_INITPINS_BMS2_SDA_PIN, kPORT_MuxAlt10);

    PORT1->PCR[8] =
        ((PORT1->PCR[8] &
          /* Mask bits to zero which are setting */
          (~(PORT_PCR_PS_MASK | PORT_PCR_PE_MASK | PORT_PCR_PV_MASK | PORT_PCR_ODE_MASK | PORT_PCR_IBE_MASK)))

         /* Pull Select: Enables internal pullup resistor. */
         | PORT_PCR_PS(PCR_PS_ps1)

         /* Pull Enable: Enables. */
         | PORT_PCR_PE(PCR_PE_pe1)

         /* Pull Value: Low. */
         | PORT_PCR_PV(PCR_PV_pv0)

         /* Open Drain Enable: Enables. */
         | PORT_PCR_ODE(PCR_ODE_ode1)

         /* Input Buffer Enable: Enables. */
         | PORT_PCR_IBE(PCR_IBE_ibe1));

 

 

I can view the peripheral register at runtime and see that both pins are configured as expected:

aberger_1-1722357571195.png

However, the pin outputs remain low. (I am measuring the voltage levels on the Arduino Header J2-20 and J2-18 on the demo board). 

I am trying to use the I3C peripheral to communicate with I2C devices, so the following I3C Initialization routine runs after BOARD_InitPins() is called in my main():

 

#include "fsl_i3c.h"

#define I2C_BAUD_HZ 100000U
#define I3C_PPBAUD_HZ 4000000U

void I3cKinetis::Configure(void) 
{
    uint32_t clockFreqHz = CLOCK_GetFreq(kCLOCK_CoreSysClk); // 96 MHz

    i3c_master_config_t fslConfig;
    I3C_MasterGetDefaultConfig(&fslConfig);

    // Configure for I2C
    fslConfig.disableTimeout = true;
    fslConfig.hKeep = kI3C_MasterPassiveSDASCL;
    fslConfig.enableOpenDrainHigh = false;
    fslConfig.enableOpenDrainStop = true;
    fslConfig.baudRate_Hz.i2cBaud = I2C_BAUD_HZ ;
    // For now, just use the i2c baudrate for opendrain baudrate
    fslConfig.baudRate_Hz.i3cOpenDrainBaud = I2C_BAUD_HZ ;
    // but the Push-Pull baudrate is given by
    // clockFreqHz/(2*(PPBAUD + 1).
    // where PPBAUD must be an integer between [0, 15].
    // So the Push-Pull baudrate can't be slower than
    // clockFreqHz/(2*16)
    fslConfig.baudRate_Hz.i3cPushPullBaud = I3C_PPBAUD_HZ ;

    I3C_MasterInit(I3C0, &fslConfig, clockFreqHz);
}

 

 

Are there extra steps I need to take to configure the I3C pins for open drain, with pull-up?

0 Kudos
Reply
11 Replies

838 Views
HangZhang
NXP Employee
NXP Employee

Hi @aberger 

You can download the MCXA153 SDK from the NXP official website.

Select Board | MCUXpresso SDK Builder (nxp.com)

HangZhang_0-1722415500492.png

In SDK_2_16_000_FRDM-MCXA153\boards\frdmmcxa153\driver_examples\i3c,
there are i3c examples.
there are pin config in the example, you can refer to it.

Hope this will help you.

BR

Hang

0 Kudos
Reply

820 Views
aberger
Contributor V

This isn't actually helpful. I took a look at the "i3c_polling_b2b_transfer_master" example. Even though it claims to first execute a transfer in I2C mode, the pins are not configured for Open Drain (with Pullup Enabled). Without Open Drain, I cannot communicate with a target device that requires support for clock stretching. So my question remains: how to actually get the I3C pins configured for Open Drain, with Pullup Enabled

(I will note that Config Tools did succeed at configuring I2C pins for Open drain, with Pullup Enabled. I don't understand why the same configuration, specified in the routing details for the I3C pins, does not achieve Open Drain behavior). 

aberger_0-1722461739231.png

 

0 Kudos
Reply

788 Views
HangZhang
NXP Employee
NXP Employee

Hi @aberger 

I understand your question.
During pin initialization, there is no need to configure open drain mode. Because this has already been implemented inside the chip, you don't need to worry.
If you want to test the open drain status, you need to test it when transmitting data.

BR

Hang

0 Kudos
Reply

676 Views
aberger
Contributor V

As mentioned in the original post, measurement of the I3C pins on an oscilloscope shows that they remain LOW even after the pin initialization is executed (with Open Drain, and Pullup enabled). As a result, when I try to execute a transfer, I3C_MasterTransferBlocking returns kStatus_I3C_Busy (because the masterState was detected to be kI3C_MasterStateSlvReq, i.e. slave holding SDA low). However, I believe that it is not the slave holding SDA low, but that the MCXA has failed to configure the I3C pins as open drain (both SDA and SCL remain low).

I've attached a minimum working example. 

I noticed that the i3c_master_enable_t included in fsl_i3c.h does not include an enumeration for I2C Controller mode (MSTENA = 0b11). Is this a problem?

Lastly, the description of I2CBAUD in the Reference Manual with regards to how the I2C baudrate is calculated is quite unclear. From the manual:

I2C Baud Rate

Specifies the I2C low and high times in ODBAUD counts:

  • I2CBAUD >> 1 is the main count load, and it is count - 1. So, I2CBAUD >> 1: I2CBAUD = 0 for one ODBAUD beat and I2CBAUD = 1 for two ODBAUD beats.
  • If I2CBAUD[28] is 1, then the low time has one extra ODBAUD beat. The I2CBAUD field is normally 3, where ODBAUD gives 200 ns. For I2CBAUD >> 1, I2CBAUD = 1, which means two ODBAUD beats. To meet the requirements for Fast-mode Plus (Fm+), (2 + 1) * 200 = 600 ns low, with 2 * 200 = 400 ns high for 1 μs period. For Fast mode (Fm), I2CBAUD is normally 11 (giving 2.6 μs) or 6 (giving 2.4 μs).

Should I understand this to mean the following:

T_low_I2C = ((I2CBAUD >> 1) + 1 + (I2CBAUD & 0x1)) * T_ODBAUD

T_high_I2C = ((I2CBAUD >> 1) + 1) * T_ODBAUD

which implies:

T_I2C = (2 + 2*(I2CBAUD >> 1) + (I2CBAUD & 0x1)) * T_ODBAUD

This works for the example of I2CBAUD = 11, but not for I2CBAUD = 6. However, in the attached project I have configured the following:

  • FCLK = 24 MHz (I3CFCLKDIV = 4)
  • Push-Pull baudrate = 2 MHz
  • Open-Drain baudrate = 500 kHz
  • I2C baudrate = 100 kHz

I can see from the Peripherals that

  • PPBAUD = 5
  • ODBAUD = 3
  • I2CBAUD = 8

Since the I2C baudrate is 5x slower than the OD baudrate, this suggests that 

T_I2C = ((I2CBAUD >> 1) + 1) * T_ODBAUD

But this calculation doesn't agree with any of the examples in the Reference Manual.

Can you help me understand where my calculation is wrong so that I may figure out the I2CBAUD settings (and related clock frequencies and divisors) necessary for my application (which requires an I2C baudrate of 100 kHz)?

 

0 Kudos
Reply

611 Views
HangZhang
NXP Employee
NXP Employee

Hi @aberger 

1. You can try measuring this pin through an oscilloscope when sending commands or data.

2.  When you use the I2C, you can use kI3C_TypeI2C,

HangZhang_0-1723444156711.png

3. 

• FCLK = 24 MHz, I3CFCLKDIV = 4
• Push-Pull baudrate = 2 MHz (PPBAUD = 5)
• Open-Drain baudrate = 500 kHz (ODBAUD = 3)
• I2CBAUD = 8
ODBAUD calculation:

TODBAUD = 1/500kHz = 2us.

Tlow_I2c = (8/2 + 1 +0) *2 us = 10 us

Thigh_i2c = (8/2 + 1)*2 = 10us,

Ti2c = 10 +10 = 20 us

So the Fi2c = 50kHz.

This means that with I2CBAUD = 8, your I2C clock frequency would be 50 kHz, which is different from the expected 100 kHz. To achieve a 100 kHz I2C clock, you would need to adjust the I2CBAUD value accordingly.

BR

Hang

0 Kudos
Reply

596 Views
aberger
Contributor V

Hi @HangZhang ,

1. This is precisely what I am doing: measuring the I3C pins (P1_8 and P1_9) with an oscilloscope when sending commands or data. See the previously attached project. Upon execution of BOARD_InitBootPins(), the pins remain held low (unexpected behavior). Upon execution of I3cSendCommand() (which is configured to send with a busType of kI3C_TypeI2C),  I3C_MasterTransferBlocking() returns early with a kStatus_I3C_Busy because the masterState was detected as kI3C_MasterStateSlvReq ("slave holding SDA low"). So the pins are never released to an open drain and pulled high.

2. I am using kI3C_TypeI2C. See the definitions of I3cSendCommand() and I3cRecieve().

3. I agree with your calculation, based on my reading of the reference manual. However, Config Tools shows that the Requested and Calculated I2C baud are both 100 kHz:

aberger_0-1723479794712.png

Maybe Config Tools is just wrong here. But since I can't actually get a command to send in the example project, I cannot see the CLK line on a scope to measure the actual frequency for I2CBAUD = 8. 

Furthermore, using the same algorithm, the example from the Reference Manual with T_OD = 200 ns, I2CBAUD = 6 does not work using the algorithm you described. The manual claims this will provide an I2C period of 2.4 µs

aberger_1-1723480102804.png

Instead, the algorithm that we identified above yields:

T_OD = 200 ns

T_low_i2c = 800 ns

T_high_i2c = 800 ns

T_i2c = 1.6 µs

f_i2c = 625 kHz

So something is wrong with either the our algorithm, the Reference Manual, Config Tools, or the firmware algorithm itself. 

0 Kudos
Reply

544 Views
HangZhang
NXP Employee
NXP Employee

Hi @aberger 

I tested the P0_16 and P0_17 in i3c_polling_b2b_transfer through oscilloscope. when transfer the command and data. The SDA is high.

I have attached an oscilloscope image.

HangZhang_0-1723691033118.png

It can work.

And i tested the P1_8 and P1_9, it can not work.

You can check the schematic,

HangZhang_0-1723700958729.png

P0_16 has connected a pull-up resistor, and P1_8 has not connected a pull-up resistor.

So if you want to use the P1_8 as the SDA function,

you need to connect a pull-up resistor.

BR

Hang

 

0 Kudos
Reply

532 Views
aberger
Contributor V

Then what is the point of the internal pull-up configuration for the I3C pins?

aberger_0-1723738125378.png

The Data Sheet states that the pullup for I3C pins is 1.75 kOhm. 

aberger_1-1723738169747.png

Furthermore, I will reiterate than when routing the I2C pins LPI2C0_SDA to P1_8 and LPI2C0_SDA to P1_9 with Open drain, and Pullup Enabled, those lines are pulled high without the need for external pullup resistors. I still don't understand why the same configuration, specified in the routing details for the I3C pins, does not achieve Open Drain behavior. 

0 Kudos
Reply

525 Views
aberger
Contributor V

I'll also add that the operation shown here (https://community.nxp.com/t5/MCX-Microcontrollers/I3C-SDA-and-SCL-pin-configured-for-Pullup-Enabled-...) only demonstrates that SDA is open-drain and using the pull-up resistor. I need the SCL to be open-drain as well to permit clock-stretching by the target device. In your oscilloscope capture, the SCL is clearly push-pull. However, the Reference manual clearly states that clock-stretching is supported by the I3C peripheral.

aberger_0-1723739265667.png

However, perhaps the highlighted sentence means that the internal pull-ups are not sufficient when operating in MSTENA = 11b (I2C Controller mode)?

Furthermore, your solution only demonstrates that SDA is open-drain and using the pull-up resistor. I need the SCL to be open-drain as well to permit clock-stretching by the target device. In your oscilloscope capture, the SCL is clearly push-pull. The Reference manual clearly states that this is supported.

aberger_0-1723739265667.png

However, perhaps the highlighted sentence means that the internal pull-ups are not sufficient when operating in MSTENA = 11b (I2C Controller mode)? If so, it should be clearly stated somewhere that external pullups are necessary for I2C support when using the I3C peripheral.

0 Kudos
Reply

490 Views
HangZhang
NXP Employee
NXP Employee

Hi @aberger 

1. SCL can automatically switch between open drain mode and push pull mode.

HangZhang_0-1723796537653.png

2. As you said, external pullups are necessary for I2C support when using the I3C peripheral.

In i3c circuit design, it is usually necessary to maintain compatibility with i2c circuits, as shown in the schematic diagram, which defaults to i3c functionality. When i2c connection is required, R59 needs to be removed and R61 and R62 need to be installed.

HangZhang_1-1723796607291.png

BR

Hang

0 Kudos
Reply

670 Views
aberger
Contributor V

I'll quickly add that if the pins in question (P1_8 and P1_9) are configured as GPIO Inputs, Open Drain, Pullup Enabled, then *they do get pulled high* upon execution of the BOARD_InitBootPins() routine at the top of main().

0 Kudos
Reply