PowerPC MPC8313E

最近更换mpc8313的phy芯片,由原来的lxt972Phy更换为DP83849I,在此记录下本人在驱动开发过程中的点滴记录,以备日后查询,基于vxbus的网络驱动,vxBus驱动的注册遵循一致的方法,驱动接口为:


 device_method_t dp83849PhyMethods[] =
    {
    DEVMETHOD(miiModeGet,      dp83849PhyModeGet),
    DEVMETHOD(miiModeSet,      dp83849PhyModeSet),
    DEVMETHOD(vxbDrvUnlink,    dp83849PhyInstUnlink),
    { 0, 0 }
    };
 
 struct drvBusFuncs dp83849PhyFuncs =
    {
    dp83849PhyDevInstInit,      /* devInstanceInit */
    dp83849PhyDevInstInit2,     /* devInstanceInit2 */
    dp83849PhyDevInstConnect    /* devInstanceConnect */
    };
 
struct vxbDevRegInfo dp83849PhyDevRegistration =
    {
    NULL,               /* pNext */
    VXB_DEVID_DEVICE,   /* devID */
    VXB_BUSID_MII,      /* busID = MII Bus */
    VXBUS_VERSION_3,      /* busVer */
    "dp83849Phy",        /* drvName */
    &dp83849PhyFuncs,       /* pDrvBusFuncs */
    dp83849PhyMethods,      /* pMethods */
    dp83849PhyProbe         /* devProbe */
    };
 
void dp83849PhyRegister(void)
    {
    vxbDevRegister (&dp83849PhyDevRegistration);
    return;
    }

要编写驱动,主要去实现上面模块中的相关功能,首先编写dp83849PhyProbe,在函数中识别flash的ID,编写其他相关的函数,接下来在sysLib.c中注册系统驱动


#include "Dp83849Phy.c"
void sysHwInit (void)
{
 dp83849PhyRegister();
}

接下来,在系统硬件配置hwconf.c中更改phyAddr地址,具体地址参照phy芯片硬件设计


const struct hcfResource motEtsecHEnd0Resources[] = 
    {
    { "regBase",    HCF_RES_INT,    { (void *)(CCSBAR + 0x24000) } },
    { "intr0",      HCF_RES_INT,    { (void *)INUM_TSEC1_TX} },
    { "intr0Level", HCF_RES_INT,    { (void *)INUM_TSEC1_TX } },
    { "intr1",      HCF_RES_INT,    { (void *)INUM_TSEC1_RX } },
    { "intr1Level", HCF_RES_INT,    { (void *)INUM_TSEC1_RX } },
    { "intr2",      HCF_RES_INT,    { (void *)INUM_TSEC1_ERR } },
    { "intr2Level", HCF_RES_INT,    { (void *)INUM_TSEC1_ERR } },
    { "phyAddr",    HCF_RES_INT,    { (void *)14 }},
    { "miiIfName",  HCF_RES_STRING, { (void *)"tsecMdio" } },
    { "miiIfUnit",  HCF_RES_INT,    { (void *)0 } }
    };

接下来,由于本次硬件设计采用RMII接口,所以在config.h中更改硬件配置字


/* RMII */
 
#define HRCW_HIGH_BYTE2     0x24 

接下来更改系统MAC寄存器,在vxbEtsecEnd.c中修改下列函数,根据系统硬件配置字设置ETSEC_ECNTRL寄存器的ETSEC_ECNTRL_R100M


LOCAL STATUS etsecLinkUpdate
    (
    VXB_DEVICE_ID pDev
    )
{
     switch (IFM_SUBTYPE(pDrvCtrl->etsecCurMedia))
        {
        case IFM_1000_T:
        case IFM_1000_SX:
            CSR_SETBIT_4(pDev, ETSEC_MACCFG2, ETSEC_IFMODE_GMII_TBI);
            /* R100M is "don't care" for gigE, but clear it anyway */
            CSR_CLRBIT_4(pDev, ETSEC_ECNTRL, ETSEC_ECNTRL_R100M);
            pDrvCtrl->etsecEndObj.mib2Tbl.ifSpeed = 1000000000;
            break;
 
        case IFM_100_TX:
            CSR_SETBIT_4(pDev, ETSEC_MACCFG2, ETSEC_IFMODE_MII);
            //CSR_SETBIT_4(pDev, ETSEC_MACCFG2, ETSEC_MACCFG2_PREAMBLE_LEN | ETSEC_IFMODE_MII | ETSEC_MACCFG2_PADCRC | ETSEC_MACCFG2_FULL_DUPLEX);
            /* Set R100M bit if configured for reduced pin mode RMII */
            if (CSR_READ_4(pDev, ETSEC_ECNTRL) & ETSEC_ECNTRL_RMM)
                CSR_SETBIT_4(pDev, ETSEC_ECNTRL, ETSEC_ECNTRL_R100M);
            //printf("100M ccfg2 = %08x ecntrl = %08x\n", CSR_READ_4(pDev, ETSEC_MACCFG2), CSR_READ_4(pDev, ETSEC_ECNTRL));
            pDrvCtrl->etsecEndObj.mib2Tbl.ifSpeed = 100000000;
            break;
 
        case IFM_10_T:
            CSR_SETBIT_4(pDev, ETSEC_MACCFG2, ETSEC_IFMODE_MII);
            //CSR_SETBIT_4(pDev, ETSEC_MACCFG2, ETSEC_MACCFG2_PREAMBLE_LEN | ETSEC_IFMODE_MII | ETSEC_MACCFG2_PADCRC | ETSEC_MACCFG2_FULL_DUPLEX);
            /* The R100M bit is always 0 for 10Mbps operation. */
            if(CSR_READ_4(pDev, ETSEC_ECNTRL) & ETSEC_ECNTRL_RMM)
                CSR_CLRBIT_4(pDev, ETSEC_ECNTRL, ETSEC_ECNTRL_R100M);
            //printf("10M ccfg2 = %08x ecntrl = %08x\n", CSR_READ_4(pDev, ETSEC_MACCFG2), CSR_READ_4(pDev, ETSEC_ECNTRL));
            pDrvCtrl->etsecEndObj.mib2Tbl.ifSpeed = 10000000;
            break;
 
        default:
            break;
        }
 
}

值此基本上已经完成驱动程序的修改,由于网络不通,无法加载系统镜像,无法调试,本人的解决办法是,先把vxWorks.bin通过仿真器烧写到flash固定位置,boot上电运行时,再从flash加载到RAM_LOW_ADDR地址处开始运行,这样在网络不通的情况下,可以加载系统镜像进行调试,所以修改bootsehll.c程序,并在autoboot函数中调用:


/*启动时从norflash中拷贝系统镜像到VXWORKS启动地址,然后转到此处执行zhb_2020.12.23*/
void copyVxToRam(void)
{
	char *pVxRamAddr = RAM_LOW_ADRS;
	char* pVxFlashAddr = FLASH_BASE_ADRS + 0x400000;
	int i = 0;
	int* pEnterAddr;
	FUNCPTR absEntry;
 
	for (i = 0; i < 0x300000; i++)
		pVxRamAddr[i] = pVxFlashAddr[i];
 
	pEnterAddr = (int*)pVxRamAddr;
	printf("start Vxworks at %08x.....\n", pEnterAddr);
	absEntry = pEnterAddr;
	(absEntry)();
}

编译boot程序和系统镜像,用仿真器烧写到flash中运行,下面就可以进行调试了。对于phy芯片的调用,可以利用vxBusShow查看设备pDev,然后在shell中用MII_READ,MII_WRITE进行测试


-> vxBusShow
Registered Bus Types:
  MII_Bus @ 0x00208d60
  Local_Bus @ 0x00206138
 
Registered Device Drivers:
  ppcIntCtlr at 0x00207904 on bus Local_Bus, funcs @ 0x002078f8
        VxBus version 2
  quiccIntCtlr at 0x00208a2c on bus Local_Bus, funcs @ 0x002089f8
  quiccTimerDev at 0x002068ec on bus Local_Bus, funcs @ 0x002068d0
        VxBus version 2
  motetsec at 0x002026b0 on bus Local_Bus, funcs @ 0x00202584
  ns16550 at 0x0020734c on bus Local_Bus, funcs @ 0x002072dc
  ns16550 at 0x00207304 on bus PCI_Bus, funcs @ 0x002072dc
  ppcDecTimerDev at 0x00208f00 on bus Local_Bus, funcs @ 0x00208ee4
  tsecMdio at 0x00208ea4 on bus Local_Bus, funcs @ 0x00208e78
  mv88E1x11Phy at 0x00208e38 on bus MII_Bus, funcs @ 0x00208e08
  lxt972Phy at 0x00207250 on bus MII_Bus, funcs @ 0x00207244
  bcm54xxPhy at 0x00208da8 on bus MII_Bus, funcs @ 0x00208d9c
  miiBus at 0x00208d18 on bus PCI_Bus, funcs @ 0x00208cbc
  miiBus at 0x00208cd8 on bus Local_Bus, funcs @ 0x00208cbc
  plbCtlr at 0x00206160 on bus Local_Bus, funcs @ 0x00206154
  dp83849Phy at 0x00202544 on bus MII_Bus, funcs @ 0x00202538
 
Busses and Devices Present:
  Local_Bus @ 0x0023f848 with bridge @ 0x002061a0
    Device Instances:
        quiccIntCtlr unit 0 on Local_Bus @ 0x00240808 with busInfo 0x00000000
        ppcIntCtlr unit 0 on Local_Bus @ 0x00240908 with busInfo 0x00000000
        tsecMdio unit 0 on Local_Bus @ 0x00240a08 with busInfo 0x00000000
        motetsec unit 0 on Local_Bus @ 0x00240b08 with busInfo 0x00000000
        motetsec unit 1 on Local_Bus @ 0x00240c08 with busInfo 0x00000000
        ppcDecTimerDev unit 0 on Local_Bus @ 0x00240d08 with busInfo 0x00000000
        quiccTimerDev unit 0 on Local_Bus @ 0x00240e08 with busInfo 0x00000000
        quiccTimerDev unit 1 on Local_Bus @ 0x00240f08 with busInfo 0x00000000
        ns16550 unit 0 on Local_Bus @ 0x00241008 with busInfo 0x00000000
        ns16550 unit 1 on Local_Bus @ 0x00241208 with busInfo 0x00000000
        miiBus unit 0 on Local_Bus @ 0x00241708 with busInfo 0x0023ff08
        miiBus unit 1 on Local_Bus @ 0x00245b08 with busInfo 0x0023ff48
    Orphan Devices:
        legacy unit 0 on Local_Bus @ 0x00241408 with busInfo 0x00000000
  MII_Bus @ 0x0023ff08 with bridge @ 0x00241708
    Device Instances:
        dp83849Phy unit 0 on MII_Bus @ 0x00245908 with busInfo 0x00000000
    Orphan Devices:
  MII_Bus @ 0x0023ff48 with bridge @ 0x00245b08
    Device Instances:
        dp83849Phy unit 1 on MII_Bus @ 0x00245d08 with busInfo 0x00000000
    Orphan Devices:
 
value = 1 = 0x1

对于以太网报文的测试,我们可以增加测试程序,从中断中捕获报文分析,测试以太网发送报文

 
LOCAL int etsecEndEncap
    (
    ETSEC_DRV_CTRL * pDrvCtrl,
    M_BLK_ID pMblk
    )
    {
    ETSEC_DESC * pDesc = NULL, * pFirst;
    ETSEC_TX_FCB * pFcb;
    M_BLK_ID pCurr, pStart;
    UINT32 firstIdx, lastIdx = 0;
    struct ether_header * eh;
    int used = 0, i;
    int j = 0;
 
   // printf("send net data ......\n");
    //for (j = 0; j < pMblk->mBlkHdr.mLen; j++)
     //   printf("%02x ", pMblk->mBlkHdr.mData[j]);
   // printf("\n");
}

测试以太网接收报文

 
void usrPrintNet(ST_INT port, ST_VOID* pM)
{
	char gsBuf[L2_DATA_MSG_SIZE];
	int i = 0;
	M_BLK_ID pMblk = (M_BLK_ID)pM;
 
	memcpy(gsBuf, pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen);
	if (g_debug_net == 1)
	{
		printf("revCnt = %d\n", gsvEthInfo[port].allPacketCount);
		for (i = 0; i < pMblk->mBlkHdr.mLen; i++)
			printf("%02x ", gsBuf[i]);
		printf("\n");
	}
}
LOCAL void etsecEndRxHandle
    (
    void * pArg
    )
{
    usrPrintNet(pDrvCtrl->etsecDev->unitNumber,pMblk);
}

注意:如果你的驱动程序在boot和系统镜像中存在两份,务必保持驱动程序的一致性,否则可能出现奇怪的现象,调试中发现以太网发送中断不能进,最后发现是boot和vxWorks中的驱动程序不一致导致的,折腾了两天,我也是醉了