I2C issues depending on Release/Debug(MKL02Z32)

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

I2C issues depending on Release/Debug(MKL02Z32)

1,060 Views
claeskjellstrom
Contributor III

Hi, I have been using the I2C code for couple of month and it has been working from time to time. The problem is that sometimes the I2C bus is busy and sometimes not after reset. It seems like when running in Release mode(-O0) it sends out correct number of clockpulses(SCL) so the bus is not busy, but when running in debug and halted in main() the SDA line is low(and sometimes not). Using -O0 optimization for both Release&Debug. I have three slaves on the bus(24LC02,LPS25HB and LSM6DS3). The application is a 4-20mA transmitter so I need to make sure that with no output signal the current need to be stable at 4mA. The outputsignal >4mA is controlled by PWM(1&2). I'm logging the output from LPS25HB on UART which has been working for month. The I2C code I'm using is from mma8451(Author: B34443) with some minor changes regarding dummy read, but main problem is that the bus is sometimes busy and sometimes not. Pullup 10K(both SCL and SDA) and bus speed ~100KHz.

void main(void)
{
__disable_irq();

BOARD_InitBootClocks();
DBG_Init();
IRQ_PORT_Init();
UART0_Init();
TPM1_Init();
I2C_Init();
SysTick_Init();

I2C init

void I2C_Init(void)
{
/* enable clock gate to module */
SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK;

/* PORTA3 (pin 5) is configured as I2C0_SCL */
PORTA->PCR[3U] = (PORTA->PCR[3U] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(2U);

/* PORTA4 (pin 6) is configured as I2C0_SDA */
PORTA->PCR[4U] = (PORTA->PCR[4U] & ~PORT_PCR_MUX_MASK) | PORT_PCR_MUX(2U);

/* set I2C0 in Master mode */
// I2C0->C1 = I2C_C1_MST_MASK;

/* set I2C to 2MHz/ 20 = 100KHz */
I2C0->F = 0U;

/* enable I2C */
I2C0->C1 = I2C_C1_IICEN_MASK;
}

Note: the clock gate enable to PORTA has been enabled previously in DBG_Init():

Normally the code stops at

 

void i2c_wait(I2C_Type *base)
{
// wait flag
while((base->S & I2C_S_IICIF_MASK)==0U);
// clear flag
base->S |= I2C_S_IICIF_MASK;
}

or

void pause(I2C_Type *base)
{
while(base->S & I2C_S_BUSY_MASK);
}

Using a J-link(segger)

Regards

Claes

Labels (1)
0 Kudos
4 Replies

974 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi claes kjellstrom,

 You can modify your external 10K pull up ressistor on I2C_SCL and I2C_SDA pin to 4.7k Pull up, as the internal pull up is weak.

  You mentioned, when you use the debug mode, some times, the I2C_SDA line is low, it caused the bus busy issues.

  Could you also please add some wave pictures about it? Whether it is pulled low by your slave or not?

  If it is always in the master phase, the busy happens, you can try to disconnect your slave, whether the pin still be pulled low or not?

  About the code, you also can try the SDK code for your KL02, which can be downloaded from this link:

  Welcome | MCUXpresso SDK Builder 

  Any updated information, please kindly let me know.

Best Regards,

Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

  

0 Kudos

974 Views
claeskjellstrom
Contributor III

Hi Kerry,

Just took a screendump and question is why is the bus busy ?. ->S TCF=1 and BUSY=1

Regards

Claes

I2C busy.png

0 Kudos

974 Views
kerryzhou
NXP TechSupport
NXP TechSupport

Hi claes kjellstrom

  Do you connect one I2C master and one I2C slave in the I2C bus, or connect more master or slaves?

  Or one KL02 as I2C master, three slaves on the bus(24LC02,LPS25HB and LSM6DS3)?

   You can leave only one slave on the I2C bus, whether you still meet the debug I2C busy issues?

  Please also check this post, it will useful to you:

I2C device dead-lock recovery 

  You can try the above post's solutions, whether it is useful to you or not.

  If you still have questions about it, please kindly let me know.

   

Best Regards,

Kerry

 

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

 

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

974 Views
claeskjellstrom
Contributor III

Hi Kerry,

I have verified with stronger pullups but can't see any differens, the big issue seems like when you are powering up the board during debug it will halt directly after main and the bus is busy, when application runs in release mode it will start to send and receive, however it might stop or it will run for days as I read the pressure and temperature from LPS25HB. Due to high current(17mA) I'm not using LSM6DS3(but it actually worked for days) so that IC is removed. I'm not using the eeprom but it's mounted on the board. The circuit board is small and very short traces to I2C so that is not an issue. Yes, I'm using MCUXpresso IDE + SDK 2.3.1 MKL02xx, and I try to avoid using any drivers since they manage to occupie to much flash, but I'm also aware of the risk of it, specially timing and handling error regarding I2C. It's difficult to accept that it has been working for days and now it's not and no changes on the hardware so far. Below is the main code all the way to the while loop.

void main(void)
{
__disable_irq();

BOARD_InitBootClocks();
DBG_Init();
IRQ_PORT_Init();
UART0_Init();
TPM1_Init();
I2C_Init();
SysTick_Init();

/* set position */
i2c.rx_buff_ptr = EE_BLOCK0;
/* read block 0, 8 bytes from address eeprom block 0 - 7 */
I2C_BlockRead(ADR_24LC02B, EE_BLOCK0, &i2c.rx_buff[i2c.rx_buff_ptr], EE_BLK_SIZE);

/* verify ram if eeprom formatted */
if(!(Verify_Eeprom(&i2c.rx_buff[EE_BLOCK0])))
{
/* init 8 bytes(1 page) */
Init_eeprom_var(EE_BLOCK0);
/* set tx pointer */
i2c.tx_buff_ptr = EE_BLOCK0;
/* write 8 cleared bytes to page 0 in eeprom */
I2C_BlockWrite(ADR_24LC02B, EE_BLOCK0, &i2c.tx_buff[i2c.tx_buff_ptr], EE_BLK_SIZE);
}
else
{
/* set position */
i2c.rx_buff_ptr = EE_BLOCK0;
/* read config from i2c buffer */
sens.cnf_sim = i2c.rx_buff[i2c.rx_buff_ptr++];
/* read offset pwm_2 */
Sens16.u8[0U] = i2c.rx_buff[i2c.rx_buff_ptr++];
Sens16.u8[1U] = i2c.rx_buff[i2c.rx_buff_ptr];
sens.offs_pwm2 = Sens16.u16;
}

/* set aligned pwm */
TPM1_Chn_Init(TPM_CHN1, ALIGNED_PWM);
TPM1_Chn_Init(TPM_CHN0, ALIGNED_PWM);
/* set 0% duty cycle */
Set_TPM1_CnV(TPM_CHN1, 0U);
Set_TPM1_CnV(TPM_CHN0, 0U);
/* tpm counter increments on every counter clock */
Start_TPM1_Count(CLK_INC);

/* send info to operator */
Uart_Tx_String(&F_msg1[0], true);
Uart_Tx_String(&F_msg2[0], true);
Uart_Tx_String(&F_msg3[0], true);

/* enable UART0 Interrupt */
NVIC_EnableIRQ(UART0_IRQn);
Enable_UART0_Rx_Irq();

/* init correct index */
uart.log_out = L_PRESS_LPS25;

/* setup measurement with LPS25HB */
Setup_LPS25HB();

/* start mode state */
Change_State(_INT1_LPS25HR, _ONE_TASK);

/* enable SysTick vector */
NVIC_EnableIRQ(SysTick_IRQn);

/* enable global irq flag */
__enable_irq();

//////////////////////////////////////////////////////////////////////////////////////
// Function : Main loop //
//////////////////////////////////////////////////////////////////////////////////////

while(1)
{
if(uart.cmnd_status & _NEW_CMND)
{
Disable_UART0_Rx_Irq();
Uart_Cmnd_Handler();
uart.cmnd_status &= ~_NEW_CMND;
uart.rx_ptr = 0U;
Enable_UART0_Rx_Irq();
}
else if(uart.cmnd_status & _RSP_CMND)
{
Uart_Tx_Char(uart.uart_txbuff[uart.tx_ptr++]);

if(uart.tx_ptr >= _UART_BUFF_SIZE)
{
uart.tx_ptr = 0U;
uart.cmnd_status &= ~_RSP_CMND;
}
}
}
}

Regards

Claes

0 Kudos