I want to write to an EEPROM via the I2C bus and I'm following the steps in the data manual (SLLS519G). I'm finding that I need to put a delay between successive page writes, so the sequence is: send address, send 32 bytes, delay, send address, send 32 bytes ...
I'm waiting for TXE every time I set I2CDAO, as in the data manual.
If I don't delay only the first 32 bytes are written and the rest aren't.
Am I missing something or should there be a delay and if so how long (or does it depend on the EEPROM used?)
The EEPROM manual (it's an ST M24C64) says to set the device address, and then poll for ACK on the i2c bus (SDA low); if there's no ACK then the E2 is not ready, so repeat the start/device address sequence until it is.
So, how do I check if there's an ACK or not using the TUSB's registers?
Well, it doesn't seem too busy in here. Maybe if I just try the write several times with a short delay?
int retry = 3; while ((write(...) != NO_ERROR) && (--retry > 0)) { delay();}
What do you think?
Pete
The page-write operation is initiated in the same way as byte write, with the exception that a stop condition is not generated after the first EPROM [DATA] is transmitted. The following describes the sequence of writing 32 bytes in page mode. Device Address + EPROM [High Byte]
The page-write operation is initiated in the same way as byte write, with the exception that a stop condition is not generated after the first EPROM [DATA] is transmitted. The following describes the sequence of writing 32 bytes in page mode.
Device Address + EPROM [High Byte]
The MCU clears bit 0 (SWR) in the I2CSTA register. This forces the I2C controller to not generate a stop condition after the contents of the I2CDAO register are transmitted.
The MCU writes the device address (bit 0 (R/W) = 0) to the I2CADR register (write operation).
The MCU writes the high byte of the EEPROM address into the I2CDAO register
Bit 3 (TXE) in the I2CSTA register is cleared (indicating busy).
The contents of the I2CADR register are transmitted to the device (preceded by start condition on SDA).
The contents of the I2CDAO register are transmitted to the device (EEPROM address).
Bit 3 (TXE) in the I2CSTA register is set and interrupts the MCU, indicating that the I2CDAO register contents have been transmitted.
EPROM [Low Byte]
The MCU writes the low byte of the EEPROM address into the I2CDAO register.
Bit 3 (TXE) in the I2CSTA register is cleared (indicates busy).
EPROM [DATA]—31 Bytes
The data to be written to the EEPROM are written by the MCU into the I2CDAO register.
The contents of the I2CDAO register are transmitted to the device (EEPROM data).
This operation repeats 31 times.
EPROM [DATA]—Last Byte
The MCU sets bit 0 (SWR) in the I2CSTA register. This forces the I2C controller to generate a stop condition after the contents of the I2CDAO register are transmitted.
The MCU writes the last date byte to be written to the EEPROM, into the I2CDAO register.
The contents of the I2CDAO register are transmitted to EEPROM (EEPROM data).
The I2C controller generates a stop condition after the contents of the I2CDAO register are transmitted.
Thanks for your reply. It looks like you've pasted me a section from the data manual that I referred to in my first post. To clarify what I'm doing:
WORD index = 0; BYTE err = NO_ERROR; while ((err == NO_ERROR) && (index < SIZE)) { err = i2cWrite(0, index, 32, &buffer[index]); index += 32; }
Where i2cWrite is a function taken directly from the TI Bootcode Source Listing SLLC139. It writes the first 32 byte chunk but not subsequent ones. The manual for the EEPROM I'm using says that if it is not ready to write, it will not acknowledge the device select. So my question is: can I detect when the device select is not acknowledged or do I just retry the i2cWrite a number of times with pauses (assuming that if the function fails, say, 5 times in a row there's a hardware error).
Looking at the steps you posted:
The procedure could fail when I2CADR is set, but there's no step for checking that. Or is the address not transmitted until I2CDAO is written?
The following is a code portion taken from our EEPROM burner's FW source code.
----------------------------------
BYTE i2cWrite(BYTE bDeviceAddress, WORD wAddress, WORD wNumber, PBYTE pbDataArray){ BYTE bTemp,bHiAddress; bI2CSTA &= ~(I2CSTA_SRD | I2CSTA_SWR); // clear SRD and SWR bit
// If error, return a value other than zero. if(wNumber == 0x00) return NO_ERROR;
if(bDeviceCategory == I2C_CATEGORY_1){ // cat 1 bI2CADR = (BYTE)(wAddress << 1); }else{ // cat 2 or 3 bTemp = bDeviceAddress & MASK_I2C_DEVICE_ADDRESS; // write device address and RW=0 bTemp = bTemp << 1; bTemp |= BIT_I2C_DEVICE_TYPE_MEMORY; // add control code
// check if data address is higher than 0xff in cat 2 device if((bDeviceCategory == I2C_CATEGORY_2) && (wAddress > 0x00ff)){ bHiAddress = (BYTE)(wAddress >> 8) & MASK_I2C_DEVICE_ADDRESS; bHiAddress = bHiAddress << 1; bTemp |= bHiAddress; } bI2CADR = bTemp; // write out device address
if(bDeviceCategory == I2C_CATEGORY_3){ bI2CDAO = (BYTE)(wAddress >> 8); // write out high byte of address if(i2cWaitForWrite() != NO_ERROR) return ERROR; // bus error }
bI2CDAO = (BYTE)(wAddress & 0xff); // write out low byte of address if(i2cWaitForWrite() != NO_ERROR) return ERROR; // bus error }
// SRD should be cleared. while(wNumber > 1){ bI2CDAO = *pbDataArray++; if(i2cWaitForWrite() != NO_ERROR) return ERROR; // bus error wNumber--; }
// write the last byte bI2CSTA |= I2CSTA_SWR; // set SWR bit bI2CDAO = *pbDataArray; // write out the data
if(i2cWaitForWrite() != NO_ERROR) return ERROR; // bus error return NO_ERROR;}
-------------------------
I can notice from there that some delays are being inserted (i2cWaitForWrite), and SDR bit is being cleared... Let me know if it's useful.
Right, the code portion you've quoted is exactly what I meant by "... i2cWrite is a function taken directly from the TI Bootcode Source Listing SLLC139"
I've got a category 3 device, so looking at the code for i2cWrite, it does this:
You will notice there's no wait between steps 1 & 2. i2cWaitForWrite is not a time delay, it polls the TXE bit which indicates that the data has been sent. My EEPROM manual says that if it is not ready to receive the next command, it does not acknowledge the device address byte. So how can I check if the device is ready using the TUSB's controller. What I want is
Do you see what I mean?
In case of the TUSB3410 device accesses a Cat 3 device like this: Two bytes of data are written to addresses i and i+1. Two bytes of data address, A15 to A0, are sent out before the data bytes (Take a look at the attached Write-I2C-Cat3.jpg).
Note: There are certain restrictions to the types of EEPROM devices that can be used. I2C EEPROM devices available on the market can be grouped by the way they are addressed on the I2C bus. It is necessary to consider this when selecting a device for use with a TI USB controller, since some types are not supported with some controllers, and in some cases the device address may need to be configured differently depending on the type.
I appreciate the time you're spending to help me, and I think we're getting to the heart of it now. I have code that I'm confident will correctly write data to the EEPROM, and I am confident because the TI docs are clear, and also because I based my code on the TI bootcode example. The problem is that if I do writing in a loop, the first one will succeed and the next write will fail. I know the reason for this - to quote the EEPROM manual:
During the internal Write cycle, the device disconnects itself from the bus, and writes a copy of the data from its internal latches to the memory cells. The maximum Write time (tw) is shown in Table 17 and Table 18 , but the typical time is shorter. To make use of this, a polling sequence can be used by the bus master. The sequence, as shown in Figure 10 , is:
1. Initial condition: a Write cycle is in progress.
2. Step 1: the bus master issues a Start condition followed by a device select code (the first byte of the new instruction).
3. Step 2: if the device is busy with the internal Write cycle, no Ack will be returned and the bus master goes back to Step 1. If the device has terminated the internal Write cycle, it responds with an Ack, indicating that the device is ready to receive the second part of the instruction (the first byte of this instruction having been sent during Step 1).
I have attached their figure 10 (with my annotations in red) which shows how they think it should be done. My question is, how do I do the part marked ???, detect when the EEPROM is busy? By the way the EEPROM is one that is supported by the TUSB (it is listed in the TUSB burner manual), so no worries there.
Peter
How about this part of the M24C64 EEPROM’s datasheet? 4.3 Acknowledge bit (ACK): The acknowledge bit is used to indicate a successful byte transfer. The bus transmitter, whether it be bus master or slave device, releases Serial Data (SDA) after sending eight bits of data. During the 9th clock pulse period, the receiver pulls Serial Data (SDA) Low to acknowledge the receipt of the eight data bits. If you can somehow write one byte data transfers, one after the other you could monitor each ACK. This is just to make some experimentation. Please let me know if it makes sense.
How about this part of the M24C64 EEPROM’s datasheet?
4.3 Acknowledge bit (ACK): The acknowledge bit is used to indicate a successful byte transfer. The bus transmitter, whether it be bus master or slave device, releases Serial Data (SDA) after sending eight bits of data. During the 9th clock pulse period, the receiver pulls Serial Data (SDA) Low to acknowledge the receipt of the eight data bits.
If you can somehow write one byte data transfers, one after the other you could monitor each ACK. This is just to make some experimentation. Please let me know if it makes sense.
Actually I have resorted to putting in a delay for now. But..., what I would like to know is - how do I test the acknowledge bit with the TUSB?
Thanks for your help.
I'm not sure if any bits in I2CSTA (I2C Status and Control Register) can help you out to test the ack in the E2.
Regards,
Ismael
ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". TI AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY TI. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM TI.
Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms of Use of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms of Use of this site. TI and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.