这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [原创]关于动态修改VXWORKS下MAC地址的方法!

共8条 1/1 1 跳转至

[原创]关于动态修改VXWORKS下MAC地址的方法!

菜鸟
2007-04-24 19:27:40     打赏

关于动态修改VXWORKS下MAC地址的问题!
由于我用的FREESCALE的COLDFIRE MCF527X系列的芯片,他的MAC地址一般是放到FLASH的最末尾的一个扇区里的最后的部分!
如下图:
CPU: Motorola M5275AB. Processor #0.
Memory Size: 0x2008000. BSP version 1.2/0.
WDB Comm Type: WDB_COMM_END
WDB: Ready.
-> d 0xffffff00
ffffff00: 2c30 2974 723a 7678 776f 726b 7320 653d *,0)tr:vxworks e=*
ffffff10: 3139 322e 3136 382e 302e 3135 3520 683d *192.168.0.155 h=*
ffffff20: 3139 322e 3136 382e 302e 3337 2067 3d31 *192.168.0.37 g=1*
ffffff30: 3932 2e31 3638 2e30 2e32 2075 3d74 7220 *92.168.0.2 u=tr *
ffffff40: 7077 3d31 2074 6e3d 7472 206f 3d6d 6f74 *pw=1 tn=tr o=mot*
ffffff50: 6665 6331 00ff ffff ffff ffff ffff ffff *fec1............*
ffffff60: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff70: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff80: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffff90: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffa0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffb0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffc0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffd0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
ffffffe0: ffff ffff ffff ffff ffff ffff ffff ffff *................*
fffffff0: ffff ffff ffff ffff 00a0 1e52 7588 ff00 *...........Ru...*
value = 21 = 0x15
00a0 1e52 7588 就是MAC地址!
系统启动的时候,自己会从这LOAD MAC地址!
用的是以下的函数:
/*****************************************************************************
*
* sysFecEnetAddrGet - return an ethernet address for the board
*
* RETURNS: OK
*
* NOMANUAL
*/

STATUS sysFecEnetAddrGet
(
UINT32 motCpmAddr,
UCHAR * enetAddr
)
{
#ifndef ETHERNET_ADR_SET
memcpy(enetAddr, motFecEnetAddr, 6);
return(OK);
#else
int index;
char enetAddrTemp[6];
STATUS return_status;

return_status = sysEnetAddrGet( 0, (UINT8 *)enetAddrTemp);
/* swap bytes */
for ( index = 0; index < 6; index++)
{
enetAddr[index] = enetAddrTemp[5 - index];
}

#endif
}

#endif /* INCLUDE_END */

其实关键的是这个函数:sysEnetAddrGet
/*******************************************************************************
*
* sysEnetAddrGet - get the hardware Ethernet address
*
* This routine determines the unique Ethernet address for the CPU board and
* copies it to <addr>, such that the low-order byte is `addr[0]' and the
* high-order byte is `addr[5]'. The memory area pointed to by <addr> is
* six bytes.
*
* RETURNS: OK, or ERROR if the Ethernet address cannot be returned.
*/

STATUS sysEnetAddrGet
(
int unit,
UINT8 * addr
)
{
char bytes[7];

if (unit != 0)
return (ERROR);

/* read the variable address bytes */

sysNvRamGet (bytes, 6, ENET_NVRAM_OFFSET);

/* if the network address is not initialized, return ERROR */
if ( (bytes[0] == -1) && (bytes[1] == -1)
&& (bytes[2] == -1) && (bytes[3] == -1)
&& (bytes[4] == -1) && (bytes[5] == -1))
{
return (ERROR);
}

addr[5] = ((ENET_DEFAULT & 0x0000ff00) >> 8); /* High order */
addr[4] = ((ENET_DEFAULT & 0x00ff0000) >> 16);
addr[3] = ((ENET_DEFAULT & 0xff000000) >> 24);
addr[2] = bytes[3];
addr[1] = bytes[4];
addr[0] = bytes[5]; /* Low order */

return (OK);
}
这是获取MAC地址的函数:sysNvRamGet
STATUS sysNvRamGet
(
char *string, /* where to copy non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)

{
char *read_ptr;

if ((strLen < 0) || (offset < 0 )
|| ((offset + strLen) > NV_RAM_SIZE))
return (ERROR);

read_ptr = (char *)offset; /* boot line begins at <offset> = 0 */

while (strLen--)
{
*string = NV_RAM_READ (read_ptr);
string++, read_ptr++;
}
*string = EOS;

return (OK);
}


但是怎么设呢???
******************************************************************************
*
* sysEnetAddrSet - set the Ethernet address for this board
*
* This routine sets the variable portion of the Ethernet address, the first
* three bytes contain a fixed manufacturer's code, while the last 3 bytes are
* set locally, to generate a unique Ethernet address on the local network.
*
* RETURN: OK, always.
*
* NOMANUAL
*/

STATUS sysEnetAddrSet
(
char byte5, /* Ethernet address high order byte */
char byte4,
char byte3,
char byte2,
char byte1,
char byte0 /* Ethernet address low order byte */
)
{
char bytes[6];

/* Save six bytes in NVRAM */

bytes[0] = byte5; bytes[1] = byte4; bytes[2] = byte3;
bytes[3] = byte2; bytes[4] = byte1; bytes[5] = byte0;

sysNvRamSet (bytes, 6, ENET_NVRAM_OFFSET);

return (OK);
}
#endif /* ETHERNET_ADR_SET */
再者最核心的是调用:sysNvRamSet;
/*******************************************************************************
*
* sysNvRamSet - write to non-volatile RAM
*
* This routine copies a specified string into non-volatile RAM.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamGet()
*/

STATUS sysNvRamSet
(
char *string, /* string to be copied into non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)

{
char *NvBuf, *srcBuf;
FLASH flash;
STATUS result;
int index, buint8s;
void * blocks[1];


if ((offset < 0)
|| (strLen < 0)
|| ((offset + strLen) > NV_RAM_SIZE))
return ERROR;

/* get a copy of the buffer
* first, define a buffer large enough for a whole flash block
* We use memory normally assigned to the booted image.
*/
NvBuf = (char *)0x1000;
blocks[0]=(void *)NvBuf;

/* copy the contents of NVRAM into the buffer */
srcBuf = (char *)PARAM_SECTOR_ADDRESS;
for ( index = 0; index < (PARAM_SEC_SIZE - NV_RAM_SIZE); index++)
{
NvBuf[index] = srcBuf[index];
}

result = sysNvRamGet
(
&NvBuf[PARAM_SEC_SIZE - NV_RAM_SIZE], /* where to copy */
NV_RAM_SIZE - 1, /* maximum number of bytes to copy */
0 /* byte offset into non-volatile RAM */
);

/* copy the new parameters into the buffer */
while (strLen--)
{
NvBuf[PARAM_SEC_SIZE - NV_RAM_SIZE + offset] = *string;
string++, offset++;
}

flash.blockptr=(void *)blocks;
flash.blocksz = PARAM_SEC_SIZE;
flash.sector=PARAM_SEC;
flash.numblocks=1;

buint8s = am29xxxx_write((AM29XXXX *)ROM_BASE_ADRS, &flash, NULL, NULL);

if (buint8s != PARAM_SEC_SIZE)
{
printf("Flash programming error: %d uint8s of %d written!\n",
buint8s, PARAM_SEC_SIZE);
}

/* verify data */
for ( index = 0; index < (PARAM_SEC_SIZE); index++)
{
if ( NvBuf[index] != srcBuf[index])
{
result = ERROR;
goto exit;
}
}

exit:
return result;
}

Press any key to stop auto-boot...
7
在启动的时候输入N就可以修改MAC地址,其实也是调用的sysNvRamSet函数;
[VxWorks Boot]: N
Current Ethernet Address is: 00:a0:1e:52:75:88
Modify only the last 3 bytes (board unique portion) of Ethernet Address.
The first 3 bytes are fixed at manufacturer's default address block.
00- 00
a0- a0
1e- 1e
52- 52
75- 75
88- 88

New Ethernet Address is: 00:a0:1e:52:75:88

我就想要是在 VXWORKS启动后自己也调用sysNvRamSet函数,不是就可以动态的修改MAC地址了么????
但试了以下,在VXWORKS里调用sysNvRamSet函数,就会死机为什么呢??????
仔细研究了以下:sysNvRamSet函数里的东西发现:
char *NvBuf,
NvBuf = (char *)0x1000;
(char *)0x1000是什么不就是VXWORKS的启动地址么???
Attached TCP/IP interface to motfec0.
0x1fa5b00 (tNetTask): duplicate IP address 192.168.0.155 sent from ethernet addr
ess 00:04:5a:44:8b:91 to target ethernet address 00:a0:1e:52:75:88
Warning: no netmask specified.
Attaching network interface lo0... done.
Loading... 845496 + 292816
Starting at 0x1000...?????
怎么能这样定义:
原来问题在这里:

把char *NvBuf,修改以下:
char NvBuf[64*1024], *srcBuf;/*NvBuf的大小为最后一个扇区的大小多了也无所谓,小了可不行!*/
//NvBuf = (char *)0x1000;
这就不要了!这样就可以动态修改修改MAC地址了!但是要启动后VXWORKS才会去读新的MAC地址!
其实这sysNvRamSet还有好多的功能,就是往FLASH里写数,就完全当做NVRAM用了!不光修改MAC地址,具体的自己用吧!

sysNvRamSet(bytes, 6, ENET_NVRAM_OFFSET);只要把ENET_NVRAM_OFFSET这偏移量修改一下就可以了!
通过以下的函数读出来就可以:
/******************************************************************************
*
* sysNvRamGet - get the contents of non-volatile RAM
*
* This routine copies the contents of non-volatile memory into a specified
* string. The string is terminated with an EOS.
*
* RETURNS: OK, or ERROR if access is outside the non-volatile RAM range.
*
* SEE ALSO: sysNvRamSet()
*/

STATUS sysNvRamGet
(
char *string, /* where to copy non-volatile RAM */
int strLen, /* maximum number of bytes to copy */
int offset /* byte offset into non-volatile RAM */
)

{
char *read_ptr;

if ((strLen < 0) || (offset < 0 )
|| ((offset + strLen) > NV_RAM_SIZE))
return (ERROR);

read_ptr = (char *)offset; /* boot line begins at <offset> = 0 */

while (strLen--)
{
*string = NV_RAM_READ (read_ptr);
string++, read_ptr++;
}
*string = EOS;

return (OK);
}
以上的函数MCF527X的BSP里就有的!只要你装了TORNADO2.2 for coldfire!
至于其他的平台大家自己参照吧!思路已经给出来了!


[align=right][color=#000066][此贴子已经被作者于2007-4-24 11:50:14编辑过][/color][/align]



关键词: 原创     关于     动态     修改     VXWORKS     地址     方法    

菜鸟
2007-04-29 08:35:00     打赏
2楼

感觉挺好的!清晰

duplicate IP address 192.168.0.155 曾经困扰了我许久,有碰到IP冲突就死机的情况,这下找到思路去分析分析了。

谢谢


菜鸟
2007-05-09 23:21:00     打赏
3楼
忒好了

菜鸟
2007-05-10 06:06:00     打赏
4楼
有没有不重新启动直接修改mac的方法?

菜鸟
2007-05-10 21:34:00     打赏
5楼

有没有不重新启动直接修改mac的方法?"

应该也可以的你把以太网的函数重新引导一次!

你自己试验吧,结果告诉大家!


菜鸟
2007-05-11 19:13:00     打赏
6楼

好文章,坛子里面好久都没有这么好的文章了。

其实我们也可以在flash中存储很多启动初始化的信息,并且可以动态修改保存,就像在windows中使用配置文件一样。

看了你的文章确实收获不小呀!


菜鸟
2007-06-02 22:43:00     打赏
7楼

hao


菜鸟
2007-06-13 22:03:00     打赏
8楼
我是在usrBootLineInit 中把strcpy (BOOT_LINE_ADRS, DEFAULT_BOOT_LINE)替换成自己的函数,使其可以去读取FLASH中存的参数启动(MAC,IP,启动方式等),然后在bootCmdLoop或应用程序中可以添加修改FALSH中启动参数的命令和函数

共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]