导 航┆主 站┆文 章┆资 料┆下 载┆美 食┆读 书┆笑 话┆博 客┆论 坛
>> Tony嵌入式开发论坛静态版首页
查看完全版本:Tony嵌入式开发论坛

 

    动态修改VXWORKS下MAC地址的问题(转)
    作者:chenlei188 时间:2008-8-29 20:55:15

    在另一个论坛看到的,呼声比较高;

    转:

    由于我用的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!
    至于其他的平台大家自己参照吧!思路已经给出来了

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:lastwing 时间:2008-9-5 15:44:30

    那行

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:tearring 时间:2008-9-4 12:39:29

    还是懂硬件的好啊

    学习学习

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:maomaotr 时间:2008-9-1 20:32:17

    后来发现PPC都是通过E2ROM设置的,比放在flash里面方便多了!

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:chenlei188 时间:2008-9-1 20:05:54

    小弟,佩服佩服!~~

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:maomaotr 时间:2008-9-1 14:53:42

    这是我写的,我记得放在了Amine的论坛里面!

    几年前写的,MCF527X操作的是自己的flash当成NVRAM!

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------


    作者:MyForever 时间:2008-9-1 16:03:59

    maomaotr弄过的平台很多啊

    佩服一下,6.x的修改命令是M好像

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------



查看完全版本:Tony嵌入式开发论坛
Copyright 2006-2008 Cevx.Com Cevx.Net 制作 版权所有
网友发帖仅代表个人观点,与本论坛立场无关