]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/commitdiff
eth.c simplified - transmit written as blocking operation till packet is transmitted
authorJan Dolezal <pm.jenik@gmail.com>
Mon, 2 Sep 2013 10:27:16 +0000 (12:27 +0200)
committerJan Dolezal <pm.jenik@gmail.com>
Mon, 2 Sep 2013 10:27:16 +0000 (12:27 +0200)
rpp/include/rpp/eth.h
rpp/include/sys/hw_reg_access.h
rpp/src/rpp/eth.c
rpp/src/sys/notification.c
rpp/src/sys/sys_startup.c

index c821358925b300e0e671ecd80a07d8bf901a0ab0..c0c00b3133f6e516239c04aa7cbb2bae4efb7c89 100644 (file)
 #include "os/os.h"
 #include "lwip/netif.h"
 
-#define TICKS_PHY_AUTONEG  4000
-#define PHY_LINK_MONITOR_INT      0 /* turn on handling interrupt risen when link status is changed (cable out or in) */
+#define TICKS_PHY_AUTONEG         4000
+#define PHY_LINK_MONITOR_INT      0 /* turn on handling interrupt - not implemented now */
 
 /* this MAC address is used when user put NULL on the right place when calling postInit function */
-#define RPP_MAC_ADDR {0x12,0x34,0x56,0x78,0x9a,0xbc}
+#define RPP_MAC_ADDR             {0x12,0x34,0x56,0x78,0x9a,0xbc}
 #if STATIC_IP_ADDRESS
-#define RPP_IP_ADDR        0xC0A8F701 /* 192.168.247.1   IP4_ADDR(rppip, 192,168,0,10);       */
-#define RPP_NETMASK        0xFFFFFF00 /* 255.255.255.0   IP4_ADDR(rppnetmask, 255,255,255,0); */
-#define RPP_GW             0xC0A8F7FE /* 192.168.247.254 IP4_ADDR(rppgw, 192,168,0,254);      */
+#define RPP_IP_ADDR               0xC0A8F701 /* 192.168.247.1   IP4_ADDR(rppip, 192,168,0,10);       */
+#define RPP_NETMASK               0xFFFFFF00 /* 255.255.255.0   IP4_ADDR(rppnetmask, 255,255,255,0); */
+#define RPP_GW                    0xC0A8F7FE /* 192.168.247.254 IP4_ADDR(rppgw, 192,168,0,254);      */
 #endif
 
-#define NO_PHY_ALIVE       -1
-#define DFLT_PHY_NOT_ALIVE -1
-#define UNKN_DUPLEX_MODE   -2 /* this could mean that autonegotiation was not completed yet */
-#define MACADDR_NOT_SET    -3
-#define PHY_LINK_DOWN      -4
+#define NO_PHY_ALIVE             -1
+#define DFLT_PHY_NOT_ALIVE       -1
+#define UNKN_DUPLEX_MODE         -2 /* this could mean that autonegotiation was not completed yet */
+#define MACADDR_NOT_SET          -3
+#define PHY_LINK_DOWN            -4
 
-#define NETIF_ADD_ERR      -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
-#define DHCP_MEM_ERR       -11
-#define DHCP_BIND_TIMEOUT  -12
+#define NETIF_ADD_ERR            -10 /* could be one of previous, except PHY_LINK_DOWN - currently */
+#define DHCP_MEM_ERR             -11
+#define DHCP_BIND_TIMEOUT        -12
 
+#ifdef DEBUG
 #define rpp_debug_printf rpp_sci_printf
+#else
+#define rpp_debug_printf(...)
+#endif
+
+/**
+ * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
+ */
+#define MAC_BIG_LETTERS           1
 
 /**
  * ETH module system startup initialization.
@@ -87,10 +96,6 @@ int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray);
  */
 uint32_t rpp_eth_phylinkstat(uint32_t instNum);
 
-/**
- * configures whether rpp_eth_get_macAddrStr() creates string with big or small latin letters
- */
-#define MAC_BIG_LETTERS 1
 /**
  * Fills macStr field with MAC address of given network interface instance as 'string'
  *
@@ -102,14 +107,20 @@ uint32_t rpp_eth_phylinkstat(uint32_t instNum);
 void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr);
 
 /**
- * Fills ipStr field with IP address in ip_addr_t as 'string'
+ * Fills ipStr field with IP address in ip_addr_t as 'string';
+ * prepares an IP address to ipStr in form of null terminated string;
+ * each byte of ip is converted to one of 4 field in IPv4 IP address format 0xAABBCCDD -> "aaa.bbb.ccc.ddd"
  *
  * @note up to 16 bytes will be filled {1-3 * 4 IP fields + 3 dots + 1 null termination}
  *
+ *
  * @param ip ip address to be converted
  * @param ipStr pointer to string where ip will be filled as text
  */
-inline void rpp_eth_getIPDecimalStr(ip_addr_t ip, uint8_t *ipStr);
+inline void rpp_eth_getIPDecimalStr(ip_addr_t ip, uint8_t *ipStr)
+{
+       snprintf((char *)ipStr, 16, "%d.%d.%d.%d",(ip.addr >> 24),((ip.addr >> 16) & 0xff),((ip.addr >> 8) & 0xff),(ip.addr & 0xff));
+}
 
 /**
  * Fills ip.addr with converted ipstr. Checks for correct format of IP string
index f7e376b9f147324c3869093fa6037af43334cdd3..aa8a793c2dec412845e2b74e1f928cd46aeae306 100644 (file)
 //
 //*****************************************************************************
 #define HWREG(x)                                                              \
-        (*((volatile unsigned long *)(x)))
+        (*((volatile unsigned int *)(x)))
 #define HWREGH(x)                                                             \
         (*((volatile unsigned short *)(x)))
 #define HWREGB(x)                                                             \
         (*((volatile unsigned char *)(x)))
 #define HWREGBITW(x, b)                                                       \
-        HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 |                \
-              (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
+        HWREG(((unsigned int)(x) & 0xF0000000) | 0x02000000 |                \
+              (((unsigned int)(x) & 0x000FFFFF) << 5) | ((b) << 2))
 #define HWREGBITH(x, b)                                                       \
-        HWREGH(((unsigned long)(x) & 0xF0000000) | 0x02000000 |               \
-               (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
+        HWREGH(((unsigned int)(x) & 0xF0000000) | 0x02000000 |               \
+               (((unsigned int)(x) & 0x000FFFFF) << 5) | ((b) << 2))
 #define HWREGBITB(x, b)                                                       \
-        HWREGB(((unsigned long)(x) & 0xF0000000) | 0x02000000 |               \
-               (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))
+        HWREGB(((unsigned int)(x) & 0xF0000000) | 0x02000000 |               \
+               (((unsigned int)(x) & 0x000FFFFF) << 5) | ((b) << 2))
 
 
 
index 2d3465083b9575cc208ca6637799324fae976bb1..980b6cc571cc57b3897dc6986a7eb62525dfdac1 100644 (file)
 /* Number of EMAC Instances */
 #define MAX_EMAC_INSTANCE         1
 
-/* config whether only one task for driver will be used *//* this controls, whether there will be one task handling interrupts for receive, send bd handeling or link status change or even receive threshold */
-/* only one task should be used due to stability of system (it seems that LwIP doesn't handle it well when it has separate tasks for receive and send bd handler) / memory savings (in fact it ate so much memory, that it fell often) */
-#define ONE_DRIVER_TASK           0
-
-/*
- * if this is set, the link value is set only once upon start/cable connection
- * it this is not set, then each time cable is plugged or unplugged, the interface link status is updated
- * and when dhcp is enabled, it is negotiated
- */
-#define ONCE_LINK_SETUP            1
-
 #define DEFAULT_PHY_ADDR          0x1
 #define FIND_FIRST_PHY_ALIVE      1 /* or use default (phy_address: 1) */
 #define NUM_OF_PHYs               32
@@ -133,6 +122,8 @@ static struct netif hdkNetIF[MAX_EMAC_INSTANCE];
 /* rpp startup init indicator */
 static boolean_t initialized = FALSE, postInitialized = FALSE;
 
+boolean_t sendDone = TRUE;
+
 /* free pbuf notification */
 #if !NO_SYS
 xSemaphoreHandle pbufFreed;
@@ -164,12 +155,6 @@ void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
        macStr[outindex] = '\0';
 }
 
-/* prepares an IP address to ipStr in form of null terminated string; each byte of ip is converted to one of 4 field in IPv4 IP address format 0xAABBCCDD -> "aaa.bbb.ccc.ddd" */
-inline void rpp_eth_getIPDecimalStr(ip_addr_t ip, uint8_t *ipStr)
-{
-       snprintf((char *)ipStr, 16, "%d.%d.%d.%d",(ip.addr >> 24),((ip.addr >> 16) & 0xff),((ip.addr >> 8) & 0xff),(ip.addr & 0xff));
-}
-
 /* @param ip will be filled accroding to content of ipstr */
 err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
 {
@@ -253,20 +238,6 @@ err_t rpp_eth_hw_init(struct hdkif *hdkif);
  */
 err_t rpp_eth_hw_init_postInit(struct netif *netif);
 
-#if ONE_DRIVER_TASK
-/*
- * Task which handles driver's stuff
- */
-void rpp_eth_driver(void *arg);
-#endif
-
-#if PHY_LINK_MONITOR_INT
-/*
- * function which handles changes of link status
- */
-void linkStatusChanged(void *arg);
-#endif
-
 /********************************************** utility functions **********************************************/
 
 /*
@@ -354,9 +325,6 @@ int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
     int8_t retVal = SUCCESS;
     struct netif *netif = &hdkNetIF[instNum];
     u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
-#ifdef DEBUG
-    uint8_t ipString[16];
-#endif
 
     /* ----- lwIP stuff ----- */
     struct ip_addr ip_addr;
@@ -403,37 +371,18 @@ int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
 
     hdkif = (struct hdkif *) netif->state;
 #if !NO_SYS
-    /* TODO: rewrite these to functions from sys_arch.* not only here for compatibility with other systems then freeRTOS if it is possible (does not seem likely now) */
     /* ----- freeRTOS elements ----- */
     /* semaphore blocking receive task (rpp_eth_recv_raw) from receive operation, till RX interrupt occurs and notify it */
     vSemaphoreCreateBinary(hdkif->goRX);
     vSemaphoreCreateBinary(hdkif->goTX);
-#if PHY_LINK_MONITOR_INT
-    vSemaphoreCreateBinary(hdkif->goLink);
-#endif
-       /* create semaphore notificating that pbuf was freed FIXME: bad solution */
-       vSemaphoreCreateBinary(pbufFreed);/*
-       if( pbufFreed == NULL ){
-               rpp_debug_printf((const char *) "Insufficient memory.");
-       }*/
-#if ONE_DRIVER_TASK
-    xTaskCreate( rpp_eth_driver, "ethDriver", 250, netif, 0, NULL);
-#else /* ONE_DRIVER_TASK */
+       /* create semaphore notificating that pbuf was freed */
+       vSemaphoreCreateBinary(pbufFreed);
     /* run task rpp_eth_recv_raw */
     xTaskCreate( rpp_eth_recv_raw, "RXHandler", 200, netif, 0, NULL );
-    /* run task handling transmitted buffer descriptors */
-    xTaskCreate( rpp_eth_send_bd_handler, "TXHandler", 200, hdkif, 0, NULL );
-#if PHY_LINK_MONITOR_INT
-    /* run task handling link status changes */
-    xTaskCreate( linkStatusChanged, "LNKHandler", 100, netif, 0, NULL );
-    /* enable linkint on vim level */
-#endif /* PHY_LINK_MONITOR_INT */
-#endif /* ONE_DRIVER_TASK */
     /* ----- end - freeRTOS ----- */
 #endif /* !NO_SYS */
-    vim_mask_set(LNKInterruptVectorNumber);
 
-    /* TODO: copy this to link interrupt handler/ it must be done, so we do it here when link interrupt handler is not used */
+    /* if we don't use link int change, then it must be done here */
 #if !PHY_LINK_MONITOR_INT
     if(rpp_eth_phylinkstat(hdkif->inst_num))
     {
@@ -443,23 +392,18 @@ int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
        if(dhcp_start(netif) != ERR_OK)
        {
-#ifdef DEBUG
                rpp_debug_printf((const char *) "dhcp mem err\r\n");
-#endif
                return DHCP_MEM_ERR;
        }
-#ifdef DEBUG
        rpp_debug_printf((const char *) "binding DHCP\r");
-#endif
        while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--))/*sys_check_timeouts()*/;
-#ifdef DEBUG
        if(!dhcpBindWait)
                rpp_debug_printf((const char *) "dhcp binding timeout...\r\n");
-#endif
 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
        autoip_start(netif);
 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
 #ifdef DEBUG
+        uint8_t ipString[16];
        rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
        rpp_debug_printf((const char *) "Address: %s\r\n", ipString);
        rpp_eth_getIPDecimalStr(netif->netmask, ipString);
@@ -473,6 +417,15 @@ int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
        rpp_debug_printf((const char *)"cable not connected\r\n");
         retVal = PHY_LINK_DOWN;
     }
+
+#else /* !PHY_LINK_MONITOR_INT */
+    /* now when we established environment needed for phy link status change we can allow it */
+    /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
+    HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
+
+    /* enable MISC interrupt - link monitoring in EMAC controle module */
+    HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
+
 #endif /* !PHY_LINK_MONITOR_INT */
     /* ----- end - lwIP stuff ----- */
 
@@ -539,9 +492,6 @@ err_t rpp_eth_hw_init(struct hdkif *hdkif)
     /* we have pull-down resistor, so after reset, we only need to put ETHRST pin to log. high */
     hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),1);
 
-    /* don't run link status change interrupt yet - there is not yet prepared all the stuff we need */
-    vim_mask_clr(LNKInterruptVectorNumber);
-
     /* initializes EMAC control module and EMAC module */
     EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base);
     /* initializes MDIO module (reset) */
@@ -580,15 +530,11 @@ err_t rpp_eth_hw_init(struct hdkif *hdkif)
         }
         if(!physAlive)
         {
-#ifdef DEBUG
             rpp_debug_printf((const char *) "no phy found, phys: %d\r\n", physAlive);
-#endif
                return NO_PHY_ALIVE;
         }
 #else
-#ifdef DEBUG
         rpp_debug_printf((const char *) "default phy not alive\r\n");
-#endif
        return DFLT_PHY_NOT_ALIVE;
 #endif
     }
@@ -599,9 +545,10 @@ err_t rpp_eth_hw_init(struct hdkif *hdkif)
     /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
 
 
-    /* acknowledge EMAC control module RX and TX interrupts */
+    /* acknowledge EMAC control module RX, TX and MISC interrupts */
        EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
        EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
+       EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
 
     /* sets which channel will receive broadcasts */
        EMACRxBroadCastEnable(hdkif->emac_base, CHANNEL);
@@ -614,6 +561,9 @@ err_t rpp_eth_hw_init(struct hdkif *hdkif)
        EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
        EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
 
+       /* switch of send bd handling and when sending, just wait till send was done and then return (making the driver simple) */
+       //vim_mask_clr(TXinterruptVectorNumber);
+
        return SUCCESS;
 }
 
@@ -633,9 +583,7 @@ err_t rpp_eth_hw_init_postInit(struct netif *netif)
     rxch = &(hdkif->rxch);
     txch = &(hdkif->txch);
 
-#ifdef DEBUG
     rpp_debug_printf((const char *) "autoneg started - check on cable if it's connected!\r\n");
-#endif
 
 
        /*
@@ -704,21 +652,13 @@ err_t rpp_eth_hw_init_postInit(struct netif *netif)
            pbuf_cnt++;
        }
 
-#ifdef DEBUG
        if(!pbuf_cnt)rpp_debug_printf((const char *) "no pbufs attached to rx buffer descriptors during init\n");
-#endif
 
        last_rxbd->next = NULL;
        rxch->active_tail = last_rxbd;
 
        num_bd = ( ((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1 );
-#if RPP_ETH_STATS
-       preparedRxPBUFs = filledRXbds = num_bd;
-       preparedRxPBUFChains = pbuf_cnt;
-#endif
-#ifdef DEBUG
        rpp_debug_printf((const char *) "%d pbuf chains allocated for %d rx buffer descriptors\n", pbuf_cnt, num_bd);
-#endif
        /* for flow control or QoS - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
        /* EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd); */ /* not used */
 
@@ -762,12 +702,10 @@ err_t rpp_eth_hw_init_postInit(struct netif *netif)
     while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
 #endif
 
-#ifdef DEBUG
     if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
        rpp_debug_printf((const char *) "aneg finished \r\n");
     else
        rpp_debug_printf((const char *) "aneg timeout \r\n");
-#endif
 
     /* provide informations retrieved from autoneg to EMAC module */
     hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
@@ -777,20 +715,16 @@ err_t rpp_eth_hw_init_postInit(struct netif *netif)
     } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
        EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
     } else {
-#ifdef DEBUG
        rpp_debug_printf((const char *) "Unknown duplex mode\r\n");
-#endif
        return UNKN_DUPLEX_MODE;
     }
+#endif /* !PHY_LINK_MONITOR_INT */
 
-    /* TODO: reorganize code for linkint handling and maybe add functions for it */
-#else /* !PHY_LINK_MONITOR_INT */
-    /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
-    HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
+    /* enable hostpend interrupts in emac module */
+    HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
 
-    /* enable MISC interrupt for link monitoring in EMAC controle module */
-    HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
-#endif /* !PHY_LINK_MONITOR_INT */
+    /* enable hostpend interrupts in emac control module */
+    HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
 
        /* enable EMAC's Media Independent Interface TX and RX */
        EMACMIIEnable(hdkif->emac_base);
@@ -802,46 +736,20 @@ err_t rpp_eth_hw_init_postInit(struct netif *netif)
        return SUCCESS;
 }
 
-/********************************************** send and receive functions / ISRs **********************************************/
 
-/* function to find out, whether LwIP does not mind more threads */
-/* this one handles all interrupts comming */
-#if ONE_DRIVER_TASK
-void rpp_eth_driver(void *arg)
-{
-       boolean_t active;
-       struct netif *netif = (struct netif *) arg;
-       struct hdkif *hdkif = (struct hdkif *) netif->state;
-       for(;;)
-       {
-        active = FALSE;
-        if (sys_arch_sem_wait(&(hdkif->goTX), 1) != SYS_ARCH_TIMEOUT){
-               SYS_ARCH_DECL_PROTECT(lev);
-               SYS_ARCH_PROTECT(lev);
-               rpp_eth_send_bd_handler(hdkif);
-               SYS_ARCH_UNPROTECT(lev);
-               vim_mask_set(TXinterruptVectorNumber);
-               active = TRUE;
-               }
-               if (sys_arch_sem_wait(&(hdkif->goRX), 1) != SYS_ARCH_TIMEOUT){
-               SYS_ARCH_DECL_PROTECT(lev);
-               SYS_ARCH_PROTECT(lev);
-                       rpp_eth_recv_raw(netif);
-               SYS_ARCH_UNPROTECT(lev);
-                       vim_mask_set(RXinterruptVectorNumber);
-               active = TRUE;
-               }
-#if PHY_LINK_MONITOR_INT
-        if (sys_arch_sem_wait(&(hdkif->goLink), 1) != SYS_ARCH_TIMEOUT){
-               linkStatusChanged(netif);
-               vim_mask_set(LNKInterruptVectorNumber);
-        }
-#endif
-        if(active)continue;
-        taskYIELD(); /* if there is no request to be handled let other tasks work */
-       }
-}
-#endif
+
+
+
+
+
+
+
+
+
+
+
+
+/********************************************** send and receive functions / ISRs **********************************************/
 
 err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
 {
@@ -855,52 +763,47 @@ err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
         */
        SYS_ARCH_PROTECT(lev);
 
+       /* protect from access receive acces from interrupt */
+#if !SYS_LIGHTWEIGHT_PROT
+       uint32_t prevProt = (uint32_t) _get_CPSR() & 0x80;
+       _disable_IRQ();
+#endif
+
+
        /* adjust the packet length if less than minimum required */
        if(p->tot_len < MIN_PKT_LEN) {
           p->tot_len = MIN_PKT_LEN;
           p->len = MIN_PKT_LEN;
        }
 
-       /**
-        * Bump the reference count on the pbuf to prevent it from being
-        * freed till we are done with it.
-        *
-        */
-       pbuf_ref(p);
-
        /* call the actual transmit function */
        retVal = rpp_eth_send_raw(netif, p);
 
        /* Return to prior interrupt state and return. */
        SYS_ARCH_UNPROTECT(lev);
 
+#if !SYS_LIGHTWEIGHT_PROT
+    if(!prevProt)_enable_IRQ();
+#endif
+
        return retVal;
 }
 
+/**
+ * send packet, blocks till it is sent
+ * every send uses bds on the beginning of CPPI RAM
+ */
 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
 {
        struct pbuf *q;
-       volatile struct emac_tx_bd *curr_bd, *active_head, *bd_end;
+       volatile struct emac_tx_bd *curr_bd, *bd_end;
        struct hdkif *hdkif;
-       struct txch *txch;
-       err_t retVal = SUCCESS;
 
     hdkif = (struct hdkif *) netif->state;
-       txch = &(hdkif->txch);
+       curr_bd = (struct emac_tx_bd *) hdkif->emac_ctrl_ram;
 
-#if RPP_ETH_STATS
-       preparedTxPBUFs++;
-       preparedTxPBUFChains += pbuf_clen(p);
-#endif
-
-       /* Get the buffer descriptor which is free to transmit */
-       curr_bd = txch->free_head;
-
-       active_head = curr_bd;
-
-       /* Update the total packet length */
-       curr_bd->flags_pktlen &= ~0xFFFF;
-       curr_bd->flags_pktlen |= p->tot_len;
+       /* destroy all flags previously set and update the total packet length */
+       curr_bd->flags_pktlen = p->tot_len;
 
        /* Indicate the start of the packet */
        curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
@@ -914,65 +817,32 @@ err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
            bd_end = curr_bd;
            curr_bd->pbuf = p;
            curr_bd = curr_bd->next;
-#if RPP_ETH_STATS
-           filledTXbds++;
-#endif
+           curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
        }
 
        /* Indicate the end of the packet */
        bd_end->next = NULL;
        bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
 
-#if RPP_ETH_STATS
-       filledTXPKTs++;
-#endif
+    /* don't write to hdp till it turns zero */
+    while (0 != *((volatile uint32_t *) (hdkif->emac_base + EMAC_TXHDP(CHANNEL)) ));
+    /* notify hw where to start transmission from */
+    HWREG(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) = hdkif->emac_ctrl_ram;
+       //EMACTxHdrDescPtrWrite(hdkif->emac_base, hdkif->emac_ctrl_ram, CHANNEL);
 
-       txch->free_head = curr_bd;
+       /* wait till queued pkt is sent */
 
-       /* For the first time, write the HDP with the filled bd */
-       if(txch->active_tail == NULL) {
-           EMACTxHdrDescPtrWrite(hdkif->emac_base, (unsigned int)(active_head), CHANNEL);
-       }
-       /*
-        * Chain the bd's. If the DMA engine, already reached the end of the chain,
-        * the EOQ will be set. In that case, the HDP shall be written again.
-        */
-       else {
-               curr_bd = txch->active_tail;
-           /* TODO: (This is a workaround) Wait for the EOQ bit is set */
-           while (EMAC_DSC_FLAG_EOQ != (curr_bd->flags_pktlen & EMAC_DSC_FLAG_EOQ)); /* XXX: it stucked here, when calling from recv interrupt - ICMP ping to the board running and nc -d */
-           /* TODO: (This is a workaround) Don't write to TXHDP0 until it turns to zero */
-               while (0 != *((u32_t *)0xFCF78600));
-           curr_bd->next = active_head;
-           if (EMAC_DSC_FLAG_EOQ == (curr_bd->flags_pktlen & EMAC_DSC_FLAG_EOQ)) {
-             /* Write the Header Descriptor Pointer and start DMA */
-             EMACTxHdrDescPtrWrite(hdkif->emac_base, (unsigned int)(active_head), 0);
-             curr_bd->flags_pktlen &= ~EMAC_DSC_FLAG_EOQ;
-           }
-           /*
-           curr_bd = txch->active_tail;
-           curr_bd->next = active_head;*/ /* first chain new stuff to transmit */
-           /* Test if the EOQ bit is set, if it is, set TXnHDP */
-           /*if(EMAC_DSC_FLAG_EOQ == (curr_bd->flags_pktlen & EMAC_DSC_FLAG_EOQ))
-           {*/
-               /* Don't write to TX0HDP until it turns to zero - because EOQ was set, it should be zero already */
-               /*while (0 != *((uint32_t *) (hdkif->emac_base + EMAC_TXHDP(CHANNEL)) ));*/
-               /* Write the Header Descriptor Pointer and start DMA */
-               /*EMACTxHdrDescPtrWrite(hdkif->emac_base, (unsigned int)(active_head), CHANNEL);
-               curr_bd->flags_pktlen &= ~EMAC_DSC_FLAG_EOQ;
-           }*/
-       }
+       while (!(bd_end->flags_pktlen & EMAC_DSC_FLAG_EOQ) || (((struct emac_tx_bd *)(hdkif->emac_ctrl_ram))->flags_pktlen & EMAC_DSC_FLAG_OWNER));
 
-       txch->active_tail = bd_end;
+       EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t) bd_end);
 
-#if RPP_ETH_STATS
-       tx_bd_handled = FALSE;
-    beforeHandled.active_tail = txch->active_tail;
-    beforeHandled.free_head = txch->free_head;
-    beforeHandled.next_bd_to_process = txch->next_bd_to_process;
-#endif
+    EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
 
-       return retVal;
+       /* restore bds chain */
+       bd_end->next = curr_bd;
+
+    LINK_STATS_INC(link.xmit);
+       return SUCCESS;
 }
 
 void rpp_eth_recv_raw(void *arg)
@@ -989,30 +859,20 @@ void rpp_eth_recv_raw(void *arg)
 
 
 #if !NO_SYS && !ONE_DRIVER_TASK
-       //SYS_ARCH_DECL_PROTECT(lev);
+       SYS_ARCH_DECL_PROTECT(lev);
     for(;;)
     {
        vim_mask_set(RXinterruptVectorNumber);
        sys_arch_sem_wait(&(hdkif->goRX), 0);
-       //SYS_ARCH_PROTECT(lev);
+       SYS_ARCH_PROTECT(lev);
 #endif
 
 
-#if RPP_ETH_STATS
-       received = FALSE;
-       beforeRecv.active_head = rxch->active_head;
-       beforeRecv.active_tail = rxch->active_tail;
-       beforeRecv.free_head = rxch->free_head;
-       beforeRecv.freed_pbuf_len = rxch->freed_pbuf_len;
-#endif
-
            /* Get the bd which contains the earliest filled data */
            curr_bd = rxch->active_head;
            last_bd = rxch->active_tail;
 
-#ifdef DEBUG
            if(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP)rpp_debug_printf((const char *) "ERR: Active head is not SOP!\n");
-#endif
 
            /**
             * Process the descriptors as long as data is available
@@ -1046,10 +906,6 @@ void rpp_eth_recv_raw(void *arg)
                        /* If the earlier pbuf ended, update the chain */
                        if(pbuf->next == NULL)
                        {
-#if RPP_ETH_STATS
-                               preparedRxPBUFChains--;
-                               filledRxPBUFChains++;
-#endif
                            pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
                        }
 
@@ -1063,7 +919,7 @@ void rpp_eth_recv_raw(void *arg)
 #ifdef DEBUG
                        if(curr_bd == NULL)rpp_debug_printf((const char *) "rx curr_bd set to zero!\n");
 #endif
-                       /* FIXME: curr_bd here could be NULL - a solution could be: we need to keep at least TCP_MSS bytes, so allocate at least that if not possible block */
+                       /* FIXME: curr_bd here could be NULL - (currently solved by having always allocated enough pbufs -> waiting for pbuf_free() function) a solution could be: we need to keep at least TCP_MSS bytes, so allocate at least that if not possible block */
                    } while((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
 
                    /**
@@ -1073,13 +929,6 @@ void rpp_eth_recv_raw(void *arg)
                    */
                    pbuf->next = NULL;
 
-#if RPP_ETH_STATS
-                   handledRXPKTs++;
-                   filledRXbds -= ((((uint32_t)curr_bd - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd)) + 1);
-                   filledRxPBUFs += pbuf_clen(pbuf);
-                   preparedRxPBUFs -= pbuf_clen(pbuf);
-#endif
-
                    /* Adjust the link statistics */
                    LINK_STATS_INC(link.recv);
 
@@ -1114,7 +963,6 @@ void rpp_eth_recv_raw(void *arg)
                     * from the upper layer
                     */
                    rxch->freed_pbuf_len += len_to_alloc;
-                   /* FIXME: this does not work well */
 #if !NO_SYS
                    /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
                    /* XXX: this is not fixed in NO_SYS version - problem is when curr_bd is set to NULL (see above), and we don't obtain new_pbuf
@@ -1187,119 +1035,11 @@ void rpp_eth_recv_raw(void *arg)
            }
                EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
 
-#if RPP_ETH_STATS
-       received = TRUE;
-       afterRecv.active_head = rxch->active_head;
-       afterRecv.active_tail = rxch->active_tail;
-       afterRecv.free_head = rxch->free_head;
-       afterRecv.freed_pbuf_len = rxch->freed_pbuf_len;
-#endif
-#if !NO_SYS && !ONE_DRIVER_TASK
-               //SYS_ARCH_UNPROTECT(lev);
-    }
-#endif
-}
-
-void rpp_eth_send_bd_handler(void *arg)
-{
-       struct hdkif *hdkif = (struct hdkif *) arg;
-       struct txch *txch = &(hdkif->txch);
-       volatile struct emac_tx_bd *curr_bd, *next_bd_to_process;
-
-#if !NO_SYS && !ONE_DRIVER_TASK
-       SYS_ARCH_DECL_PROTECT(lev);
-       for(;;){
-       vim_mask_set(TXinterruptVectorNumber);
-       sys_arch_sem_wait(&(hdkif->goTX), 0);
-       SYS_ARCH_PROTECT(lev);
-#else
-#endif
-           next_bd_to_process = txch->next_bd_to_process;
-           curr_bd = next_bd_to_process;
-
-           /* Check for correct start of packet */
-           while((curr_bd->flags_pktlen) & EMAC_DSC_FLAG_SOP)
-           {
-
-               /* Make sure that the transmission is over */
-               while((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) == EMAC_DSC_FLAG_OWNER); /* XXX: place where it stucks sometimes */
-
-               /* Traverse till the end of packet is reached */
-               while(((curr_bd->flags_pktlen) & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP)
-               {
-                   curr_bd = curr_bd->next;
-#ifdef DEBUG
-                   if(!inCPPI((uint32_t)curr_bd))rpp_sci_printk((const char *) "tx handl traverse to EOP - bad bd->next ptr\n");
-#endif
-               }
-
-               next_bd_to_process->flags_pktlen &= ~(EMAC_DSC_FLAG_SOP);
-               curr_bd->flags_pktlen &= ~(EMAC_DSC_FLAG_EOP);
-
-               /**
-                * If there are no more data transmitted, the next interrupt
-                * shall happen with the pbuf associated with the free_head
-                */
-               if(curr_bd->next == NULL)
-               {
-                   txch->next_bd_to_process = txch->free_head;
-               }
-               else
-               {
-                   txch->next_bd_to_process = curr_bd->next;
-               }
-
-               /* Acknowledge the EMAC and free the corresponding pbuf */
-               EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t)curr_bd);
-
-               pbuf_free((struct pbuf *)curr_bd->pbuf);
-
-               LINK_STATS_INC(link.xmit);
-
-               next_bd_to_process = txch->next_bd_to_process;
-               curr_bd = next_bd_to_process;
-               }
-
-               EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
-
-#if RPP_ETH_STATS
-           tx_bd_handled = TRUE;
-        afterHandled.active_tail = txch->active_tail;
-        afterHandled.free_head = txch->free_head;
-        afterHandled.next_bd_to_process = txch->next_bd_to_process;
-#endif
 #if !NO_SYS && !ONE_DRIVER_TASK
                SYS_ARCH_UNPROTECT(lev);
-       }
-#endif
-}
-
-#if PHY_LINK_MONITOR_INT
-void linkStatusChanged(void *arg)
-{
-       struct netif *netif = (struct netif*) arg;
-       struct hdkif *hdkif = (struct hdkif*) netif->state;
-       uint8_t instNum = hdkif->inst_num;
-#if !NO_SYS && !ONE_DRIVER_TASK
-       for(;;){
-       vim_mask_set(LNKInterruptVectorNumber);
-       sys_arch_sem_wait(&(hdkif->goLink), 0);
-#else
-#endif
-           rpp_sci_printf((const char *) "link is %s\n",rpp_eth_phylinkstat(instNum)?"UP":"DOWN");
-           /* do whatever necessary for link status change here */
-
-               /* acknowledge MDIO module */
-               HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
-               HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
-
-               /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
-               EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
-#if !NO_SYS && !ONE_DRIVER_TASK
     }
 #endif
 }
-#endif /* PHY_LINK_MONITOR_INT */
 
 void RxIntHandler(u32_t instNum)
 {
@@ -1335,33 +1075,148 @@ void RxIntHandler(u32_t instNum)
 
 void TxIntHandler(u32_t instNum)
 {
+       //struct hdkif *hdkif = &hdkif_data[instNum];
 #if !NO_SYS
        vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
        xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
 #else
-       rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
+       //sendDone = TRUE;
+       //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
 #endif
 }
 
+/**
+ * TX err codes:
+ *
+ * 0 No error
+ * 1h SOP error; the buffer is the first buffer in a packet, but the SOP bit is not set in software.
+ * 2h Ownership bit not set in SOP buffer
+ * 3h Zero next buffer descriptor pointer without EOP
+ * 4h Zero buffer pointer
+ * 5h Zero buffer length
+ * 6h Packet length error (sum of buffers is less than packet length)
+ *
+ *
+ * RX err codes:
+ *
+ * 0 No error
+ * 1h Reserved
+ * 2h Ownership bit not set in SOP buffer
+ * 3h Reserved
+ * 4h Zero buffer pointer
+ */
+boolean_t HostPendErrHandler(void)
+{
+       uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
+       uint32_t reg;
+       struct hdkif *hdkif;
+
+       while(index){
+               hdkif = &hdkif_data[--index];
+           if(EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND)errFound = TRUE;
+       }
+       if(!errFound)return FALSE; /* this is not the cause of the interrupt */
+       rpp_sci_printk((const char *) "HOSTPEND err\n");
+       reg = HWREG(hdkif->emac_base + EMAC_MACSTATUS);
+       rpp_sci_printk((const char *) "TXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_TXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_TXERRCH_SHIFT) & 0x7));
+       rpp_sci_printk((const char *) "RXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_RXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_RXERRCH_SHIFT) & 0x7));
+       /* no acknowledge - emac module has to be restarted */
+       return TRUE; /* this was the reason of interrupt */
+}
+
 #if PHY_LINK_MONITOR_INT
 boolean_t LinkIntHandler(void)
 {
        uint8_t index = MAX_EMAC_INSTANCE, phyFound = FALSE;
        struct hdkif *hdkif;
+       uint16_t regContent;
+       volatile unsigned int autonegFinishWait = 0xFFFFFFF;
+    volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
 
        /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
        while(index){
        hdkif = &hdkif_data[--index];
-           if( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && (HWREG(hdkif->emac_base + EMAC_MACINVECTOR) & EMAC_MACINVECTOR_LINKINT0) )phyFound = TRUE;
+           if( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_LINKINT0 )phyFound = TRUE;
        }
     if(!phyFound)return FALSE;
-#if !NO_SYS
-    vim_mask_clr(LNKInterruptVectorNumber); /* see sys_startup.c */
-    xSemaphoreGiveFromISR(hdkif->goLink, NULL);
-#else
+    struct netif *netif = &hdkNetIF[hdkif->inst_num];
+
     /* we handles here connection of cable after startup, not changes of linkstatus */
-    /* do whatever necessary for link status change here */
 
+    /* wait for autonegotiation to be done */
+#if ONCE_LINK_SETUP
+    while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE);
+#else /* ONCE_LINK_SETUP */
+    while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE & autonegFinishWait--);
+#endif /* ONCE_LINK_SETUP */
+
+    /* provide informations retrieved from autoneg to EMAC module */
+    hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
+    if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
+       EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
+       /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
+    } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
+       EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
+    } else {
+       /* acknowledge MDIO module */
+       HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
+       HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
+
+       /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
+       EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
+       return FALSE;
+    }
+    /* if link is up configure lwip struct netif */
+    if(rpp_eth_phylinkstat(hdkif->inst_num))
+    {
+#if STATIC_IP_ADDRESS
+       netif_set_up(netif);
+#elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
+       if(dhcp_start(netif) != ERR_OK) /* XXX: can't be used from ISR (mem_malloc()) */
+       {
+               return DHCP_MEM_ERR;
+       }
+#if ONCE_LINK_SETUP
+       while(netif->dhcp->state != DHCP_BOUND);
+#else
+       while(netif->dhcp->state != DHCP_BOUND & dhcpBindWait--);
+       if(!dhcpBindWait)
+       {
+               /* acknowledge MDIO module */
+               HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
+               HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
+
+               /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
+               EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
+               return FALSE;
+       }
+#endif
+#else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
+       autoip_start(netif);
+#endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
+#if ONCE_LINK_SETUP
+        /* turn this interrupt off */
+        HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) &= (~EMAC_CTRL_MISC_LINKINT0ENB & 0xf);
+#endif /* ONCE_LINK_SETUP */
+    }
+    else
+    {
+#if ONCE_LINK_SETUP
+       /* acknowledge MDIO module */
+       HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
+       HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
+
+       /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
+       EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
+       return FALSE;
+#else
+#if STATIC_IP_ADDRESS
+       netif_set_down(netif);
+#elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
+       dhcp_stop(netif);
+#endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
+#endif
+    }
 
        /* acknowledge MDIO module */
        HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
@@ -1369,9 +1224,9 @@ boolean_t LinkIntHandler(void)
 
        /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
        EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
-#endif
+
        return TRUE;
 }
-#endif
+#endif /* PHY_LINK_MONITOR_INT */
 
 #endif /* rppCONFIG_INCLUDE_ETH */
index 942580e0dc3d9676c315c226302b2086f4f94707..a56e465d86ae8d3aaa7fc18bd8a490f41323535a 100644 (file)
@@ -27,6 +27,7 @@
 //#include "os_task.h"
 
 #include "sys/sys.h"
+#include "rpp/eth.h"
 
 /* USER CODE END */
 
@@ -260,12 +261,14 @@ void linNotification(linBASE_t *lin, uint32_t flags)
     }
 }
 
-#define PHY_LINK_MONITOR_INT 0
-
+extern boolean_t HostPendErrHandler(void);
+#if PHY_LINK_MONITOR_INT
 extern boolean_t LinkIntHandler(void);
+#endif
 #pragma INTERRUPT(MDIOMiscInt, IRQ)
 void MDIOMiscInt(void)
 {
+       if(HostPendErrHandler())return;
 #if PHY_LINK_MONITOR_INT
        if(LinkIntHandler())return;
 #endif
index e71202f4d9176480efd8ee6e4930e24f512cf1b2..930aefd6d6392233fa6b1540687d0e694296ad84 100644 (file)
@@ -917,7 +917,7 @@ void _c_int00()
                         | (0U << 9U)
                         | (0U << 10U)
                         | (0U << 11U)
-                        | (0U << 12U)       // MDIOMiscInt
+                        | (1U << 12U)       // MDIOMiscInt
                         | (1U << 13U)       // EMACCore0TxIsr
                         | (0U << 14U)
                         | (1U << 15U)       // EMACCore0RxIsr