Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: ZeroMQ_PicoTCP_Publisher_demo
Fork of lpc1768-picotcp-eth by
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 }
Generated on Sat Jul 16 2022 21:55:15 by
