cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
eric.boutet
Adventurer
Adventurer
18,222 Views
Registered: ‎10-14-2015

MAC address EEPROM Petalinux

Jump to solution

Hi,

 

I know that there are a lot forum post about mac address, but no one can't solve my problem.

I have a SoM with mac address within an custom eeprom i2c. I add inside the FSBL "FsblHookBeforeHandoff" function the ethernet phy configuration including reading MAC from eeprom. I use the "XEmacPs_SetMacAddress" function to setup it. All is working fine. After that, when u-boot is loading, I get the generic MAC when I have configured in the petalinux project. The same issue is reproduced when I call "ifconfig" from linux.

 

I have read that undef CONFIG_ETHADDR in the platform-top.h in the u-boot config file could solve the problem. It seems not... In fact, I don't know if "XEmacPs_SetMacAddress" should save the mac for u-boot or I don't know if u-boot and/or linux replace the mac read with the generic mac...etc.

 

Thanks in advance.

0 Kudos
1 Solution

Accepted Solutions
eric.boutet
Adventurer
Adventurer
26,351 Views
Registered: ‎10-14-2015

Hi,

 

After a long delay of work, I was faced to solve this issue and I got it ! For every one has a eeprom on-board, want to read it from FSBL and pass it to u-boot and linux, below is the procedure :

 

  1. Open the file fsbl_hook.c and go to the function 'u32 FsblHookBeforeHandoff(void)'. Do all you need in it.
  2. Read the mac address store in the EERPOM. In my case, it is an I2C communication.
  3. Once got, store it in a unsigned char array, you must write it to the OCM, but not everywhere. The FSBL do not use address from 0xFFFFFC00 to 0xFFFFFFFF. Below is an example how to store it. The form of this string is very important because u-boot needs it. '\n' is very important !!!
    	// Saving MAC address in the OCM memory at 0xFFFF FC00
    	// Create string to copy in the OCM
    	sprintf(ethaddr, "ethaddr=%02x:%02x:%02x:%02x:%02x:%02x\n", EmacPsMAC[0], EmacPsMAC[1], EmacPsMAC[2], EmacPsMAC[3], EmacPsMAC[4], EmacPsMAC[5]);
    	// Copy string to memory
    	for(i=0; i< strlen(ethaddr)+1; i++)
    		 Xil_Out8(0xFFFFFC00+i, ethaddr[i]);
  4. Open the file platform-top.h in u-boot config folder.
  5. You need to undefine CONFIG_PREBOOT and replace by your preboot. In my case I has copied the original auto generated preboot in the platform-auto.h and add "env import -t 0xFFFFFC00;".
    #undef CONFIG_PREBOOT
    #define CONFIG_PREBOOT	"echo U-BOOT for ${hostname};setenv preboot; echo;env import -t 0xFFFFFC00;dhcp"
  6. Rebuild the petalinux project and update your SD of QSPI memory. You will see that the variable 'ethaddr' has been changed to the one read in your eeprom.

Hope this post will help someone.

Eric

View solution in original post

0 Kudos
22 Replies
achutha
Xilinx Employee
Xilinx Employee
18,209 Views
Registered: ‎07-01-2010

@eric.boutet

 

Have you check this post?

https://forums.xilinx.com/t5/Embedded-Linux/How-to-get-mac-address-from-serial-eeprom-on-Petalinux-2014-4/td-p/652144

 

Regards,
Achutha

---------------------------------------------------------------------------------------------
Kindly note- Please mark the Answer as "Accept as solution" if information provided is helpful.

Give Kudos to a post which you think is helpful and reply oriented.
----------------------------------------------------------------------------------------
0 Kudos
eric.boutet
Adventurer
Adventurer
18,200 Views
Registered: ‎10-14-2015

@achutha

 

Hi,

 

Yes it is exactly one of the post I was talking about in my last post. Below is what I did and the result.

 

FSBL :

 

In the fsblhooks.c, I add in the function " u32 FsblHookBeforeHandoff(void)" this (below), I debug the FSBL with the SDK and I can correctly read and write the MAC. The hooks return success. 

        XEmacPs EmacPsInstance;
	XEmacPs *EmacPsInstancePtr = (XEmacPs*) &EmacPsInstance;
	int Status;
	u16 PhyData, PhyAddr, PhyType;
	XEmacPs_Config *Config;
	volatile int i;

    uint32_t serialNumber;
    ProductNumberInfo_t productNumberInfo;
    uint8_t macAddress[6];
    char EmacPsMAC[6];
    int MacAddrSet = 0;

    // Initialise the EEPROM.
	if (EN_SUCCEEDED(Eeprom_Initialise()))
    {
		// Read the EEPROM.
		if (EN_SUCCEEDED(Eeprom_Read()))
		{
		    // After reading the EEPROM, the information is stored in its own translation unit - we can
		    // query it using the EEPROM API functions.
			if (EN_SUCCEEDED(Eeprom_GetModuleInfo(&serialNumber, &productNumberInfo, (uint64_t*)&macAddress))){
				fsbl_printf(DEBUG_GENERAL,"MAC address configured successfully from EEPROM\n\r");
				EmacPsMAC[0] = macAddress[5];
				EmacPsMAC[1] = macAddress[4];
				EmacPsMAC[2] = macAddress[3];
				EmacPsMAC[3] = macAddress[2];
				EmacPsMAC[4] = macAddress[1];
				EmacPsMAC[5] = macAddress[0];
				MacAddrSet = 1;
			}

		}
    }
	if (MacAddrSet == 0){
		EN_PRINTF("Error reading EEPROM, using default MAC address\r\n");
		EmacPsMAC[0] = 0x00;
		EmacPsMAC[1] = 0x0a;
		EmacPsMAC[2] = 0x35;
		EmacPsMAC[3] = 0x01;
		EmacPsMAC[4] = 0x02;
		EmacPsMAC[5] = 0x03;
	}


	Config = XEmacPs_LookupConfig(XPAR_XEMACPS_0_DEVICE_ID);

	Status = XEmacPs_CfgInitialize(EmacPsInstancePtr, Config,
					Config->BaseAddress);

	if (Status != XST_SUCCESS) {
		fsbl_printf(DEBUG_INFO,"Error in initialize\r\n");
		return XST_FAILURE;
	}

	/*
	 * Set the MAC address
	 */
	Status = XEmacPs_SetMacAddress(EmacPsInstancePtr, EmacPsMAC, 1);
	if (Status != XST_SUCCESS) {
		fsbl_printf(DEBUG_INFO,"Error setting MAC address\r\n");
		return XST_FAILURE;
	}

	XEmacPs_SetMdioDivisor(EmacPsInstancePtr, MDC_DIV_224);

	// Issue a reset to phy
	Status  = XEmacPs_PhyRead(EmacPsInstancePtr, PhyAddr, 0x0, &PhyData);
	PhyData |= 0x8000;
	Status = XEmacPs_PhyWrite(EmacPsInstancePtr, PhyAddr, 0x0, PhyData);
	for (i=0; i<100000; i++);
	Status |= XEmacPs_PhyRead(EmacPsInstancePtr, PhyAddr, 0x0, &PhyData);
	if (Status != XST_SUCCESS)
	{
		fsbl_printf(DEBUG_GENERAL,"Error reset phy \n\r");
		return -1;
	} else {
		return 0;
	}

U-BOOT:

 

 

In the file " ./subsystems/linux/configs/u-boot/platform-top.h" I add the undef for the mac address:

#include <configs/platform-auto.h>

#undef CONFIG_ETHADDR

 

U-Boot startup:

 

 

 

When I load the image on the Zynq, I get this :

U-Boot 2015.04 (Dec 02 2015 - 13:32:33)

DRAM:  ECC disabled 512 MiB
SF: Detected S25FL512S_256K with page size 512 Bytes, erase size 256 KiB, total 64 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Gem.e000b000
Error: Gem.e000b000 address not set.

U-BOOT for PetaLinux

Gem.e000b000 Waiting for PHY auto negotiation to complete.... done
Gem.e000b000: mac address is not valid
Hit any key to stop autoboot:  4  3  2  1  0 
U-Boot-PetaLinux> 

Linux startup:

In the linux, when I call ifconfig, I get the generic MAC address who was generated by the petalinux-config command even if I clear the define in u-boot config and even if u-boot tell that the mac is not valid.

 

Regards.

 

Eric

 

0 Kudos
linnj
Xilinx Employee
Xilinx Employee
18,187 Views
Registered: ‎09-10-2008
Hi Eric,

I don't have the answer but am interested as it's a common problem to be solved. It does look like others got it work with FSBL. The u-boot recommended practice goes thru the details some, have you looked into it?

https://github.com/Xilinx/u-boot-xlnx/blob/master/doc/README.enetaddr

I also notice that others are doing it this way and they mention another environment variable ETHMACSKIP that might be useful.

https://wiki.trenz-electronic.de/display/PD/MAC+Address+usage

If I have more time later I'll mess with it but let use know if you get it figured out as this is something many others will need too.

Thanks
John

0 Kudos
eric.boutet
Adventurer
Adventurer
18,044 Views
Registered: ‎10-14-2015

Hi John

 

I did some tests with your reference. I try to set eth0macskip in the environment in the paltform-top.h and I didn't get any positive result. About the readme.enetaddr, I'm a bit confused.  I also tried the trenz-electronic procedure, but nothing more.

 

I ask to the company where I bought the SoM and I'm waiting for the answer.

 

If you have more information, let me know.

 

Regards

0 Kudos
der_hainz
Visitor
Visitor
17,779 Views
Registered: ‎11-25-2015

Hello,

 

I have exactly the same problem, does anyone already solved that problem?

 

 

0 Kudos
vanmierlo
Mentor
Mentor
17,765 Views
Registered: ‎06-10-2008

For a Trenz module you need something completely different. They decided to use a non-i2c eeprom AFAIR and inserted a CPLD in between to complicate matters.

0 Kudos
trenz-al
Scholar
Scholar
17,742 Views
Registered: ‎11-09-2013

hi

 

the problem of MAC address is not in any way related to the place where the MAC is stored. Using Xilinx ETH uboot drivers there is no fully clean way at all.

 

The only way that works is (this works regardless how MAC is stored):

 

1) FSBL reads MAC address

2) FSBL sets PS ETH MAC registers

3) FSBL writes formatted MAC address to "shared RAM"

4) uboot has added small snipped in preboot script

5) preboot script imports from shared RAM

https://wiki.trenz-electronic.de/display/PD/MAC+Address+usage

 

We do this flow for our modules and we get EEPROM loaded MAC address working properly in uboot and in linux with stock not patched uboot code.

 

We know no other way of doing it (if not patching uboot)

 

0 Kudos
eric.boutet
Adventurer
Adventurer
26,352 Views
Registered: ‎10-14-2015

Hi,

 

After a long delay of work, I was faced to solve this issue and I got it ! For every one has a eeprom on-board, want to read it from FSBL and pass it to u-boot and linux, below is the procedure :

 

  1. Open the file fsbl_hook.c and go to the function 'u32 FsblHookBeforeHandoff(void)'. Do all you need in it.
  2. Read the mac address store in the EERPOM. In my case, it is an I2C communication.
  3. Once got, store it in a unsigned char array, you must write it to the OCM, but not everywhere. The FSBL do not use address from 0xFFFFFC00 to 0xFFFFFFFF. Below is an example how to store it. The form of this string is very important because u-boot needs it. '\n' is very important !!!
    	// Saving MAC address in the OCM memory at 0xFFFF FC00
    	// Create string to copy in the OCM
    	sprintf(ethaddr, "ethaddr=%02x:%02x:%02x:%02x:%02x:%02x\n", EmacPsMAC[0], EmacPsMAC[1], EmacPsMAC[2], EmacPsMAC[3], EmacPsMAC[4], EmacPsMAC[5]);
    	// Copy string to memory
    	for(i=0; i< strlen(ethaddr)+1; i++)
    		 Xil_Out8(0xFFFFFC00+i, ethaddr[i]);
  4. Open the file platform-top.h in u-boot config folder.
  5. You need to undefine CONFIG_PREBOOT and replace by your preboot. In my case I has copied the original auto generated preboot in the platform-auto.h and add "env import -t 0xFFFFFC00;".
    #undef CONFIG_PREBOOT
    #define CONFIG_PREBOOT	"echo U-BOOT for ${hostname};setenv preboot; echo;env import -t 0xFFFFFC00;dhcp"
  6. Rebuild the petalinux project and update your SD of QSPI memory. You will see that the variable 'ethaddr' has been changed to the one read in your eeprom.

Hope this post will help someone.

Eric

View solution in original post

0 Kudos
trenz-al
Scholar
Scholar
16,412 Views
Registered: ‎11-09-2013

We are doing exactly this already a long time, and have docuemented it also.

 

https://wiki.trenz-electronic.de/display/PD/MAC+Address+usage

 

this link I already posted, it included the description, and the FSBL files for our modules included the "env patch to RAM" code..

 

There is no other way without patching u-boot or xilinx drivers.

0 Kudos
eric.boutet
Adventurer
Adventurer
13,540 Views
Registered: ‎10-14-2015
Yes I base on your procedure but nowhere you have documented the fsbl hook... There is no way to get the hook fike example on your link...So, I wrote it to help other one that was stuck to it
0 Kudos
trenz-al
Scholar
Scholar
13,527 Views
Registered: ‎11-09-2013

from our company website downloads there are some designs for our modules that implement this feature.

 

We do not document larger code snippets in the wiki, maybe we should.

 

And if there is something you think we have and you do not find it, then please DO ASK, we are pretty helpful also on random help requests not directly related to our products.

0 Kudos
vanmierlo
Mentor
Mentor
13,520 Views
Registered: ‎06-10-2008

@trenz-al wrote:

There is no other way without patching u-boot or xilinx drivers.


True. But had you (Trenz) chosen to use an I2C eeprom on MIO I2C I think it would be realistic to expect this being supported in a future version of the default Xilinx FSBL, U-boot and (peta)linux. By using a non-I2C eeprom and a CPLD interface in between you're condemned to always patch I guess.

0 Kudos
trenz-al
Scholar
Scholar
13,516 Views
Registered: ‎11-09-2013

We have many products, plenty of them using I2C on true I2C pins or on PL, and there is no way to use those EEPROM.

 

This is generic issue not related to our products.

 

We decided to use the non MIO EEPROM on TE0720 from simple reasons:

 

LEAVE ALL free MIO to USER, so the user can connect as many peripherals to the MIO. And to be as much as compatible to zedboard where 8 MIO are available to the user.

 

The only other option there would have been I2C mux to connect the EEPROM temporary to the MDIO pins, and then change PS configuration. We did not use that path.

 

And many thanks for telling us that we are

 

"condemned"!

 

We do not patch anything. The fsbl_hooks.c modification is not patching, this is the standard customization provided by Xilinx for the board manufacturers.

0 Kudos
vanmierlo
Mentor
Mentor
13,498 Views
Registered: ‎06-10-2008

I apologize if I offended you by my choice of words. That was not my intention.

0 Kudos
trenz-al
Scholar
Scholar
13,494 Views
Registered: ‎11-09-2013

No problems, I was told by others the same already (that you did not mean it that way).

 

TE0720 was our first Zynq SOM and we tried to find the best compromise, or actually we tried to not compromise any features. And we wanted to keep as much legacy compatibility to  older Spartan 6 SoM. So that caused and design choice that does invoke one small additional step in the fsbl_hooks. Maybe it has been not explained that way clearly enough.

 

In overall I agree with you, the MAC address mess is something that uboot mainteners should clean up, or optionally Xilinx could change their driver to allow mac address setting in more flexible way.

 

 

0 Kudos
eric.boutet
Adventurer
Adventurer
13,485 Views
Registered: ‎10-14-2015
Hi,

I started this post forum because I was stuck on the FSBL code. I just really don't want to get the credit of trenz's solution. I have to thank you this solution, this is the best solution without patching u-boot.
0 Kudos
trenz-al
Scholar
Scholar
13,473 Views
Registered: ‎11-09-2013

all good.

 

and excuse me too, I am sometimes to allergic. We try hard, but sometimes its not a easy to please all.

 

I should have documented the fsbl parameter passing code better. I wanted but did not get to it.

 

BTW, Xilinx is doing things better, in the FSBL for the Zynq Ultrascale+ there is a special memory segment allocated with name: "handout parameters" so that would possible be good place for the parameter passing...

 

 

0 Kudos
krishnam
Visitor
Visitor
7,577 Views
Registered: ‎12-02-2016

Hi Eric,

 

I want to achieve MAC address setting using the data available in the FRAM available on the board.

I am using an SD card along for booting Zynq702 and running the application.

 

I tried to incorporate the steps that you have mentioned by hard coding the mac address as set below.

I am not seeing the hard coded mac address being taking effect in the fsbl --> UBoot --> Kernel, please suggest where am i doing wrong. No debug print is printed on the console, how can i capture debug print.

u32 FsblHookBeforeHandoff(void)
{
u32 Status,i;
u8 i2CReadData[7] = {0};
u8 i2CWriteData[2] = {0};
u16 FRAMreadAddr = 0x003C;
u8 i2cDeviceAddr = 0x50;
u8 ethAddr[7]= "";
Status = XST_SUCCESS;

/*Initialize I2C Master Controller in PS*/
xI2CDeviceInit1();

/*Read Base Board & SOM board Info from FRAM */
i2CWriteData [0] = FRAMreadAddr >> 8;//MSB Address
i2CWriteData [1] = FRAMreadAddr;//LSB Address

xI2cTransfer1 (1, i2cDeviceAddr, 2, i2CWriteData, 0);//FRAM

xI2cTransfer1 (1, i2cDeviceAddr, 4, &i2CReadData[3], 1);

/*This has to be changed after MAC address of GRL is received from IEEE*/
i2CReadData[0] = 0x00;
i2CReadData[1] = 0x0a;
i2CReadData[2] = 0x35;
i2CReadData[3] = 0x00;
i2CReadData[4] = 0x55;
i2CReadData[5] = 0x55;
/*
* User logic to be added here.
* Errors to be stored in the status variable and returned
*/
/*
// Saving MAC address in the OCM memory at 0xFFFF FC00
// Create string to copy in the OCM
sprintf(ethAddr, "ethaddr=%02x:%02x:%02x:%02x:%02x:%02x\n", i2CReadData[0], i2CReadData[1], i2CReadData[2], i2CReadData[3], i2CReadData[4], i2CReadData[5]);
// Copy string to memory
for(i=0; i< strlen(ethAddr)+1; i++)
{
Xil_Out8(0xFFFFFC00+i, ethAddr[i]);
fsbl_printf(DEBUG_GENERAL,"%d \r\n", ethAddr[i]);
}
*/

fsbl_printf(DEBUG_INFO,"create pointer to OCM to store MAC Address\r\n");
char *p_env = (char*) 0xFFFFFC00;

fsbl_printf(DEBUG_INFO,"Store MAC Address to OCM\r\n");
for(i = 0; i < 6; i++)
{
xil_printf("%02x ", i2CReadData);
*p_env = i2CReadData;
p_env++;
}

fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n");

return (Status);
}

0 Kudos
jrhtech
Voyager
Voyager
7,263 Views
Registered: ‎10-04-2017

  What I find so annoying is that even though this issue is 2 years old is the Trenz still hasn't really documented the hidden FSBL code which I only figured out after have USB issues(and then MAC issues too)

  Instead of hiding the code is some ridiculous place where you have to find it and copy it why would you not just create a FSBL patch in your BSP so when people make their own builds based on your petalinux it just works.  

0 Kudos
jrhtech
Voyager
Voyager
6,766 Views
Registered: ‎10-04-2017
Another gotcha on this, if you change the preboot in your build but you have run saveenv in u-boot you will not get the defaults in the updated binary. Saveenv writes to eeprom and this version of the env takes priority over the built-in env even when u-boot has been updated. I ran run eraseenv in u-boot to erase the env in flash.
0 Kudos
gteague
Contributor
Contributor
6,608 Views
Registered: ‎03-16-2012

I have recent experience with this solution. I am using Petalinux 2017.4.

 

I followed the accepted solution. However, uboot could not access the OCM and repeatedly reset the PS.

 

See the details here:

 

https://forums.xilinx.com/t5/Embedded-Linux/Reading-MPSOC-OCM-from-UBoot/td-p/863789

 

In short, you need to add the following line to your platform-top.h file (in addition to the lines relating to CONFIG_PREBOOT) to enable access to OCM from uboot:

#define CONFIG_DEFINE_TCM_OCM_MMAP

 

This fixed it for me and everything is working correctly.

desulmelionel
Observer
Observer
4,606 Views
Registered: ‎06-12-2018

hey i am trying to achieve the same thing.

However after all the modification and a new build petalinux does not boot.

I am currently running 2018.1 did you run into the same issue if so what would the work around be.

0 Kudos