3 Replies Latest reply on Mar 30, 2020 2:34 AM by RakshithM_16

    I2C problem with FRAM



      I am working on a CY8C3866AXI-040 dev kit, and trying to create an I2C communication with an external Cypress FerroRAM (and an external EEPROM too). I have already watched all the default example codes of Cypress about I2C. In the following code, I send 8 byte to the FRAM, then try to request these bytes from it. All 3 commands seems to be succeeded, because I got master status 0. But I can't see the result. The read buffer remains its original content. What is wrong in my code?
      (The hardware set up and the I2C configuration in the top design: (UDB, internal clock source, 100 kbps) are OK.

      Thank you for your answers.


      #define I2C_DATA_CNT 8u
      #define I2C_WR 0u
      #define I2C_RD 1u
      uint8 mr_status;
      uint8 dev_sel = 0xA0;           // 1010 00 0 0
      uint8 location[2] = {0x00, 0x00};
      uint8 wr_buffer[I2C_DATA_CNT+2] = {0x00, 0x00, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B};
      uint8 rd_buffer[I2C_DATA_CNT] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87};
          if(UART_1_RX_STS_FIFO_NOTEMPTY) {          // Input character
              rx_buffer = UART_1_GetChar();
              if(rx_buffer == 0x77) {                // typing 'w': write
                  dev_sel = 0xA0;
                  mr_status = I2C_1_MasterWriteBuf(dev_sel, (uint8*) wr_buffer, sizeof(wr_buffer)+sizeof(location), I2C_1_MODE_COMPLETE_XFER);
                  while(!(I2C_1_MasterStatus() & I2C_1_MSTAT_WR_CMPLT));
                  putByteUART(mr_status);     // just puts the byte, 0 means ok
              else if(rx_buffer == 0x72) {           // 'r'  read
                  // In order to do a read from a specific address, do a write operation with the memory address bytes alone:
                  dev_sel = 0xA0;
                  mr_status = I2C_1_MasterWriteBuf(dev_sel, (uint8*)location, sizeof(location), I2C_1_MODE_NO_STOP);
                  while(!(I2C_1_MasterStatus() & I2C_1_MSTAT_WR_CMPLT));
                  dev_sel = 0xA1;               // Because LSB bit is the W/R
                  mr_status = I2C_1_MasterReadBuf(dev_sel, (uint8*)rd_buffer, sizeof(rd_buffer), I2C_1_MODE_REPEAT_START);
                  // mr_status = I2C_1_MasterReadBuf(dev_sel, (uint8*)rd_buffer, 8, I2C_1_MODE_REPEAT_START);
                  while(!(I2C_1_MasterStatus() & I2C_1_MSTAT_RD_CMPLT)); //Wait till the master completes writing
                  putByteUART(rd_buffer[0]);  // unfortunately this byte remains 0x80
                  UART_1_PutString(" ");
                  putByteUART(rd_buffer[1]);  // 0x81 instead of 0x65, this is the problem
        • 1. Re: I2C problem with FRAM

          Hi BaWe_4587896,


          Can you please let me know the address of the slave? You need to provide the 7 bit address and the component takes care of the read and write bit.

          Also can you please let me know why you have given delays in between the I2C API calls? Can you please share the entire project so that we can debug the project from our end?


          Thanks and Regards,

          Rakshith M B

          • 2. Re: I2C problem with FRAM

            Hi Rakshith M B,

            The slave device has an 8 bit-wide "device select" address (the dev_sel variable) and a 16 bit wide slave address. I think, the slave address is doesn't matter, because each byte of it is addressable (I choosed the 0x0000). The structure of the device select byte is in the attached image (and a write cycle).

            When I use CyDelay, I am waiting for the answer of the slave, because I mean, it takes some time.
            I try to upload the project in a rar file. Thank you the answer.

            Best regards,
            Bálint Wéber

            Slave address.png

            • 3. Re: I2C problem with FRAM

              Hi BaWe_4587896,


              I believe what you are talking about is the Device Select bits of the I2C Address. I was not referring to that in my previous comment.


              I am referring to the MSB of the I2C slave address. The slave address as you have mentioned is 1010 0000 which is 0xA0. But for most of PSoC I2C components we need to provide the 7-bit address excluding the R/W' bit. In your case it is 101 0000 which 0x50.


              The component automatically shifts the bits and adds the R/W' bit depending on the API that you have used. For example, if you go into the definition of the read API - I2C_1_MasterReadBuf you will find that the slave address that you have provided for the API is left shifted by 1 and then the read bit is ORed with the slave address to give the final 8-bit address of the I2C slave as shown -

              I2C_1_SLAVE_ADDR_SHIFT and I2C_1_READ_FLAG are 0x01.

              So when you give 0x50 (101 0000) it gets left shifted by 1 (1010 0000) and then ORed with 0x01 to give 0xA1. This is done so that you do not have to change the slave address each time you read/write from/to the slave .


              You can also remove the CyDelay(10) in line 84 as the while loop is a blocking statement and it waits for the transaction to complete. The user need not explicitly provide delays.


              Regarding the status 0 that you were receiving, the master used to query for the slave with the wrong address. Since no slave will ACK the address there will not be any data transfer. I2C transaction as such is complete and thus a 0 is returned even though there is no address match. You can try this by disconnecting your slave and then running the master program. You will still receive a 0 as the master status.


              After making these changes to the project I was able to run the I2C communication suucessfully.


              Please let me know if you are still facing issue.


              Thanks and Regards,

              Rakshith M B

              1 of 1 people found this helpful