/* * Copyright (c) 2001, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Author: Adam Dunkels * * $Id: netdev.c,v 1.8 2006/06/07 08:39:58 adam Exp $ */ /*---------------------------------------------------------------------------*/ #include "uip.h" #include "uip_arp.h" #include "header.h" #include "stm32_eth.h" /* STM32 ethernet library */ #include /* for memcpy */ /*---------------------------------------------------------------------------*/ #define NETDEV_DEFAULT_MACADDR0 (0x08) #define NETDEV_DEFAULT_MACADDR1 (0x00) #define NETDEV_DEFAULT_MACADDR2 (0x27) #define NETDEV_DEFAULT_MACADDR3 (0x69) #define NETDEV_DEFAULT_MACADDR4 (0x5B) #define NETDEV_DEFAULT_MACADDR5 (0x45) /*---------------------------------------------------------------------------*/ static void netdev_TxDscrInit(void); static void netdev_RxDscrInit(void); /*---------------------------------------------------------------------------*/ typedef union _TranDesc0_t { uint32_t Data; struct { uint32_t DB : 1; uint32_t UF : 1; uint32_t ED : 1; uint32_t CC : 4; uint32_t VF : 1; uint32_t EC : 1; uint32_t LC : 1; uint32_t NC : 1; uint32_t LSC : 1; uint32_t IPE : 1; uint32_t FF : 1; uint32_t JT : 1; uint32_t ES : 1; uint32_t IHE : 1; uint32_t : 3; uint32_t TCH : 1; uint32_t TER : 1; uint32_t CIC : 2; uint32_t : 2; uint32_t DP : 1; uint32_t DC : 1; uint32_t FS : 1; uint32_t LSEG : 1; uint32_t IC : 1; uint32_t OWN : 1; }; } TranDesc0_t, * pTranDesc0_t; typedef union _TranDesc1_t { uint32_t Data; struct { uint32_t TBS1 :13; uint32_t : 3; uint32_t TBS2 :12; uint32_t : 3; }; } TranDesc1_t, * pTranDesc1_t; typedef union _RecDesc0_t { uint32_t Data; struct { uint32_t RMAM_PCE : 1; uint32_t CE : 1; uint32_t DE : 1; uint32_t RE : 1; uint32_t RWT : 1; uint32_t FT : 1; uint32_t LC : 1; uint32_t IPHCE : 1; uint32_t LS : 1; uint32_t FS : 1; uint32_t VLAN : 1; uint32_t OE : 1; uint32_t LE : 1; uint32_t SAF : 1; uint32_t DERR : 1; uint32_t ES : 1; uint32_t FL :14; uint32_t AFM : 1; uint32_t OWN : 1; }; } RecDesc0_t, * pRecDesc0_t; typedef union _recDesc1_t { uint32_t Data; struct { uint32_t RBS1 :13; uint32_t : 1; uint32_t RCH : 1; uint32_t RER : 1; uint32_t RBS2 :14; uint32_t DIC : 1; }; } RecDesc1_t, * pRecDesc1_t; typedef union _EnetDmaDesc_t { uint32_t Data[4]; // Rx DMA descriptor struct { RecDesc0_t RxDesc0; RecDesc1_t RxDesc1; uint32_t * pBuffer; union { uint32_t * pBuffer2; union _EnetDmaDesc_t * pEnetDmaNextDesc; }; } Rx; // Tx DMA descriptor struct { TranDesc0_t TxDesc0; TranDesc1_t TxDesc1; uint32_t * pBuffer1; union { uint32_t * pBuffer2; union _EnetDmaDesc_t * pEnetDmaNextDesc; }; } Tx; } EnetDmaDesc_t, * pEnetDmaDesc_t; /*---------------------------------------------------------------------------*/ uint8_t RxBuff[UIP_CONF_BUFFER_SIZE] __attribute__ ((aligned (4))); uint8_t TxBuff[UIP_CONF_BUFFER_SIZE] __attribute__ ((aligned (4))); EnetDmaDesc_t EnetDmaRx __attribute__((aligned (128))); EnetDmaDesc_t EnetDmaTx __attribute__ ((aligned (128))); /*---------------------------------------------------------------------------*/ void netdev_init(void) { GPIO_InitTypeDef GPIO_InitStructure; ETH_InitTypeDef ETH_InitStructure; /* Enable ETHERNET clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx | RCC_AHB1Periph_ETH_MAC_PTP, ENABLE); /* Enable GPIOs clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE); /* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /*Select RMII Interface*/ SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII); /* ETHERNET pins configuration */ /* PA ETH_RMII_REF_CLK: PA1 ETH_RMII_MDIO: PA2 ETH_RMII_MDINT: PA3 ETH_RMII_CRS_DV: PA7 */ /* Configure PA1, PA2, PA3 and PA7*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Connect PA1, PA2, PA3 and PA7 to ethernet module*/ GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); /* PB ETH_RMII_TX_EN: PG11 */ /* Configure PG11*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); /* Connect PG11 to ethernet module*/ GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH); /* PC ETH_RMII_MDC: PC1 ETH_RMII_RXD0: PC4 ETH_RMII_RXD1: PC5 */ /* Configure PC1, PC4 and PC5*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); /* Connect PC1, PC4 and PC5 to ethernet module*/ GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); /* PG ETH_RMII_TXD0: PG13 ETH_RMII_TXD1: PG14 */ /* Configure PG13 and PG14*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); /* Connect PG13 and PG14 to ethernet module*/ GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH); /* Reset ETHERNET on AHB Bus */ ETH_DeInit(); /* Software reset */ ETH_SoftwareReset(); /* Wait for software reset */ while(ETH_GetSoftwareResetStatus()==SET); /* ETHERNET Configuration ------------------------------------------------------*/ /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */ ETH_StructInit(Ð_InitStructure); /* Fill ETH_InitStructure parametrs */ /*------------------------ MAC -----------------------------------*/ ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable ; ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable; ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable; ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable; ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Enable; ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable; ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect; ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex; ETH_InitStructure.ETH_Speed = ETH_Speed_100M; unsigned int PhyAddr; union { uint32_t HI_LO; struct { uint16_t LO; uint16_t HI; }; } PHYID; for(PhyAddr = 0; 32 > PhyAddr; PhyAddr++) { // datasheet for the ks8721bl ethernet controller (http://www.micrel.com/_PDF/Ethernet/datasheets/ks8721bl-sl.pdf) // page 20 --> PHY Identifier 1 and 2 PHYID.HI = ETH_ReadPHYRegister(PhyAddr,2); // 0x0022 PHYID.LO = ETH_ReadPHYRegister(PhyAddr,3); // 0x1619 if ((0x00221619 == PHYID.HI_LO) || (0x0007C0F1 == PHYID.HI_LO)) break; } /* Configure Ethernet */ ETH_Init(Ð_InitStructure, PhyAddr); netdev_TxDscrInit(); netdev_RxDscrInit(); ETH_Start(); } /*---------------------------------------------------------------------------*/ void netdev_init_mac(void) { struct uip_eth_addr macAddress; /* set the default MAC address */ macAddress.addr[0] = NETDEV_DEFAULT_MACADDR0; macAddress.addr[1] = NETDEV_DEFAULT_MACADDR1; macAddress.addr[2] = NETDEV_DEFAULT_MACADDR2; macAddress.addr[3] = NETDEV_DEFAULT_MACADDR3; macAddress.addr[4] = NETDEV_DEFAULT_MACADDR4; macAddress.addr[5] = NETDEV_DEFAULT_MACADDR5; uip_setethaddr(macAddress); } /*---------------------------------------------------------------------------*/ unsigned int netdev_read(void) { uint32_t size; /*check for validity*/ if(0 == EnetDmaRx.Rx.RxDesc0.OWN) { /*Get the size of the packet*/ size = EnetDmaRx.Rx.RxDesc0.FL; // CRC memcpy(uip_buf, RxBuff, size); //string.h library*/ } else { return 0; } /* Give the buffer back to ENET */ EnetDmaRx.Rx.RxDesc0.OWN = 1; /* Start the receive operation */ ETH->DMARPDR = 1; /* Return no error */ return size; } /*---------------------------------------------------------------------------*/ void netdev_send(void) { while(EnetDmaTx.Tx.TxDesc0.OWN); /* Copy the application buffer to the driver buffer Using this MEMCOPY_L2L_BY4 makes the copy routine faster than memcpy */ memcpy(TxBuff, uip_buf, uip_len); /* Assign ENET address to Temp Tx Array */ EnetDmaTx.Tx.pBuffer1 = (uint32_t *)TxBuff; /* Setting the Frame Length*/ EnetDmaTx.Tx.TxDesc0.Data = 0; EnetDmaTx.Tx.TxDesc0.TCH = 1; EnetDmaTx.Tx.TxDesc0.LSEG = 1; EnetDmaTx.Tx.TxDesc0.FS = 1; EnetDmaTx.Tx.TxDesc0.DC = 0; EnetDmaTx.Tx.TxDesc0.DP = 0; EnetDmaTx.Tx.TxDesc1.Data = 0; EnetDmaTx.Tx.TxDesc1.TBS1 = (uip_len&0xFFF); /* Start the ENET by setting the VALID bit in dmaPackStatus of current descr*/ EnetDmaTx.Tx.TxDesc0.OWN = 1; /* Start the transmit operation */ ETH->DMATPDR = 1; } /*---------------------------------------------------------------------------*/ static void netdev_RxDscrInit(void) { /* Initialization */ /* Assign temp Rx array to the ENET buffer */ EnetDmaRx.Rx.pBuffer = (uint32_t *)RxBuff; /* Initialize RX ENET Status and control */ EnetDmaRx.Rx.RxDesc0.Data = 0; /* Initialize the next descriptor- In our case its single descriptor */ EnetDmaRx.Rx.pEnetDmaNextDesc = &EnetDmaRx; EnetDmaRx.Rx.RxDesc1.Data = 0; EnetDmaRx.Rx.RxDesc1.RER = 0; // end of ring EnetDmaRx.Rx.RxDesc1.RCH = 1; // end of ring /* Set the max packet size */ EnetDmaRx.Rx.RxDesc1.RBS1 = UIP_CONF_BUFFER_SIZE; /* Setting the VALID bit */ EnetDmaRx.Rx.RxDesc0.OWN = 1; /* Setting the RX NEXT Descriptor Register inside the ENET */ ETH->DMARDLAR = (uint32_t)&EnetDmaRx; } /*---------------------------------------------------------------------------*/ static void netdev_TxDscrInit(void) { /* ENET Start Address */ EnetDmaTx.Tx.pBuffer1 = (uint32_t *)TxBuff; /* Next Descriptor Address */ EnetDmaTx.Tx.pEnetDmaNextDesc = &EnetDmaTx; /* Initialize ENET status and control */ EnetDmaTx.Tx.TxDesc0.TCH = 1; EnetDmaTx.Tx.TxDesc0.Data = 0; EnetDmaTx.Tx.TxDesc1.Data = 0; /* Tx next set to Tx descriptor base */ ETH->DMATDLAR = (uint32_t)&EnetDmaTx; }