SCB_P4_v3_0 errata ID 295713

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

cross mob
WaPi_297581
Level 2
Level 2
Welcome! 5 questions asked First question asked

The component datasheet states that an error will occur "...if execution of the function is interrupted for a time longer than the restart condition, between setting the restart generation command and writing the address byte into the TX FIFO."  Can anyone elaborate on the details?

The datasheet also states that the workaround is to "Call the SCB_I2CMasterWriteBuf() function inside the critical section so it will not be interrupted when you need to execute a write transaction with a restart condition."  What is a "critical section"?  Can anyone elaborate on the details?  I need to be confident that I can avoid this problem.

0 Likes
1 Solution
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

> Are you aware of Cypress documentation that provides more elaboration on specific errata?

I'm sorry, but I'm not aware of.

> While the datasheet errata doesn't mention it, do you think this applies to SCB_I2CMasterReadBuf()?

I'm afraid that yes, it does.

> Reading data from a slave requires a "dummy" write before calling SCB_I2CMasterReadBuf() with "RESTART" for the mode.  The "read" portion of the transfer is a "RESTART"with the address following the restart condition.

Actually, generating "RESTART" as mode is included in "I2C_I2CMasterReadBuf()" of  I2C (SCB mode) [v4.0].

(Sorry, I don't have access to v3.0 but I'm assuming that they are about same.)

> Since the I2C is handled by interrupts, the i2c transfer doesn't work if the critical section is before the "dummy" write (with NO_STOP mode parameter) and after the SCB_I2CMasterReadBuf()  (with RESTART parameter).

Your are correct. So calling SCB_I2CMasterReadBuf() between CyEnterCriticalSection and CyExitCriticalSection is not a good idea.

The last part of "I2C_I2CMasterReadBuf()" is

======================

        /* Generate Start or ReStart */

        if(I2C_CHECK_I2C_MODE_RESTART(mode))

        {

            I2C_I2C_MASTER_GENERATE_RESTART;

            I2C_TX_FIFO_WR_REG = slaveAddress;

        }

        else

        {

            I2C_TX_FIFO_WR_REG = slaveAddress;

            I2C_I2C_MASTER_GENERATE_START;

        }

    }

    I2C_EnableInt();   /* Release lock */

    return(errStatus);

}

======================

So this function is not protecting the process from interrupt between "RESTART" and assigning I2C_TX_FIFO_WR_REG.

IMHO, this function will work for the "most" of the time,

but if your application is a mission critical one and can not fail anytime,

may be modifying the function something like below will take care of the problem.

==============

    uint8_t interrupt_status ;

        /* Generate Start or ReStart */

        if(I2C_CHECK_I2C_MODE_RESTART(mode))

        {

         interrupt_status = CyEnterCriticalSection() ; // disable interrupt and safe current interrupt status

            I2C_I2C_MASTER_GENERATE_RESTART;

            I2C_TX_FIFO_WR_REG = slaveAddress;

         CyExitCriticalSection(interrupt_status) ; // enable interrupt again

        }

        else

        {

==============

As usual, your mileage may vary and proceed at your own risk.

moto

View solution in original post

0 Likes
3 Replies
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

IMHO, the first section means that once restart condition is generated, the address byte must be written within a limited time.

But if there is/are interrupt with higher priority generated, it could block the I2C transaction longer than it can put up with.

So the second section means that for the critical operation, we can temporary disable interrupt so that the operation will not be disturbed by an interrupt.

To do this in PSoC Creator we can write

==============

    uint8_t interrupt_status ;

    interrupt_status = CyEnterCriticalSection() ; // disable interrupt and safe current interrupt status

    // do something important here such as SCB_I2CMasterWriteBuf()

    CyExitCriticalSection(interrupt_status) ; // enable interrupt again

==============

FYI, we can access I2C specification from

https://www.nxp.com/docs/en/user-guide/UM10204.pdf

moto

Are you aware of Cypress documentation that provides more elaboration on specific errata?

While the datasheet errata doesn't mention it, do you think this applies to SCB_I2CMasterReadBuf()? 

Reading data from a slave requires a "dummy" write before calling SCB_I2CMasterReadBuf() with "RESTART" for the mode.  The "read" portion of the transfer is a "RESTART"with the address following the restart condition.

Since the I2C is handled by interrupts, the i2c transfer doesn't work if the critical section is before the "dummy" write (with NO_STOP mode parameter) and after the SCB_I2CMasterReadBuf()  (with RESTART parameter).

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

> Are you aware of Cypress documentation that provides more elaboration on specific errata?

I'm sorry, but I'm not aware of.

> While the datasheet errata doesn't mention it, do you think this applies to SCB_I2CMasterReadBuf()?

I'm afraid that yes, it does.

> Reading data from a slave requires a "dummy" write before calling SCB_I2CMasterReadBuf() with "RESTART" for the mode.  The "read" portion of the transfer is a "RESTART"with the address following the restart condition.

Actually, generating "RESTART" as mode is included in "I2C_I2CMasterReadBuf()" of  I2C (SCB mode) [v4.0].

(Sorry, I don't have access to v3.0 but I'm assuming that they are about same.)

> Since the I2C is handled by interrupts, the i2c transfer doesn't work if the critical section is before the "dummy" write (with NO_STOP mode parameter) and after the SCB_I2CMasterReadBuf()  (with RESTART parameter).

Your are correct. So calling SCB_I2CMasterReadBuf() between CyEnterCriticalSection and CyExitCriticalSection is not a good idea.

The last part of "I2C_I2CMasterReadBuf()" is

======================

        /* Generate Start or ReStart */

        if(I2C_CHECK_I2C_MODE_RESTART(mode))

        {

            I2C_I2C_MASTER_GENERATE_RESTART;

            I2C_TX_FIFO_WR_REG = slaveAddress;

        }

        else

        {

            I2C_TX_FIFO_WR_REG = slaveAddress;

            I2C_I2C_MASTER_GENERATE_START;

        }

    }

    I2C_EnableInt();   /* Release lock */

    return(errStatus);

}

======================

So this function is not protecting the process from interrupt between "RESTART" and assigning I2C_TX_FIFO_WR_REG.

IMHO, this function will work for the "most" of the time,

but if your application is a mission critical one and can not fail anytime,

may be modifying the function something like below will take care of the problem.

==============

    uint8_t interrupt_status ;

        /* Generate Start or ReStart */

        if(I2C_CHECK_I2C_MODE_RESTART(mode))

        {

         interrupt_status = CyEnterCriticalSection() ; // disable interrupt and safe current interrupt status

            I2C_I2C_MASTER_GENERATE_RESTART;

            I2C_TX_FIFO_WR_REG = slaveAddress;

         CyExitCriticalSection(interrupt_status) ; // enable interrupt again

        }

        else

        {

==============

As usual, your mileage may vary and proceed at your own risk.

moto

0 Likes