Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Reading the SODIMM SPD using I2C

Status
Not open for further replies.

asi123

Newbie level 6
Joined
Mar 5, 2010
Messages
13
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Israel
Activity points
1,498
So, this is what I did.



I took the code from xilinx examples for Low_Driver_IIC and change it a bit.



/***************************** Include Files *********************************/

#include "xparameters.h"
#include "xiic.h"
#include "xil_io.h"

/************************** Constant Definitions *****************************/

/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define IIC_BASE_ADDRESS XPAR_IIC_0_BASEADDR

/*
* The following constant defines the address of the IIC Slave device on the
* IIC bus. Note that since the address is only 7 bits, this constant is the
* address divided by 2.
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
* Please refer the User Guide's of the respective boards for further
* information about the IIC slave address of IIC EEPROM's.
*/
#define EEPROM_ADDRESS 0x50 /* 0xA0 as an 8 bit number */

/*
* The page size determines how much data should be written at a time.
* The ML300 board supports a page size of 32 and 16
* The write function should be called with this as a maximum byte count.
*/
#define PAGE_SIZE 128

/*
* The Starting address in the IIC EEPROM on which this test is performed
*/
#define EEPROM_TEST_START_ADDRESS 0


/**************************** Type Definitions *******************************/

/*
* The AddressType for ML300/ML310/ML510 boards should be u16 as the address
* pointer in the on board EEPROM is 2 bytes.
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
* be u8 as the address pointer in the on board EEPROM is 1 bytes.
*/
typedef u8 AddressType;



/************************** Variable Definitions **************************/


u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page */
u8 EepromIicAddr; /* Variable for storing Eeprom IIC address */

/*****************************************************************************/
/**
* Main function to call the low level EEPROM example.
*
* @param None.
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
*
* @note None.
*
******************************************************************************/
int main(void)
{
volatile unsigned ReceivedByteCount;
u16 StatusReg;
AddressType Address;
int Index;

Address = EEPROM_TEST_START_ADDRESS;
EepromIicAddr = EEPROM_ADDRESS;

for (Index = 0; Index < PAGE_SIZE; Index++) {
ReadBuffer[Index] = 0;
}

/*
* Set the address register to the specified address by writing
* the address to the device, this must be tried until it succeeds
* because a previous write to the device could be pending and it
* will not ack until that write is complete.
*/
do {
StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
ReceivedByteCount = XIic_Send(IIC_BASE_ADDRESS,
EepromIicAddr,
(u8 *)&Address,
sizeof(Address),
XIIC_STOP);
}
} while (ReceivedByteCount != sizeof(Address));

/*
* Read the number of bytes at the specified address from the EEPROM.
*/
ReceivedByteCount = XIic_Recv(IIC_BASE_ADDRESS, EepromIicAddr,
ReadBuffer, PAGE_SIZE, XIIC_STOP);

/*
* Return the number of bytes read from the EEPROM.
*/
return ReceivedByteCount;
}



And this is what I'm getting in the buffer at the end



ImageShack® - Online Photo and Video Hosting



Obviously not the SPD :smileysad:



Any idea guys?



Thanks a lot.



Assaf.
 

I'm basically getting a counter instead of the SPD.

Now I used the example from xilinx iic_ddr2

/******************************************************************************
*
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* (c) Copyright 2007 Xilinx Inc.
* All rights reserved.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file iic_ddr2.c
*
* This file consists of a polled mode design example which uses the Xilinx
* IIC peripheral in dynamic mode and low-level driver to exercise the DDR2
* SPD EEPROM on the ML505/ML506/ML507 board.
*
* @note
*
* None.
*
* <pre>
* </pre>
*
******************************************************************************/

/***************************** Include Files *********************************/
#include <stdio.h>
#include "xio.h"
#include "xbasic_types.h"
#include "xiic.h"
#include "xparameters.h"

#ifdef PPC440CACHE
#include "xcache_l.h"
#endif

/************************** Constant Definitions *****************************/

/*
* The Starting address in the IIC EEPROM on which this test is performed.
*/
#define EEPROM_TEST_START_ADDRESS 0x0

/*
* The following constant defines the address of the IIC
* device on the IIC bus. Note that since the address is only 7 bits, this
* constant is the address divided by 2.
*/
#define EEPROM_ADDRESS 0x50

/*
* The page size determines how much data should be written at a time.
* The ML310/ML300 board supports a page size of 32 and 16.
* The write function should be called with this as a maximum byte count.
*/
#define PAGE_SIZE 64

#define IIC_SLAVE_ADDRESS 1

/**************************** Type Definitions *******************************/

typedef Xuint8 AddressType;

/************************** Function Prototypes ******************************/

XStatus XIicLowLevelEepromDump();
XStatus XIicLowLevelEepromInit();

Xuint8 EepromReadByte(AddressType Address, Xuint8 *BufferPtr,
Xuint8 ByteCount);
Xuint8 EepromWriteByte(AddressType Address, Xuint8 *BufferPtr,
Xuint8 ByteCount);

/************************** Variable Definitions *****************************/

Xuint8 WriteBuffer[PAGE_SIZE]; /* Write buffer for writing a page. */

Xuint8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page. */

/************************** Function Definitions *****************************/

/*****************************************************************************/
/**
* Main function to call the low level EEPROM example.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
XStatus TestStatus=XST_FAILURE;
int main (void)
{

#ifdef PPC440CACHE
XCache_EnableICache(PPC440_ICACHE);
XCache_EnableDCache(PPC440_DCACHE);
#endif


print("IIC Dynamic mode DDR2 SPD EEPROM access example - ");
/*
* Initialize the IIC Core.
*/
TestStatus = XIicLowLevelEepromInit();
if (TestStatus != XST_SUCCESS)
{
print("Test failed (during initialization)\r\n");
return XST_FAILURE;
}

/*
* Perform the Read operation.
*/
TestStatus = XIicLowLevelEepromDump();
if (TestStatus != XST_SUCCESS)
{
print("Test failed\r\n");
return XST_FAILURE;
}

print ("Test passed\r\n");
#ifdef PPC440CACHE
XCache_DisableDCache();
XCache_DisableICache();
#endif
return XST_SUCCESS;
}

/******************************************************************************
* The function uses the low level driver of IIC to read from the IIC device
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
XStatus XIicLowLevelEepromDump()
{
Xuint8 BytesRead;
Xuint8 StatusReg;
Xuint8 Index;

/*
* Make sure all the Fifo's are cleared and Bus is Not busy.
*/
do
{
StatusReg = XIo_In8(XPAR_IIC_EEPROM_BASEADDR + 0x107);
StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK |
XIIC_SR_TX_FIFO_EMPTY_MASK |
XIIC_SR_BUS_BUSY_MASK);
}while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK |
XIIC_SR_TX_FIFO_EMPTY_MASK));

/*
* Initialize the read buffer, the write buffer is not used in this example.
*/
for (Index = 0; Index < PAGE_SIZE; Index++)
{
WriteBuffer[Index] = Index;
ReadBuffer[Index] = 0;
}

/*
* Skip writing to the EEPROM.
*/
/********************
BytesWritten = EepromWriteByte(EEPROM_TEST_START_ADDRESS, WriteBuffer,
PAGE_SIZE);
*********************/

xil_printf("\r\nCalling DDR2 SPD EEPROM ReadByte Routine\r\n");
/*
* Read from the EEPROM.
*/
BytesRead = EepromReadByte(EEPROM_TEST_START_ADDRESS, ReadBuffer,
PAGE_SIZE);
xil_printf("\r\nBytesRead = %d\r\n", BytesRead);
if(BytesRead != PAGE_SIZE)
{
return XST_FAILURE;
}

/*
* Display read buffer.
*/
for (Index = 0; Index < PAGE_SIZE; Index++)
{
/*****************************************************************
if (ReadBuffer[Index] != WriteBuffer[Index])
{
return XST_FAILURE;
}

ReadBuffer[Index] = 0;
******************************************************************/
xil_printf("ReadBuffer[%d] = %02X\r\n", Index, ReadBuffer[Index]);
}

return XST_SUCCESS;
}

/*****************************************************************************/
/**
* This function writes a buffer of bytes to the IIC serial EEPROM.
*
* @param Address contains the start address in the EEPROM to write to.
* @param BufferPtr contains the address of the data to write.
* @param ByteCount contains the number of bytes in the buffer to be written.
* Note that this should not exceed the page size of the EEPROM as
* noted by the constant PAGE_SIZE.
*
* @return The number of bytes written, a value less than that which was
* specified as an input indicates an error.
*
* @note None.
*
******************************************************************************/
Xuint8 EepromWriteByte(AddressType Address, Xuint8 *BufferPtr,
Xuint8 ByteCount)
{
Xuint8 SentByteCount;
Xuint8 WriteBuffer[sizeof(Address) + PAGE_SIZE];
Xuint8 Index;

/*
* A temporary write buffer must be used which contains both the address
* and the data to be written, put the address in first based upon the
* size of the address for the EEPROM
*/
if (sizeof(AddressType) == 2)
{
WriteBuffer[0] = (Xuint8)(Address >> 8);
WriteBuffer[1] = (Xuint8)(Address);
}
else if (sizeof(AddressType) == 1)
{
WriteBuffer[0] = (Xuint8)(Address);
}

/*
* Put the data in the write buffer following the address.
*/
for (Index = 0; Index < ByteCount; Index++)
{
WriteBuffer[sizeof(Address) + Index] = BufferPtr[Index];
}

/*
* Write a page of data at the specified address to the EEPROM.
*/
SentByteCount = XIic_DynSend(XPAR_IIC_EEPROM_BASEADDR, EEPROM_ADDRESS, WriteBuffer,
sizeof(Address) + PAGE_SIZE, XIIC_STOP);

/*
* Return the number of bytes written to the EEPROM.
*/
return SentByteCount - sizeof(Address);
}

/******************************************************************************
* This function reads a number of bytes from the IIC serial EEPROM into a
* specified buffer.
*
* @param Address contains the start address in the EEPROM to read from.
* @param BufferPtr contains the address of the data buffer to be filled.
* @param ByteCount contains the number of bytes in the buffer to be read.
* This value is constrained by the page size of the device such
* that up to 64K may be read in one call.
*
* @return The number of bytes read. A value less than the specified input
* value indicates an error.
*
* @note None.
*
******************************************************************************/
Xuint8 EepromReadByte(AddressType Address, Xuint8 *BufferPtr, Xuint8 ByteCount)
{
Xuint8 ReceivedByteCount;
Xuint8 SentByteCount;
Xuint16 StatusReg;

/*
* Position the Read pointer to specific location in the EEPROM.
*/
do
{

StatusReg = XIo_In8(XPAR_IIC_EEPROM_BASEADDR + 0x107);
if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK))
{
SentByteCount = XIic_DynSend(XPAR_IIC_EEPROM_BASEADDR, EEPROM_ADDRESS,
(Xuint8 *)&Address, sizeof(Address),
XIIC_REPEATED_START);
}
}while(SentByteCount != sizeof(Address));

/*
* Receive the data.
*/
ReceivedByteCount = XIic_DynRecv(XPAR_IIC_EEPROM_BASEADDR, EEPROM_ADDRESS,
BufferPtr, ByteCount);

/*
* Return the number of bytes received from the EEPROM.
*/
return ReceivedByteCount;
}

/******************************************************************************
* The function uses the low level driver of IIC to initialize the core.
*
* @param None.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note None.
*
******************************************************************************/
XStatus XIicLowLevelEepromInit()
{
XStatus Status;

/*
* Initialize the IIC Core.
*/
Status = XIic_DynInit(XPAR_IIC_EEPROM_BASEADDR);
if(Status != XST_SUCCESS)
{
return XST_FAILURE;
}

return XST_SUCCESS;
}

and this is what I got

IIC Dynamic mode DDR2 SPD EEPROM access example -
Calling DDR2 SPD EEPROM ReadByte Routine

BytesRead = 64
ReadBuffer[0] = 00
ReadBuffer[1] = 01
ReadBuffer[2] = 02
ReadBuffer[3] = 03
ReadBuffer[4] = 04
ReadBuffer[5] = 05
ReadBuffer[6] = 06
ReadBuffer[7] = 07
ReadBuffer[8] = 08
ReadBuffer[9] = 09
ReadBuffer[10] = 0A
ReadBuffer[11] = 0B
ReadBuffer[12] = 0C
ReadBuffer[13] = 0D
ReadBuffer[14] = 0E
ReadBuffer[15] = 0F
ReadBuffer[16] = 00
ReadBuffer[17] = 01
ReadBuffer[18] = 02
ReadBuffer[19] = 03
ReadBuffer[20] = 04
ReadBuffer[21] = 05
ReadBuffer[22] = 06
ReadBuffer[23] = 07
ReadBuffer[24] = 08
ReadBuffer[25] = 09
ReadBuffer[26] = 0A
ReadBuffer[27] = 0B
ReadBuffer[28] = 0C
ReadBuffer[29] = 0D
ReadBuffer[30] = 0E
ReadBuffer[31] = 0F
ReadBuffer[32] = 00
ReadBuffer[33] = 01
ReadBuffer[34] = 02
ReadBuffer[35] = 03
ReadBuffer[36] = 04
ReadBuffer[37] = 05
ReadBuffer[38] = 06
ReadBuffer[39] = 07
ReadBuffer[40] = 08
ReadBuffer[41] = 09
ReadBuffer[42] = 0A
ReadBuffer[43] = 0B
ReadBuffer[44] = 0C
ReadBuffer[45] = 0D
ReadBuffer[46] = 0E
ReadBuffer[47] = 0F
ReadBuffer[48] = 00
ReadBuffer[49] = 01
ReadBuffer[50] = 02
ReadBuffer[51] = 03
ReadBuffer[52] = 04
ReadBuffer[53] = 05
ReadBuffer[54] = 06
ReadBuffer[55] = 07
ReadBuffer[56] = 08
ReadBuffer[57] = 09
ReadBuffer[58] = 0A
ReadBuffer[59] = 0B
ReadBuffer[60] = 0C
ReadBuffer[61] = 0D
ReadBuffer[62] = 0E
ReadBuffer[63] = 0F
Test passed

Any idea guys?

Thanks a lot.

Assaf.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top