We are adsp21569 SHARC processor for Communicating with AT24C256C EEPROM on TWI, using baremetal programming.
If System Clock is configured as 125 MHz both read and write operations are working as expected.
If System Clock is configured as 400 MHz. we are receiving timeout error, On checking the master status register we are seeing the master read buffer error.
Provide the guidance on how to resolve the issue.
Code is available below for your reference
/*! ***********************************************************************************************************
* \fn dp_scm_init_i2c
* \brief Perform the I2C Initialization
* This function is used to Initialize the I2C.
****************************************************************************************************************/
int dp_scm_init_i2c(void)
{
int iRetVal = DP_SUCCESS;
// unsigned short usClkDiv = 13;
// unsigned short usPreScalVal = 12;
// unsigned short usFrequency = 400;
/* PORTx_MUX registers */
*pREG_PORTB_MUX = TWI1_SCL_PORTB_MUX | TWI1_SDA_PORTB_MUX;
/* PORTx_FER registers */
*pREG_PORTB_FER = TWI1_SCL_PORTB_FER | TWI1_SDA_PORTB_FER;
// Set the TWI controller
*pREG_TWI1_CTL = BITM_TWI_CTL_EN |
((DP_SCM_I2C_PRE_SCALE << BITP_TWI_CTL_PRESCALE) & BITM_TWI_CTL_PRESCALE) | 0;
// Setting clock duty cycle
//*pREG_TWI1_CLKDIV = (DP_SCM_I2C_CLKDIV << BITP_TWI_CLKDIV_CLKHI) | DP_SCM_I2C_CLKDIV;
*pREG_TWI1_CLKDIV = (13 << BITP_TWI_CLKDIV_CLKHI) | 13;
*pREG_TWI1_MSTRCTL = BITM_TWI_MSTRCTL_FAST | 0;
// Set the device address
*pREG_TWI1_MSTRADDR = EEPROM_ID;
*pREG_TWI1_FIFOCTL = BITM_TWI_FIFOCTL_RXFLUSH|BITM_TWI_FIFOCTL_TXFLUSH;
*pREG_TWI1_FIFOCTL = 0;
// Clear status bits
*pREG_TWI1_MSTRSTAT = (ENUM_TWI_MSTRSTAT_BUFWRERR_YES |
ENUM_TWI_MSTRSTAT_BUFRDERR_YES |
ENUM_TWI_MSTRSTAT_DNAK_YES |
ENUM_TWI_MSTRSTAT_ANAK_YES |
ENUM_TWI_MSTRSTAT_LOSTARB_YES | 0);
// Clearing all pending interrupt flags
*pREG_TWI1_ISTAT = 0xFFFF;
return iRetVal;
}
/*! ***********************************************************************************************************
* \fn dp_scm_i2c_write
* \brief To write I2C
* This function is used to write data through I2C.
****************************************************************************************************************/
int dp_scm_i2c_write(unsigned char *in_pucData, unsigned short in_usDataLength)
{
int iRetVal = DP_SUCCESS;
unsigned long ulTimeOut = 0;
unsigned short usLooper = 0;
volatile unsigned long ulIntStatus = 0;
/*Pointer Validation*/
if(in_pucData == NULL)
{
iRetVal = DP_SCM_INVALID_POINTER;
}
else
{
// Flush FIFO in case a previous transfer encountered an error
*pREG_TWI1_FIFOCTL = BITM_TWI_FIFOCTL_RXFLUSH|BITM_TWI_FIFOCTL_TXFLUSH;
*pREG_TWI1_FIFOCTL = 0;
// Set up the transfer
*pREG_TWI1_MSTRCTL = (in_usDataLength << 6) | /* set count to a 2 but we'll never let it finish*/
BITM_TWI_MSTRCTL_EN | /* enable*/
0;
for (usLooper = 0; usLooper < in_usDataLength; usLooper++)
{
// Load value into TX register
*pREG_TWI1_TXDATA8 = in_pucData[usLooper];
// Wait for transfer to complete
ulTimeOut = DP_SCM_I2C_TX_TIMEOUT;
while(ulTimeOut)
{
ulTimeOut--;
ulIntStatus = *pREG_TWI1_ISTAT;
if((ulIntStatus & BITM_TWI_ISTAT_TXSERV) == BITM_TWI_ISTAT_TXSERV)
{
break;
}
}
if(ulTimeOut != 0)
{
*pREG_TWI1_ISTAT |= BITM_TWI_ISTAT_TXSERV; // Clear tx status latch
}
else
{
iRetVal = DP_SCM_I2C_TX_TIMEOUT_ERROR;
break;
}
}
*pREG_TWI1_ISTAT |= BITM_TWI_ISTAT_MCOMP;
}
return iRetVal;
}
/*! ***********************************************************************************************************
* \fn dp_scm_i2c_write_and_read
* \brief To read I2C
* This function is used to read data through I2C.
****************************************************************************************************************/
int dp_scm_i2c_write_and_read(unsigned char *in_pucAddress, unsigned char *out_pucData)
{
int iRetVal = DP_SUCCESS;
unsigned long ulTimeOut = 0;
volatile unsigned long ulISTAT = 0;
unsigned short usLooper = 0;
/*Pointer Validation*/
if((in_pucAddress == NULL) || (out_pucData == NULL))
{
iRetVal = DP_SCM_INVALID_POINTER;
}
else
{
// Flush FIFO in case a previous transfer encountered an error
*pREG_TWI1_FIFOCTL = BITM_TWI_FIFOCTL_RXFLUSH|BITM_TWI_FIFOCTL_TXFLUSH;
*pREG_TWI1_FIFOCTL = 0;
*pREG_TWI1_TXDATA8 = in_pucAddress[0];
// Set up the transfer
*pREG_TWI1_MSTRCTL = (2 << 6) | /* set count to a 2 but we'll never let it finish*/
BITM_TWI_MSTRCTL_EN | /* enable*/
0;
ulTimeOut = DP_SCM_I2C_TX_TIMEOUT;
while(ulTimeOut--)
{
// dp_scm_delay_ms(5);
ulISTAT = *pREG_TWI1_ISTAT;
if((ulISTAT & BITM_TWI_ISTAT_TXSERV) == BITM_TWI_ISTAT_TXSERV)
{
break;
}
}
if(ulTimeOut != 0)
{
*pREG_TWI1_ISTAT |= BITM_TWI_ISTAT_TXSERV; // Clear tx status latch
}
else
{
iRetVal = DP_SCM_I2C_TX_TIMEOUT_ERROR;
}
if(DP_SUCCESS == iRetVal)
{
*pREG_TWI1_MSTRCTL |= BITM_TWI_MSTRCTL_RSTART;
*pREG_TWI1_TXDATA8 = in_pucAddress[1];
ulTimeOut = DP_SCM_I2C_TX_TIMEOUT;
while(ulTimeOut--)
{
ulISTAT = *pREG_TWI1_ISTAT;
if((ulISTAT & BITM_TWI_ISTAT_MCOMP) == BITM_TWI_ISTAT_MCOMP)
{
break;
}
}
if(ulTimeOut != 0)
{ // Clear tx status latch
iRetVal = DP_SUCCESS;
}
else
{
iRetVal = DP_SCM_I2C_TX_TIMEOUT_ERROR;
}
*pREG_TWI1_ISTAT |= BITM_TWI_ISTAT_MCOMP;
}
/*Read Data*/
if(DP_SUCCESS == iRetVal)
{
// Enable master transmitter
*pREG_TWI1_MSTRCTL = BITM_TWI_MSTRCTL_DIR | // receive mode
(1 << 6) | // set count to a 1
BITM_TWI_MSTRCTL_EN | // enable
0;
ulTimeOut = DP_SCM_I2C_RX_TIMEOUT;
while(ulTimeOut--)
{
// dp_scm_delay_ms(5);
ulISTAT = *pREG_TWI1_ISTAT;
if((ulISTAT & BITM_TWI_ISTAT_MCOMP) == BITM_TWI_ISTAT_MCOMP)
{
break;
}
}
if(ulTimeOut != 0)
{
*pREG_TWI1_ISTAT |= BITM_TWI_ISTAT_MCOMP;
*out_pucData = *pREG_TWI1_RXDATA8; // Clear tx status latch
}
else
{
iRetVal = DP_SCM_I2C_RX_TIMEOUT_ERROR;
}
}
}
return iRetVal;
}