Daniele Lacamera / lpc1768-picotcp-eth-polling

Dependents:   ZeroMQ_PicoTCP_Publisher_demo

Fork of lpc1768-picotcp-eth by TASS Belgium

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pico_dev_mbed_emac.cpp Source File

pico_dev_mbed_emac.cpp

00001 /******************************************************************************
00002 PicoTCP. Copyright (c) 2012-2013 TASS Belgium NV. Some rights reserved.
00003 See LICENSE and COPYING for usage. https://github.com/tass-belgium/picotcp
00004 
00005 This library is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License Version 2
00007 as published by the Free Software Foundation;
00008 
00009 Some of the code contained in this file is based on mbed.org 
00010 mbed/libraries/mbed/vendor/NXP/capi/ethernet_api.c module, 
00011 licensed under the Apache License, Version 2.0
00012 and is Copyright (c) 2006-2013 ARM Limited
00013 
00014 Authors: Maxime Vincent, Andrei Carp
00015 
00016 ******************************************************************************/
00017 
00018 #include "mbed.h"
00019 extern "C" {
00020 #include "pico_dev_mbed_emac.h"
00021 #include "pico_dev_mbed_emac_private.h"
00022 #include "pico_config.h"
00023 #include "pico_device.h"
00024 #include "pico_stack.h"
00025 #include "LPC17xx.h"
00026 #include <string.h>
00027 }
00028 #include "PicoCondition.h"
00029 #include "proxy_endpoint.h"
00030 
00031 //static PicoCondition rx_condition;
00032 
00033 /*******************************
00034  * Local structs and typedefs  *
00035  *******************************/
00036 __packed struct RX_DESC_TypeDef {                        /* RX Descriptor struct              */
00037    unsigned int Packet;
00038    unsigned int Ctrl;
00039 };
00040 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
00041 
00042 __packed struct RX_STAT_TypeDef {                        /* RX Status struct                  */
00043    unsigned int Info;
00044    unsigned int HashCRC;
00045 };
00046 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
00047 
00048 __packed struct TX_DESC_TypeDef {                        /* TX Descriptor struct              */
00049    unsigned int Packet;
00050    unsigned int Ctrl;
00051 };
00052 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
00053 
00054 __packed struct TX_STAT_TypeDef {                        /* TX Status struct                  */
00055    unsigned int Info;
00056 };
00057 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
00058 
00059 // To be allocated in the ETH AHB RAM
00060 __packed typedef struct emac_dma_data {
00061   RX_STAT_TypeDef   p_rx_stat[NUM_RX_FRAG];   /**< Pointer to RX statuses */
00062   RX_DESC_TypeDef   p_rx_desc[NUM_RX_FRAG];   /**< Pointer to RX descriptor list */
00063   TX_STAT_TypeDef   p_tx_stat[NUM_TX_FRAG];   /**< Pointer to TX statuses */
00064   TX_DESC_TypeDef   p_tx_desc[NUM_TX_FRAG];   /**< Pointer to TX descriptor list */
00065   uint8_t           rx_buf[NUM_RX_FRAG][ETH_MAX_MTU];      /**< RX pbuf pointer list, zero-copy mode */
00066   uint8_t           tx_buf[NUM_TX_FRAG][ETH_MAX_MTU];      /**< TX pbuf pointer list, zero-copy mode */
00067 } EMAC_DMA_DATA_T;
00068 
00069 struct pico_device_mbed_emac {
00070   struct pico_device dev;
00071   uint16_t mtu;
00072   uint8_t mac[PICO_SIZE_ETH];
00073   EMAC_DMA_DATA_T * dma_data;
00074 };
00075 
00076 /********************
00077  * Global variables *
00078  ********************/
00079 //uint16_t lBuffer[ETH_MAX_MTU>>1] __attribute__((section("AHBSRAM0")));
00080 
00081 /*******************
00082  * Local variables *
00083  *******************/
00084 static uint16_t *rptr;
00085 static uint16_t *tptr;
00086 static EMAC_DMA_DATA_T dma_data_ahbsram __attribute__((section("AHBSRAM1")));
00087 
00088 DigitalOut led_link(LED2);  /* Link */
00089 DigitalOut led_rx(LED3);    /* Rx */
00090 DigitalOut led_tx(LED4);    /* Tx */
00091 
00092 /**************************************
00093  * Private helper function prototypes *
00094  **************************************/
00095 static void _emac_init(struct pico_device_mbed_emac * mbdev);
00096 static void _emac_destroy(struct pico_device *dev);
00097 static int _emac_write_PHY (int PhyReg, int Value);
00098 static int _emac_read_PHY (unsigned char PhyReg);
00099 static void _emac_rx_descr_init (struct pico_device_mbed_emac * mbdev);
00100 static void _emac_tx_descr_init (struct pico_device_mbed_emac * mbdev);
00101 static int _emac_send_frame(struct pico_device * dev, void * buf, int len);
00102 static void _emac_phy_status(void const * dev);
00103 static inline unsigned int _emac_clockselect();
00104 static int _pico_emac_poll(struct pico_device *dev, int loop_score);
00105 
00106 struct pico_device *interrupt_mbdev;
00107 
00108 /*****************
00109  * CMSIS defines *
00110  *****************/
00111 // Timer: For periodic PHY update
00112 osTimerDef(_emac_phy_status, _emac_phy_status);
00113 
00114 /******************************
00115  * Public interface functions *
00116  ******************************/
00117 uint32_t intStatus;
00118 
00119 
00120 void ENET_IRQHandler(void)
00121 {
00122     // Get interrupt flag for enabled interrupts
00123     intStatus = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable);
00124     
00125     if(intStatus & INT_TX_UNDERRUN)
00126     {
00127       // this case should be treated
00128       //printf("TX_UNDERRUN\r\n");
00129     }
00130 
00131     if(intStatus & INT_RX_OVERRUN)
00132     {
00133       // this case should be treated
00134       //printf("INT_RX_OVERRUN\r\n");
00135     }
00136  
00137     if(intStatus & INT_RX_DONE)
00138     {
00139         picotcp_async_interrupt(interrupt_mbdev);
00140         //rx_condition.unlock();
00141  
00142     }
00143     
00144     // Clears _ALL_ EMAC interrupt flags
00145     LPC_EMAC->IntClear = intStatus;
00146 }
00147 
00148 static int _emac_poll(struct pico_device_mbed_emac * mbdev);
00149 /*
00150 void rxThreadCore(void const *arg)
00151     {
00152     struct pico_device_mbed_emac *dev = (struct pico_device_mbed_emac *)arg;
00153     printf("rx Thread started.\n");
00154 
00155     while(true) {
00156         rx_condition.lock();
00157         _emac_poll(dev);
00158 
00159     }
00160 }
00161 */
00162 
00163 
00164 
00165 struct pico_device *pico_emac_create(char *name)
00166 {
00167   struct pico_device_mbed_emac *mbdev = (struct pico_device_mbed_emac*) pico_zalloc(sizeof(struct pico_device_mbed_emac));
00168 
00169   if (!mbdev)
00170     return NULL;
00171 
00172   // Set pointer to ETH AHB RAM
00173   mbdev->dma_data = &dma_data_ahbsram;
00174 
00175   // Read MAC address from HW
00176   mbed_mac_address((char *)mbdev->mac);
00177   
00178   //printf("ETH> Set MAC address to: %x:%x:%x:%x:%x:%x\r\n", mbdev->mac[0], mbdev->mac[1], mbdev->mac[2], mbdev->mac[3], mbdev->mac[4], mbdev->mac[5]);
00179 
00180   mbdev->mtu = ETH_MAX_MTU;
00181 
00182   if(0 != pico_device_init((struct pico_device *)mbdev, name, mbdev->mac)) {
00183     //printf ("ETH> Loop init failed.\n");
00184     _emac_destroy(&mbdev->dev);
00185     return NULL;
00186   }
00187   
00188   //pico_queue_protect(((struct pico_device *)mbdev)->q_in);
00189 
00190   // Set function pointers
00191   mbdev->dev.send = _emac_send_frame;
00192   mbdev->dev.poll = _pico_emac_poll; /* IRQ MODE */
00193   ///
00194   mbdev->dev.dsr = _pico_emac_poll;
00195   mbdev->dev.destroy = _emac_destroy;
00196 
00197   // Init EMAC and PHY
00198   _emac_init(mbdev);
00199 
00200   // Create periodic PHY status update thread
00201   osTimerId phy_timer = osTimerCreate(osTimer(_emac_phy_status), osTimerPeriodic, (void *)mbdev);
00202   osTimerStart(phy_timer, 100);
00203   
00204   //Thread *rxThread = new Thread(rxThreadCore, (void*)mbdev);
00205   
00206   //rxThread->set_priority(osPriorityLow);
00207 
00208   //printf("ETH> Device %s created.\r\n", mbdev->dev.name);
00209 
00210   return (struct pico_device *)mbdev;
00211 }
00212 
00213 /****************************
00214  * Private helper functions *
00215  ****************************/
00216  
00217 // Public interface: create/destroy.
00218 void _emac_destroy(struct pico_device *dev)
00219 {
00220   pico_device_destroy(dev);
00221 }
00222 
00223 //extern unsigned int SystemFrequency;
00224 static inline unsigned int _emac_clockselect() {  
00225   if(SystemCoreClock < 10000000) {
00226     return 1;
00227   } else if(SystemCoreClock <  15000000) {
00228     return 2;
00229   } else if(SystemCoreClock <  20000000) {
00230     return 3;
00231   } else if(SystemCoreClock <  25000000) {
00232     return 4;
00233   } else if(SystemCoreClock <  35000000) {
00234     return 5;
00235   } else if(SystemCoreClock <  50000000) {
00236     return 6;
00237   } else if(SystemCoreClock <  70000000) {
00238     return 7;
00239   } else if(SystemCoreClock <  80000000) {
00240     return 8;
00241   } else if(SystemCoreClock <  90000000) {
00242     return 9;
00243   } else if(SystemCoreClock < 100000000) {
00244     return 10;
00245   } else if(SystemCoreClock < 120000000) {
00246     return 11;
00247   } else if(SystemCoreClock < 130000000) {
00248     return 12;
00249   } else if(SystemCoreClock < 140000000) {
00250     return 13;
00251   } else if(SystemCoreClock < 150000000) {
00252     return 15;
00253   } else if(SystemCoreClock < 160000000) {
00254     return 16;
00255   } else {
00256     return 0;
00257   }
00258 }
00259 
00260 // configure port-pins for use with LAN-controller,
00261 // reset it and send the configuration-sequence
00262 void _emac_init(struct pico_device_mbed_emac * mbdev)
00263 {
00264   unsigned int clock = _emac_clockselect();
00265   // the DP83848C PHY clock can be up to 25 Mhz
00266   // that means sysclock = 96 Mhz divided by 4 = 24 Mhz
00267   // So we *could* set the clock divider to 4 (meaning "clock" = 0)
00268   //clock = 0;
00269   
00270   // Initializes the EMAC ethernet controller
00271   unsigned int regv,tout,id1,id2;
00272 
00273   // Power Up the EMAC controller.
00274   LPC_SC->PCONP |= 0x40000000;
00275 
00276   // on rev. 'A' and later, P1.6 should NOT be set.
00277   LPC_PINCON->PINSEL2 = 0x50150105;
00278   LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
00279 
00280   // Reset all EMAC internal modules.
00281   LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
00282                    MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
00283   LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
00284 
00285   // A short delay after reset.
00286   for (tout = 100; tout; tout--) __NOP();            // A short delay
00287 
00288   // Initialize MAC control registers.
00289   LPC_EMAC->MAC1 = MAC1_PASS_ALL;
00290   LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
00291   //  MAC2 = MAC2_CRC_EN | MAC2_PAD_EN | MAC2_VLAN_PAD_EN;
00292 
00293   LPC_EMAC->MAXF = ETH_MAX_MTU; 
00294   LPC_EMAC->CLRT = CLRT_DEF;
00295   LPC_EMAC->IPGR = IPGR_DEF;
00296 
00297   // Enable Reduced MII interface.
00298   LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
00299   
00300   LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;    // Set clock
00301   LPC_EMAC->MCFG |= MCFG_RES_MII;                    // and reset
00302 
00303   for(tout = 100; tout; tout--) __NOP();             // A short delay
00304 
00305   LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
00306   LPC_EMAC->MCMD = 0;
00307 
00308   LPC_EMAC->SUPP = SUPP_RES_RMII;                    // Reset Reduced MII Logic.
00309 
00310   for (tout = 100; tout; tout--) __NOP();            // A short delay
00311 
00312   LPC_EMAC->SUPP = 0;
00313 
00314   // Put the DP83848C in reset mode
00315   _emac_write_PHY (PHY_REG_BMCR, 0x8000);
00316 
00317   // Wait for hardware reset to end.
00318   for (tout = 0; tout < 0x100000; tout++) {
00319     regv = _emac_read_PHY (PHY_REG_BMCR);
00320     if (!(regv & 0x8000)) {
00321       // Reset complete
00322       break;
00323     }
00324   }
00325 
00326   // Check if this is a DP83848C PHY.
00327   id1 = _emac_read_PHY (PHY_REG_IDR1);
00328   id2 = _emac_read_PHY (PHY_REG_IDR2);
00329   if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) {
00330     // Configure the PHY device
00331     //printf("PHY> DP83848C_ID PHY found!\r\n");
00332     // Use autonegotiation about the link speed.
00333     _emac_write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG);
00334     // Wait to complete Auto_Negotiation.
00335     for (tout = 0; tout < 0x100000; tout++) {
00336       regv = _emac_read_PHY (PHY_REG_BMSR);
00337       if (regv & 0x0020) {
00338         // Autonegotiation Complete.
00339         break;
00340       }
00341     }
00342   }
00343 
00344   /* Check the link status. */
00345   for (tout = 0; tout < 0x10000; tout++) {
00346     regv = _emac_read_PHY (PHY_REG_STS);
00347     if (regv & 0x0001) {
00348       // Link is on
00349       //printf("PHY> Link active!\r\n");
00350       break;
00351     }
00352   }
00353 
00354   // Configure Full/Half Duplex mode.
00355   if (regv & 0x0004) {
00356     // Full duplex is enabled.
00357     LPC_EMAC->MAC2    |= MAC2_FULL_DUP;
00358     LPC_EMAC->Command |= CR_FULL_DUP;
00359     LPC_EMAC->IPGT     = IPGT_FULL_DUP;
00360   }
00361   else {
00362     // Half duplex mode.
00363     LPC_EMAC->IPGT = IPGT_HALF_DUP;
00364   }
00365 
00366   // Configure 100MBit/10MBit mode
00367   if (regv & 0x0002) {
00368     // 10MBit mode
00369     LPC_EMAC->SUPP = 0;
00370   }
00371   else {
00372     // 100MBit mode
00373     LPC_EMAC->SUPP = SUPP_SPEED;
00374   }
00375 
00376   // Set the Ethernet MAC Address registers
00377   LPC_EMAC->SA0 = (mbdev->mac[0] << 8) | mbdev->mac[1];
00378   LPC_EMAC->SA1 = (mbdev->mac[2] << 8) | mbdev->mac[2];
00379   LPC_EMAC->SA2 = (mbdev->mac[4] << 8) | mbdev->mac[5];
00380 
00381   // Initialize Tx and Rx DMA Descriptors
00382   _emac_rx_descr_init(mbdev);
00383   _emac_tx_descr_init(mbdev);
00384   
00385   // Receive Unicast, Broadcast and Perfect Match Packets
00386   LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
00387 
00388   // Enable receive and transmit mode of MAC Ethernet core
00389   LPC_EMAC->Command  |= (CR_RX_EN | CR_TX_EN);
00390   LPC_EMAC->MAC1     |= MAC1_REC_EN;
00391 
00392   // Enable EMAC interrupts.
00393   LPC_EMAC->IntEnable = INT_RX_DONE | INT_RX_OVERRUN | INT_TX_DONE | INT_TX_FIN | INT_TX_ERR | INT_TX_UNDERRUN;
00394 
00395   // Reset all interrupts
00396   LPC_EMAC->IntClear  = 0xFFFF;
00397 
00398   NVIC_SetPriority(ENET_IRQn, EMAC_INTERRUPT_PRIORITY);
00399 
00400   // Enable the interrupt.
00401   NVIC_EnableIRQ(ENET_IRQn);
00402   // Associate the interrupt to this device
00403   interrupt_mbdev = (struct pico_device *)mbdev;
00404   
00405 }
00406 
00407 
00408 static int _emac_write_PHY (int PhyReg, int Value)
00409 {
00410   unsigned int timeOut;
00411 
00412   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
00413   LPC_EMAC->MWTD = Value;
00414 
00415   // Wait until operation completed
00416   for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {
00417     if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
00418       return 0;
00419     }
00420   }
00421   return -1;
00422 }
00423 
00424 static int _emac_read_PHY (unsigned char PhyReg)
00425 {
00426   unsigned int timeOut;
00427 
00428   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
00429   LPC_EMAC->MCMD = MCMD_READ;
00430 
00431   for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) {   // Wait until operation completed
00432     if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
00433       LPC_EMAC->MCMD = 0;
00434       return LPC_EMAC->MRDD;                             // Return a 16-bit value.
00435     }
00436   }
00437   
00438   return -1;
00439 }
00440 
00441 
00442 void rx_descr_init (void)
00443 {
00444   unsigned int i;
00445 
00446   for (i = 0; i < NUM_RX_FRAG; i++) {
00447     RX_DESC_PACKET(i)  = RX_BUF(i);
00448     RX_DESC_CTRL(i)    = RCTRL_INT | (ETH_MAX_MTU-1);
00449     RX_STAT_INFO(i)    = 0;
00450     RX_STAT_HASHCRC(i) = 0;
00451   }
00452 
00453   // Set EMAC Receive Descriptor Registers.
00454   LPC_EMAC->RxDescriptor    =   RX_DESC_BASE;
00455   LPC_EMAC->RxStatus        =   RX_STAT_BASE;
00456   LPC_EMAC->RxDescriptorNumber= NUM_RX_FRAG-1;
00457 
00458   // Rx Descriptors Point to 0
00459   LPC_EMAC->RxConsumeIndex  = 0;
00460 }
00461 
00462 
00463 void tx_descr_init (void) {
00464   unsigned int i;
00465 
00466   for (i = 0; i < NUM_TX_FRAG; i++) {
00467     TX_DESC_PACKET(i) = TX_BUF(i);
00468     TX_DESC_CTRL(i)   = 0;
00469     TX_STAT_INFO(i)   = 0;
00470   }
00471 
00472   // Set EMAC Transmit Descriptor Registers.
00473   LPC_EMAC->TxDescriptor    = TX_DESC_BASE;
00474   LPC_EMAC->TxStatus        = TX_STAT_BASE;
00475   LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
00476 
00477   // Tx Descriptors Point to 0
00478   LPC_EMAC->TxProduceIndex  = 0;
00479 }
00480 
00481 
00482 static void _emac_rx_descr_init (struct pico_device_mbed_emac * mbdev)
00483 {
00484   unsigned int i;
00485 
00486   for (i = 0; i < NUM_RX_FRAG; i++) {
00487     // Fill in pointers to ETH DMA AHB RAM
00488     mbdev->dma_data->p_rx_desc[i].Packet =  (uint32_t)&(mbdev->dma_data->rx_buf[i][0]);
00489     mbdev->dma_data->p_rx_desc[i].Ctrl = RCTRL_INT | (ETH_MAX_MTU-1);
00490     mbdev->dma_data->p_rx_stat[i].Info = 0;
00491     mbdev->dma_data->p_rx_stat[i].HashCRC = 0;
00492   }
00493 
00494   // Set EMAC Receive Descriptor Registers.
00495   LPC_EMAC->RxDescriptor        = (uint32_t)&(mbdev->dma_data->p_rx_desc[0]);
00496   LPC_EMAC->RxStatus            = (uint32_t)&(mbdev->dma_data->p_rx_stat[0]);
00497   LPC_EMAC->RxDescriptorNumber  = NUM_RX_FRAG-1;
00498 
00499   // Rx Descriptors Point to 0
00500   LPC_EMAC->RxConsumeIndex  = 0;
00501 }
00502 
00503 static void _emac_tx_descr_init (struct pico_device_mbed_emac * mbdev) {
00504   unsigned int i;
00505 
00506   for (i = 0; i < NUM_TX_FRAG; i++) {
00507     mbdev->dma_data->p_tx_desc[i].Packet =  (uint32_t)&(mbdev->dma_data->tx_buf[i][0]);
00508     mbdev->dma_data->p_tx_desc[i].Ctrl = 0;
00509     mbdev->dma_data->p_tx_stat[i].Info = 0;
00510   }
00511   
00512   // Set EMAC Transmit Descriptor Registers.
00513   LPC_EMAC->TxDescriptor    = (uint32_t)&(mbdev->dma_data->p_tx_desc[0]);
00514   LPC_EMAC->TxStatus        = (uint32_t)&(mbdev->dma_data->p_tx_stat[0]);
00515   LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
00516 
00517   // Tx Descriptors Point to index 0
00518   LPC_EMAC->TxProduceIndex  = 0;
00519 }
00520 
00521 
00522 // async send, returning amount of data sent, and 0 if the buffers are busy
00523 static int _emac_send_frame(struct pico_device *dev, void * buf, int len)
00524 {
00525   struct pico_device_mbed_emac *mbdev = (struct pico_device_mbed_emac *) dev;
00526   uint16_t size = len;
00527   uint32_t bufferIndex = LPC_EMAC->TxProduceIndex;
00528   uint16_t pSize = (size+1u)>>1u;
00529   uint16_t * data = (uint16_t *)buf;
00530   int data_sent = 0;
00531 
00532   // When TxProduceIndex == TxConsumeIndex, the transmit buffer is empty.
00533   // When TxProduceIndex == TxConsumeIndex -1 (taking wraparound into account), the transmit buffer is full!
00534   // We should check if there is still a tx_desc FREE!! Consume < Produce (wrapping!!)  
00535   int cons = (int)LPC_EMAC->TxConsumeIndex;
00536   int prod = (int)LPC_EMAC->TxProduceIndex;
00537   int txfree = 0;
00538   
00539   if (prod == cons)
00540     txfree = NUM_TX_FRAG;
00541   else if (prod > cons)
00542     txfree = NUM_TX_FRAG - prod + cons - 1;
00543   else if (prod < cons)
00544     txfree = cons - prod - 1; 
00545   
00546   if (txfree == 0)
00547   {
00548     //printf("p%i c%i stat:%d\r\n",prod,cons,LPC_EMAC->TxStatus);
00549     return 0;
00550   }
00551   
00552   // set tx descriptors for send
00553   tptr = (uint16_t *)(mbdev->dma_data->p_tx_desc[bufferIndex].Packet);
00554     
00555   // copy data to AHB RAM (16-bit copies)
00556   while(pSize)
00557   {
00558     *tptr++ = *data++;
00559     pSize--;
00560   }
00561   
00562   data_sent = size;
00563 
00564   // send data, no interrupt needed I see, for now
00565   mbdev->dma_data->p_tx_desc[bufferIndex].Ctrl &= ~0x7FF;
00566   mbdev->dma_data->p_tx_desc[bufferIndex].Ctrl = (((uint32_t)size -1) & 0x7FF) | TCTRL_LAST | TCTRL_INT;
00567   
00568   //printf("ETH> sent %d bytes\r\n",data_sent);
00569 
00570   // advance the TxProduceIndex
00571   bufferIndex = (bufferIndex+1)%NUM_TX_FRAG;
00572   LPC_EMAC->TxProduceIndex = bufferIndex;
00573         
00574   // Toggle TX LED
00575   led_tx= !led_tx;
00576 
00577   return data_sent;
00578 }
00579 
00580 
00581 /* polls for new data
00582    returns amount of bytes received -- 0 when no new data arrived */
00583 static int _emac_poll(struct pico_device_mbed_emac * mbdev)
00584 {
00585     uint32_t index = LPC_EMAC->RxConsumeIndex;
00586     int retval = 0;
00587 
00588     // Consume all packets available
00589     while(index != LPC_EMAC->RxProduceIndex)
00590     {
00591       uint32_t info = mbdev->dma_data->p_rx_stat[index].Info;
00592       uint32_t RxLen = (info & RINFO_SIZE) - 3u;
00593       rptr = (uint16_t *)(mbdev->dma_data->p_rx_desc[index].Packet);
00594 
00595       if(!( (RxLen >= ETH_MAX_MTU) || (info & RINFO_ERR_MASK) ) )
00596       {
00597         // copy uin16_t (that's per 2 bytes) data content // Uhm... why??
00598         uint16_t lRxLen = RxLen>>1;
00599         //uint16_t * lptr = lBuffer;
00600         //while(lRxLen)
00601         //{
00602         //    *lptr++ = *rptr++;
00603         //    lRxLen--;
00604         //}
00605         //if(RxLen & 0x1)
00606         //    *lptr = (*rptr) & 0xFF ;
00607             
00608         //printf("ETH> recv %d bytes: %x:%x\r\n", RxLen, lBuffer[0],lBuffer[1]);
00609         
00610         // call the stack and pass this packet to it
00611         pico_stack_recv((struct pico_device *)mbdev,(uint8_t *)rptr,RxLen);
00612       } else {
00613         //printf("RxError?\r\n");
00614       }
00615       retval += RxLen;
00616       
00617       // Increment RxConsumeIndex
00618       index = (index+1)%NUM_RX_FRAG;
00619       LPC_EMAC->RxConsumeIndex = index;
00620                 
00621       // Toggle RX LED
00622       //led_rx= !led_rx;
00623     }
00624     
00625     return retval;
00626 }
00627 
00628 static int _pico_emac_poll(struct pico_device *dev, int loop_score)
00629 {
00630   struct pico_device_mbed_emac *mb = (struct pico_device_mbed_emac *) dev;
00631   
00632   while(loop_score > 0)
00633   {
00634     // check for new frame(s) and send to pico stack
00635     // return loop_score if no frame has arrived
00636     if (!(_emac_poll(mb)))
00637         return loop_score;
00638     loop_score--;
00639   }
00640   return loop_score;
00641 }
00642 
00643 
00644 /* Read PHY status */
00645 static uint8_t _emac_update_phy_status(uint32_t linksts)
00646 {
00647   uint8_t changed = 0;
00648   static uint32_t oldlinksts = 0;
00649     
00650   if (oldlinksts != linksts)
00651     changed = 1;
00652         
00653   if (changed)
00654   {
00655     oldlinksts = linksts;
00656     
00657     // Update link active status
00658     if (linksts & DP8_VALID_LINK)
00659     {
00660       led_link = 1;
00661       //printf("PHY> Link ACTIVE!     --");
00662     }
00663     else
00664     {
00665       led_link = 0;
00666       //printf("PHY> Link inactive... --");
00667     }
00668 
00669     // Full or half duplex
00670     if (linksts & DP8_FULLDUPLEX)
00671       printf(" Full duplex mode ! --");
00672     else
00673       printf(" No full duplex...! --");
00674 
00675     // Configure 100MBit/10MBit mode.
00676     if (linksts & DP8_SPEED10MBPS)
00677       printf(" @  10 MBPS\r\n");
00678     else
00679       printf(" @ 100 MBPS\r\n");
00680   }
00681 
00682   return changed;
00683 }
00684 
00685 // Starts a read operation via the MII link (non-blocking)
00686 static void _emac_mii_read_noblock(uint32_t PhyReg) 
00687 {
00688   // Read value at PHY address and register
00689   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
00690   LPC_EMAC->MCMD = MCMD_READ;
00691 }
00692 
00693 /* Reads current MII link busy status */
00694 static uint32_t _emac_mii_is_busy(void)
00695 {
00696   return (uint32_t) (LPC_EMAC->MIND & MIND_BUSY);
00697 }
00698 
00699 // Starts a read operation via the MII link (non-blocking)
00700 static uint32_t _emac_mii_read_data(void)
00701 {
00702   uint32_t data = LPC_EMAC->MRDD;
00703   LPC_EMAC->MCMD = 0;
00704 
00705   return data;
00706 }
00707 
00708 // Phy status update state machine
00709 static void _emac_phy_status(void const * dev)
00710 {
00711   static uint8_t phyustate = 0;
00712   uint32_t changed = 0;
00713 
00714   switch (phyustate) {
00715     default:
00716     case 0:
00717       // Read BMSR to clear faults
00718       _emac_mii_read_noblock(PHY_REG_STS);
00719       phyustate = 1;
00720       break;
00721 
00722     case 1:
00723       // Wait for read status state
00724       if (!_emac_mii_is_busy()) {
00725         // Update PHY status
00726         changed = _emac_update_phy_status(_emac_mii_read_data());
00727         phyustate = 0;
00728       }
00729       break;
00730   }
00731 }