8 Replies Latest reply on Feb 25, 2020 6:49 AM by LePo_1062026

    PSoC5LP : Clock of fixed function I2C componnent

    MaMi_1205306

      Hi,

       

      We use fixed function I2C slave component of PSoC5LP.

       

      1) Place I2C Slave ( fixed function ) component in PSoC Creator.

      2) Set the data rate to 100 ksps.

      3) Set the BUS_CLK ( CPU ) and MASTER_CLK to 24MHz.

       

      It works normally after the build.

       

      However, while the CPU is running,
      Switch 24MHz of CPU_CLK to 3MHz by using API.

       

      Then, the following events were confirmed.

       

      -- I2C data rate becomes 12.5kbps ( = 100kbps / 8 )

      -- In I2C communication, Communication fails if 4 bytes or more data is read at a time. ( Communication successful up to 3 Bytes )

       

      Is the above recognition correct?
      Do you have a way to improve these?

       

      Regards,

        • 1. Re: PSoC5LP : Clock of fixed function I2C componnent
          LePo_1062026

          MaMi,

           

          It appears your I2C clock is derived from the BUS_CLK (or MASTER_CLK).  When you reduce the BUS_CLK by a factor of 8, you end up reducing the SPI clock by the same factor.

           

          There are two ways to prevent this.  One way requires a little SW and the other is only at compile-time.

           

          If you are willing to share your project, I can directly help.

           

          If not, the SW method is to change the I2C clock divider value using I2C_SetDivider(uint16 clkDivider).

          Perform the following steps:

          uin32_t clockval;
          // Read the I2C clock divider value. 
          clockval = I2C_GetDividerRegister();  // the value is the actual divider value -1
          clockval += 1;    // adjust to correct for the value -1
          clockval *= 8;    // scale the clock back up to 100 Kbps when using BUS_CLK = 3MHz
          clockval -= 1;    // re-adjust it back to value-1
          // Set this adjusted value in the I2C clock
          I2C_SetDivider(clockval);    // You should be back to 100 Kbps
          

           

          The other way involves sourcing the I2C clock from the MASTER_CLK (@ 24MHz) and leaving it at 24MHz.  This way, the I2C clock remains at 100 Kbps.

          Use the API call CyBusClk_SetDivider() to change the BUS_CLK divider to scale the BUS_CLK from 24MHz to 3 MHz by setting divider value to 8-1.

           

          Len

          1 of 1 people found this helpful
          • 2. Re: PSoC5LP : Clock of fixed function I2C componnent
            MaMi_1205306

            Len-san,

             

            We would like to conrifm two points.

             

            1.

            In I2C communication, Communication fails if 4 bytes or more data is read at a time. ( Communication successful up to 3 Bytes )

             

            Do you have comments on the above issue.

            Do you think this behavior is due to a clock drop?

             

            2.

            You say that :

            The other way involves sourcing the I2C clock from the MASTER_CLK (@ 24MHz) and leaving it at 24MHz.  This way, the I2C clock remains at 100 Kbps.

             

            We think that the clock source of fixed function I2C is fixed to the bus clock. See the image below.

             

            Regards,

            • 3. Re: PSoC5LP : Clock of fixed function I2C componnent
              LePo_1062026

              MaMi.

              1.

              In I2C communication, Communication fails if 4 bytes or more data is read at a time. ( Communication successful up to 3 Bytes )

               

              Do you have comments on the above issue.

              Do you think this behavior is due to a clock drop?

              What I2C Rx status are you using to determine when to read the 4 bytes?  I've looked at the I2C component.  There does not appear to have a 4 byte FIFO (or any FIFO) as part of the Rx data.  Instead you have to initialize the data buffer location to store the incoming data using I2C_SlaveInitWriteBuf().

               

              Are you using I2C_SlaveGetWriteBufSize() to make sure that 4 bytes are in the buffer before trying to read it?   If the I2C clock is reduced by 8 times, then it will take 8 times longer to transfer the 4 bytes than if the I2C was at full speed (100Kbps).

               

              Depending on what you are using to determine the time to read 4 bytes, it may not be correct.  Using the I2C_SlaveGetWriteBufSize() will determine if 4 bytes are in the buffer for you to read.  Additionally you need to perform a  I2C_SlaveClearWriteBuf() after reading the required bytes to clear the buffer count.

              2.

              You say that :

              The other way involves sourcing the I2C clock from the MASTER_CLK (@ 24MHz) and leaving it at 24MHz.  This way, the I2C clock remains at 100 Kbps.

              You are correct.  This is probably because you are using the Fixed Function version of I2C or the UDB version with the internal clock.  If you change the I2C configuration to UDB with external clock, you can control the input clock source.

              Configure the external I2C clock like this:

              This way the I2C component will be sourced from the MASTER_CLK (always at 24MHz) and will have the required clock frequency of 1.6MHz to clock the datarate at 100Kbps.

               

              Len

              • 4. Re: PSoC5LP : Clock of fixed function I2C componnent
                MaMi_1205306

                Len-san,


                Thank you for your reply.

                 

                I would like you to additionally tell us about 1.

                 

                Before changing the clock, continuous reading of 4 bytes is possible.
                If you change the clock from 24MHz to 3MHz,
                An error occurs when reading 4 bytes continuously (normal up to 3 bytes, 4 bytes error).

                This behavior was the same not only for fixed function I2C but also for UDB based I2C.

                Did you see a reproduction of the behavior of this issue?

                 

                Regards,

                • 5. Re: PSoC5LP : Clock of fixed function I2C componnent
                  LePo_1062026

                  You're welcome MaMi.

                   

                  As part of my reply regarding 1. I asked:

                  What I2C Rx status are you using to determine when to read the 4 bytes?  I've looked at the I2C component.  There does not appear to have a 4 byte FIFO (or any FIFO) as part of the Rx data.  Instead you have to initialize the data buffer location to store the incoming data using I2C_SlaveInitWriteBuf().

                   

                  Are you using I2C_SlaveGetWriteBufSize() to make sure that 4 bytes are in the buffer before trying to read it?   If the I2C clock is reduced by 8 times, then it will take 8 times longer to transfer the 4 bytes than if the I2C was at full speed (100Kbps).

                  I never received a reply from you.   In general, you need some feedback from the I2C component whether there are 4 bytes in the Rx buffer.  This is true whether you are transferring at 100Kbps (CPU @ 24MHz) or at 12.5 Kbps (CPU @ 3MHz).

                   

                  Len

                   

                  PS:  If you are willing to share your project, I can be more specific to your issue.

                  • 6. Re: PSoC5LP : Clock of fixed function I2C componnent
                    MaMi_1205306

                    Len-san,

                     

                    The usage was corrected. Excuse me.

                     

                    This fixed function I2C used was a "master setting", "not a slave".

                    The following API is used to read data.

                    I2C_MasterReadBuf (uint8 slaveAddress, uint8 * rdData, uint8 cnt, uint8 mode)

                     

                    Before the above call, I2C_DisableInt () and I2C_MasterClearStatus () are executed.

                     

                    The usage of the I2C_MasterReadBuf () function is the method described in the Code Example.

                     

                    When you change the 24MHz of master clock to 3MHz,

                    Could you confirm whether this API does not work properly?

                     

                     

                    The following are not directly called and used.

                    I2C_SlaveInitWriteBuf ()

                    I2C_SlaveClearWriteBuf ()

                     

                    Regards,

                    • 7. Re: PSoC5LP : Clock of fixed function I2C componnent
                      LePo_1062026

                      MaMi,

                       

                      I'm confused.  Your first post said:

                      We use fixed function I2C slave component of PSoC5LP.

                       

                      1) Place I2C Slave ( fixed function ) component in PSoC Creator.

                      2) Set the data rate to 100 ksps.

                      3) Set the BUS_CLK ( CPU ) and MASTER_CLK to 24MHz.

                      Yet your last post said:

                      This fixed function I2C used was a "master setting", "not a slave".

                      The following API is used to read data.

                      Which is it?

                       

                      If it happens to be that the PSoC5 I2C fixed function block is acting as a Master, what is the Slave?  Is it another PSoC?

                       

                      If the slave is not a PSoC and not under your control, my understanding is that normally the I2C peripherals are clocked at 100KHz and if acceptable to both ends they can be clocked faster.

                       

                      If you have NO CONTROL of the Slave and you change from MASTER_CLK = 24MHz (I2C clock = 100KHz) to MASTER_CLK = 3MHz (I2C = 12.5KHz), the Slave may not like it due to its SW implementation.  It might be timed improperly and is expecting the last byte of I2C data from the Master to be completed sooner than it actually is.

                       

                      If you have to switch the PSoC CPU clock from 24MHz to 3MHz, please take one of my previous suggestions.  For example, clock the I2C FF block from the MASTER_CLK (always at 24MHz) and change the BUS_CLK divider from  divide by 1 to divide by 8.

                       

                      Len

                      • 8. Re: PSoC5LP : Clock of fixed function I2C componnent
                        LePo_1062026

                        MaMi,

                         

                        I hope all is well with you.   I haven't seen a response from you in a week.

                         

                        Let me try to answer another question of yours.

                        When you change the 24MHz of master clock to 3MHz,

                        Could you confirm whether this API does not work properly?

                        I don't have any I2C peripherals.  I tend to use SPI peripherals.  However in either case, I2C or SPI are synchronous serial protocols. This means that the data and clock are separate signals.   Each data bit is clocked.  When I converted a SPI component to I2C component in a previous project, I also set the I2C master clock to 24MHz.  The oscilloscope I am using can decode the I2C (or SPI) data and clock and the output is as expected.

                        When I set the I2C master clock to 3 MHz, the output was 8 times slower but still correct.  Therefore, I would say the API is working as specified.

                         

                        You can do something similar if you have a oscilloscope.  You don't need to have it decode the I2C.  You can decoded it by "eye".  The output should be identical except the 3MHz will be 8 times slower.

                         

                        Theory #1

                        I suspect that the I2C slave peripheral you are using is effectively dropping the last byte of 4 bytes because it is taking too long to transmit.  It is probably timing out because it is expecting the data to be transmitted at 100Kbps instead of 12.5Kbps at 3MHz clock.

                         

                        What is the I2C slave peripheral you are using?  What is the part #?

                         

                        Theory #2

                        It could be possible that something in your PSoC SW is aborting the last byte of transmission as the I2C master.  I can't know if this is the case without you sharing your project.

                         

                        I'm trying to help as much as I can, but I'm lacking your project specifics to be more accurate.

                         

                        Len