Using I2C to configure LMS7002M

Hi,

Thanks for all the help so far.

Was just exploring some options to configure LMS 7002M chip.

Is it possible to use I2C to configure LMS7002M registers? I am not sure because in LimeSDR design, I2C has been used to interface with EEPROM where LMS Chip is the master. If we want to use I2C to interface with EEPROM in the same way (LMS is master) as well as to interface with FPGA for configuration (LMS as slave), will it be ok?

Also, do you know of any particular reason why I2C was not used instead of SPI at the first place? Was it due to any technical issue or it’s just a matter of choice?

Thanks in advance for your help.

Regards
Gaurav

Hi @gchat,

I2C is dedicated for LMS7002M internal MCU first of all. But it is possible to connect another I2C EEPROM memory with different address as it is in LimeSDR-USB board. Just one note - you have to initiate LMS7002M MCU to boot from EEPROM. Hence it should be something like this:

  1. External SPI master initiates LMS7002M internal MCU boot from EEPROM;
  2. LMS7002M MCU reads register settings from another EEPROM and configures LMS7002M registers.

You will need a custom LMS7002M MCU firmware for this task.

SPI is much simpler to deal with from external master point of view. Virtually any MCU may be SPI master. I2C is doable as well, but it is more complex to implement if there is no dedicated module for this.

Thanks @Zack for the response.

I meant doing everything through I2C. For example. the steps would be:

  1. I2C master (FPGA in this case) initiates LMS7002M internal MCU boot from EEPROM. My doubt is whether the same chip (LMS7002M) can be master and slave one after the other or it’s an issue?

  2. I2C master configures LMS7002M registers directly using I2C.

I understand that a custom MCU would be needed, but is it possible technically? I understand SPI is simpler to implement but we are just exploring the options at the moment.

Thanks and regards
Gaurav

Hi @gchat,

No chance. It should be done via SPI. You may use some small MCU, or even very simple logic to transfer a few commands via SPI to initiate LMS7002M boot. You mentioned I2C will be implemented in FPGA. Hence you may make SPI master module which will do this task.

It is master only.

I still don’t understand why? If the LMS chip has I2C pins, it should be possible to make it a slave and FPGA sends command as master? Am I missing something important here?

Thanks

Because of hardware implementation.

Not possible to change I2C controller mode because of hardware implementation. Again - master only.

If you will have FPGA anyway if I understand correctly. Hence I see no problem to implement a small controller in FPGA and initiate LMS7002M MCU boot.

Ok I understand your point. So as per HW implementation of LMS Chip, it can only be used as a Master. Correct?

This is being already done in provided LimeSDR code right? As per the documents, FPGA resets LMS Chip that triggers MCU boot from EEPROM. Isn’t it the case? Otherwise how this is being handled please?

Thanks for all your help so far.

Correct.

In LimeSDR-USB FPGA implementation all the settings are initiated from a software running on PC. FPGA in this case is just a glue logic (well, a little bit more, but it doesn’t matter) between USB MCU and LMS7002M. But you can implement your own FPGA code which does exactly what you want.

You mean LimeSuite kind-of software right that would send command like MCU_FW_WR to write to LMS MCU. But which command is used to Reset I am not aware. Is it “CMD_SSTREAM_RST”?

Hi Zack! You wrote,

I want to use another EEPROM to store the settings, please give the text of the example program to access another EEPROM.

Regards, Victor.

Hi @Victor,

Here is an example:

//secondary MCU EEPROM (IC3)
#define I2C_ADDR_EEPROM2	0xAE

unsigned char EEPROM_test (unsigned char I2C_Addr, unsigned char test_data)
{
	//write
	EECTRL = 9; //send start sequence
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	I2C_Addr &= ~(1 << 0);//write addr
	EEDATA = I2C_Addr; //slave I2C addr EEPROM WR
	EECTRL = 3; //transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EEDATA = 0x00; //mem addr high
	EECTRL = 3; //transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EEDATA = 0x00; //mem addr low
	EECTRL = 3; //transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EEDATA = test_data; //mem data
	EECTRL = 3; //transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EECTRL = 5;//send stop sequence
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	Delay_us (10000);	//wait till eeprom finishes to write

	//read
	EECTRL = 9;//send start sequence
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	I2C_Addr &= ~(1 << 0);//write addr
	EEDATA = I2C_Addr; //slave I2C addr EEPROM WR
	EECTRL = 3;//transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy
		
	EEDATA = 0x00; //mem addr high
	EECTRL = 3;//transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy
		
	EEDATA = 0x00; //mem addr low
	EECTRL = 3;//transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EECTRL = 9; //start
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	I2C_Addr |= (1UL << (0));
	EEDATA = I2C_Addr; //slave I2C addr EEPROM RD
	EECTRL = 3;//transmit byte
	while (EECTRL & 0x40){}; //wait till I2C bus busy
	
	/*EECTRL = 2;//receive byte and send ACK
	while (EECTRL & 0x40){}; //wait till I2C bus busy*/
		
	EECTRL = 6;//Receive a byte from EEPROM and do not send ACK
	while (EECTRL & 0x40){}; //wait till I2C bus busy

	EECTRL = 5;//send stop sequence
	while (EECTRL & 0x40){}; //wait till I2C bus busy		
		
	Delay_us (1000);
		
	if (EEDATA == test_data) return 1; //test passed?
	else return 0;		
}
1 Like

Thank you very much!
Regards, Victor.