Is it possible to sleep during I2C transactions?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
user_1669321
Level 5
Level 5
100 replies posted 50 replies posted 25 replies posted

Hi,

I currently have some blocking I2C that runs perfectly on PSoC 4. I was wondering if it's possible to use the I2C interrupts instead and sleep between interrupts? According to AN86233, "All other peripherals and clocks continue to run" during sleep, so I'm assuming that it would be possible to sleep between the I2C transaction steps. However, My code is blocked in CySysPmSleep(). Here's my code for the I2C read:

// buf[0]: ADDRESS + W

// buf[1]: REG ADDRESS

int I2C_Read(unsigned char *buf, int bufSize) {

    uint32_t slaveAdr = (buf[0] >> 1) & 0x7F;

   

    // Sending Start and register

    if ( I2C_I2CMasterSendStart(slaveAdr, 0) != I2C_I2C_MSTR_NO_ERROR ) {

        return -1;

    }

    if ( I2C_I2CMasterWriteByte(buf[1]) != I2C_I2C_MSTR_NO_ERROR ) {

        return -1;

    }

    // Sending Restart and reading data

    I2C_I2CMasterReadBuf(slaveAdr, buf, bufSize, I2C_I2C_MODE_COMPLETE_XFER | I2C_I2C_MODE_REPEAT_START);

    while( !(I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT) ) {

        CySysPmSleep();

    }

   

    return bufSize;

}

The code for a Write is pretty similar. However, it's stuck at CySysPmSleep(). Is it possible at all to sleep between I2C interrupts?

Thank you,

Fred

0 Likes
1 Solution

What I got from reading the API code (I think) is that the flags from MasterStatus are set in the I2C interrupt, so upon waking up from sleep and servicing the I2C interrupt, the while loop condition should not be satisfied anymore.

Anyways, I got it working by reducing the speed of the I2C bus. I think maybe that the 1 byte transactions were done too fast, so by the time the CPU was at the CySysPmSleep() line, the I2C transaction was already done.

Thank you!

View solution in original post

4 Replies
himam_31
Employee
Employee
50 likes received 25 likes received 10 likes received

Any interrupt can wake the device from sleep.Exit from sleep mode occurs when an interrupt is triggered. Upon exiting sleep, PSoC re-enters active mode. The configuration of sleep wakeup sources requires only that their interrupts be enabled. I2C interrupts will be enabled by default.

Thanks,

Hima

0 Likes
user_1669321
Level 5
Level 5
100 replies posted 50 replies posted 25 replies posted

Thank you Hima.

So that tells me that my idea is correct, so there must be a problem with my code. Do you see something wrong with my approach? Am I using the wrong API functions?

Fred

0 Likes
Anonymous
Not applicable

From a code perspective:

// Sending Restart and reading data

    I2C_I2CMasterReadBuf(slaveAdr, buf, bufSize, I2C_I2C_MODE_COMPLETE_XFER | I2C_I2C_MODE_REPEAT_START);

    while( !(I2C_I2CMasterStatus() & I2C_I2C_MSTAT_RD_CMPLT) ) {

        CySysPmSleep();

    }

Looks like it will just try to go back to sleep on waking up? The CPU resumes execution at the instruction after where it went to sleep, so in your case the CPU will wake up at the end of the while loop, and will proceed to check the while loop conditions. If these are still true, then it will go back to sleep. And, unless I2C_I2CMasterStatus() or I2C_I2C_MSTAT_RD_CMPLT are getting set between the end of the while loop and the CySySPmSleep() call, then the unit will just sit in the while loop forever.

0 Likes

What I got from reading the API code (I think) is that the flags from MasterStatus are set in the I2C interrupt, so upon waking up from sleep and servicing the I2C interrupt, the while loop condition should not be satisfied anymore.

Anyways, I got it working by reducing the speed of the I2C bus. I think maybe that the 1 byte transactions were done too fast, so by the time the CPU was at the CySysPmSleep() line, the I2C transaction was already done.

Thank you!