A PicoTCP driver for the lpc1768 mbed board

Dependents:   lpc1768-picotcp-demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test TCPSocket_HelloWorld_PicoTCP ... more

Committer:
daniele
Date:
Sun Jun 16 19:45:09 2013 +0000
Revision:
6:32c8501737cd
Parent:
5:50ba2a185f35
Child:
7:608779751f85
Removed superfluous copy of the rx frame;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 0:b6a2ecc0d29e 1 /******************************************************************************
tass 0:b6a2ecc0d29e 2 PicoTCP. Copyright (c) 2012-2013 TASS Belgium NV. Some rights reserved.
tass 0:b6a2ecc0d29e 3 See LICENSE and COPYING for usage. https://github.com/tass-belgium/picotcp
tass 0:b6a2ecc0d29e 4
tass 0:b6a2ecc0d29e 5 This library is free software; you can redistribute it and/or
tass 0:b6a2ecc0d29e 6 modify it under the terms of the GNU General Public License Version 2
tass 0:b6a2ecc0d29e 7 as published by the Free Software Foundation;
tass 0:b6a2ecc0d29e 8
tass 0:b6a2ecc0d29e 9 Some of the code contained in this file is based on mbed.org
tass 0:b6a2ecc0d29e 10 mbed/libraries/mbed/vendor/NXP/capi/ethernet_api.c module,
tass 0:b6a2ecc0d29e 11 licensed under the Apache License, Version 2.0
tass 0:b6a2ecc0d29e 12 and is Copyright (c) 2006-2013 ARM Limited
tass 0:b6a2ecc0d29e 13
tass 0:b6a2ecc0d29e 14 Authors: Maxime Vincent, Andrei Carp
tass 0:b6a2ecc0d29e 15
tass 0:b6a2ecc0d29e 16 ******************************************************************************/
tass 0:b6a2ecc0d29e 17
tass 0:b6a2ecc0d29e 18 #include "mbed.h"
tass 0:b6a2ecc0d29e 19 extern "C" {
tass 0:b6a2ecc0d29e 20 #include "pico_dev_mbed_emac.h"
tass 0:b6a2ecc0d29e 21 #include "pico_dev_mbed_emac_private.h"
tass 0:b6a2ecc0d29e 22 #include "pico_config.h"
tass 0:b6a2ecc0d29e 23 #include "pico_device.h"
tass 0:b6a2ecc0d29e 24 #include "pico_stack.h"
tass 0:b6a2ecc0d29e 25 #include "LPC17xx.h"
tass 0:b6a2ecc0d29e 26 #include <string.h>
tass 0:b6a2ecc0d29e 27 }
daniele 3:8689b9c62672 28 #include "PicoCondition.h"
daniele 4:296b82a1b4b2 29 #include "proxy_endpoint.h"
daniele 3:8689b9c62672 30
daniele 5:50ba2a185f35 31 //static PicoCondition rx_condition;
tass 0:b6a2ecc0d29e 32
tass 0:b6a2ecc0d29e 33 /*******************************
tass 0:b6a2ecc0d29e 34 * Local structs and typedefs *
tass 0:b6a2ecc0d29e 35 *******************************/
tass 0:b6a2ecc0d29e 36 __packed struct RX_DESC_TypeDef { /* RX Descriptor struct */
tass 0:b6a2ecc0d29e 37 unsigned int Packet;
tass 0:b6a2ecc0d29e 38 unsigned int Ctrl;
tass 0:b6a2ecc0d29e 39 };
tass 0:b6a2ecc0d29e 40 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
tass 0:b6a2ecc0d29e 41
tass 0:b6a2ecc0d29e 42 __packed struct RX_STAT_TypeDef { /* RX Status struct */
tass 0:b6a2ecc0d29e 43 unsigned int Info;
tass 0:b6a2ecc0d29e 44 unsigned int HashCRC;
tass 0:b6a2ecc0d29e 45 };
tass 0:b6a2ecc0d29e 46 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
tass 0:b6a2ecc0d29e 47
tass 0:b6a2ecc0d29e 48 __packed struct TX_DESC_TypeDef { /* TX Descriptor struct */
tass 0:b6a2ecc0d29e 49 unsigned int Packet;
tass 0:b6a2ecc0d29e 50 unsigned int Ctrl;
tass 0:b6a2ecc0d29e 51 };
tass 0:b6a2ecc0d29e 52 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
tass 0:b6a2ecc0d29e 53
tass 0:b6a2ecc0d29e 54 __packed struct TX_STAT_TypeDef { /* TX Status struct */
tass 0:b6a2ecc0d29e 55 unsigned int Info;
tass 0:b6a2ecc0d29e 56 };
tass 0:b6a2ecc0d29e 57 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
tass 0:b6a2ecc0d29e 58
tass 0:b6a2ecc0d29e 59 // To be allocated in the ETH AHB RAM
tass 0:b6a2ecc0d29e 60 __packed typedef struct emac_dma_data {
tass 0:b6a2ecc0d29e 61 RX_STAT_TypeDef p_rx_stat[NUM_RX_FRAG]; /**< Pointer to RX statuses */
tass 0:b6a2ecc0d29e 62 RX_DESC_TypeDef p_rx_desc[NUM_RX_FRAG]; /**< Pointer to RX descriptor list */
tass 0:b6a2ecc0d29e 63 TX_STAT_TypeDef p_tx_stat[NUM_TX_FRAG]; /**< Pointer to TX statuses */
tass 0:b6a2ecc0d29e 64 TX_DESC_TypeDef p_tx_desc[NUM_TX_FRAG]; /**< Pointer to TX descriptor list */
tass 0:b6a2ecc0d29e 65 uint8_t rx_buf[NUM_RX_FRAG][ETH_MAX_MTU]; /**< RX pbuf pointer list, zero-copy mode */
tass 0:b6a2ecc0d29e 66 uint8_t tx_buf[NUM_TX_FRAG][ETH_MAX_MTU]; /**< TX pbuf pointer list, zero-copy mode */
tass 0:b6a2ecc0d29e 67 } EMAC_DMA_DATA_T;
tass 0:b6a2ecc0d29e 68
tass 0:b6a2ecc0d29e 69 struct pico_device_mbed_emac {
tass 0:b6a2ecc0d29e 70 struct pico_device dev;
tass 0:b6a2ecc0d29e 71 uint16_t mtu;
tass 0:b6a2ecc0d29e 72 uint8_t mac[PICO_SIZE_ETH];
tass 0:b6a2ecc0d29e 73 EMAC_DMA_DATA_T * dma_data;
tass 0:b6a2ecc0d29e 74 };
tass 0:b6a2ecc0d29e 75
tass 0:b6a2ecc0d29e 76 /********************
tass 0:b6a2ecc0d29e 77 * Global variables *
tass 0:b6a2ecc0d29e 78 ********************/
daniele 6:32c8501737cd 79 //uint16_t lBuffer[ETH_MAX_MTU>>1] __attribute__((section("AHBSRAM0")));
tass 0:b6a2ecc0d29e 80
tass 0:b6a2ecc0d29e 81 /*******************
tass 0:b6a2ecc0d29e 82 * Local variables *
tass 0:b6a2ecc0d29e 83 *******************/
tass 0:b6a2ecc0d29e 84 static uint16_t *rptr;
tass 0:b6a2ecc0d29e 85 static uint16_t *tptr;
tass 0:b6a2ecc0d29e 86 static EMAC_DMA_DATA_T dma_data_ahbsram __attribute__((section("AHBSRAM1")));
tass 0:b6a2ecc0d29e 87
tass 0:b6a2ecc0d29e 88 DigitalOut led_link(LED2); /* Link */
tass 0:b6a2ecc0d29e 89 DigitalOut led_rx(LED3); /* Rx */
tass 0:b6a2ecc0d29e 90 DigitalOut led_tx(LED4); /* Tx */
tass 0:b6a2ecc0d29e 91
tass 0:b6a2ecc0d29e 92 /**************************************
tass 0:b6a2ecc0d29e 93 * Private helper function prototypes *
tass 0:b6a2ecc0d29e 94 **************************************/
tass 0:b6a2ecc0d29e 95 static void _emac_init(struct pico_device_mbed_emac * mbdev);
tass 0:b6a2ecc0d29e 96 static void _emac_destroy(struct pico_device *dev);
tass 0:b6a2ecc0d29e 97 static int _emac_write_PHY (int PhyReg, int Value);
tass 0:b6a2ecc0d29e 98 static int _emac_read_PHY (unsigned char PhyReg);
tass 0:b6a2ecc0d29e 99 static void _emac_rx_descr_init (struct pico_device_mbed_emac * mbdev);
tass 0:b6a2ecc0d29e 100 static void _emac_tx_descr_init (struct pico_device_mbed_emac * mbdev);
tass 0:b6a2ecc0d29e 101 static int _emac_send_frame(struct pico_device * dev, void * buf, int len);
tass 0:b6a2ecc0d29e 102 static void _emac_phy_status(void const * dev);
tass 0:b6a2ecc0d29e 103 static inline unsigned int _emac_clockselect();
tass 0:b6a2ecc0d29e 104 static int _pico_emac_poll(struct pico_device *dev, int loop_score);
tass 0:b6a2ecc0d29e 105
daniele 5:50ba2a185f35 106 struct pico_device *interrupt_mbdev;
daniele 5:50ba2a185f35 107
tass 0:b6a2ecc0d29e 108 /*****************
tass 0:b6a2ecc0d29e 109 * CMSIS defines *
tass 0:b6a2ecc0d29e 110 *****************/
tass 0:b6a2ecc0d29e 111 // Timer: For periodic PHY update
tass 0:b6a2ecc0d29e 112 osTimerDef(_emac_phy_status, _emac_phy_status);
tass 0:b6a2ecc0d29e 113
tass 0:b6a2ecc0d29e 114 /******************************
tass 0:b6a2ecc0d29e 115 * Public interface functions *
tass 0:b6a2ecc0d29e 116 ******************************/
tass 0:b6a2ecc0d29e 117 uint32_t intStatus;
tass 0:b6a2ecc0d29e 118
daniele 4:296b82a1b4b2 119
tass 0:b6a2ecc0d29e 120 void ENET_IRQHandler(void)
tass 0:b6a2ecc0d29e 121 {
tass 0:b6a2ecc0d29e 122 // Get interrupt flag for enabled interrupts
tass 0:b6a2ecc0d29e 123 intStatus = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable);
tass 0:b6a2ecc0d29e 124
tass 0:b6a2ecc0d29e 125 if(intStatus & INT_TX_UNDERRUN)
tass 0:b6a2ecc0d29e 126 {
tass 0:b6a2ecc0d29e 127 // this case should be treated
tass 0:b6a2ecc0d29e 128 //printf("TX_UNDERRUN\r\n");
tass 0:b6a2ecc0d29e 129 }
tass 0:b6a2ecc0d29e 130
tass 0:b6a2ecc0d29e 131 if(intStatus & INT_RX_OVERRUN)
tass 0:b6a2ecc0d29e 132 {
tass 0:b6a2ecc0d29e 133 // this case should be treated
tass 0:b6a2ecc0d29e 134 //printf("INT_RX_OVERRUN\r\n");
tass 0:b6a2ecc0d29e 135 }
tass 0:b6a2ecc0d29e 136
tass 0:b6a2ecc0d29e 137 if(intStatus & INT_RX_DONE)
tass 0:b6a2ecc0d29e 138 {
daniele 5:50ba2a185f35 139 picotcp_async_interrupt(interrupt_mbdev);
daniele 5:50ba2a185f35 140 //rx_condition.unlock();
daniele 4:296b82a1b4b2 141
tass 0:b6a2ecc0d29e 142 }
tass 0:b6a2ecc0d29e 143
tass 0:b6a2ecc0d29e 144 // Clears _ALL_ EMAC interrupt flags
tass 0:b6a2ecc0d29e 145 LPC_EMAC->IntClear = intStatus;
tass 0:b6a2ecc0d29e 146 }
tass 0:b6a2ecc0d29e 147
daniele 3:8689b9c62672 148 static int _emac_poll(struct pico_device_mbed_emac * mbdev);
daniele 5:50ba2a185f35 149 /*
daniele 3:8689b9c62672 150 void rxThreadCore(void const *arg)
daniele 3:8689b9c62672 151 {
daniele 3:8689b9c62672 152 struct pico_device_mbed_emac *dev = (struct pico_device_mbed_emac *)arg;
daniele 3:8689b9c62672 153 printf("rx Thread started.\n");
daniele 3:8689b9c62672 154
daniele 3:8689b9c62672 155 while(true) {
daniele 3:8689b9c62672 156 rx_condition.lock();
daniele 3:8689b9c62672 157 _emac_poll(dev);
daniele 5:50ba2a185f35 158
daniele 3:8689b9c62672 159 }
daniele 3:8689b9c62672 160 }
daniele 5:50ba2a185f35 161 */
daniele 3:8689b9c62672 162
daniele 3:8689b9c62672 163
tass 0:b6a2ecc0d29e 164
tass 0:b6a2ecc0d29e 165 struct pico_device *pico_emac_create(char *name)
tass 0:b6a2ecc0d29e 166 {
tass 0:b6a2ecc0d29e 167 struct pico_device_mbed_emac *mbdev = (struct pico_device_mbed_emac*) pico_zalloc(sizeof(struct pico_device_mbed_emac));
tass 0:b6a2ecc0d29e 168
tass 0:b6a2ecc0d29e 169 if (!mbdev)
tass 0:b6a2ecc0d29e 170 return NULL;
tass 0:b6a2ecc0d29e 171
tass 0:b6a2ecc0d29e 172 // Set pointer to ETH AHB RAM
tass 0:b6a2ecc0d29e 173 mbdev->dma_data = &dma_data_ahbsram;
tass 0:b6a2ecc0d29e 174
tass 0:b6a2ecc0d29e 175 // Read MAC address from HW
tass 0:b6a2ecc0d29e 176 mbed_mac_address((char *)mbdev->mac);
tass 0:b6a2ecc0d29e 177
tass 0:b6a2ecc0d29e 178 //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]);
tass 0:b6a2ecc0d29e 179
tass 0:b6a2ecc0d29e 180 mbdev->mtu = ETH_MAX_MTU;
tass 0:b6a2ecc0d29e 181
tass 0:b6a2ecc0d29e 182 if(0 != pico_device_init((struct pico_device *)mbdev, name, mbdev->mac)) {
tass 0:b6a2ecc0d29e 183 //printf ("ETH> Loop init failed.\n");
tass 0:b6a2ecc0d29e 184 _emac_destroy(&mbdev->dev);
tass 0:b6a2ecc0d29e 185 return NULL;
tass 0:b6a2ecc0d29e 186 }
daniele 1:5704aeb1157d 187
daniele 5:50ba2a185f35 188 //pico_queue_protect(((struct pico_device *)mbdev)->q_in);
tass 0:b6a2ecc0d29e 189
tass 0:b6a2ecc0d29e 190 // Set function pointers
tass 0:b6a2ecc0d29e 191 mbdev->dev.send = _emac_send_frame;
daniele 3:8689b9c62672 192 //mbdev->dev.poll = _pico_emac_poll; /* IRQ MODE */
daniele 5:50ba2a185f35 193 mbdev->dev.dsr = _pico_emac_poll;
tass 0:b6a2ecc0d29e 194 mbdev->dev.destroy = _emac_destroy;
tass 0:b6a2ecc0d29e 195
tass 0:b6a2ecc0d29e 196 // Init EMAC and PHY
tass 0:b6a2ecc0d29e 197 _emac_init(mbdev);
tass 0:b6a2ecc0d29e 198
tass 0:b6a2ecc0d29e 199 // Create periodic PHY status update thread
tass 0:b6a2ecc0d29e 200 osTimerId phy_timer = osTimerCreate(osTimer(_emac_phy_status), osTimerPeriodic, (void *)mbdev);
daniele 2:a8d9cf10e65a 201 osTimerStart(phy_timer, 100);
daniele 3:8689b9c62672 202
daniele 5:50ba2a185f35 203 //Thread *rxThread = new Thread(rxThreadCore, (void*)mbdev);
daniele 4:296b82a1b4b2 204
daniele 3:8689b9c62672 205 //rxThread->set_priority(osPriorityLow);
tass 0:b6a2ecc0d29e 206
tass 0:b6a2ecc0d29e 207 //printf("ETH> Device %s created.\r\n", mbdev->dev.name);
tass 0:b6a2ecc0d29e 208
tass 0:b6a2ecc0d29e 209 return (struct pico_device *)mbdev;
tass 0:b6a2ecc0d29e 210 }
tass 0:b6a2ecc0d29e 211
tass 0:b6a2ecc0d29e 212 /****************************
tass 0:b6a2ecc0d29e 213 * Private helper functions *
tass 0:b6a2ecc0d29e 214 ****************************/
tass 0:b6a2ecc0d29e 215
tass 0:b6a2ecc0d29e 216 // Public interface: create/destroy.
tass 0:b6a2ecc0d29e 217 void _emac_destroy(struct pico_device *dev)
tass 0:b6a2ecc0d29e 218 {
tass 0:b6a2ecc0d29e 219 pico_device_destroy(dev);
tass 0:b6a2ecc0d29e 220 }
tass 0:b6a2ecc0d29e 221
tass 0:b6a2ecc0d29e 222 //extern unsigned int SystemFrequency;
tass 0:b6a2ecc0d29e 223 static inline unsigned int _emac_clockselect() {
tass 0:b6a2ecc0d29e 224 if(SystemCoreClock < 10000000) {
tass 0:b6a2ecc0d29e 225 return 1;
tass 0:b6a2ecc0d29e 226 } else if(SystemCoreClock < 15000000) {
tass 0:b6a2ecc0d29e 227 return 2;
tass 0:b6a2ecc0d29e 228 } else if(SystemCoreClock < 20000000) {
tass 0:b6a2ecc0d29e 229 return 3;
tass 0:b6a2ecc0d29e 230 } else if(SystemCoreClock < 25000000) {
tass 0:b6a2ecc0d29e 231 return 4;
tass 0:b6a2ecc0d29e 232 } else if(SystemCoreClock < 35000000) {
tass 0:b6a2ecc0d29e 233 return 5;
tass 0:b6a2ecc0d29e 234 } else if(SystemCoreClock < 50000000) {
tass 0:b6a2ecc0d29e 235 return 6;
tass 0:b6a2ecc0d29e 236 } else if(SystemCoreClock < 70000000) {
tass 0:b6a2ecc0d29e 237 return 7;
tass 0:b6a2ecc0d29e 238 } else if(SystemCoreClock < 80000000) {
tass 0:b6a2ecc0d29e 239 return 8;
tass 0:b6a2ecc0d29e 240 } else if(SystemCoreClock < 90000000) {
tass 0:b6a2ecc0d29e 241 return 9;
tass 0:b6a2ecc0d29e 242 } else if(SystemCoreClock < 100000000) {
tass 0:b6a2ecc0d29e 243 return 10;
tass 0:b6a2ecc0d29e 244 } else if(SystemCoreClock < 120000000) {
tass 0:b6a2ecc0d29e 245 return 11;
tass 0:b6a2ecc0d29e 246 } else if(SystemCoreClock < 130000000) {
tass 0:b6a2ecc0d29e 247 return 12;
tass 0:b6a2ecc0d29e 248 } else if(SystemCoreClock < 140000000) {
tass 0:b6a2ecc0d29e 249 return 13;
tass 0:b6a2ecc0d29e 250 } else if(SystemCoreClock < 150000000) {
tass 0:b6a2ecc0d29e 251 return 15;
tass 0:b6a2ecc0d29e 252 } else if(SystemCoreClock < 160000000) {
tass 0:b6a2ecc0d29e 253 return 16;
tass 0:b6a2ecc0d29e 254 } else {
tass 0:b6a2ecc0d29e 255 return 0;
tass 0:b6a2ecc0d29e 256 }
tass 0:b6a2ecc0d29e 257 }
tass 0:b6a2ecc0d29e 258
tass 0:b6a2ecc0d29e 259 // configure port-pins for use with LAN-controller,
tass 0:b6a2ecc0d29e 260 // reset it and send the configuration-sequence
tass 0:b6a2ecc0d29e 261 void _emac_init(struct pico_device_mbed_emac * mbdev)
tass 0:b6a2ecc0d29e 262 {
tass 0:b6a2ecc0d29e 263 unsigned int clock = _emac_clockselect();
tass 0:b6a2ecc0d29e 264 // the DP83848C PHY clock can be up to 25 Mhz
tass 0:b6a2ecc0d29e 265 // that means sysclock = 96 Mhz divided by 4 = 24 Mhz
tass 0:b6a2ecc0d29e 266 // So we *could* set the clock divider to 4 (meaning "clock" = 0)
tass 0:b6a2ecc0d29e 267 //clock = 0;
tass 0:b6a2ecc0d29e 268
tass 0:b6a2ecc0d29e 269 // Initializes the EMAC ethernet controller
tass 0:b6a2ecc0d29e 270 unsigned int regv,tout,id1,id2;
tass 0:b6a2ecc0d29e 271
tass 0:b6a2ecc0d29e 272 // Power Up the EMAC controller.
tass 0:b6a2ecc0d29e 273 LPC_SC->PCONP |= 0x40000000;
tass 0:b6a2ecc0d29e 274
tass 0:b6a2ecc0d29e 275 // on rev. 'A' and later, P1.6 should NOT be set.
tass 0:b6a2ecc0d29e 276 LPC_PINCON->PINSEL2 = 0x50150105;
tass 0:b6a2ecc0d29e 277 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
tass 0:b6a2ecc0d29e 278
tass 0:b6a2ecc0d29e 279 // Reset all EMAC internal modules.
tass 0:b6a2ecc0d29e 280 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
tass 0:b6a2ecc0d29e 281 MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
tass 0:b6a2ecc0d29e 282 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
tass 0:b6a2ecc0d29e 283
tass 0:b6a2ecc0d29e 284 // A short delay after reset.
tass 0:b6a2ecc0d29e 285 for (tout = 100; tout; tout--) __NOP(); // A short delay
tass 0:b6a2ecc0d29e 286
tass 0:b6a2ecc0d29e 287 // Initialize MAC control registers.
tass 0:b6a2ecc0d29e 288 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
tass 0:b6a2ecc0d29e 289 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
tass 0:b6a2ecc0d29e 290 // MAC2 = MAC2_CRC_EN | MAC2_PAD_EN | MAC2_VLAN_PAD_EN;
tass 0:b6a2ecc0d29e 291
tass 0:b6a2ecc0d29e 292 LPC_EMAC->MAXF = ETH_MAX_MTU;
tass 0:b6a2ecc0d29e 293 LPC_EMAC->CLRT = CLRT_DEF;
tass 0:b6a2ecc0d29e 294 LPC_EMAC->IPGR = IPGR_DEF;
tass 0:b6a2ecc0d29e 295
tass 0:b6a2ecc0d29e 296 // Enable Reduced MII interface.
tass 0:b6a2ecc0d29e 297 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
tass 0:b6a2ecc0d29e 298
tass 0:b6a2ecc0d29e 299 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; // Set clock
tass 0:b6a2ecc0d29e 300 LPC_EMAC->MCFG |= MCFG_RES_MII; // and reset
tass 0:b6a2ecc0d29e 301
tass 0:b6a2ecc0d29e 302 for(tout = 100; tout; tout--) __NOP(); // A short delay
tass 0:b6a2ecc0d29e 303
tass 0:b6a2ecc0d29e 304 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
tass 0:b6a2ecc0d29e 305 LPC_EMAC->MCMD = 0;
tass 0:b6a2ecc0d29e 306
tass 0:b6a2ecc0d29e 307 LPC_EMAC->SUPP = SUPP_RES_RMII; // Reset Reduced MII Logic.
tass 0:b6a2ecc0d29e 308
tass 0:b6a2ecc0d29e 309 for (tout = 100; tout; tout--) __NOP(); // A short delay
tass 0:b6a2ecc0d29e 310
tass 0:b6a2ecc0d29e 311 LPC_EMAC->SUPP = 0;
tass 0:b6a2ecc0d29e 312
tass 0:b6a2ecc0d29e 313 // Put the DP83848C in reset mode
tass 0:b6a2ecc0d29e 314 _emac_write_PHY (PHY_REG_BMCR, 0x8000);
tass 0:b6a2ecc0d29e 315
tass 0:b6a2ecc0d29e 316 // Wait for hardware reset to end.
tass 0:b6a2ecc0d29e 317 for (tout = 0; tout < 0x100000; tout++) {
tass 0:b6a2ecc0d29e 318 regv = _emac_read_PHY (PHY_REG_BMCR);
tass 0:b6a2ecc0d29e 319 if (!(regv & 0x8000)) {
tass 0:b6a2ecc0d29e 320 // Reset complete
tass 0:b6a2ecc0d29e 321 break;
tass 0:b6a2ecc0d29e 322 }
tass 0:b6a2ecc0d29e 323 }
tass 0:b6a2ecc0d29e 324
tass 0:b6a2ecc0d29e 325 // Check if this is a DP83848C PHY.
tass 0:b6a2ecc0d29e 326 id1 = _emac_read_PHY (PHY_REG_IDR1);
tass 0:b6a2ecc0d29e 327 id2 = _emac_read_PHY (PHY_REG_IDR2);
tass 0:b6a2ecc0d29e 328 if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) {
tass 0:b6a2ecc0d29e 329 // Configure the PHY device
tass 0:b6a2ecc0d29e 330 //printf("PHY> DP83848C_ID PHY found!\r\n");
tass 0:b6a2ecc0d29e 331 // Use autonegotiation about the link speed.
tass 0:b6a2ecc0d29e 332 _emac_write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG);
tass 0:b6a2ecc0d29e 333 // Wait to complete Auto_Negotiation.
tass 0:b6a2ecc0d29e 334 for (tout = 0; tout < 0x100000; tout++) {
tass 0:b6a2ecc0d29e 335 regv = _emac_read_PHY (PHY_REG_BMSR);
tass 0:b6a2ecc0d29e 336 if (regv & 0x0020) {
tass 0:b6a2ecc0d29e 337 // Autonegotiation Complete.
tass 0:b6a2ecc0d29e 338 break;
tass 0:b6a2ecc0d29e 339 }
tass 0:b6a2ecc0d29e 340 }
tass 0:b6a2ecc0d29e 341 }
tass 0:b6a2ecc0d29e 342
tass 0:b6a2ecc0d29e 343 /* Check the link status. */
tass 0:b6a2ecc0d29e 344 for (tout = 0; tout < 0x10000; tout++) {
tass 0:b6a2ecc0d29e 345 regv = _emac_read_PHY (PHY_REG_STS);
tass 0:b6a2ecc0d29e 346 if (regv & 0x0001) {
tass 0:b6a2ecc0d29e 347 // Link is on
tass 0:b6a2ecc0d29e 348 //printf("PHY> Link active!\r\n");
tass 0:b6a2ecc0d29e 349 break;
tass 0:b6a2ecc0d29e 350 }
tass 0:b6a2ecc0d29e 351 }
tass 0:b6a2ecc0d29e 352
tass 0:b6a2ecc0d29e 353 // Configure Full/Half Duplex mode.
tass 0:b6a2ecc0d29e 354 if (regv & 0x0004) {
tass 0:b6a2ecc0d29e 355 // Full duplex is enabled.
tass 0:b6a2ecc0d29e 356 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
tass 0:b6a2ecc0d29e 357 LPC_EMAC->Command |= CR_FULL_DUP;
tass 0:b6a2ecc0d29e 358 LPC_EMAC->IPGT = IPGT_FULL_DUP;
tass 0:b6a2ecc0d29e 359 }
tass 0:b6a2ecc0d29e 360 else {
tass 0:b6a2ecc0d29e 361 // Half duplex mode.
tass 0:b6a2ecc0d29e 362 LPC_EMAC->IPGT = IPGT_HALF_DUP;
tass 0:b6a2ecc0d29e 363 }
tass 0:b6a2ecc0d29e 364
tass 0:b6a2ecc0d29e 365 // Configure 100MBit/10MBit mode
tass 0:b6a2ecc0d29e 366 if (regv & 0x0002) {
tass 0:b6a2ecc0d29e 367 // 10MBit mode
tass 0:b6a2ecc0d29e 368 LPC_EMAC->SUPP = 0;
tass 0:b6a2ecc0d29e 369 }
tass 0:b6a2ecc0d29e 370 else {
tass 0:b6a2ecc0d29e 371 // 100MBit mode
tass 0:b6a2ecc0d29e 372 LPC_EMAC->SUPP = SUPP_SPEED;
tass 0:b6a2ecc0d29e 373 }
tass 0:b6a2ecc0d29e 374
tass 0:b6a2ecc0d29e 375 // Set the Ethernet MAC Address registers
tass 0:b6a2ecc0d29e 376 LPC_EMAC->SA0 = (mbdev->mac[0] << 8) | mbdev->mac[1];
tass 0:b6a2ecc0d29e 377 LPC_EMAC->SA1 = (mbdev->mac[2] << 8) | mbdev->mac[2];
tass 0:b6a2ecc0d29e 378 LPC_EMAC->SA2 = (mbdev->mac[4] << 8) | mbdev->mac[5];
tass 0:b6a2ecc0d29e 379
tass 0:b6a2ecc0d29e 380 // Initialize Tx and Rx DMA Descriptors
tass 0:b6a2ecc0d29e 381 _emac_rx_descr_init(mbdev);
tass 0:b6a2ecc0d29e 382 _emac_tx_descr_init(mbdev);
tass 0:b6a2ecc0d29e 383
tass 0:b6a2ecc0d29e 384 // Receive Unicast, Broadcast and Perfect Match Packets
tass 0:b6a2ecc0d29e 385 LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
tass 0:b6a2ecc0d29e 386
tass 0:b6a2ecc0d29e 387 // Enable receive and transmit mode of MAC Ethernet core
tass 0:b6a2ecc0d29e 388 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN);
tass 0:b6a2ecc0d29e 389 LPC_EMAC->MAC1 |= MAC1_REC_EN;
tass 0:b6a2ecc0d29e 390
tass 0:b6a2ecc0d29e 391 // Enable EMAC interrupts.
tass 0:b6a2ecc0d29e 392 LPC_EMAC->IntEnable = INT_RX_DONE | INT_RX_OVERRUN | INT_TX_DONE | INT_TX_FIN | INT_TX_ERR | INT_TX_UNDERRUN;
tass 0:b6a2ecc0d29e 393
tass 0:b6a2ecc0d29e 394 // Reset all interrupts
tass 0:b6a2ecc0d29e 395 LPC_EMAC->IntClear = 0xFFFF;
tass 0:b6a2ecc0d29e 396
tass 0:b6a2ecc0d29e 397 NVIC_SetPriority(ENET_IRQn, EMAC_INTERRUPT_PRIORITY);
tass 0:b6a2ecc0d29e 398
tass 0:b6a2ecc0d29e 399 // Enable the interrupt.
tass 0:b6a2ecc0d29e 400 NVIC_EnableIRQ(ENET_IRQn);
daniele 5:50ba2a185f35 401 // Associate the interrupt to this device
daniele 5:50ba2a185f35 402 interrupt_mbdev = (struct pico_device *)mbdev;
tass 0:b6a2ecc0d29e 403
tass 0:b6a2ecc0d29e 404 }
tass 0:b6a2ecc0d29e 405
tass 0:b6a2ecc0d29e 406
tass 0:b6a2ecc0d29e 407 static int _emac_write_PHY (int PhyReg, int Value)
tass 0:b6a2ecc0d29e 408 {
tass 0:b6a2ecc0d29e 409 unsigned int timeOut;
tass 0:b6a2ecc0d29e 410
tass 0:b6a2ecc0d29e 411 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
tass 0:b6a2ecc0d29e 412 LPC_EMAC->MWTD = Value;
tass 0:b6a2ecc0d29e 413
tass 0:b6a2ecc0d29e 414 // Wait until operation completed
tass 0:b6a2ecc0d29e 415 for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {
tass 0:b6a2ecc0d29e 416 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
tass 0:b6a2ecc0d29e 417 return 0;
tass 0:b6a2ecc0d29e 418 }
tass 0:b6a2ecc0d29e 419 }
tass 0:b6a2ecc0d29e 420 return -1;
tass 0:b6a2ecc0d29e 421 }
tass 0:b6a2ecc0d29e 422
tass 0:b6a2ecc0d29e 423 static int _emac_read_PHY (unsigned char PhyReg)
tass 0:b6a2ecc0d29e 424 {
tass 0:b6a2ecc0d29e 425 unsigned int timeOut;
tass 0:b6a2ecc0d29e 426
tass 0:b6a2ecc0d29e 427 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
tass 0:b6a2ecc0d29e 428 LPC_EMAC->MCMD = MCMD_READ;
tass 0:b6a2ecc0d29e 429
tass 0:b6a2ecc0d29e 430 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { // Wait until operation completed
tass 0:b6a2ecc0d29e 431 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
tass 0:b6a2ecc0d29e 432 LPC_EMAC->MCMD = 0;
tass 0:b6a2ecc0d29e 433 return LPC_EMAC->MRDD; // Return a 16-bit value.
tass 0:b6a2ecc0d29e 434 }
tass 0:b6a2ecc0d29e 435 }
tass 0:b6a2ecc0d29e 436
tass 0:b6a2ecc0d29e 437 return -1;
tass 0:b6a2ecc0d29e 438 }
tass 0:b6a2ecc0d29e 439
tass 0:b6a2ecc0d29e 440
tass 0:b6a2ecc0d29e 441 void rx_descr_init (void)
tass 0:b6a2ecc0d29e 442 {
tass 0:b6a2ecc0d29e 443 unsigned int i;
tass 0:b6a2ecc0d29e 444
tass 0:b6a2ecc0d29e 445 for (i = 0; i < NUM_RX_FRAG; i++) {
tass 0:b6a2ecc0d29e 446 RX_DESC_PACKET(i) = RX_BUF(i);
tass 0:b6a2ecc0d29e 447 RX_DESC_CTRL(i) = RCTRL_INT | (ETH_MAX_MTU-1);
tass 0:b6a2ecc0d29e 448 RX_STAT_INFO(i) = 0;
tass 0:b6a2ecc0d29e 449 RX_STAT_HASHCRC(i) = 0;
tass 0:b6a2ecc0d29e 450 }
tass 0:b6a2ecc0d29e 451
tass 0:b6a2ecc0d29e 452 // Set EMAC Receive Descriptor Registers.
tass 0:b6a2ecc0d29e 453 LPC_EMAC->RxDescriptor = RX_DESC_BASE;
tass 0:b6a2ecc0d29e 454 LPC_EMAC->RxStatus = RX_STAT_BASE;
tass 0:b6a2ecc0d29e 455 LPC_EMAC->RxDescriptorNumber= NUM_RX_FRAG-1;
tass 0:b6a2ecc0d29e 456
tass 0:b6a2ecc0d29e 457 // Rx Descriptors Point to 0
tass 0:b6a2ecc0d29e 458 LPC_EMAC->RxConsumeIndex = 0;
tass 0:b6a2ecc0d29e 459 }
tass 0:b6a2ecc0d29e 460
tass 0:b6a2ecc0d29e 461
tass 0:b6a2ecc0d29e 462 void tx_descr_init (void) {
tass 0:b6a2ecc0d29e 463 unsigned int i;
tass 0:b6a2ecc0d29e 464
tass 0:b6a2ecc0d29e 465 for (i = 0; i < NUM_TX_FRAG; i++) {
tass 0:b6a2ecc0d29e 466 TX_DESC_PACKET(i) = TX_BUF(i);
tass 0:b6a2ecc0d29e 467 TX_DESC_CTRL(i) = 0;
tass 0:b6a2ecc0d29e 468 TX_STAT_INFO(i) = 0;
tass 0:b6a2ecc0d29e 469 }
tass 0:b6a2ecc0d29e 470
tass 0:b6a2ecc0d29e 471 // Set EMAC Transmit Descriptor Registers.
tass 0:b6a2ecc0d29e 472 LPC_EMAC->TxDescriptor = TX_DESC_BASE;
tass 0:b6a2ecc0d29e 473 LPC_EMAC->TxStatus = TX_STAT_BASE;
tass 0:b6a2ecc0d29e 474 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
tass 0:b6a2ecc0d29e 475
tass 0:b6a2ecc0d29e 476 // Tx Descriptors Point to 0
tass 0:b6a2ecc0d29e 477 LPC_EMAC->TxProduceIndex = 0;
tass 0:b6a2ecc0d29e 478 }
tass 0:b6a2ecc0d29e 479
tass 0:b6a2ecc0d29e 480
tass 0:b6a2ecc0d29e 481 static void _emac_rx_descr_init (struct pico_device_mbed_emac * mbdev)
tass 0:b6a2ecc0d29e 482 {
tass 0:b6a2ecc0d29e 483 unsigned int i;
tass 0:b6a2ecc0d29e 484
tass 0:b6a2ecc0d29e 485 for (i = 0; i < NUM_RX_FRAG; i++) {
tass 0:b6a2ecc0d29e 486 // Fill in pointers to ETH DMA AHB RAM
tass 0:b6a2ecc0d29e 487 mbdev->dma_data->p_rx_desc[i].Packet = (uint32_t)&(mbdev->dma_data->rx_buf[i][0]);
tass 0:b6a2ecc0d29e 488 mbdev->dma_data->p_rx_desc[i].Ctrl = RCTRL_INT | (ETH_MAX_MTU-1);
tass 0:b6a2ecc0d29e 489 mbdev->dma_data->p_rx_stat[i].Info = 0;
tass 0:b6a2ecc0d29e 490 mbdev->dma_data->p_rx_stat[i].HashCRC = 0;
tass 0:b6a2ecc0d29e 491 }
tass 0:b6a2ecc0d29e 492
tass 0:b6a2ecc0d29e 493 // Set EMAC Receive Descriptor Registers.
tass 0:b6a2ecc0d29e 494 LPC_EMAC->RxDescriptor = (uint32_t)&(mbdev->dma_data->p_rx_desc[0]);
tass 0:b6a2ecc0d29e 495 LPC_EMAC->RxStatus = (uint32_t)&(mbdev->dma_data->p_rx_stat[0]);
tass 0:b6a2ecc0d29e 496 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
tass 0:b6a2ecc0d29e 497
tass 0:b6a2ecc0d29e 498 // Rx Descriptors Point to 0
tass 0:b6a2ecc0d29e 499 LPC_EMAC->RxConsumeIndex = 0;
tass 0:b6a2ecc0d29e 500 }
tass 0:b6a2ecc0d29e 501
tass 0:b6a2ecc0d29e 502 static void _emac_tx_descr_init (struct pico_device_mbed_emac * mbdev) {
tass 0:b6a2ecc0d29e 503 unsigned int i;
tass 0:b6a2ecc0d29e 504
tass 0:b6a2ecc0d29e 505 for (i = 0; i < NUM_TX_FRAG; i++) {
tass 0:b6a2ecc0d29e 506 mbdev->dma_data->p_tx_desc[i].Packet = (uint32_t)&(mbdev->dma_data->tx_buf[i][0]);
tass 0:b6a2ecc0d29e 507 mbdev->dma_data->p_tx_desc[i].Ctrl = 0;
tass 0:b6a2ecc0d29e 508 mbdev->dma_data->p_tx_stat[i].Info = 0;
tass 0:b6a2ecc0d29e 509 }
tass 0:b6a2ecc0d29e 510
tass 0:b6a2ecc0d29e 511 // Set EMAC Transmit Descriptor Registers.
tass 0:b6a2ecc0d29e 512 LPC_EMAC->TxDescriptor = (uint32_t)&(mbdev->dma_data->p_tx_desc[0]);
tass 0:b6a2ecc0d29e 513 LPC_EMAC->TxStatus = (uint32_t)&(mbdev->dma_data->p_tx_stat[0]);
tass 0:b6a2ecc0d29e 514 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
tass 0:b6a2ecc0d29e 515
tass 0:b6a2ecc0d29e 516 // Tx Descriptors Point to index 0
tass 0:b6a2ecc0d29e 517 LPC_EMAC->TxProduceIndex = 0;
tass 0:b6a2ecc0d29e 518 }
tass 0:b6a2ecc0d29e 519
tass 0:b6a2ecc0d29e 520
tass 0:b6a2ecc0d29e 521 // async send, returning amount of data sent, and 0 if the buffers are busy
tass 0:b6a2ecc0d29e 522 static int _emac_send_frame(struct pico_device *dev, void * buf, int len)
tass 0:b6a2ecc0d29e 523 {
tass 0:b6a2ecc0d29e 524 struct pico_device_mbed_emac *mbdev = (struct pico_device_mbed_emac *) dev;
tass 0:b6a2ecc0d29e 525 uint16_t size = len;
tass 0:b6a2ecc0d29e 526 uint32_t bufferIndex = LPC_EMAC->TxProduceIndex;
tass 0:b6a2ecc0d29e 527 uint16_t pSize = (size+1u)>>1u;
tass 0:b6a2ecc0d29e 528 uint16_t * data = (uint16_t *)buf;
tass 0:b6a2ecc0d29e 529 int data_sent = 0;
tass 0:b6a2ecc0d29e 530
tass 0:b6a2ecc0d29e 531 // When TxProduceIndex == TxConsumeIndex, the transmit buffer is empty.
tass 0:b6a2ecc0d29e 532 // When TxProduceIndex == TxConsumeIndex -1 (taking wraparound into account), the transmit buffer is full!
tass 0:b6a2ecc0d29e 533 // We should check if there is still a tx_desc FREE!! Consume < Produce (wrapping!!)
tass 0:b6a2ecc0d29e 534 int cons = (int)LPC_EMAC->TxConsumeIndex;
tass 0:b6a2ecc0d29e 535 int prod = (int)LPC_EMAC->TxProduceIndex;
tass 0:b6a2ecc0d29e 536 int txfree = 0;
tass 0:b6a2ecc0d29e 537
tass 0:b6a2ecc0d29e 538 if (prod == cons)
tass 0:b6a2ecc0d29e 539 txfree = NUM_TX_FRAG;
tass 0:b6a2ecc0d29e 540 else if (prod > cons)
tass 0:b6a2ecc0d29e 541 txfree = NUM_TX_FRAG - prod + cons - 1;
tass 0:b6a2ecc0d29e 542 else if (prod < cons)
tass 0:b6a2ecc0d29e 543 txfree = cons - prod - 1;
tass 0:b6a2ecc0d29e 544
tass 0:b6a2ecc0d29e 545 if (txfree == 0)
tass 0:b6a2ecc0d29e 546 {
tass 0:b6a2ecc0d29e 547 //printf("p%i c%i stat:%d\r\n",prod,cons,LPC_EMAC->TxStatus);
tass 0:b6a2ecc0d29e 548 return 0;
tass 0:b6a2ecc0d29e 549 }
tass 0:b6a2ecc0d29e 550
tass 0:b6a2ecc0d29e 551 // set tx descriptors for send
tass 0:b6a2ecc0d29e 552 tptr = (uint16_t *)(mbdev->dma_data->p_tx_desc[bufferIndex].Packet);
tass 0:b6a2ecc0d29e 553
tass 0:b6a2ecc0d29e 554 // copy data to AHB RAM (16-bit copies)
tass 0:b6a2ecc0d29e 555 while(pSize)
tass 0:b6a2ecc0d29e 556 {
tass 0:b6a2ecc0d29e 557 *tptr++ = *data++;
tass 0:b6a2ecc0d29e 558 pSize--;
tass 0:b6a2ecc0d29e 559 }
tass 0:b6a2ecc0d29e 560
tass 0:b6a2ecc0d29e 561 data_sent = size;
tass 0:b6a2ecc0d29e 562
tass 0:b6a2ecc0d29e 563 // send data, no interrupt needed I see, for now
tass 0:b6a2ecc0d29e 564 mbdev->dma_data->p_tx_desc[bufferIndex].Ctrl &= ~0x7FF;
tass 0:b6a2ecc0d29e 565 mbdev->dma_data->p_tx_desc[bufferIndex].Ctrl = (((uint32_t)size -1) & 0x7FF) | TCTRL_LAST | TCTRL_INT;
tass 0:b6a2ecc0d29e 566
tass 0:b6a2ecc0d29e 567 //printf("ETH> sent %d bytes\r\n",data_sent);
tass 0:b6a2ecc0d29e 568
tass 0:b6a2ecc0d29e 569 // advance the TxProduceIndex
tass 0:b6a2ecc0d29e 570 bufferIndex = (bufferIndex+1)%NUM_TX_FRAG;
tass 0:b6a2ecc0d29e 571 LPC_EMAC->TxProduceIndex = bufferIndex;
tass 0:b6a2ecc0d29e 572
tass 0:b6a2ecc0d29e 573 // Toggle TX LED
tass 0:b6a2ecc0d29e 574 led_tx= !led_tx;
tass 0:b6a2ecc0d29e 575
tass 0:b6a2ecc0d29e 576 return data_sent;
tass 0:b6a2ecc0d29e 577 }
tass 0:b6a2ecc0d29e 578
daniele 5:50ba2a185f35 579
tass 0:b6a2ecc0d29e 580 /* polls for new data
tass 0:b6a2ecc0d29e 581 returns amount of bytes received -- 0 when no new data arrived */
tass 0:b6a2ecc0d29e 582 static int _emac_poll(struct pico_device_mbed_emac * mbdev)
tass 0:b6a2ecc0d29e 583 {
tass 0:b6a2ecc0d29e 584 uint32_t index = LPC_EMAC->RxConsumeIndex;
tass 0:b6a2ecc0d29e 585 int retval = 0;
tass 0:b6a2ecc0d29e 586
tass 0:b6a2ecc0d29e 587 // Consume all packets available
tass 0:b6a2ecc0d29e 588 while(index != LPC_EMAC->RxProduceIndex)
tass 0:b6a2ecc0d29e 589 {
tass 0:b6a2ecc0d29e 590 uint32_t info = mbdev->dma_data->p_rx_stat[index].Info;
tass 0:b6a2ecc0d29e 591 uint32_t RxLen = (info & RINFO_SIZE) - 3u;
tass 0:b6a2ecc0d29e 592 rptr = (uint16_t *)(mbdev->dma_data->p_rx_desc[index].Packet);
tass 0:b6a2ecc0d29e 593
tass 0:b6a2ecc0d29e 594 if(!( (RxLen >= ETH_MAX_MTU) || (info & RINFO_ERR_MASK) ) )
tass 0:b6a2ecc0d29e 595 {
daniele 6:32c8501737cd 596 // copy uin16_t (that's per 2 bytes) data content // Uhm... why??
tass 0:b6a2ecc0d29e 597 uint16_t lRxLen = RxLen>>1;
daniele 6:32c8501737cd 598 //uint16_t * lptr = lBuffer;
daniele 6:32c8501737cd 599 //while(lRxLen)
daniele 6:32c8501737cd 600 //{
daniele 6:32c8501737cd 601 // *lptr++ = *rptr++;
daniele 6:32c8501737cd 602 // lRxLen--;
daniele 6:32c8501737cd 603 //}
daniele 6:32c8501737cd 604 //if(RxLen & 0x1)
daniele 6:32c8501737cd 605 // *lptr = (*rptr) & 0xFF ;
tass 0:b6a2ecc0d29e 606
tass 0:b6a2ecc0d29e 607 //printf("ETH> recv %d bytes: %x:%x\r\n", RxLen, lBuffer[0],lBuffer[1]);
tass 0:b6a2ecc0d29e 608
tass 0:b6a2ecc0d29e 609 // call the stack and pass this packet to it
daniele 6:32c8501737cd 610 pico_stack_recv((struct pico_device *)mbdev,(uint8_t *)rptr,RxLen);
tass 0:b6a2ecc0d29e 611 } else {
tass 0:b6a2ecc0d29e 612 //printf("RxError?\r\n");
tass 0:b6a2ecc0d29e 613 }
tass 0:b6a2ecc0d29e 614 retval += RxLen;
tass 0:b6a2ecc0d29e 615
tass 0:b6a2ecc0d29e 616 // Increment RxConsumeIndex
tass 0:b6a2ecc0d29e 617 index = (index+1)%NUM_RX_FRAG;
tass 0:b6a2ecc0d29e 618 LPC_EMAC->RxConsumeIndex = index;
tass 0:b6a2ecc0d29e 619
tass 0:b6a2ecc0d29e 620 // Toggle RX LED
daniele 6:32c8501737cd 621 //led_rx= !led_rx;
tass 0:b6a2ecc0d29e 622 }
tass 0:b6a2ecc0d29e 623
tass 0:b6a2ecc0d29e 624 return retval;
tass 0:b6a2ecc0d29e 625 }
daniele 5:50ba2a185f35 626
tass 0:b6a2ecc0d29e 627 static int _pico_emac_poll(struct pico_device *dev, int loop_score)
tass 0:b6a2ecc0d29e 628 {
tass 0:b6a2ecc0d29e 629 struct pico_device_mbed_emac *mb = (struct pico_device_mbed_emac *) dev;
tass 0:b6a2ecc0d29e 630
tass 0:b6a2ecc0d29e 631 while(loop_score > 0)
tass 0:b6a2ecc0d29e 632 {
tass 0:b6a2ecc0d29e 633 // check for new frame(s) and send to pico stack
tass 0:b6a2ecc0d29e 634 // return loop_score if no frame has arrived
tass 0:b6a2ecc0d29e 635 if (!(_emac_poll(mb)))
tass 0:b6a2ecc0d29e 636 return loop_score;
tass 0:b6a2ecc0d29e 637 loop_score--;
tass 0:b6a2ecc0d29e 638 }
tass 0:b6a2ecc0d29e 639 return loop_score;
tass 0:b6a2ecc0d29e 640 }
daniele 5:50ba2a185f35 641
tass 0:b6a2ecc0d29e 642
tass 0:b6a2ecc0d29e 643 /* Read PHY status */
tass 0:b6a2ecc0d29e 644 static uint8_t _emac_update_phy_status(uint32_t linksts)
tass 0:b6a2ecc0d29e 645 {
tass 0:b6a2ecc0d29e 646 uint8_t changed = 0;
tass 0:b6a2ecc0d29e 647 static uint32_t oldlinksts = 0;
tass 0:b6a2ecc0d29e 648
tass 0:b6a2ecc0d29e 649 if (oldlinksts != linksts)
tass 0:b6a2ecc0d29e 650 changed = 1;
tass 0:b6a2ecc0d29e 651
tass 0:b6a2ecc0d29e 652 if (changed)
tass 0:b6a2ecc0d29e 653 {
tass 0:b6a2ecc0d29e 654 oldlinksts = linksts;
tass 0:b6a2ecc0d29e 655
tass 0:b6a2ecc0d29e 656 // Update link active status
tass 0:b6a2ecc0d29e 657 if (linksts & DP8_VALID_LINK)
tass 0:b6a2ecc0d29e 658 {
tass 0:b6a2ecc0d29e 659 led_link = 1;
tass 0:b6a2ecc0d29e 660 //printf("PHY> Link ACTIVE! --");
tass 0:b6a2ecc0d29e 661 }
tass 0:b6a2ecc0d29e 662 else
tass 0:b6a2ecc0d29e 663 {
tass 0:b6a2ecc0d29e 664 led_link = 0;
tass 0:b6a2ecc0d29e 665 //printf("PHY> Link inactive... --");
tass 0:b6a2ecc0d29e 666 }
tass 0:b6a2ecc0d29e 667
tass 0:b6a2ecc0d29e 668 // Full or half duplex
tass 0:b6a2ecc0d29e 669 if (linksts & DP8_FULLDUPLEX)
tass 0:b6a2ecc0d29e 670 printf(" Full duplex mode ! --");
tass 0:b6a2ecc0d29e 671 else
tass 0:b6a2ecc0d29e 672 printf(" No full duplex...! --");
tass 0:b6a2ecc0d29e 673
tass 0:b6a2ecc0d29e 674 // Configure 100MBit/10MBit mode.
tass 0:b6a2ecc0d29e 675 if (linksts & DP8_SPEED10MBPS)
tass 0:b6a2ecc0d29e 676 printf(" @ 10 MBPS\r\n");
tass 0:b6a2ecc0d29e 677 else
tass 0:b6a2ecc0d29e 678 printf(" @ 100 MBPS\r\n");
tass 0:b6a2ecc0d29e 679 }
tass 0:b6a2ecc0d29e 680
tass 0:b6a2ecc0d29e 681 return changed;
tass 0:b6a2ecc0d29e 682 }
tass 0:b6a2ecc0d29e 683
tass 0:b6a2ecc0d29e 684 // Starts a read operation via the MII link (non-blocking)
tass 0:b6a2ecc0d29e 685 static void _emac_mii_read_noblock(uint32_t PhyReg)
tass 0:b6a2ecc0d29e 686 {
tass 0:b6a2ecc0d29e 687 // Read value at PHY address and register
tass 0:b6a2ecc0d29e 688 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
tass 0:b6a2ecc0d29e 689 LPC_EMAC->MCMD = MCMD_READ;
tass 0:b6a2ecc0d29e 690 }
tass 0:b6a2ecc0d29e 691
tass 0:b6a2ecc0d29e 692 /* Reads current MII link busy status */
tass 0:b6a2ecc0d29e 693 static uint32_t _emac_mii_is_busy(void)
tass 0:b6a2ecc0d29e 694 {
tass 0:b6a2ecc0d29e 695 return (uint32_t) (LPC_EMAC->MIND & MIND_BUSY);
tass 0:b6a2ecc0d29e 696 }
tass 0:b6a2ecc0d29e 697
tass 0:b6a2ecc0d29e 698 // Starts a read operation via the MII link (non-blocking)
tass 0:b6a2ecc0d29e 699 static uint32_t _emac_mii_read_data(void)
tass 0:b6a2ecc0d29e 700 {
tass 0:b6a2ecc0d29e 701 uint32_t data = LPC_EMAC->MRDD;
tass 0:b6a2ecc0d29e 702 LPC_EMAC->MCMD = 0;
tass 0:b6a2ecc0d29e 703
tass 0:b6a2ecc0d29e 704 return data;
tass 0:b6a2ecc0d29e 705 }
tass 0:b6a2ecc0d29e 706
tass 0:b6a2ecc0d29e 707 // Phy status update state machine
tass 0:b6a2ecc0d29e 708 static void _emac_phy_status(void const * dev)
tass 0:b6a2ecc0d29e 709 {
tass 0:b6a2ecc0d29e 710 static uint8_t phyustate = 0;
tass 0:b6a2ecc0d29e 711 uint32_t changed = 0;
tass 0:b6a2ecc0d29e 712
tass 0:b6a2ecc0d29e 713 switch (phyustate) {
tass 0:b6a2ecc0d29e 714 default:
tass 0:b6a2ecc0d29e 715 case 0:
tass 0:b6a2ecc0d29e 716 // Read BMSR to clear faults
tass 0:b6a2ecc0d29e 717 _emac_mii_read_noblock(PHY_REG_STS);
tass 0:b6a2ecc0d29e 718 phyustate = 1;
tass 0:b6a2ecc0d29e 719 break;
tass 0:b6a2ecc0d29e 720
tass 0:b6a2ecc0d29e 721 case 1:
tass 0:b6a2ecc0d29e 722 // Wait for read status state
tass 0:b6a2ecc0d29e 723 if (!_emac_mii_is_busy()) {
tass 0:b6a2ecc0d29e 724 // Update PHY status
tass 0:b6a2ecc0d29e 725 changed = _emac_update_phy_status(_emac_mii_read_data());
tass 0:b6a2ecc0d29e 726 phyustate = 0;
tass 0:b6a2ecc0d29e 727 }
tass 0:b6a2ecc0d29e 728 break;
tass 0:b6a2ecc0d29e 729 }
tass 0:b6a2ecc0d29e 730 }