This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1310: Proper I2C slave module reset sequence for cc13xx/cc26xx

Part Number: CC1310

I am using cc1310 with Contiki OS, and are currently working with the MCU acting as an I2C slave.

We want to be able to handle unpredictable scenarios as e.g. described in processors.wiki.ti.com/.../I2C_Tips by resetting the I2C slave module. It seems we are able to reproduce such a type of issue by having the master device request data and not put any data in the SDR register for cc1310 to reply. In this case it seems the cc1310 will clock stretch indefinitely - and the only reliable way we found to get out of it is a reboot(!).

Does anyone have any suggestions on a proper reset sequence for the i2c slave module? Our current unsuccessful attempt:

I2CSlaveIntDisable(INT_I2C_IRQ);
I2CSlaveIntDisable(I2C0_BASE, interrupt_flags);

I2CSlaveDisable(I2C0_BASE);

PRCMPeripheralRunDisable(PRCM_PERIPH_I2C0);
PRCMPeripheralSleepDisable(PRCM_PERIPH_I2C0);
PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_I2C0);
PRCMLoadSet();
while(!PRCMLoadGet());

IOCPinTypeGpioInput(I2C_SLAVE_SDA_PIN);
IOCPinTypeGpioInput(I2C_SLAVE_SCL_PIN);
IOCIOPortPullSet(I2C_SLAVE_SDA_PIN, IOC_NO_IOPULL);
IOCIOPortPullSet(I2C_SLAVE_SCL_PIN, IOC_NO_IOPULL);

And then the reverse to bring it back up.

Regards,

Andreas

  • Hi,

    this code

    PRCMPeripheralRunDisable(PRCM_PERIPH_I2C0);
    PRCMPeripheralSleepDisable(PRCM_PERIPH_I2C0);
    PRCMPeripheralDeepSleepDisable(PRCM_PERIPH_I2C0);
    PRCMLoadSet();
    while(!PRCMLoadGet());

    will not really switch off the I2C peripheral, but just disable the clock for this module. So the module is frozen, but not powered off and hence, the register values remain. The power management design on the CC13xx/CC26xx does not allow to explicitly power-cycle peripherals, but only whole power domains. Figure 6-1 in the TRM illustrates that.

    So you would need to power-cycle the serial power domain with the following code:

    ti_lib_prcm_power_domain_off(PRCM_DOMAIN_SERIAL);
    while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) 
        != PRCM_DOMAIN_POWER_OFF)) {}
    
    ti_lib_prcm_power_domain_om(PRCM_DOMAIN_SERIAL);
    while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) 
        != PRCM_DOMAIN_POWER_ON)) {}
    

    But that brings you into trouble when using UART or SPI at the same time.

  • Thanks for you input Richard. I did actually try the power domain exactly as you suggest earlier, but as you mention, it is not very graceful towards UART and SPI. I really was hoping to avoid this approach + patch a recovery for UART and SPI. Is this a borderline bug - is it not reasonable to expect I2CSlaveDisable() + I2CSlaveEnable() to reset any logical states in the module? In any case, do you see any other solution here? Some register we can safely reset e.g.?