关于动态修改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]
			
			
			
						
			
 我要赚赏金
