Skip to content

r_iic_master: external I2C STOP triggers I2C_MASTER_EVENT_xX_COMPLETE before actual transmission #414

@sierraatomic

Description

@sierraatomic

Tested on R7FA4E10B2CFM.

Preparation:
r_iic_master is opened (p_api->open) and in result STIE/SPIE interrupts are disabled (iic_master_open_hw_master)

Bug trigger:
If another master (or an EMI event) changes the SDA line state (easily simulated by grounding SDA to GND for a moment), the IIC module will silently (because SPIE interrupt is disabled) detect the I2C stop and set ICSR2_b.STOP flag.

Effects:

  1. User attempts (for example) to read data by calling p_api->read
  2. In iic_master_run_hw_master STIE, SPIE interrupts will be enabled.
  3. Since the ICSR2_b.STOP flag is set, this will trigger the eri interrupt
  4. iic_master_err_master will detect the IIC_MASTER_ERR_EVENT_STOP flag and send I2C_MASTER_EVENT_RX_COMPLETE to the user before receiving any data
  5. iic_master_err_master will also disable STIE/SPIE interrupts
  6. iic_master_rxi_master will continue receiving data in the background (user application will assume the transfer has already completed) and (if the data buffer was on the stack) will corrupt the memory
  7. After all data has beed transferred, iic_master_rxi_master will send an I2C STOP, which will set (again) silently (because SPIE interrupt is disabled) the ICSR2_b.STOP flag
  8. Bug is triggered again and is ready to affect a new transfer

Temporary walkaround:
My quick fix is to check before each p_api->read/p_api->write call if the ICSR2_b.STOP flag is set and clear it.
It will limit the bug trigger window to time between p_api->read/p_api->write call and
p_ctrl->p_reg->ICIER = IIC_MASTER_INTERRUPT_ENABLE_INIT_MASK | R_IIC0_ICIER_STIE_Msk | R_IIC0_ICIER_SPIE_Msk; line in iic_master_run_hw_master.

Additional comment:
This walkaround is not ideal, because this bug can be also triggered by EMI event during transmission.
In my opinion additional checks should be implemented in iic_master_err_master to check if IIC_MASTER_ERR_EVENT_STOP is valid (all data has been transferred) before sending the I2C_MASTER_EVENT_xX_COMPLETE event to the user app.
If the IIC_MASTER_ERR_EVENT_STOP is invalid - abort the transmission (including sending the I2C_MASTER_EVENT_ABORTED event to the user app because transferred data is potentialy damaged).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions